From 3f71680ac0eb7646707b82e768f1302fcff3a357 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 10 Mar 2021 13:47:14 +0000 Subject: [PATCH 0001/1271] Warn when a mark is applied to a fixture Fixes #3664 --- changelog/3664.deprecation.rst | 1 + doc/en/how-to/fixtures.rst | 3 +-- src/_pytest/deprecated.py | 2 ++ src/_pytest/fixtures.py | 4 ++++ src/_pytest/mark/structures.py | 4 ++++ testing/python/fixtures.py | 18 ++++++++++++++++++ 6 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 changelog/3664.deprecation.rst diff --git a/changelog/3664.deprecation.rst b/changelog/3664.deprecation.rst new file mode 100644 index 00000000000..b12273ef070 --- /dev/null +++ b/changelog/3664.deprecation.rst @@ -0,0 +1 @@ +Deprecate applying a mark to a fixture diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index a2eb211e182..420b0d1a584 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1667,8 +1667,7 @@ into an ini-file: def my_fixture_that_sadly_wont_use_my_other_fixture(): ... - Currently this will not generate any error or warning, but this is intended - to be handled by `#3664 `_. + Currently this will generate a deprecation warning. .. _`override fixtures`: diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 596574877bf..1bdadb34374 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -95,6 +95,8 @@ "see https://docs.pytest.org/en/latest/deprecations.html#node-fspath-in-favor-of-pathlib-and-node-path", ) +MARKED_FIXTURE = PytestDeprecationWarning("Marks cannot be applied to fixtures") + # You want to make some `__init__` or function "private". # # def my_private_function(some, args): diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index b0a895a04ef..bbce454c399 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -54,6 +54,7 @@ from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest from _pytest.deprecated import FILLFUNCARGS +from _pytest.deprecated import MARKED_FIXTURE from _pytest.deprecated import NODE_FSPATH from _pytest.deprecated import YIELD_FIXTURE from _pytest.mark import Mark @@ -1222,6 +1223,9 @@ def __call__(self, function: FixtureFunction) -> FixtureFunction: "fixture is being applied more than once to the same function" ) + if hasattr(function, "pytestmark"): + warnings.warn(MARKED_FIXTURE, stacklevel=2) + function = wrap_function_to_error_out_if_called_directly(function, self) name = self.name or function.__name__ diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index d2f21e1684d..737a3ad058e 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -29,6 +29,7 @@ from ..compat import NotSetType from _pytest.config import Config from _pytest.deprecated import check_ispytest +from _pytest.deprecated import MARKED_FIXTURE from _pytest.outcomes import fail from _pytest.warning_types import PytestUnknownMarkWarning @@ -399,6 +400,9 @@ def store_mark(obj, mark: Mark) -> None: assert isinstance(mark, Mark), mark # Always reassign name to avoid updating pytestmark in a reference that # was only borrowed. + if hasattr(obj, "_pytestfixturefunction"): + warnings.warn(MARKED_FIXTURE, stacklevel=2) + obj.pytestmark = get_unpacked_marks(obj) + [mark] diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 3eb4b80f39e..3d52c1c6019 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -3612,6 +3612,24 @@ def test_fixture_disallow_twice(self): def foo(): raise NotImplementedError() + def test_fixture_disallow_on_marked_functions(self): + """Test that applying @pytest.fixture to a marked function warns (#3364).""" + with pytest.warns(pytest.PytestDeprecationWarning): + + @pytest.fixture + @pytest.mark.usefixtures("tmp_path") + def foo(): + raise NotImplementedError() + + def test_fixture_disallow_marks_on_fixtures(self): + """Test that applying a mark to a fixture warns (#3364).""" + with pytest.warns(pytest.PytestDeprecationWarning): + + @pytest.mark.usefixtures("tmp_path") + @pytest.fixture + def foo(): + raise NotImplementedError() + class TestContextManagerFixtureFuncs: def test_simple(self, pytester: Pytester) -> None: From 12efc584791ee70151bbc1d6c10fa6faa330cd2c Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Fri, 19 Mar 2021 09:43:22 +0000 Subject: [PATCH 0002/1271] document deprecation in deprecations.rst --- doc/en/deprecations.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 6ecb37b385a..482c5e18de6 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -29,6 +29,14 @@ As pytest tries to move off `py.path.local Date: Fri, 19 Mar 2021 09:44:39 +0000 Subject: [PATCH 0003/1271] update MARKED_FIXTURE deprecation message --- src/_pytest/deprecated.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 1bdadb34374..a0498a3d040 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -95,7 +95,7 @@ "see https://docs.pytest.org/en/latest/deprecations.html#node-fspath-in-favor-of-pathlib-and-node-path", ) -MARKED_FIXTURE = PytestDeprecationWarning("Marks cannot be applied to fixtures") +MARKED_FIXTURE = PytestDeprecationWarning("Marks applied to fixtures have no effect") # You want to make some `__init__` or function "private". # From 5227279c150cfc23a4c73c9538ed81a141a641b6 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Fri, 19 Mar 2021 09:47:19 +0000 Subject: [PATCH 0004/1271] Update changelog/3664.deprecation.rst --- changelog/3664.deprecation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/3664.deprecation.rst b/changelog/3664.deprecation.rst index b12273ef070..6436910a69d 100644 --- a/changelog/3664.deprecation.rst +++ b/changelog/3664.deprecation.rst @@ -1 +1 @@ -Deprecate applying a mark to a fixture +Applying a mark to a fixture function is deprecated. Doing so has no effect. From 5c286d19d80f60e9f1f607f517e9df7cda2ff6b1 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sun, 9 Oct 2022 20:11:51 +0100 Subject: [PATCH 0005/1271] Update doc/en/deprecations.rst --- doc/en/deprecations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 88978b6fe58..8ff0fe30d8f 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -276,7 +276,7 @@ deprecation warning is now raised. Applying a mark to a fixture function ------------------------------------- -.. deprecated:: 6.3 +.. deprecated:: 7.2 Applying a mark to a fixture function is deprecated. Doing so has no effect, and will raise an error in the next version. From aa9cc7e8b4f57e1c2fc15c5f7f2212c45c3ae267 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 9 Oct 2022 19:11:56 +0000 Subject: [PATCH 0006/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/fixtures.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 04035a6423f..3cb152eeb8a 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -53,9 +53,7 @@ from _pytest.config import Config from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest -from _pytest.deprecated import FILLFUNCARGS from _pytest.deprecated import MARKED_FIXTURE -from _pytest.deprecated import NODE_FSPATH from _pytest.deprecated import YIELD_FIXTURE from _pytest.mark import Mark from _pytest.mark import ParameterSet From a1b10b552abeec24a859a4596eef530d1c6f46da Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sun, 9 Oct 2022 20:23:53 +0100 Subject: [PATCH 0007/1271] use getfixturemarker --- src/_pytest/mark/structures.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 32137e8fd74..31797f563c5 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -387,11 +387,14 @@ def store_mark(obj, mark: Mark) -> None: This is used to implement the Mark declarations/decorators correctly. """ assert isinstance(mark, Mark), mark - # Always reassign name to avoid updating pytestmark in a reference that - # was only borrowed. - if hasattr(obj, "_pytestfixturefunction"): + + from ..fixtures import getfixturemarker + + if getfixturemarker(obj) is not None: warnings.warn(MARKED_FIXTURE, stacklevel=2) + # Always reassign name to avoid updating pytestmark in a reference that + # was only borrowed. obj.pytestmark = [*get_unpacked_marks(obj), mark] From 24fd2928780ea1f073d26a9ba415d62ff4101138 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 10 Oct 2022 12:28:14 +0100 Subject: [PATCH 0008/1271] Update changelog/3664.deprecation.rst Co-authored-by: Bruno Oliveira --- changelog/3664.deprecation.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog/3664.deprecation.rst b/changelog/3664.deprecation.rst index 6436910a69d..0a00e26c19f 100644 --- a/changelog/3664.deprecation.rst +++ b/changelog/3664.deprecation.rst @@ -1 +1,3 @@ -Applying a mark to a fixture function is deprecated. Doing so has no effect. +Applying a mark to a fixture function now issues a warning: marks in fixtures never had any effect, but it is a common user error to apply a mark to a fixture (for example ``usefixtures``) and expect it to work. + +This will become an error in the future. From d86df89a9291c29e19af3a762bd38bd959f1325c Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 10 Oct 2022 12:28:22 +0100 Subject: [PATCH 0009/1271] Update doc/en/deprecations.rst Co-authored-by: Bruno Oliveira --- doc/en/deprecations.rst | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 8ff0fe30d8f..25be02d41b3 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -278,7 +278,18 @@ Applying a mark to a fixture function .. deprecated:: 7.2 -Applying a mark to a fixture function is deprecated. Doing so has no effect, and will raise an error in the next version. +Applying a mark to a fixture function never had any effect, but it is a common user error. + +.. code-block:: python + + @pytest.mark.usefixtures("clean_database") + @pytest.fixture + def user() -> User: + ... + +Users expected in this case that the ``usefixtures`` mark would have its intended effect of using the ``clean_database`` fixture when ``user`` was invoked, when in fact it has no effect at all. + +Now pytest will issue a warning when it encounters this problem, and will raise an error in the future versions. Backward compatibilities in ``Parser.addoption`` From 7759a9d3c2d6805f1e080512f40a3ada9207e66c Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 10 Oct 2022 12:28:30 +0100 Subject: [PATCH 0010/1271] Update src/_pytest/deprecated.py Co-authored-by: Bruno Oliveira --- src/_pytest/deprecated.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index d6b48a3c975..fb528e38bda 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -107,7 +107,10 @@ "#configuring-hook-specs-impls-using-markers", ) -MARKED_FIXTURE = PytestDeprecationWarning("Marks applied to fixtures have no effect") +MARKED_FIXTURE = PytestDeprecationWarning( + "Marks applied to fixtures have no effect\n" + "See docs: https://docs.pytest.org/en/stable/deprecations.html#applying-a-mark-to-a-fixture-function" +) # You want to make some `__init__` or function "private". # From 0de2aa93f0e214341af40f63f498a0498cc07832 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 11:30:13 +0000 Subject: [PATCH 0011/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/en/deprecations.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 25be02d41b3..e61bf5567b1 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -281,7 +281,6 @@ Applying a mark to a fixture function Applying a mark to a fixture function never had any effect, but it is a common user error. .. code-block:: python - @pytest.mark.usefixtures("clean_database") @pytest.fixture def user() -> User: From f7542f629232633b8c9bfeee5c14de19e1070d7f Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 10 Oct 2022 13:48:26 +0100 Subject: [PATCH 0012/1271] move tests into deprecated_test, and test for number of warnings issued --- testing/deprecated_test.py | 32 ++++++++++++++++++++++++++++++++ testing/python/fixtures.py | 18 ------------------ 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index d468b443541..01b91ce6dc6 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -279,3 +279,35 @@ def test_importing_instance_is_deprecated(pytester: Pytester) -> None: match=re.escape("The pytest.Instance collector type is deprecated"), ): from _pytest.python import Instance # noqa: F401 + + +def test_fixture_disallow_on_marked_functions(): + """Test that applying @pytest.fixture to a marked function warns (#3364).""" + with pytest.warns( + pytest.PytestDeprecationWarning, + match=r"Marks applied to fixtures have no effect", + ) as record: + + @pytest.fixture + @pytest.mark.parametrize("example", ["hello"]) + @pytest.mark.usefixtures("tmp_path") + def foo(): + raise NotImplementedError() + + assert len(record) == 1 + + +def test_fixture_disallow_marks_on_fixtures(): + """Test that applying a mark to a fixture warns (#3364).""" + with pytest.warns( + pytest.PytestDeprecationWarning, + match=r"Marks applied to fixtures have no effect", + ) as record: + + @pytest.mark.parametrize("example", ["hello"]) + @pytest.mark.usefixtures("tmp_path") + @pytest.fixture + def foo(): + raise NotImplementedError() + + assert len(record) == 2 diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 4f53ffddcc5..3ce5cb34ddd 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -3620,24 +3620,6 @@ def test_fixture_disallow_twice(self): def foo(): raise NotImplementedError() - def test_fixture_disallow_on_marked_functions(self): - """Test that applying @pytest.fixture to a marked function warns (#3364).""" - with pytest.warns(pytest.PytestDeprecationWarning): - - @pytest.fixture - @pytest.mark.usefixtures("tmp_path") - def foo(): - raise NotImplementedError() - - def test_fixture_disallow_marks_on_fixtures(self): - """Test that applying a mark to a fixture warns (#3364).""" - with pytest.warns(pytest.PytestDeprecationWarning): - - @pytest.mark.usefixtures("tmp_path") - @pytest.fixture - def foo(): - raise NotImplementedError() - class TestContextManagerFixtureFuncs: def test_simple(self, pytester: Pytester) -> None: From 7f73722c4adedd3b9da6d7efe5b699a5bbc0ee0d Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 10 Oct 2022 13:52:26 +0100 Subject: [PATCH 0013/1271] add a test for fixture between mark decorators --- testing/deprecated_test.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 01b91ce6dc6..2934e69cc91 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -294,6 +294,9 @@ def test_fixture_disallow_on_marked_functions(): def foo(): raise NotImplementedError() + # it's only possible to get one warning here because you're already prevented + # from applying @fixture twice + # ValueError("fixture is being applied more than once to the same function") assert len(record) == 1 @@ -310,4 +313,20 @@ def test_fixture_disallow_marks_on_fixtures(): def foo(): raise NotImplementedError() - assert len(record) == 2 + assert len(record) == 2 # one for each mark decorator + + +def test_fixture_disallowed_between_marks(): + """Test that applying a mark to a fixture warns (#3364).""" + with pytest.warns( + pytest.PytestDeprecationWarning, + match=r"Marks applied to fixtures have no effect", + ) as record: + + @pytest.mark.parametrize("example", ["hello"]) + @pytest.fixture + @pytest.mark.usefixtures("tmp_path") + def foo(): + raise NotImplementedError() + + assert len(record) == 2 # one for each mark decorator From 246ceb84bdd7999225b44e10f220ede1d75c21d5 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Mon, 10 Oct 2022 13:58:05 +0100 Subject: [PATCH 0014/1271] Update doc/en/deprecations.rst --- doc/en/deprecations.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index e5fe61ab661..17055dfb97c 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -388,6 +388,7 @@ Applying a mark to a fixture function Applying a mark to a fixture function never had any effect, but it is a common user error. .. code-block:: python + @pytest.mark.usefixtures("clean_database") @pytest.fixture def user() -> User: From a2feb6bd000fef069ec3065d46470f59c2d24450 Mon Sep 17 00:00:00 2001 From: Erik Hasse Date: Thu, 18 May 2023 00:19:36 -0500 Subject: [PATCH 0015/1271] add a warning about modifying the root logger during tests --- AUTHORS | 1 + changelog/11011.doc.rst | 1 + doc/en/how-to/logging.rst | 7 +++++++ 3 files changed, 9 insertions(+) create mode 100644 changelog/11011.doc.rst diff --git a/AUTHORS b/AUTHORS index 92b0b2a1a55..b5b4cc1a173 100644 --- a/AUTHORS +++ b/AUTHORS @@ -128,6 +128,7 @@ Eric Hunsberger Eric Liu Eric Siegerman Erik Aronesty +Erik Hasse Erik M. Bray Evan Kepner Fabien Zarifian diff --git a/changelog/11011.doc.rst b/changelog/11011.doc.rst new file mode 100644 index 00000000000..5faabba9c8f --- /dev/null +++ b/changelog/11011.doc.rst @@ -0,0 +1 @@ +Added a warning about modifying the root logger during tests when using ``caplog``. diff --git a/doc/en/how-to/logging.rst b/doc/en/how-to/logging.rst index 9957a9bb886..b9f522fa4d0 100644 --- a/doc/en/how-to/logging.rst +++ b/doc/en/how-to/logging.rst @@ -172,6 +172,13 @@ the records for the ``setup`` and ``call`` stages during teardown like so: The full API is available at :class:`pytest.LogCaptureFixture`. +.. warning:: + + The ``caplog`` fixture adds a handler to the root logger to capture logs. If the root logger is + modified during a test, for example with ``logging.config.dictConfig``, this handler may be + removed and cause no logs to be captured. To avoid this, ensure that any root logger configuration + only adds to the existing handlers. + .. _live_logs: From 264e7ac32733572fad3892ba0e830dba7cc87cf0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 14 Jun 2023 09:22:34 +0300 Subject: [PATCH 0016/1271] reference: add doc for `Package` We document the other py collectors, we should document `Package` as well. --- doc/en/reference/reference.rst | 6 ++++++ src/_pytest/python.py | 3 +++ 2 files changed, 9 insertions(+) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 7107218b38b..f591eb21e7d 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -926,6 +926,12 @@ Parser .. autoclass:: pytest.Parser() :members: +Package +~~~~~~~ + +.. autoclass:: pytest.Package() + :members: + OptionGroup ~~~~~~~~~~~ diff --git a/src/_pytest/python.py b/src/_pytest/python.py index ad847c8afe2..2036819cf8f 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -659,6 +659,9 @@ def _importtestmodule(self): class Package(Module): + """Collector for files and directories in a Python packages -- directories + with an `__init__.py` file.""" + def __init__( self, fspath: Optional[LEGACY_PATH], From bd88a6412d7518c94ebdb4bbfcff39accd771d4f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 14 Jun 2023 09:19:56 +0300 Subject: [PATCH 0017/1271] reference: separate node types to their own section I think it's helpful to separate the node classes from the other objects, as they have their own unique usage. I've chosen not to alphabetize the order, but to use a logical order instead. Also slightly improve the docstrings. --- doc/en/reference/reference.rst | 144 +++++++++++++++++---------------- src/_pytest/main.py | 5 ++ src/_pytest/nodes.py | 21 +++-- src/_pytest/python.py | 12 ++- 4 files changed, 99 insertions(+), 83 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index f591eb21e7d..6154bbf2537 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -783,25 +783,17 @@ reporting or interaction with exceptions: .. autofunction:: pytest_leave_pdb -Objects -------- - -Full reference to objects accessible from :ref:`fixtures ` or :ref:`hooks `. - - -CallInfo -~~~~~~~~ - -.. autoclass:: pytest.CallInfo() - :members: +Collection tree objects +----------------------- +These are the collector and item classes (collectively called "nodes") which +make up the collection tree. -Class -~~~~~ +Node +~~~~ -.. autoclass:: pytest.Class() +.. autoclass:: _pytest.nodes.Node() :members: - :show-inheritance: Collector ~~~~~~~~~ @@ -810,52 +802,52 @@ Collector :members: :show-inheritance: -CollectReport -~~~~~~~~~~~~~ +Item +~~~~ -.. autoclass:: pytest.CollectReport() +.. autoclass:: pytest.Item() :members: :show-inheritance: - :inherited-members: -Config -~~~~~~ +File +~~~~ -.. autoclass:: pytest.Config() +.. autoclass:: pytest.File() :members: + :show-inheritance: -ExceptionInfo -~~~~~~~~~~~~~ +FSCollector +~~~~~~~~~~~ -.. autoclass:: pytest.ExceptionInfo() +.. autoclass:: _pytest.nodes.FSCollector() :members: + :show-inheritance: +Session +~~~~~~~ -ExitCode -~~~~~~~~ - -.. autoclass:: pytest.ExitCode +.. autoclass:: pytest.Session() :members: + :show-inheritance: -File -~~~~ +Package +~~~~~~~ -.. autoclass:: pytest.File() +.. autoclass:: pytest.Package() :members: :show-inheritance: +Module +~~~~~~ -FixtureDef -~~~~~~~~~~ - -.. autoclass:: _pytest.fixtures.FixtureDef() +.. autoclass:: pytest.Module() :members: :show-inheritance: -FSCollector -~~~~~~~~~~~ +Class +~~~~~ -.. autoclass:: _pytest.nodes.FSCollector() +.. autoclass:: pytest.Class() :members: :show-inheritance: @@ -873,10 +865,52 @@ FunctionDefinition :members: :show-inheritance: -Item -~~~~ -.. autoclass:: pytest.Item() +Objects +------- + +Objects accessible from :ref:`fixtures ` or :ref:`hooks ` +or importable from ``pytest``. + + +CallInfo +~~~~~~~~ + +.. autoclass:: pytest.CallInfo() + :members: + +CollectReport +~~~~~~~~~~~~~ + +.. autoclass:: pytest.CollectReport() + :members: + :show-inheritance: + :inherited-members: + +Config +~~~~~~ + +.. autoclass:: pytest.Config() + :members: + +ExceptionInfo +~~~~~~~~~~~~~ + +.. autoclass:: pytest.ExceptionInfo() + :members: + + +ExitCode +~~~~~~~~ + +.. autoclass:: pytest.ExitCode + :members: + + +FixtureDef +~~~~~~~~~~ + +.. autoclass:: _pytest.fixtures.FixtureDef() :members: :show-inheritance: @@ -907,31 +941,12 @@ Metafunc .. autoclass:: pytest.Metafunc() :members: -Module -~~~~~~ - -.. autoclass:: pytest.Module() - :members: - :show-inheritance: - -Node -~~~~ - -.. autoclass:: _pytest.nodes.Node() - :members: - Parser ~~~~~~ .. autoclass:: pytest.Parser() :members: -Package -~~~~~~~ - -.. autoclass:: pytest.Package() - :members: - OptionGroup ~~~~~~~~~~~ @@ -947,13 +962,6 @@ PytestPluginManager :inherited-members: :show-inheritance: -Session -~~~~~~~ - -.. autoclass:: pytest.Session() - :members: - :show-inheritance: - TestReport ~~~~~~~~~~ diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 155d4300e2c..803b95a2033 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -462,6 +462,11 @@ def __missing__(self, path: Path) -> str: @final class Session(nodes.FSCollector): + """The root of the collection tree. + + ``Session`` collects the initial paths given as arguments to pytest. + """ + Interrupted = Interrupted Failed = Failed # Set on the session by runner.pytest_sessionstart. diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index dbd6b0a4273..667a02b77af 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -157,10 +157,11 @@ def _create(self, *k, **kw): class Node(metaclass=NodeMeta): - """Base class for Collector and Item, the components of the test - collection tree. + r"""Base class of :class:`Collector` and :class:`Item`, the components of + the test collection tree. - Collector subclasses have children; Items are leaf nodes. + ``Collector``\'s are the internal nodes of the tree, and ``Item``\'s are the + leaf nodes. """ # Implemented in the legacypath plugin. @@ -525,15 +526,17 @@ def get_fslocation_from_item(node: "Node") -> Tuple[Union[str, Path], Optional[i class Collector(Node): - """Collector instances create children through collect() and thus - iteratively build a tree.""" + """Base class of all collectors. + + Collector create children through `collect()` and thus iteratively build + the collection tree. + """ class CollectError(Exception): """An error during collection, contains a custom message.""" def collect(self) -> Iterable[Union["Item", "Collector"]]: - """Return a list of children (items and collectors) for this - collection node.""" + """Collect children (items and collectors) for this collector.""" raise NotImplementedError("abstract") # TODO: This omits the style= parameter which breaks Liskov Substitution. @@ -577,6 +580,8 @@ def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[ class FSCollector(Collector): + """Base class for filesystem collectors.""" + def __init__( self, fspath: Optional[LEGACY_PATH] = None, @@ -660,7 +665,7 @@ class File(FSCollector): class Item(Node): - """A basic test invocation item. + """Base class of all test invocation items. Note that for a single function there might be multiple test invocation items. """ diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 2036819cf8f..b24dc90d8ee 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -522,7 +522,7 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]: class Module(nodes.File, PyCollector): - """Collector for test classes and functions.""" + """Collector for test classes and functions in a Python module.""" def _getobj(self): return self._importtestmodule() @@ -791,7 +791,7 @@ def _get_first_non_fixture_func(obj: object, names: Iterable[str]) -> Optional[o class Class(PyCollector): - """Collector for test methods.""" + """Collector for test methods (and nested classes) in a Python class.""" @classmethod def from_parent(cls, parent, *, name, obj=None, **kw): @@ -1676,7 +1676,7 @@ def write_docstring(tw: TerminalWriter, doc: str, indent: str = " ") -> None: class Function(PyobjMixin, nodes.Item): - """An Item responsible for setting up and executing a Python test function. + """Item responsible for setting up and executing a Python test function. :param name: The full function name, including any decorations like those @@ -1833,10 +1833,8 @@ def repr_failure( # type: ignore[override] class FunctionDefinition(Function): - """ - This class is a step gap solution until we evolve to have actual function definition nodes - and manage to get rid of ``metafunc``. - """ + """This class is a stop gap solution until we evolve to have actual function + definition nodes and manage to get rid of ``metafunc``.""" def runtest(self) -> None: raise RuntimeError("function definitions are not supposed to be run as tests") From a14745550a07057f6dab798fccfb26403262253a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 23 Jun 2023 14:18:43 +0300 Subject: [PATCH 0018/1271] Merge pull request #11131 from pytest-dev/release-7.4.0 Prepare release 7.4.0 (cherry picked from commit fb03d1388b002f63973c663cb4929908a2ca81f5) --- changelog/10831.bugfix.rst | 1 - changelog/10872.improvement.rst | 1 - changelog/10901.feature.rst | 2 - changelog/10907.improvement.rst | 5 -- changelog/10940.improvement.rst | 3 - changelog/10991.improvement.rst | 1 - changelog/11005.improvement.rst | 1 - changelog/11013.improvement.rst | 1 - changelog/11031.trivial.rst | 1 - changelog/11043.improvement.rst | 3 - changelog/11068.bugfix.rst | 1 - changelog/11081.improvement.rst | 7 --- changelog/11104.bugfix.rst | 3 - changelog/1904.bugfix.rst | 1 - changelog/7781.bugfix.rst | 1 - changelog/8711.improvement.rst | 3 - changelog/9146.doc.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.0.rst | 49 ++++++++++++++++ doc/en/builtin.rst | 6 +- doc/en/changelog.rst | 92 +++++++++++++++++++++++++++++++ doc/en/getting-started.rst | 2 +- doc/en/reference/reference.rst | 4 +- 23 files changed, 148 insertions(+), 42 deletions(-) delete mode 100644 changelog/10831.bugfix.rst delete mode 100644 changelog/10872.improvement.rst delete mode 100644 changelog/10901.feature.rst delete mode 100644 changelog/10907.improvement.rst delete mode 100644 changelog/10940.improvement.rst delete mode 100644 changelog/10991.improvement.rst delete mode 100644 changelog/11005.improvement.rst delete mode 100644 changelog/11013.improvement.rst delete mode 100644 changelog/11031.trivial.rst delete mode 100644 changelog/11043.improvement.rst delete mode 100644 changelog/11068.bugfix.rst delete mode 100644 changelog/11081.improvement.rst delete mode 100644 changelog/11104.bugfix.rst delete mode 100644 changelog/1904.bugfix.rst delete mode 100644 changelog/7781.bugfix.rst delete mode 100644 changelog/8711.improvement.rst delete mode 100644 changelog/9146.doc.rst create mode 100644 doc/en/announce/release-7.4.0.rst diff --git a/changelog/10831.bugfix.rst b/changelog/10831.bugfix.rst deleted file mode 100644 index ea641dee60e..00000000000 --- a/changelog/10831.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Terminal Reporting: Fixed bug when running in ``--tb=line`` mode where ``pytest.fail(pytrace=False)`` tests report ``None``. diff --git a/changelog/10872.improvement.rst b/changelog/10872.improvement.rst deleted file mode 100644 index fe0c01a0224..00000000000 --- a/changelog/10872.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Update test log report annotation to named tuple and fixed inconsistency in docs for :hook:`pytest_report_teststatus` hook. diff --git a/changelog/10901.feature.rst b/changelog/10901.feature.rst deleted file mode 100644 index 0d99d66f67f..00000000000 --- a/changelog/10901.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added :func:`ExceptionInfo.from_exception() `, a simpler way to create an :class:`~pytest.ExceptionInfo` from an exception. -This can replace :func:`ExceptionInfo.from_exc_info() ` for most uses. diff --git a/changelog/10907.improvement.rst b/changelog/10907.improvement.rst deleted file mode 100644 index 7f011a827d3..00000000000 --- a/changelog/10907.improvement.rst +++ /dev/null @@ -1,5 +0,0 @@ -When an exception traceback to be displayed is completely filtered out (by mechanisms such as ``__tracebackhide__``, internal frames, and similar), now only the exception string and the following message are shown: - -"All traceback entries are hidden. Pass `--full-trace` to see hidden and internal frames.". - -Previously, the last frame of the traceback was shown, even though it was hidden. diff --git a/changelog/10940.improvement.rst b/changelog/10940.improvement.rst deleted file mode 100644 index f3e33cbc68d..00000000000 --- a/changelog/10940.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Improved verbose output (``-vv``) of ``skip`` and ``xfail`` reasons by performing text wrapping while leaving a clear margin for progress output. - -Added :func:`TerminalReporter.wrap_write() ` as a helper for that. diff --git a/changelog/10991.improvement.rst b/changelog/10991.improvement.rst deleted file mode 100644 index 768c08e554c..00000000000 --- a/changelog/10991.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added handling of ``%f`` directive to print microseconds in log format options, such as ``log-date-format``. diff --git a/changelog/11005.improvement.rst b/changelog/11005.improvement.rst deleted file mode 100644 index 295252514a6..00000000000 --- a/changelog/11005.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added underlying exception to cache provider path creation and write warning messages. diff --git a/changelog/11013.improvement.rst b/changelog/11013.improvement.rst deleted file mode 100644 index fe3ece93c23..00000000000 --- a/changelog/11013.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added warning when :confval:`testpaths` is set, but paths are not found by glob. In this case, pytest will fall back to searching from the current directory. diff --git a/changelog/11031.trivial.rst b/changelog/11031.trivial.rst deleted file mode 100644 index fad2cf24d5a..00000000000 --- a/changelog/11031.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Enhanced the CLI flag for ``-c`` to now include ``--config-file`` to make it clear that this flag applies to the usage of a custom config file. diff --git a/changelog/11043.improvement.rst b/changelog/11043.improvement.rst deleted file mode 100644 index 1fe0361d7f9..00000000000 --- a/changelog/11043.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -When `--confcutdir` is not specified, and there is no config file present, the conftest cutoff directory (`--confcutdir`) is now set to the :ref:`rootdir`. -Previously in such cases, `conftest.py` files would be probed all the way to the root directory of the filesystem. -If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set `--confcutdir`. diff --git a/changelog/11068.bugfix.rst b/changelog/11068.bugfix.rst deleted file mode 100644 index 45cdb105fb4..00000000000 --- a/changelog/11068.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the ``--last-failed`` whole-file skipping functionality ("skipped N files") for :ref:`non-python test files `. diff --git a/changelog/11081.improvement.rst b/changelog/11081.improvement.rst deleted file mode 100644 index ccfaf6016ae..00000000000 --- a/changelog/11081.improvement.rst +++ /dev/null @@ -1,7 +0,0 @@ -The :confval:`norecursedir` check is now performed in a :hook:`pytest_ignore_collect` implementation, so plugins can affect it. - -If after updating to this version you see that your `norecursedir` setting is not being respected, -it means that a conftest or a plugin you use has a bad `pytest_ignore_collect` implementation. -Most likely, your hook returns `False` for paths it does not want to ignore, -which ends the processing and doesn't allow other plugins, including pytest itself, to ignore the path. -The fix is to return `None` instead of `False` for paths your hook doesn't want to ignore. diff --git a/changelog/11104.bugfix.rst b/changelog/11104.bugfix.rst deleted file mode 100644 index 10f0db92515..00000000000 --- a/changelog/11104.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a regression in pytest 7.3.2 which caused to :confval:`testpaths` to be considered for loading initial conftests, -even when it was not utilized (e.g. when explicit paths were given on the command line). -Now the ``testpaths`` are only considered when they are in use. diff --git a/changelog/1904.bugfix.rst b/changelog/1904.bugfix.rst deleted file mode 100644 index 3e1a292152b..00000000000 --- a/changelog/1904.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed traceback entries hidden with ``__tracebackhide__ = True`` still being shown for chained exceptions (parts after "... the above exception ..." message). diff --git a/changelog/7781.bugfix.rst b/changelog/7781.bugfix.rst deleted file mode 100644 index 191fcd4daf4..00000000000 --- a/changelog/7781.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix writing non-encodable text to log file when using ``--debug``. diff --git a/changelog/8711.improvement.rst b/changelog/8711.improvement.rst deleted file mode 100644 index 20805e9f94d..00000000000 --- a/changelog/8711.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`_pytest.logging.LogCaptureFixture.set_level` and :func:`_pytest.logging.LogCaptureFixture.at_level` -will temporarily enable the requested ``level`` if ``level`` was disabled globally via -``logging.disable(LEVEL)``. diff --git a/changelog/9146.doc.rst b/changelog/9146.doc.rst deleted file mode 100644 index 95189b96d46..00000000000 --- a/changelog/9146.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Improve Documentation for `caplog.set_level`. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index bcc0669a62f..914e763bd9e 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.0 release-7.3.2 release-7.3.1 release-7.3.0 diff --git a/doc/en/announce/release-7.4.0.rst b/doc/en/announce/release-7.4.0.rst new file mode 100644 index 00000000000..5a0d18267d3 --- /dev/null +++ b/doc/en/announce/release-7.4.0.rst @@ -0,0 +1,49 @@ +pytest-7.4.0 +======================================= + +The pytest team is proud to announce the 7.4.0 release! + +This release contains new features, improvements, and bug fixes, +the full list of changes is available in the changelog: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Adam J. Stewart +* Alessio Izzo +* Alex +* Alex Lambson +* Brian Larsen +* Bruno Oliveira +* Bryan Ricker +* Chris Mahoney +* Facundo Batista +* Florian Bruhin +* Jarrett Keifer +* Kenny Y +* Miro Hrončok +* Ran Benita +* Roberto Aldera +* Ronny Pfannschmidt +* Sergey Kim +* Stefanie Molin +* Vijay Arora +* Ville Skyttä +* Zac Hatfield-Dodds +* bzoracler +* leeyueh +* nondescryptid +* theirix + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 7ae185f6c7d..53305eecded 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:510 + cache -- .../_pytest/cacheprovider.py:528 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -119,7 +119,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1360 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1353 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -196,7 +196,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:498 + caplog -- .../_pytest/logging.py:570 Access and control log capturing. Captured logs are available through the following properties/methods:: diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index cdc9e66f68b..391721df34d 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,98 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.0 (2023-06-23) +========================= + +Features +-------- + +- `#10901 `_: Added :func:`ExceptionInfo.from_exception() `, a simpler way to create an :class:`~pytest.ExceptionInfo` from an exception. + This can replace :func:`ExceptionInfo.from_exc_info() ` for most uses. + + + +Improvements +------------ + +- `#10872 `_: Update test log report annotation to named tuple and fixed inconsistency in docs for :hook:`pytest_report_teststatus` hook. + + +- `#10907 `_: When an exception traceback to be displayed is completely filtered out (by mechanisms such as ``__tracebackhide__``, internal frames, and similar), now only the exception string and the following message are shown: + + "All traceback entries are hidden. Pass `--full-trace` to see hidden and internal frames.". + + Previously, the last frame of the traceback was shown, even though it was hidden. + + +- `#10940 `_: Improved verbose output (``-vv``) of ``skip`` and ``xfail`` reasons by performing text wrapping while leaving a clear margin for progress output. + + Added ``TerminalReporter.wrap_write()`` as a helper for that. + + +- `#10991 `_: Added handling of ``%f`` directive to print microseconds in log format options, such as ``log-date-format``. + + +- `#11005 `_: Added the underlying exception to the cache provider's path creation and write warning messages. + + +- `#11013 `_: Added warning when :confval:`testpaths` is set, but paths are not found by glob. In this case, pytest will fall back to searching from the current directory. + + +- `#11043 `_: When `--confcutdir` is not specified, and there is no config file present, the conftest cutoff directory (`--confcutdir`) is now set to the :ref:`rootdir `. + Previously in such cases, `conftest.py` files would be probed all the way to the root directory of the filesystem. + If you are badly affected by this change, consider adding an empty config file to your desired cutoff directory, or explicitly set `--confcutdir`. + + +- `#11081 `_: The :confval:`norecursedirs` check is now performed in a :hook:`pytest_ignore_collect` implementation, so plugins can affect it. + + If after updating to this version you see that your `norecursedirs` setting is not being respected, + it means that a conftest or a plugin you use has a bad `pytest_ignore_collect` implementation. + Most likely, your hook returns `False` for paths it does not want to ignore, + which ends the processing and doesn't allow other plugins, including pytest itself, to ignore the path. + The fix is to return `None` instead of `False` for paths your hook doesn't want to ignore. + + +- `#8711 `_: :func:`caplog.set_level() ` and :func:`caplog.at_level() ` + will temporarily enable the requested ``level`` if ``level`` was disabled globally via + ``logging.disable(LEVEL)``. + + + +Bug Fixes +--------- + +- `#10831 `_: Terminal Reporting: Fixed bug when running in ``--tb=line`` mode where ``pytest.fail(pytrace=False)`` tests report ``None``. + + +- `#11068 `_: Fixed the ``--last-failed`` whole-file skipping functionality ("skipped N files") for :ref:`non-python test files `. + + +- `#11104 `_: Fixed a regression in pytest 7.3.2 which caused to :confval:`testpaths` to be considered for loading initial conftests, + even when it was not utilized (e.g. when explicit paths were given on the command line). + Now the ``testpaths`` are only considered when they are in use. + + +- `#1904 `_: Fixed traceback entries hidden with ``__tracebackhide__ = True`` still being shown for chained exceptions (parts after "... the above exception ..." message). + + +- `#7781 `_: Fix writing non-encodable text to log file when using ``--debug``. + + + +Improved Documentation +---------------------- + +- `#9146 `_: Improved documentation for :func:`caplog.set_level() `. + + + +Trivial/Internal Changes +------------------------ + +- `#11031 `_: Enhanced the CLI flag for ``-c`` to now include ``--config-file`` to make it clear that this flag applies to the usage of a custom config file. + + pytest 7.3.2 (2023-06-10) ========================= diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 2dbf7d3870c..e295c180454 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 7.3.2 + pytest 7.4.0 .. _`simpletest`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index c6629db84fa..83bbccbcbdc 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1923,9 +1923,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: --strict-markers Markers not registered in the `markers` section of the configuration file raise errors --strict (Deprecated) alias to --strict-markers - -c, --config-file FILE + -c FILE, --config-file=FILE Load configuration from `FILE` instead of trying to - locate one of the implicit configuration files + locate one of the implicit configuration files. --continue-on-collection-errors Force test execution even if collection errors occur --rootdir=ROOTDIR Define root directory for tests. Can be relative From a4a189ad99b2a7c3536de30009bb8111a0cf176e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 23 Jun 2023 14:36:48 +0300 Subject: [PATCH 0019/1271] Change PytestRemovedIn8Warning to error by default Per our backward compatibility policy. --- changelog/7363.breaking.rst | 22 ++++++++++++++++++++++ src/_pytest/warnings.py | 2 ++ testing/acceptance_test.py | 6 ++---- testing/deprecated_test.py | 14 +++++++------- testing/test_config.py | 2 +- testing/test_nose.py | 22 ++++++++++++++++------ testing/test_warnings.py | 3 ++- 7 files changed, 52 insertions(+), 19 deletions(-) create mode 100644 changelog/7363.breaking.rst diff --git a/changelog/7363.breaking.rst b/changelog/7363.breaking.rst new file mode 100644 index 00000000000..93d87b1b104 --- /dev/null +++ b/changelog/7363.breaking.rst @@ -0,0 +1,22 @@ +**PytestRemovedIn8Warning deprecation warnings are now errors by default.** + +Following our plan to remove deprecated features with as little disruption as +possible, all warnings of type ``PytestRemovedIn8Warning`` now generate errors +instead of warning messages by default. + +**The affected features will be effectively removed in pytest 8.1**, so please consult the +:ref:`deprecations` section in the docs for directions on how to update existing code. + +In the pytest ``8.0.X`` series, it is possible to change the errors back into warnings as a +stopgap measure by adding this to your ``pytest.ini`` file: + +.. code-block:: ini + + [pytest] + filterwarnings = + ignore::pytest.PytestRemovedIn8Warning + +But this will stop working when pytest ``8.1`` is released. + +**If you have concerns** about the removal of a specific feature, please add a +comment to :issue:`7363`. diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index 4aaa9445293..bb293ec0821 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -49,6 +49,8 @@ def catch_warnings_for_item( warnings.filterwarnings("always", category=DeprecationWarning) warnings.filterwarnings("always", category=PendingDeprecationWarning) + warnings.filterwarnings("error", category=pytest.PytestRemovedIn8Warning) + apply_warning_filters(config_filters, cmdline_filters) # apply filters from "filterwarnings" marks diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 5658f2fd6b8..de9e92d00f0 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1164,7 +1164,6 @@ def test_usage_error_code(pytester: Pytester) -> None: assert result.ret == ExitCode.USAGE_ERROR -@pytest.mark.filterwarnings("default::pytest.PytestUnhandledCoroutineWarning") def test_warn_on_async_function(pytester: Pytester) -> None: # In the below we .close() the coroutine only to avoid # "RuntimeWarning: coroutine 'test_2' was never awaited" @@ -1181,7 +1180,7 @@ def test_3(): return coro """ ) - result = pytester.runpytest() + result = pytester.runpytest("-Wdefault") result.stdout.fnmatch_lines( [ "test_async.py::test_1", @@ -1197,7 +1196,6 @@ def test_3(): ) -@pytest.mark.filterwarnings("default::pytest.PytestUnhandledCoroutineWarning") def test_warn_on_async_gen_function(pytester: Pytester) -> None: pytester.makepyfile( test_async=""" @@ -1209,7 +1207,7 @@ def test_3(): return test_2() """ ) - result = pytester.runpytest() + result = pytester.runpytest("-Wdefault") result.stdout.fnmatch_lines( [ "test_async.py::test_1", diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 3ceed7f5a2c..50eedb83c66 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -103,7 +103,7 @@ def test_strict_option_is_deprecated(pytester: Pytester) -> None: def test_foo(): pass """ ) - result = pytester.runpytest("--strict") + result = pytester.runpytest("--strict", "-Wdefault::pytest.PytestRemovedIn8Warning") result.stdout.fnmatch_lines( [ "'unknown' not found in `markers` configuration option", @@ -189,7 +189,7 @@ def test_skipping_msg(): pytest.skip(msg="skippedmsg") """ ) - result = pytester.runpytest(p) + result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning") result.stdout.fnmatch_lines( [ "*PytestRemovedIn8Warning: pytest.skip(msg=...) is now deprecated, " @@ -208,7 +208,7 @@ def test_failing_msg(): pytest.fail(msg="failedmsg") """ ) - result = pytester.runpytest(p) + result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning") result.stdout.fnmatch_lines( [ "*PytestRemovedIn8Warning: pytest.fail(msg=...) is now deprecated, " @@ -227,7 +227,7 @@ def test_exit_msg(): pytest.exit(msg="exitmsg") """ ) - result = pytester.runpytest(p) + result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning") result.stdout.fnmatch_lines( [ "*PytestRemovedIn8Warning: pytest.exit(msg=...) is now deprecated, " @@ -245,7 +245,7 @@ def pytest_cmdline_preparse(config, args): """ ) - result = pytester.runpytest() + result = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning") result.stdout.fnmatch_lines( [ "*PytestRemovedIn8Warning: The pytest_cmdline_preparse hook is deprecated*", @@ -299,7 +299,7 @@ def test_omits_warnings(): ... """ ) - output = pytester.runpytest() + output = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning") message = [ "*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.", "*test_nose_deprecated_with_setup.py::test_omits_warnings is using nose method: `setup_fn_no_op` (setup)", @@ -327,7 +327,7 @@ def test(self): ... """ ) - output = pytester.runpytest() + output = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning") message = [ "*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.", "*test_nose_deprecated_setup_teardown.py::Test::test is using nose-specific method: `setup(self)`", diff --git a/testing/test_config.py b/testing/test_config.py index 3aec5d7631f..257d696fa65 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1184,7 +1184,7 @@ def pytest_cmdline_preparse(args): args.append("-h") """ ) - result = pytester.runpytest() + result = pytester.runpytest("-Wignore::pytest.PytestRemovedIn8Warning") result.stdout.fnmatch_lines(["*pytest*", "*-h*"]) diff --git a/testing/test_nose.py b/testing/test_nose.py index e838e79ddd5..cc79eb45b9f 100644 --- a/testing/test_nose.py +++ b/testing/test_nose.py @@ -23,7 +23,9 @@ def test_world(): test_hello.teardown = lambda: values.append(2) """ ) - result = pytester.runpytest(p, "-p", "nose") + result = pytester.runpytest( + p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" + ) result.assert_outcomes(passed=2) @@ -76,7 +78,9 @@ def test_world(): """ ) - result = pytester.runpytest(p, "-p", "nose") + result = pytester.runpytest( + p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" + ) result.assert_outcomes(passed=2) @@ -100,7 +104,9 @@ def test_world(): """ ) - result = pytester.runpytest(p, "-p", "nose") + result = pytester.runpytest( + p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" + ) result.stdout.fnmatch_lines(["*TypeError: ()*"]) @@ -154,7 +160,9 @@ def test_world(): test_hello.teardown = my_teardown_partial """ ) - result = pytester.runpytest(p, "-p", "nose") + result = pytester.runpytest( + p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" + ) result.stdout.fnmatch_lines(["*2 passed*"]) @@ -193,7 +201,9 @@ def test_local_setup_again(): assert items["setup2"] == ["up", "down", "up"] """ ) - result = pytester.runpytest("-p", "nose") + result = pytester.runpytest( + "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" + ) result.stdout.fnmatch_lines(["*4 passed*"]) @@ -278,7 +288,7 @@ def test_first(self): assert self.visited_cls """ ) - result = pytester.runpytest() + result = pytester.runpytest("-Wignore::pytest.PytestRemovedIn8Warning") result.stdout.fnmatch_lines(["*1 passed*"]) diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 03846cb30c3..96ecad6f647 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -518,7 +518,8 @@ def test_hidden_by_system(self, pytester: Pytester, monkeypatch) -> None: assert WARNINGS_SUMMARY_HEADER not in result.stdout.str() -@pytest.mark.skip("not relevant until pytest 8.0") +# In 8.1, uncomment below and change RemovedIn8 -> RemovedIn9. +# @pytest.mark.skip("not relevant until pytest 9.0") @pytest.mark.parametrize("change_default", [None, "ini", "cmdline"]) def test_removed_in_x_warning_as_error(pytester: Pytester, change_default) -> None: """This ensures that PytestRemovedInXWarnings raised by pytest are turned into errors. From 1b7896f83d5c7ed822f5efc1d62fb33325ce2471 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 23 Jun 2023 15:25:52 +0300 Subject: [PATCH 0020/1271] Add PytestRemovedIn9Warning It's good to have it available already in all 8.* versions, even if it's not used yet. --- doc/en/reference/reference.rst | 3 +++ src/_pytest/warning_types.py | 6 ++++++ src/pytest/__init__.py | 2 ++ 3 files changed, 11 insertions(+) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 83bbccbcbdc..d5ab94bc346 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1153,6 +1153,9 @@ Custom warnings generated in some situations such as improper usage or deprecate .. autoclass:: pytest.PytestRemovedIn8Warning :show-inheritance: +.. autoclass:: pytest.PytestRemovedIn9Warning + :show-inheritance: + .. autoclass:: pytest.PytestUnhandledCoroutineWarning :show-inheritance: diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index bd5f4187343..f6b0a3a69ae 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -56,6 +56,12 @@ class PytestRemovedIn8Warning(PytestDeprecationWarning): __module__ = "pytest" +class PytestRemovedIn9Warning(PytestDeprecationWarning): + """Warning class for features that will be removed in pytest 9.""" + + __module__ = "pytest" + + class PytestReturnNotNoneWarning(PytestRemovedIn8Warning): """Warning emitted when a test function is returning value other than None.""" diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 9c1d5d204d8..58ddb3288eb 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -71,6 +71,7 @@ from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestExperimentalApiWarning from _pytest.warning_types import PytestRemovedIn8Warning +from _pytest.warning_types import PytestRemovedIn9Warning from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning from _pytest.warning_types import PytestUnhandledThreadExceptionWarning @@ -131,6 +132,7 @@ "PytestDeprecationWarning", "PytestExperimentalApiWarning", "PytestRemovedIn8Warning", + "PytestRemovedIn9Warning", "PytestReturnNotNoneWarning", "Pytester", "PytestPluginManager", From c8b1790ee783c89d1dbda837f2a67001c71da741 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 27 May 2023 14:42:19 +0300 Subject: [PATCH 0021/1271] python: change `pytest pkg/__init__.py` to only collect the `__init__.py` Module Previously it would collect the entire package, but this is not what users expect. Refs #3749 Fixes #8976 Fixes #9263 Fixes #9313 --- changelog/8976.breaking.rst | 5 ++++ doc/en/deprecations.rst | 18 +++++++++++-- src/_pytest/python.py | 4 ++- .../package_init_given_as_arg/pkg/__init__.py | 2 ++ .../package_init_given_as_arg/pkg/test_foo.py | 2 +- testing/python/collect.py | 11 +++++--- testing/test_collection.py | 25 +++++++++++++------ testing/test_doctest.py | 4 +-- testing/test_nose.py | 2 +- 9 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 changelog/8976.breaking.rst diff --git a/changelog/8976.breaking.rst b/changelog/8976.breaking.rst new file mode 100644 index 00000000000..bd9a63982b9 --- /dev/null +++ b/changelog/8976.breaking.rst @@ -0,0 +1,5 @@ +Running `pytest pkg/__init__.py` now collects the `pkg/__init__.py` file (module) only. +Previously, it collected the entire `pkg` package, including other test files in the directory, but excluding tests in the `__init__.py` file itself +(unless :confval:`python_files` was changed to allow `__init__.py` file). + +To collect the entire package, specify just the directory: `pytest pkg`. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 4f7830a2791..810f0062b5f 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -467,12 +467,26 @@ The ``yield_fixture`` function/decorator It has been so for a very long time, so can be search/replaced safely. -Removed Features ----------------- +Removed Features and Breaking Changes +------------------------------------- As stated in our :ref:`backwards-compatibility` policy, deprecated features are removed only in major releases after an appropriate period of deprecation has passed. +Some breaking changes which could not be deprecated are also listed. + + +Collecting ``__init__.py`` files no longer collects package +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionremoved:: 8.0 + +Running `pytest pkg/__init__.py` now collects the `pkg/__init__.py` file (module) only. +Previously, it collected the entire `pkg` package, including other test files in the directory, but excluding tests in the `__init__.py` file itself +(unless :confval:`python_files` was changed to allow `__init__.py` file). + +To collect the entire package, specify just the directory: `pytest pkg`. + The ``pytest.collect`` module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/python.py b/src/_pytest/python.py index ad847c8afe2..6ba568c0fa7 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -736,7 +736,9 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: this_path = self.path.parent # Always collect the __init__ first. - if path_matches_patterns(self.path, self.config.getini("python_files")): + if self.session.isinitpath(self.path) or path_matches_patterns( + self.path, self.config.getini("python_files") + ): yield Module.from_parent(self, path=self.path) pkg_prefixes: Set[Path] = set() diff --git a/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py b/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py index e69de29bb2d..9cd366295e7 100644 --- a/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py +++ b/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py @@ -0,0 +1,2 @@ +def test_init(): + pass diff --git a/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py b/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py index f174823854e..8f2d73cfa4f 100644 --- a/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py +++ b/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py @@ -1,2 +1,2 @@ -def test(): +def test_foo(): pass diff --git a/testing/python/collect.py b/testing/python/collect.py index 9bf6e00d1f0..8de216d8f54 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1420,10 +1420,15 @@ def test_package_collection_infinite_recursion(pytester: Pytester) -> None: def test_package_collection_init_given_as_argument(pytester: Pytester) -> None: - """Regression test for #3749""" + """Regression test for #3749, #8976, #9263, #9313. + + Specifying an __init__.py file directly should collect only the __init__.py + Module, not the entire package. + """ p = pytester.copy_example("collect/package_init_given_as_arg") - result = pytester.runpytest(p / "pkg" / "__init__.py") - result.stdout.fnmatch_lines(["*1 passed*"]) + items, hookrecorder = pytester.inline_genitems(p / "pkg" / "__init__.py") + assert len(items) == 1 + assert items[0].name == "test_init" def test_package_with_modules(pytester: Pytester) -> None: diff --git a/testing/test_collection.py b/testing/test_collection.py index 8b0a1ab3650..c370951b590 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1392,19 +1392,27 @@ def test_collect_pkg_init_and_file_in_args(pytester: Pytester) -> None: p = subdir.joinpath("test_file.py") p.write_text("def test_file(): pass", encoding="utf-8") - # NOTE: without "-o python_files=*.py" this collects test_file.py twice. - # This changed/broke with "Add package scoped fixtures #2283" (2b1410895) - # initially (causing a RecursionError). - result = pytester.runpytest("-v", str(init), str(p)) + # Just the package directory, the __init__.py module is filtered out. + result = pytester.runpytest("-v", subdir) result.stdout.fnmatch_lines( [ "sub/test_file.py::test_file PASSED*", + "*1 passed in*", + ] + ) + + # But it's included if specified directly. + result = pytester.runpytest("-v", init, p) + result.stdout.fnmatch_lines( + [ + "sub/__init__.py::test_init PASSED*", "sub/test_file.py::test_file PASSED*", "*2 passed in*", ] ) - result = pytester.runpytest("-v", "-o", "python_files=*.py", str(init), str(p)) + # Or if the pattern allows it. + result = pytester.runpytest("-v", "-o", "python_files=*.py", subdir) result.stdout.fnmatch_lines( [ "sub/__init__.py::test_init PASSED*", @@ -1419,10 +1427,13 @@ def test_collect_pkg_init_only(pytester: Pytester) -> None: init = subdir.joinpath("__init__.py") init.write_text("def test_init(): pass", encoding="utf-8") - result = pytester.runpytest(str(init)) + result = pytester.runpytest(subdir) result.stdout.fnmatch_lines(["*no tests ran in*"]) - result = pytester.runpytest("-v", "-o", "python_files=*.py", str(init)) + result = pytester.runpytest("-v", init) + result.stdout.fnmatch_lines(["sub/__init__.py::test_init PASSED*", "*1 passed in*"]) + + result = pytester.runpytest("-v", "-o", "python_files=*.py", subdir) result.stdout.fnmatch_lines(["sub/__init__.py::test_init PASSED*", "*1 passed in*"]) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index dfe569987ca..f189e8645fa 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -114,7 +114,7 @@ def test_simple_doctestfile(self, pytester: Pytester): reprec.assertoutcome(failed=1) def test_importmode(self, pytester: Pytester): - p = pytester.makepyfile( + pytester.makepyfile( **{ "namespacepkg/innerpkg/__init__.py": "", "namespacepkg/innerpkg/a.py": """ @@ -132,7 +132,7 @@ def my_func(): """, } ) - reprec = pytester.inline_run(p, "--doctest-modules", "--import-mode=importlib") + reprec = pytester.inline_run("--doctest-modules", "--import-mode=importlib") reprec.assertoutcome(passed=1) def test_new_pattern(self, pytester: Pytester): diff --git a/testing/test_nose.py b/testing/test_nose.py index cc79eb45b9f..7ec4026f249 100644 --- a/testing/test_nose.py +++ b/testing/test_nose.py @@ -504,7 +504,7 @@ def test_it(): pass """, ) - result = pytester.runpytest(p, "-p", "nose") + result = pytester.runpytest(p.parent, "-p", "nose") assert result.ret == 0 From 1306b84241349cb2b7c65425969c2560fa8e98af Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 25 Jun 2023 00:27:02 +0000 Subject: [PATCH 0022/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 138 ++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 49 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index c882130b03e..f4e7570da81 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -13,7 +13,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1267 plugins. +This list contains 1272 plugins. .. only:: not latex @@ -36,7 +36,7 @@ This list contains 1267 plugins. :pypi:`pytest-aiogram` May 06, 2023 N/A N/A :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Feb 12, 2022 4 - Beta pytest (>=6.1.0) :pypi:`pytest-aiohttp-client` Pytest \`client\` fixture for the Aiohttp Jan 10, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-aiomoto` pytest-aiomoto Nov 09, 2022 N/A pytest (>=7.0,<8.0) + :pypi:`pytest-aiomoto` pytest-aiomoto Jun 24, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-aioresponses` py.test integration for aioresponses Jul 29, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) @@ -146,7 +146,7 @@ This list contains 1267 plugins. :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A :pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest - :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Jan 29, 2023 5 - Production/Stable pytest (>=6.2.0) + :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Jun 23, 2023 5 - Production/Stable pytest (>=7.1.0) :pypi:`pytest-bugtong-tag` pytest-bugtong-tag is a plugin for pytest Jan 16, 2022 N/A N/A :pypi:`pytest-bugzilla` py.test bugzilla integration plugin May 05, 2010 4 - Beta N/A :pypi:`pytest-bugzilla-notifier` A plugin that allows you to execute create, update, and read information from BugZilla bugs Jun 15, 2018 4 - Beta pytest (>=2.9.2) @@ -213,16 +213,17 @@ This list contains 1267 plugins. :pypi:`pytest-colordots` Colorizes the progress indicators Oct 06, 2017 5 - Production/Stable N/A :pypi:`pytest-commander` An interactive GUI test runner for PyTest Aug 17, 2021 N/A pytest (<7.0.0,>=6.2.4) :pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method May 15, 2022 N/A pytest (>=3.6,<8) - :pypi:`pytest-compare` pytest plugin for comparing call arguments. Mar 30, 2023 5 - Production/Stable N/A + :pypi:`pytest-compare` pytest plugin for comparing call arguments. Jun 22, 2023 5 - Production/Stable N/A :pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1) :pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest - :pypi:`pytest-container` Pytest fixtures for writing container based tests Mar 21, 2023 4 - Beta pytest (>=3.10) + :pypi:`pytest-container` Pytest fixtures for writing container based tests Jun 19, 2023 4 - Beta pytest (>=3.10) :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) + :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Jun 23, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A :pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6) @@ -232,7 +233,7 @@ This list contains 1267 plugins. :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0) - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 14, 2023 N/A N/A + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 19, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -296,6 +297,7 @@ This list contains 1267 plugins. :pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all' :pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0) + :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Jun 23, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Feb 05, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) @@ -468,6 +470,7 @@ This list contains 1267 plugins. :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jul 12, 2022 4 - Beta pytest + :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) @@ -476,7 +479,7 @@ This list contains 1267 plugins. :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications May 03, 2023 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 17, 2023 N/A pytest>=3.6 + :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) @@ -493,6 +496,7 @@ This list contains 1267 plugins. :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. Jun 14, 2023 N/A N/A :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-gitconfig` Provide a gitconfig sandbox for testing Jun 22, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A @@ -523,10 +527,10 @@ This list contains 1267 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 16, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 24, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A - :pypi:`pytest-hot-reloading` Jun 16, 2023 N/A N/A + :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A :pypi:`pytest-hot-test` A plugin that tracks test changes Dec 10, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) @@ -554,7 +558,7 @@ This list contains 1267 plugins. :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Aug 09, 2022 4 - Beta N/A :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A - :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Sep 07, 2022 5 - Production/Stable N/A + :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 23, 2021 5 - Production/Stable N/A :pypi:`pytest-image-diff` Mar 09, 2023 3 - Alpha pytest @@ -593,7 +597,7 @@ This list contains 1267 plugins. :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Jun 12, 2023 3 - Alpha N/A - :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 14, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Jun 06, 2023 4 - Beta pytest :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest @@ -654,7 +658,7 @@ This list contains 1267 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Jun 04, 2023 5 - Production/Stable pytest (==7.3.1) + :pypi:`pytest-logikal` Common testing environment Jun 22, 2023 5 - Production/Stable pytest (==7.3.1) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) @@ -734,7 +738,7 @@ This list contains 1267 plugins. :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jun 05, 2023 N/A pytest (>=3.5.0) + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jun 19, 2023 N/A pytest (>=3.5.0) :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -868,7 +872,7 @@ This list contains 1267 plugins. :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A :pypi:`pytest-pylint` pytest plugin to check source code with pylint Sep 10, 2022 5 - Production/Stable pytest (>=5.4) :pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A - :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Jun 11, 2023 N/A pytest + :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Jun 19, 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) @@ -969,7 +973,7 @@ This list contains 1267 plugins. :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jun 16, 2023 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) - :pypi:`pytest-richtrace` Nov 05, 2022 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-richtrace` A pytest plugin that displays the names and information of the pytest hook functions as they are executed. Jun 20, 2023 N/A N/A :pypi:`pytest-ringo` pytest plugin to test webapplications using the Ringo webframework Sep 27, 2017 3 - Alpha N/A :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest @@ -998,14 +1002,14 @@ This list contains 1267 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 24, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 24, 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 @@ -1123,7 +1127,7 @@ This list contains 1267 plugins. :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Mar 17, 2023 5 - Production/Stable N/A :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) :pypi:`pytest-terra-fixt` Terraform and Terragrunt fixtures for pytest Sep 15, 2022 N/A pytest (==6.2.5) - :pypi:`pytest-terraform` A pytest plugin for using terraform fixtures Sep 01, 2022 N/A pytest (>=6.0) + :pypi:`pytest-terraform` A pytest plugin for using terraform fixtures Jun 20, 2023 N/A pytest (>=6.0) :pypi:`pytest-terraform-fixture` generate terraform resources to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A :pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0) @@ -1160,7 +1164,7 @@ This list contains 1267 plugins. :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-time` Jun 16, 2023 3 - Alpha pytest + :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A :pypi:`pytest-timeout` pytest plugin to abort hanging tests Jan 18, 2022 5 - Production/Stable pytest (>=5.0.0) :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A @@ -1242,7 +1246,7 @@ This list contains 1267 plugins. :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-wake` May 11, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A - :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 11, 2023 4 - Beta N/A + :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 24, 2023 4 - Beta N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest @@ -1259,7 +1263,7 @@ This list contains 1267 plugins. :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) - :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Jun 15, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Jun 19, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A @@ -1271,15 +1275,16 @@ This list contains 1267 plugins. :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (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. Jun 18, 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 May 28, 2023 N/A pytest>=7.2.0 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yamlwsgi` Run tests against wsgi apps defined in yaml May 11, 2010 N/A N/A - :pypi:`pytest-yaml-yoyo` http/https API run by yaml Jun 08, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-yaml-yoyo` http/https API run by yaml Jun 19, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A - :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Mar 29, 2023 N/A pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Jun 21, 2023 N/A pytest (>=7.2.2,<8.0.0) :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A @@ -1405,7 +1410,7 @@ This list contains 1267 plugins. Pytest \`client\` fixture for the Aiohttp :pypi:`pytest-aiomoto` - *last release*: Nov 09, 2022, + *last release*: Jun 24, 2023, *status*: N/A, *requires*: pytest (>=7.0,<8.0) @@ -2175,9 +2180,9 @@ This list contains 1267 plugins. Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. :pypi:`pytest-bug` - *last release*: Jan 29, 2023, + *last release*: Jun 23, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.0) + *requires*: pytest (>=7.1.0) Pytest plugin for marking tests as a bug @@ -2644,7 +2649,7 @@ This list contains 1267 plugins. pytest framework for testing different aspects of a common method :pypi:`pytest-compare` - *last release*: Mar 30, 2023, + *last release*: Jun 22, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -2686,7 +2691,7 @@ This list contains 1267 plugins. pytest plugin with fixtures for testing consul aware apps :pypi:`pytest-container` - *last release*: Mar 21, 2023, + *last release*: Jun 19, 2023, *status*: 4 - Beta, *requires*: pytest (>=3.10) @@ -2713,6 +2718,13 @@ This list contains 1267 plugins. The pytest plugin for your Cookiecutter templates. 🍪 + :pypi:`pytest-copier` + *last release*: Jun 23, 2023, + *status*: 4 - Beta, + *requires*: pytest>=7.1.2 + + A pytest plugin to help testing Copier templates + :pypi:`pytest-couchdbkit` *last release*: Apr 17, 2012, *status*: N/A, @@ -2777,7 +2789,7 @@ This list contains 1267 plugins. Use pytest's runner to discover and execute C++ tests :pypi:`pytest-cppython` - *last release*: Jun 14, 2023, + *last release*: Jun 19, 2023, *status*: N/A, *requires*: N/A @@ -3224,6 +3236,13 @@ This list contains 1267 plugins. PyTest plugin for generating Difido reports + :pypi:`pytest-dir-equal` + *last release*: Jun 23, 2023, + *status*: 4 - Beta, + *requires*: pytest>=7.1.2 + + pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing + :pypi:`pytest-disable` *last release*: Sep 10, 2015, *status*: 4 - Beta, @@ -4428,6 +4447,13 @@ This list contains 1267 plugins. A pytest plugin in order to provide logs via fluentd + :pypi:`pytest-fluentbit` + *last release*: Jun 16, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=7.0.0) + + A pytest plugin in order to provide logs via fluentbit + :pypi:`pytest-flyte` *last release*: May 03, 2021, *status*: N/A, @@ -4485,9 +4511,9 @@ This list contains 1267 plugins. Wrap tests with fixtures in freeze_time :pypi:`pytest-freezer` - *last release*: Jun 17, 2023, + *last release*: Jun 21, 2023, *status*: N/A, - *requires*: pytest>=3.6 + *requires*: pytest >= 3.6 Pytest plugin providing a fixture interface for spulec/freezegun @@ -4603,6 +4629,13 @@ This list contains 1267 plugins. Git repository fixture for py.test + :pypi:`pytest-gitconfig` + *last release*: Jun 22, 2023, + *status*: 4 - Beta, + *requires*: pytest>=7.1.2 + + Provide a gitconfig sandbox for testing + :pypi:`pytest-gitcov` *last release*: Jan 11, 2020, *status*: 2 - Pre-Alpha, @@ -4814,7 +4847,7 @@ This list contains 1267 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 16, 2023, + *last release*: Jun 24, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.3.1) @@ -4835,7 +4868,7 @@ This list contains 1267 plugins. Report on tests that honor constraints, and guard against regressions :pypi:`pytest-hot-reloading` - *last release*: Jun 16, 2023, + *last release*: Jun 23, 2023, *status*: N/A, *requires*: N/A @@ -5031,7 +5064,7 @@ This list contains 1267 plugins. A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api :pypi:`pytest-idem` - *last release*: Sep 07, 2022, + *last release*: Jun 23, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5304,7 +5337,7 @@ This list contains 1267 plugins. py.test JIRA integration plugin, using markers :pypi:`pytest-jira-xfail` - *last release*: Jun 14, 2023, + *last release*: Jun 19, 2023, *status*: N/A, *requires*: pytest (>=7.2.0) @@ -5731,7 +5764,7 @@ This list contains 1267 plugins. :pypi:`pytest-logikal` - *last release*: Jun 04, 2023, + *last release*: Jun 22, 2023, *status*: 5 - Production/Stable, *requires*: pytest (==7.3.1) @@ -6291,7 +6324,7 @@ This list contains 1267 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-netdut` - *last release*: Jun 05, 2023, + *last release*: Jun 19, 2023, *status*: N/A, *requires*: pytest (>=3.5.0) @@ -7229,7 +7262,7 @@ This list contains 1267 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Jun 11, 2023, + *last release*: Jun 19, 2023, *status*: N/A, *requires*: pytest @@ -7936,11 +7969,11 @@ This list contains 1267 plugins. A pytest plugin using Rich for beautiful test result formatting. :pypi:`pytest-richtrace` - *last release*: Nov 05, 2022, + *last release*: Jun 20, 2023, *status*: N/A, - *requires*: pytest (>=7.2.0,<8.0.0) - + *requires*: N/A + A pytest plugin that displays the names and information of the pytest hook functions as they are executed. :pypi:`pytest-ringo` *last release*: Sep 27, 2017, @@ -8139,7 +8172,7 @@ This list contains 1267 plugins. :pypi:`pytest-sbase` - *last release*: Jun 13, 2023, + *last release*: Jun 24, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8188,7 +8221,7 @@ This list contains 1267 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Jun 13, 2023, + *last release*: Jun 24, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9014,7 +9047,7 @@ This list contains 1267 plugins. Terraform and Terragrunt fixtures for pytest :pypi:`pytest-terraform` - *last release*: Sep 01, 2022, + *last release*: Jun 20, 2023, *status*: N/A, *requires*: pytest (>=6.0) @@ -9273,7 +9306,7 @@ This list contains 1267 plugins. Ticking on tests :pypi:`pytest-time` - *last release*: Jun 16, 2023, + *last release*: Jun 24, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -9847,7 +9880,7 @@ This list contains 1267 plugins. Local continuous test runner with pytest and watchdog. :pypi:`pytest-watcher` - *last release*: Jun 11, 2023, + *last release*: Jun 24, 2023, *status*: 4 - Beta, *requires*: N/A @@ -9966,7 +9999,7 @@ This list contains 1267 plugins. pytest plugin helps to reproduce failures for particular xdist node :pypi:`pytest-xdist-worker-stats` - *last release*: Jun 15, 2023, + *last release*: Jun 19, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.3.2,<8.0.0) @@ -10049,6 +10082,13 @@ This list contains 1267 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. + :pypi:`pytest-xvirt` + *last release*: Jun 18, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=7.1.0) + + A pytest plugin to virtualize test. For example to transparently running them on a remote box. + :pypi:`pytest-yaml` *last release*: Oct 05, 2018, *status*: N/A, @@ -10078,7 +10118,7 @@ This list contains 1267 plugins. Run tests against wsgi apps defined in yaml :pypi:`pytest-yaml-yoyo` - *last release*: Jun 08, 2023, + *last release*: Jun 19, 2023, *status*: N/A, *requires*: pytest (>=7.2.0) @@ -10106,7 +10146,7 @@ This list contains 1267 plugins. PyTest plugin to run tests concurrently, each \`yield\` switch context to other one :pypi:`pytest-yls` - *last release*: Mar 29, 2023, + *last release*: Jun 21, 2023, *status*: N/A, *requires*: pytest (>=7.2.2,<8.0.0) From 45f1a462d505438548a4dda2072093a22fbd1cb3 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sun, 25 Jun 2023 16:08:53 +0100 Subject: [PATCH 0023/1271] Apply suggestions from code review Co-authored-by: Zac Hatfield-Dodds --- doc/en/how-to/fixtures.rst | 2 +- src/_pytest/deprecated.py | 2 +- testing/deprecated_test.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index e9f7f2d4b02..c6047af1231 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1752,7 +1752,7 @@ into an ini-file: def my_fixture_that_sadly_wont_use_my_other_fixture(): ... - Currently this will generate a deprecation warning. + This generates a deprecation warning, and will become an error in Pytest 8. .. _`override fixtures`: diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 5874eeb9938..3fcf99ba417 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -122,7 +122,7 @@ "#configuring-hook-specs-impls-using-markers", ) -MARKED_FIXTURE = PytestDeprecationWarning( +MARKED_FIXTURE = PytestRemovedIn8Warning( "Marks applied to fixtures have no effect\n" "See docs: https://docs.pytest.org/en/stable/deprecations.html#applying-a-mark-to-a-fixture-function" ) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index cf067bac9d6..f4197a1f618 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -284,7 +284,7 @@ def test_importing_instance_is_deprecated(pytester: Pytester) -> None: def test_fixture_disallow_on_marked_functions(): """Test that applying @pytest.fixture to a marked function warns (#3364).""" with pytest.warns( - pytest.PytestDeprecationWarning, + pytest.PytestRemovedIn8Warning, match=r"Marks applied to fixtures have no effect", ) as record: @@ -303,7 +303,7 @@ def foo(): def test_fixture_disallow_marks_on_fixtures(): """Test that applying a mark to a fixture warns (#3364).""" with pytest.warns( - pytest.PytestDeprecationWarning, + pytest.PytestRemovedIn8Warning, match=r"Marks applied to fixtures have no effect", ) as record: @@ -319,7 +319,7 @@ def foo(): def test_fixture_disallowed_between_marks(): """Test that applying a mark to a fixture warns (#3364).""" with pytest.warns( - pytest.PytestDeprecationWarning, + pytest.PytestRemovedIn8Warning, match=r"Marks applied to fixtures have no effect", ) as record: From 518ca37caeda845376f71648714d53f26b218e82 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sun, 25 Jun 2023 16:09:04 +0100 Subject: [PATCH 0024/1271] Update doc/en/deprecations.rst --- doc/en/deprecations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 3e15f892e50..e73c1a18e5d 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -383,7 +383,7 @@ deprecation warning is now raised. Applying a mark to a fixture function ------------------------------------- -.. deprecated:: 7.2 +.. deprecated:: 7.4 Applying a mark to a fixture function never had any effect, but it is a common user error. From 9859c110cc9851a25802524f09fc58ce2aa018db Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani <86737547+tushar-deepsource@users.noreply.github.com> Date: Mon, 26 Jun 2023 12:14:41 +0530 Subject: [PATCH 0025/1271] Ensure the docstring is a string --- src/_pytest/assertion/rewrite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index ab83fee32b2..9ac4d582f2c 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -687,6 +687,7 @@ def run(self, mod: ast.Module) -> None: expect_docstring and isinstance(item, ast.Expr) and isinstance(item.value, astStr) + and isinstance(item.value.value, str) ): if sys.version_info >= (3, 8): doc = item.value.value From 4ebb2b94c289a5d1a5756a4a69c7f2ec3e0def89 Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani <86737547+tushar-deepsource@users.noreply.github.com> Date: Mon, 26 Jun 2023 12:19:42 +0530 Subject: [PATCH 0026/1271] fix code for py37 --- src/_pytest/assertion/rewrite.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 9ac4d582f2c..5d3dfcc3162 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -687,12 +687,13 @@ def run(self, mod: ast.Module) -> None: expect_docstring and isinstance(item, ast.Expr) and isinstance(item.value, astStr) - and isinstance(item.value.value, str) ): if sys.version_info >= (3, 8): doc = item.value.value else: doc = item.value.s + if not isinstance(doc, str): + return if self.is_rewrite_disabled(doc): return expect_docstring = False From 05d7e609040f0af87b2d647ef10b9deb7dd89d3c Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani Date: Mon, 26 Jun 2023 12:37:23 +0530 Subject: [PATCH 0027/1271] Add test --- testing/test_assertrewrite.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 778f843e6cf..9b4ca87b2e6 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -2055,3 +2055,14 @@ def test_max_increased_verbosity(self, pytester: Pytester) -> None: self.create_test_file(pytester, DEFAULT_REPR_MAX_SIZE * 10) result = pytester.runpytest("-vv") result.stdout.no_fnmatch_line("*xxx...xxx*") + + +class TestIssue11140: + def test_constant_not_picked_as_module_docstring(self, pytester: Pytester) -> None: + pytester.makepyfile( + """\ + 0 + """ + ) + result = pytester.runpytest() + assert result.ret == 0 From a14fc10cac90dcb075221d03c52c76dd714daab1 Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani Date: Mon, 26 Jun 2023 13:06:11 +0530 Subject: [PATCH 0028/1271] add a test function to the test --- testing/test_assertrewrite.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 9b4ca87b2e6..5833a04838d 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -2062,6 +2062,9 @@ def test_constant_not_picked_as_module_docstring(self, pytester: Pytester) -> No pytester.makepyfile( """\ 0 + + def test_foo(): + pass """ ) result = pytester.runpytest() From 5332656906dc60b29b4288eaf1842452106fce46 Mon Sep 17 00:00:00 2001 From: Tushar Sadhwani <86737547+tushar-deepsource@users.noreply.github.com> Date: Mon, 26 Jun 2023 17:02:33 +0530 Subject: [PATCH 0029/1271] Add changelog and author --- AUTHORS | 1 + changelog/11146.bugfix.rst | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog/11146.bugfix.rst diff --git a/AUTHORS b/AUTHORS index ee4ef203f0c..2acbdb98c39 100644 --- a/AUTHORS +++ b/AUTHORS @@ -370,6 +370,7 @@ Tomer Keren Tony Narlock Tor Colvin Trevor Bekolay +Tushar Sadhwani Tyler Goodlet Tzu-ping Chung Vasily Kuznetsov diff --git a/changelog/11146.bugfix.rst b/changelog/11146.bugfix.rst new file mode 100644 index 00000000000..b1794ad5723 --- /dev/null +++ b/changelog/11146.bugfix.rst @@ -0,0 +1 @@ +- Prevent constants at the top of file from being detected as docstrings. \ No newline at end of file From 4719d998d809a99937fc571c7afba6f8291a97d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Jun 2023 11:34:02 +0000 Subject: [PATCH 0030/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- changelog/11146.bugfix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/11146.bugfix.rst b/changelog/11146.bugfix.rst index b1794ad5723..03b468f3018 100644 --- a/changelog/11146.bugfix.rst +++ b/changelog/11146.bugfix.rst @@ -1 +1 @@ -- Prevent constants at the top of file from being detected as docstrings. \ No newline at end of file +- Prevent constants at the top of file from being detected as docstrings. From dd5f3773d961273d53691ebb06361639b361e9c6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 05:28:11 +0000 Subject: [PATCH 0031/1271] [pre-commit.ci] pre-commit autoupdate (#11145) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/autoflake: v2.1.1 → v2.2.0](https://github.com/PyCQA/autoflake/compare/v2.1.1...v2.2.0) - [github.com/pre-commit/mirrors-mypy: v1.3.0 → v1.4.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.3.0...v1.4.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b5089e12942..1f1cd674320 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: exclude: _pytest/(debugging|hookspec).py language_version: python3 - repo: https://github.com/PyCQA/autoflake - rev: v2.1.1 + rev: v2.2.0 hooks: - id: autoflake name: autoflake @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.3.0 + rev: v1.4.1 hooks: - id: mypy files: ^(src/|testing/) From f4e3b4ad9827276ff20c2c3a86e0637a37b09019 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 14:55:42 -0700 Subject: [PATCH 0032/1271] Drop Python 3.7 --- changelog/11151.breaking.rst | 2 + doc/en/conf.py | 21 --------- setup.cfg | 4 +- src/_pytest/_code/code.py | 2 +- src/_pytest/_code/source.py | 3 +- src/_pytest/_io/terminalwriter.py | 2 +- src/_pytest/assertion/rewrite.py | 66 ++++++++++++----------------- src/_pytest/cacheprovider.py | 2 +- src/_pytest/capture.py | 2 +- src/_pytest/compat.py | 63 --------------------------- src/_pytest/config/__init__.py | 9 ++-- src/_pytest/config/argparsing.py | 2 +- src/_pytest/config/exceptions.py | 2 +- src/_pytest/fixtures.py | 11 ++--- src/_pytest/legacypath.py | 2 +- src/_pytest/logging.py | 2 +- src/_pytest/main.py | 4 +- src/_pytest/mark/expression.py | 9 +--- src/_pytest/mark/structures.py | 2 +- src/_pytest/monkeypatch.py | 2 +- src/_pytest/nodes.py | 2 +- src/_pytest/outcomes.py | 13 +----- src/_pytest/pytester.py | 2 +- src/_pytest/python.py | 2 +- src/_pytest/python_api.py | 11 +++-- src/_pytest/recwarn.py | 4 +- src/_pytest/reports.py | 2 +- src/_pytest/runner.py | 2 +- src/_pytest/terminal.py | 2 +- src/_pytest/tmpdir.py | 24 ++++------- src/_pytest/warning_types.py | 3 +- testing/acceptance_test.py | 4 +- testing/code/test_source.py | 9 +--- testing/python/metafunc.py | 22 ---------- testing/test_assertion.py | 4 +- testing/test_assertrewrite.py | 17 +------- testing/test_compat.py | 2 +- testing/test_config.py | 14 +++--- testing/test_entry_points.py | 4 +- testing/test_skipping.py | 6 +-- testing/test_threadexception.py | 6 --- testing/test_unittest.py | 9 ---- testing/test_unraisableexception.py | 6 --- 43 files changed, 98 insertions(+), 284 deletions(-) create mode 100644 changelog/11151.breaking.rst diff --git a/changelog/11151.breaking.rst b/changelog/11151.breaking.rst new file mode 100644 index 00000000000..d846fc94cb0 --- /dev/null +++ b/changelog/11151.breaking.rst @@ -0,0 +1,2 @@ +Drop support for Python 3.7, which `reached end-of-life on 2023-06-27 +`__. diff --git a/doc/en/conf.py b/doc/en/conf.py index 32f508219a6..92607a15a9a 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -15,12 +15,10 @@ # # The full version, including alpha/beta/rc tags. # The short X.Y version. -import ast import os import shutil import sys from textwrap import dedent -from typing import List from typing import TYPE_CHECKING from _pytest import __version__ as version @@ -451,25 +449,6 @@ def setup(app: "sphinx.application.Sphinx") -> None: configure_logging(app) - # Make Sphinx mark classes with "final" when decorated with @final. - # We need this because we import final from pytest._compat, not from - # typing (for Python < 3.8 compat), so Sphinx doesn't detect it. - # To keep things simple we accept any `@final` decorator. - # Ref: https://github.com/pytest-dev/pytest/pull/7780 - import sphinx.pycode.ast - import sphinx.pycode.parser - - original_is_final = sphinx.pycode.parser.VariableCommentPicker.is_final - - def patched_is_final(self, decorators: List[ast.expr]) -> bool: - if original_is_final(self, decorators): - return True - return any( - sphinx.pycode.ast.unparse(decorator) == "final" for decorator in decorators - ) - - sphinx.pycode.parser.VariableCommentPicker.is_final = patched_is_final - # legacypath.py monkey-patches pytest.Testdir in. Import the file so # that autodoc can discover references to it. import _pytest.legacypath # noqa: F401 diff --git a/setup.cfg b/setup.cfg index bc93b1c06b9..f80665f4294 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,7 +17,6 @@ classifiers = Operating System :: POSIX Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 @@ -50,9 +49,8 @@ install_requires = pluggy>=0.12,<2.0 colorama;sys_platform=="win32" exceptiongroup>=1.0.0rc8;python_version<"3.11" - importlib-metadata>=0.12;python_version<"3.8" tomli>=1.0.0;python_version<"3.11" -python_requires = >=3.7 +python_requires = >=3.8 package_dir = =src setup_requires = diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 9b051332baf..ddc03d7527c 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -17,6 +17,7 @@ from typing import Callable from typing import ClassVar from typing import Dict +from typing import final from typing import Generic from typing import Iterable from typing import List @@ -42,7 +43,6 @@ from _pytest._io import TerminalWriter from _pytest._io.saferepr import safeformat from _pytest._io.saferepr import saferepr -from _pytest.compat import final from _pytest.compat import get_real_func from _pytest.deprecated import check_ispytest from _pytest.pathlib import absolutepath diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index 208cfb80037..cc7ac407e52 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -149,8 +149,7 @@ def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[i values: List[int] = [] for x in ast.walk(node): if isinstance(x, (ast.stmt, ast.ExceptHandler)): - # Before Python 3.8, the lineno of a decorated class or function pointed at the decorator. - # Since Python 3.8, the lineno points to the class/def, so need to include the decorators. + # The lineno points to the class/def, so need to include the decorators. if isinstance(x, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)): for d in x.decorator_list: values.append(d.lineno - 1) diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 379035d858c..eb1b469395e 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -2,12 +2,12 @@ import os import shutil import sys +from typing import final from typing import Optional from typing import Sequence from typing import TextIO from .wcwidth import wcswidth -from _pytest.compat import final # This code was initially copied from py 1.8.1, file _io/terminalwriter.py. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index ab83fee32b2..157903faf7c 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -44,17 +44,6 @@ if TYPE_CHECKING: from _pytest.assertion import AssertionState -if sys.version_info >= (3, 8): - namedExpr = ast.NamedExpr - astNameConstant = ast.Constant - astStr = ast.Constant - astNum = ast.Constant -else: - namedExpr = ast.Expr - astNameConstant = ast.NameConstant - astStr = ast.Str - astNum = ast.Num - assertstate_key = StashKey["AssertionState"]() @@ -686,12 +675,9 @@ def run(self, mod: ast.Module) -> None: if ( expect_docstring and isinstance(item, ast.Expr) - and isinstance(item.value, astStr) + and isinstance(item.value, ast.Constant) ): - if sys.version_info >= (3, 8): - doc = item.value.value - else: - doc = item.value.s + doc = item.value.value if self.is_rewrite_disabled(doc): return expect_docstring = False @@ -823,7 +809,7 @@ def pop_format_context(self, expl_expr: ast.expr) -> ast.Name: current = self.stack.pop() if self.stack: self.explanation_specifiers = self.stack[-1] - keys = [astStr(key) for key in current.keys()] + keys = [ast.Constant(key) for key in current.keys()] format_dict = ast.Dict(keys, list(current.values())) form = ast.BinOp(expl_expr, ast.Mod(), format_dict) name = "@py_format" + str(next(self.variable_counter)) @@ -877,16 +863,16 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: negation = ast.UnaryOp(ast.Not(), top_condition) if self.enable_assertion_pass_hook: # Experimental pytest_assertion_pass hook - msg = self.pop_format_context(astStr(explanation)) + msg = self.pop_format_context(ast.Constant(explanation)) # Failed if assert_.msg: assertmsg = self.helper("_format_assertmsg", assert_.msg) gluestr = "\n>assert " else: - assertmsg = astStr("") + assertmsg = ast.Constant("") gluestr = "assert " - err_explanation = ast.BinOp(astStr(gluestr), ast.Add(), msg) + err_explanation = ast.BinOp(ast.Constant(gluestr), ast.Add(), msg) err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation) err_name = ast.Name("AssertionError", ast.Load()) fmt = self.helper("_format_explanation", err_msg) @@ -902,8 +888,8 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: hook_call_pass = ast.Expr( self.helper( "_call_assertion_pass", - astNum(assert_.lineno), - astStr(orig), + ast.Constant(assert_.lineno), + ast.Constant(orig), fmt_pass, ) ) @@ -922,7 +908,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: variables = [ ast.Name(name, ast.Store()) for name in self.format_variables ] - clear_format = ast.Assign(variables, astNameConstant(None)) + clear_format = ast.Assign(variables, ast.Constant(None)) self.statements.append(clear_format) else: # Original assertion rewriting @@ -933,9 +919,9 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: assertmsg = self.helper("_format_assertmsg", assert_.msg) explanation = "\n>assert " + explanation else: - assertmsg = astStr("") + assertmsg = ast.Constant("") explanation = "assert " + explanation - template = ast.BinOp(assertmsg, ast.Add(), astStr(explanation)) + template = ast.BinOp(assertmsg, ast.Add(), ast.Constant(explanation)) msg = self.pop_format_context(template) fmt = self.helper("_format_explanation", msg) err_name = ast.Name("AssertionError", ast.Load()) @@ -947,7 +933,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: # Clear temporary variables by setting them to None. if self.variables: variables = [ast.Name(name, ast.Store()) for name in self.variables] - clear = ast.Assign(variables, astNameConstant(None)) + clear = ast.Assign(variables, ast.Constant(None)) self.statements.append(clear) # Fix locations (line numbers/column offsets). for stmt in self.statements: @@ -955,26 +941,26 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: ast.copy_location(node, assert_) return self.statements - def visit_NamedExpr(self, name: namedExpr) -> Tuple[namedExpr, str]: + def visit_NamedExpr(self, name: ast.NamedExpr) -> Tuple[ast.NamedExpr, str]: # This method handles the 'walrus operator' repr of the target # name if it's a local variable or _should_repr_global_name() # thinks it's acceptable. locs = ast.Call(self.builtin("locals"), [], []) target_id = name.target.id # type: ignore[attr-defined] - inlocs = ast.Compare(astStr(target_id), [ast.In()], [locs]) + inlocs = ast.Compare(ast.Constant(target_id), [ast.In()], [locs]) dorepr = self.helper("_should_repr_global_name", name) test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) - expr = ast.IfExp(test, self.display(name), astStr(target_id)) + expr = ast.IfExp(test, self.display(name), ast.Constant(target_id)) return name, self.explanation_param(expr) def visit_Name(self, name: ast.Name) -> Tuple[ast.Name, str]: # Display the repr of the name if it's a local variable or # _should_repr_global_name() thinks it's acceptable. locs = ast.Call(self.builtin("locals"), [], []) - inlocs = ast.Compare(astStr(name.id), [ast.In()], [locs]) + inlocs = ast.Compare(ast.Constant(name.id), [ast.In()], [locs]) dorepr = self.helper("_should_repr_global_name", name) test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) - expr = ast.IfExp(test, self.display(name), astStr(name.id)) + expr = ast.IfExp(test, self.display(name), ast.Constant(name.id)) return name, self.explanation_param(expr) def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: @@ -993,10 +979,10 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: # cond is set in a prior loop iteration below self.expl_stmts.append(ast.If(cond, fail_inner, [])) # noqa self.expl_stmts = fail_inner - # Check if the left operand is a namedExpr and the value has already been visited + # Check if the left operand is a ast.NamedExpr and the value has already been visited if ( isinstance(v, ast.Compare) - and isinstance(v.left, namedExpr) + and isinstance(v.left, ast.NamedExpr) and v.left.target.id in [ ast_expr.id @@ -1012,7 +998,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: self.push_format_context() res, expl = self.visit(v) body.append(ast.Assign([ast.Name(res_var, ast.Store())], res)) - expl_format = self.pop_format_context(astStr(expl)) + expl_format = self.pop_format_context(ast.Constant(expl)) call = ast.Call(app, [expl_format], []) self.expl_stmts.append(ast.Expr(call)) if i < levels: @@ -1024,7 +1010,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: self.statements = body = inner self.statements = save self.expl_stmts = fail_save - expl_template = self.helper("_format_boolop", expl_list, astNum(is_or)) + expl_template = self.helper("_format_boolop", expl_list, ast.Constant(is_or)) expl = self.pop_format_context(expl_template) return ast.Name(res_var, ast.Load()), self.explanation_param(expl) @@ -1098,7 +1084,7 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: comp.left = self.variables_overwrite[ comp.left.id ] # type:ignore[assignment] - if isinstance(comp.left, namedExpr): + if isinstance(comp.left, ast.NamedExpr): self.variables_overwrite[ comp.left.target.id ] = comp.left # type:ignore[assignment] @@ -1114,7 +1100,7 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: results = [left_res] for i, op, next_operand in it: if ( - isinstance(next_operand, namedExpr) + isinstance(next_operand, ast.NamedExpr) and isinstance(left_res, ast.Name) and next_operand.target.id == left_res.id ): @@ -1127,9 +1113,9 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: next_expl = f"({next_expl})" results.append(next_res) sym = BINOP_MAP[op.__class__] - syms.append(astStr(sym)) + syms.append(ast.Constant(sym)) expl = f"{left_expl} {sym} {next_expl}" - expls.append(astStr(expl)) + expls.append(ast.Constant(expl)) res_expr = ast.Compare(left_res, [op], [next_res]) self.statements.append(ast.Assign([store_names[i]], res_expr)) left_res, left_expl = next_res, next_expl @@ -1173,7 +1159,7 @@ def try_makedirs(cache_dir: Path) -> bool: def get_cache_dir(file_path: Path) -> Path: """Return the cache directory to write .pyc files for the given .py file path.""" - if sys.version_info >= (3, 8) and sys.pycache_prefix: + if sys.pycache_prefix: # given: # prefix = '/tmp/pycs' # path = '/home/user/proj/test_app.py' diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 855716d8199..a0029d6a08f 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -6,6 +6,7 @@ import os from pathlib import Path from typing import Dict +from typing import final from typing import Generator from typing import Iterable from typing import List @@ -18,7 +19,6 @@ from .reports import CollectReport from _pytest import nodes from _pytest._io import TerminalWriter -from _pytest.compat import final from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config import hookimpl diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index a8ca0869f33..3e31e3cb7d6 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -11,6 +11,7 @@ from typing import Any from typing import AnyStr from typing import BinaryIO +from typing import final from typing import Generator from typing import Generic from typing import Iterable @@ -24,7 +25,6 @@ from typing import TYPE_CHECKING from typing import Union -from _pytest.compat import final from _pytest.config import Config from _pytest.config import hookimpl from _pytest.config.argparsing import Parser diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 352211de8aa..4736bf40dbe 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -12,23 +12,12 @@ from pathlib import Path from typing import Any from typing import Callable -from typing import Generic from typing import NoReturn from typing import TYPE_CHECKING from typing import TypeVar import py -# fmt: off -# Workaround for https://github.com/sphinx-doc/sphinx/issues/10351. -# If `overload` is imported from `compat` instead of from `typing`, -# Sphinx doesn't recognize it as `overload` and the API docs for -# overloaded functions look good again. But type checkers handle -# it fine. -# fmt: on -if True: - from typing import overload as overload - if TYPE_CHECKING: from typing_extensions import Final @@ -58,17 +47,6 @@ class NotSetType(enum.Enum): NOTSET: Final = NotSetType.token # noqa: E305 # fmt: on -if sys.version_info >= (3, 8): - import importlib.metadata - - importlib_metadata = importlib.metadata -else: - import importlib_metadata as importlib_metadata # noqa: F401 - - -def _format_args(func: Callable[..., Any]) -> str: - return str(signature(func)) - def is_generator(func: object) -> bool: genfunc = inspect.isgeneratorfunction(func) @@ -338,47 +316,6 @@ def safe_isclass(obj: object) -> bool: return False -if TYPE_CHECKING: - if sys.version_info >= (3, 8): - from typing import final as final - else: - from typing_extensions import final as final -elif sys.version_info >= (3, 8): - from typing import final as final -else: - - def final(f): - return f - - -if sys.version_info >= (3, 8): - from functools import cached_property as cached_property -else: - - class cached_property(Generic[_S, _T]): - __slots__ = ("func", "__doc__") - - def __init__(self, func: Callable[[_S], _T]) -> None: - self.func = func - self.__doc__ = func.__doc__ - - @overload - def __get__( - self, instance: None, owner: type[_S] | None = ... - ) -> cached_property[_S, _T]: - ... - - @overload - def __get__(self, instance: _S, owner: type[_S] | None = ...) -> _T: - ... - - def __get__(self, instance, owner=None): - if instance is None: - return self - value = instance.__dict__[self.func.__name__] = self.func(instance) - return value - - def get_user_id() -> int | None: """Return the current user id, or None if we cannot get it reliably on the current platform.""" # win32 does not have a getuid() function. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index c9a4b7f63cb..47651ad9fa4 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -5,6 +5,7 @@ import dataclasses import enum import glob +import importlib.metadata import inspect import os import re @@ -21,6 +22,7 @@ from typing import Callable from typing import cast from typing import Dict +from typing import final from typing import Generator from typing import IO from typing import Iterable @@ -48,8 +50,6 @@ from _pytest._code import ExceptionInfo from _pytest._code import filter_traceback from _pytest._io import TerminalWriter -from _pytest.compat import final -from _pytest.compat import importlib_metadata # type: ignore[attr-defined] from _pytest.outcomes import fail from _pytest.outcomes import Skipped from _pytest.pathlib import absolutepath @@ -257,7 +257,8 @@ def directory_arg(path: str, optname: str) -> str: "logging", "reports", "python_path", - *(["unraisableexception", "threadexception"] if sys.version_info >= (3, 8) else []), + "unraisableexception", + "threadexception", "faulthandler", ) @@ -1216,7 +1217,7 @@ def _mark_plugins_for_rewrite(self, hook) -> None: package_files = ( str(file) - for dist in importlib_metadata.distributions() + for dist in importlib.metadata.distributions() if any(ep.group == "pytest11" for ep in dist.entry_points) for file in dist.files or [] ) diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index d3f01916b61..108349f1035 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -7,6 +7,7 @@ from typing import Callable from typing import cast from typing import Dict +from typing import final from typing import List from typing import Mapping from typing import NoReturn @@ -17,7 +18,6 @@ from typing import Union import _pytest._io -from _pytest.compat import final from _pytest.config.exceptions import UsageError from _pytest.deprecated import ARGUMENT_PERCENT_DEFAULT from _pytest.deprecated import ARGUMENT_TYPE_STR diff --git a/src/_pytest/config/exceptions.py b/src/_pytest/config/exceptions.py index 4f1320e758d..4031ea732f3 100644 --- a/src/_pytest/config/exceptions.py +++ b/src/_pytest/config/exceptions.py @@ -1,4 +1,4 @@ -from _pytest.compat import final +from typing import final @final diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 66722da2709..6e113492820 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -13,6 +13,7 @@ from typing import Callable from typing import cast from typing import Dict +from typing import final from typing import Generator from typing import Generic from typing import Iterable @@ -21,6 +22,7 @@ from typing import MutableMapping from typing import NoReturn from typing import Optional +from typing import overload from typing import Sequence from typing import Set from typing import Tuple @@ -35,10 +37,8 @@ from _pytest._code.code import FormattedExcinfo from _pytest._code.code import TerminalRepr from _pytest._io import TerminalWriter -from _pytest.compat import _format_args from _pytest.compat import _PytestWrapper from _pytest.compat import assert_never -from _pytest.compat import final from _pytest.compat import get_real_func from _pytest.compat import get_real_method from _pytest.compat import getfuncargnames @@ -47,7 +47,6 @@ from _pytest.compat import is_generator from _pytest.compat import NOTSET from _pytest.compat import NotSetType -from _pytest.compat import overload from _pytest.compat import safe_getattr from _pytest.config import _PluggyPlugin from _pytest.config import Config @@ -729,8 +728,10 @@ def _factorytraceback(self) -> List[str]: p = bestrelpath(session.path, fs) else: p = fs - args = _format_args(factory) - lines.append("%s:%d: def %s%s" % (p, lineno + 1, factory.__name__, args)) + lines.append( + "%s:%d: def %s%s" + % (p, lineno + 1, factory.__name__, inspect.signature(factory)) + ) return lines def __repr__(self) -> str: diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index af1d0c07e3c..7091f038a3b 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -3,6 +3,7 @@ import shlex import subprocess from pathlib import Path +from typing import final from typing import List from typing import Optional from typing import TYPE_CHECKING @@ -11,7 +12,6 @@ from iniconfig import SectionWrapper from _pytest.cacheprovider import Cache -from _pytest.compat import final from _pytest.compat import LEGACY_PATH from _pytest.compat import legacy_path from _pytest.config import Config diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 83813466016..ea856837c65 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -13,6 +13,7 @@ from pathlib import Path from typing import AbstractSet from typing import Dict +from typing import final from typing import Generator from typing import List from typing import Mapping @@ -25,7 +26,6 @@ from _pytest import nodes from _pytest._io import TerminalWriter from _pytest.capture import CaptureManager -from _pytest.compat import final from _pytest.config import _strtobool from _pytest.config import Config from _pytest.config import create_terminal_writer diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 155d4300e2c..f2327ca68ec 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -9,10 +9,12 @@ from pathlib import Path from typing import Callable from typing import Dict +from typing import final from typing import FrozenSet from typing import Iterator from typing import List from typing import Optional +from typing import overload from typing import Sequence from typing import Set from typing import Tuple @@ -22,8 +24,6 @@ import _pytest._code from _pytest import nodes -from _pytest.compat import final -from _pytest.compat import overload from _pytest.config import Config from _pytest.config import directory_arg from _pytest.config import ExitCode diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 9287bcee50c..b995518bf92 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -18,7 +18,6 @@ import dataclasses import enum import re -import sys import types from typing import Callable from typing import Iterator @@ -27,12 +26,6 @@ from typing import Optional from typing import Sequence -if sys.version_info >= (3, 8): - astNameConstant = ast.Constant -else: - astNameConstant = ast.NameConstant - - __all__ = [ "Expression", "ParseError", @@ -138,7 +131,7 @@ def reject(self, expected: Sequence[TokenType]) -> NoReturn: def expression(s: Scanner) -> ast.Expression: if s.accept(TokenType.EOF): - ret: ast.expr = astNameConstant(False) + ret: ast.expr = ast.Constant(False) else: ret = expr(s) s.accept(TokenType.EOF, reject=True) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 406da5d9da1..bc10d3b90ef 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -5,6 +5,7 @@ from typing import Any from typing import Callable from typing import Collection +from typing import final from typing import Iterable from typing import Iterator from typing import List @@ -23,7 +24,6 @@ from .._code import getfslineno from ..compat import ascii_escaped -from ..compat import final from ..compat import NOTSET from ..compat import NotSetType from _pytest.config import Config diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index 9e51ff33538..834700b1b4c 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -5,6 +5,7 @@ import warnings from contextlib import contextmanager from typing import Any +from typing import final from typing import Generator from typing import List from typing import Mapping @@ -15,7 +16,6 @@ from typing import TypeVar from typing import Union -from _pytest.compat import final from _pytest.fixtures import fixture from _pytest.warning_types import PytestWarning diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index dbd6b0a4273..83180c1266c 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -1,5 +1,6 @@ import os import warnings +from functools import cached_property from inspect import signature from pathlib import Path from typing import Any @@ -23,7 +24,6 @@ from _pytest._code.code import ExceptionInfo from _pytest._code.code import TerminalRepr from _pytest._code.code import Traceback -from _pytest.compat import cached_property from _pytest.compat import LEGACY_PATH from _pytest.config import Config from _pytest.config import ConftestImportFailure diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 1be97dda4ea..7dab4499b56 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -7,23 +7,12 @@ from typing import cast from typing import NoReturn from typing import Optional +from typing import Protocol from typing import Type from typing import TypeVar from _pytest.deprecated import KEYWORD_MSG_ARG -TYPE_CHECKING = False # Avoid circular import through compat. - -if TYPE_CHECKING: - from typing_extensions import Protocol -else: - # typing.Protocol is only available starting from Python 3.8. It is also - # available from typing_extensions, but we don't want a runtime dependency - # on that. So use a dummy runtime implementation. - from typing import Generic - - Protocol = Generic - class OutcomeException(BaseException): """OutcomeException and its subclass instances indicate and contain info diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 3df52ebe88c..0634267ae3e 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -20,6 +20,7 @@ from typing import Any from typing import Callable from typing import Dict +from typing import final from typing import Generator from typing import IO from typing import Iterable @@ -40,7 +41,6 @@ from _pytest import timing from _pytest._code import Source from _pytest.capture import _get_multicapture -from _pytest.compat import final from _pytest.compat import NOTSET from _pytest.compat import NotSetType from _pytest.config import _PluggyPlugin diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 6ba568c0fa7..5f4ba3da612 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -15,6 +15,7 @@ from typing import Any from typing import Callable from typing import Dict +from typing import final from typing import Generator from typing import Iterable from typing import Iterator @@ -40,7 +41,6 @@ from _pytest._io.saferepr import saferepr from _pytest.compat import ascii_escaped from _pytest.compat import assert_never -from _pytest.compat import final from _pytest.compat import get_default_arg_names from _pytest.compat import get_real_func from _pytest.compat import getimfunc diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 4213bd098c2..0967ae8ece6 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -9,9 +9,11 @@ from typing import Callable from typing import cast from typing import ContextManager +from typing import final from typing import List from typing import Mapping from typing import Optional +from typing import overload from typing import Pattern from typing import Sequence from typing import Tuple @@ -20,16 +22,13 @@ from typing import TypeVar from typing import Union -if TYPE_CHECKING: - from numpy import ndarray - - import _pytest._code -from _pytest.compat import final from _pytest.compat import STRING_TYPES -from _pytest.compat import overload from _pytest.outcomes import fail +if TYPE_CHECKING: + from numpy import ndarray + def _non_numeric_type_error(value, at: Optional[str]) -> TypeError: at_str = f" at {at}" if at else "" diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index d76ea020f19..b422f362730 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -5,18 +5,18 @@ from types import TracebackType from typing import Any from typing import Callable +from typing import final from typing import Generator from typing import Iterator from typing import List from typing import Optional +from typing import overload from typing import Pattern from typing import Tuple from typing import Type from typing import TypeVar from typing import Union -from _pytest.compat import final -from _pytest.compat import overload from _pytest.deprecated import check_ispytest from _pytest.deprecated import WARNS_NONE_ARG from _pytest.fixtures import fixture diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 74e8794b232..0a4044ec650 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -5,6 +5,7 @@ from typing import Any from typing import cast from typing import Dict +from typing import final from typing import Iterable from typing import Iterator from typing import List @@ -29,7 +30,6 @@ from _pytest._code.code import ReprTraceback from _pytest._code.code import TerminalRepr from _pytest._io import TerminalWriter -from _pytest.compat import final from _pytest.config import Config from _pytest.nodes import Collector from _pytest.nodes import Item diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index f861c05a451..1f14ff94484 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -6,6 +6,7 @@ from typing import Callable from typing import cast from typing import Dict +from typing import final from typing import Generic from typing import List from typing import Optional @@ -23,7 +24,6 @@ from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ExceptionInfo from _pytest._code.code import TerminalRepr -from _pytest.compat import final from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest from _pytest.nodes import Collector diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index b0cdb58ce00..089314c3e1b 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -18,6 +18,7 @@ from typing import cast from typing import ClassVar from typing import Dict +from typing import final from typing import Generator from typing import List from typing import Mapping @@ -40,7 +41,6 @@ from _pytest._io import TerminalWriter from _pytest._io.wcwidth import wcswidth from _pytest.assertion.util import running_on_ci -from _pytest.compat import final from _pytest.config import _PluggyPlugin from _pytest.config import Config from _pytest.config import ExitCode diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 3cc2bace55b..fe0855c18b0 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -7,38 +7,32 @@ from shutil import rmtree from typing import Any from typing import Dict +from typing import final from typing import Generator +from typing import Literal from typing import Optional -from typing import TYPE_CHECKING from typing import Union -from _pytest.nodes import Item -from _pytest.reports import CollectReport -from _pytest.stash import StashKey - -if TYPE_CHECKING: - from typing_extensions import Literal - - RetentionType = Literal["all", "failed", "none"] - - -from _pytest.config.argparsing import Parser - +from .pathlib import cleanup_dead_symlinks from .pathlib import LOCK_TIMEOUT from .pathlib import make_numbered_dir from .pathlib import make_numbered_dir_with_cleanup from .pathlib import rm_rf -from .pathlib import cleanup_dead_symlinks -from _pytest.compat import final, get_user_id +from _pytest.compat import get_user_id from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config import hookimpl +from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest from _pytest.fixtures import fixture from _pytest.fixtures import FixtureRequest from _pytest.monkeypatch import MonkeyPatch +from _pytest.nodes import Item +from _pytest.reports import CollectReport +from _pytest.stash import StashKey tmppath_result_key = StashKey[Dict[str, bool]]() +RetentionType = Literal["all", "failed", "none"] @final diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index f6b0a3a69ae..31726e1ce22 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -3,12 +3,11 @@ import warnings from types import FunctionType from typing import Any +from typing import final from typing import Generic from typing import Type from typing import TypeVar -from _pytest.compat import final - class PytestWarning(UserWarning): """Base class for all warnings emitted by pytest.""" diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index de9e92d00f0..453e269727c 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1,10 +1,10 @@ import dataclasses +import importlib.metadata import os import sys import types import pytest -from _pytest.compat import importlib_metadata from _pytest.config import ExitCode from _pytest.pathlib import symlink_or_skip from _pytest.pytester import Pytester @@ -139,7 +139,7 @@ class DummyDist: def my_dists(): return (DummyDist(entry_points),) - monkeypatch.setattr(importlib_metadata, "distributions", my_dists) + monkeypatch.setattr(importlib.metadata, "distributions", my_dists) params = ("-p", "mycov") if load_cov_early else () pytester.runpytest_inprocess(*params) if load_cov_early: diff --git a/testing/code/test_source.py b/testing/code/test_source.py index dc35c9496ab..260c80299b4 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -439,14 +439,9 @@ def test_comments() -> None: ''' for line in range(2, 6): assert str(getstatement(line, source)) == " x = 1" - if sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"): - tqs_start = 8 - else: - tqs_start = 10 - assert str(getstatement(10, source)) == '"""' - for line in range(6, tqs_start): + for line in range(6, 8): assert str(getstatement(line, source)) == " assert False" - for line in range(tqs_start, 10): + for line in range(8, 10): assert str(getstatement(line, source)) == '"""\ncomment 4\n"""' diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index a9e9b526934..08ea8f9107f 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -19,7 +19,6 @@ import pytest from _pytest import fixtures from _pytest import python -from _pytest.compat import _format_args from _pytest.compat import getfuncargnames from _pytest.compat import NOTSET from _pytest.outcomes import fail @@ -1036,27 +1035,6 @@ def test_3(self, arg, arg2): """ ) - def test_format_args(self) -> None: - def function1(): - pass - - assert _format_args(function1) == "()" - - def function2(arg1): - pass - - assert _format_args(function2) == "(arg1)" - - def function3(arg1, arg2="qwe"): - pass - - assert _format_args(function3) == "(arg1, arg2='qwe')" - - def function4(arg1, *args, **kwargs): - pass - - assert _format_args(function4) == "(arg1, *args, **kwargs)" - class TestMetafuncFunctional: def test_attributes(self, pytester: Pytester) -> None: diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 7119b3b5aa6..c04c31f31b6 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -199,8 +199,8 @@ def check(values, value): return check """, "mainwrapper.py": """\ + import importlib.metadata import pytest - from _pytest.compat import importlib_metadata class DummyEntryPoint(object): name = 'spam' @@ -220,7 +220,7 @@ class DummyDistInfo(object): def distributions(): return (DummyDistInfo(),) - importlib_metadata.distributions = distributions + importlib.metadata.distributions = distributions pytest.main() """, "test_foo.py": """\ diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 778f843e6cf..d0180320400 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -131,9 +131,8 @@ def test_location_is_set(self) -> None: for n in [node, *ast.iter_child_nodes(node)]: assert n.lineno == 3 assert n.col_offset == 0 - if sys.version_info >= (3, 8): - assert n.end_lineno == 6 - assert n.end_col_offset == 3 + assert n.end_lineno == 6 + assert n.end_col_offset == 3 def test_dont_rewrite(self) -> None: s = """'PYTEST_DONT_REWRITE'\nassert 14""" @@ -1270,9 +1269,6 @@ def test_simple_failure(): result.stdout.fnmatch_lines(["*E*assert (1 + 1) == 3"]) -@pytest.mark.skipif( - sys.version_info < (3, 8), reason="walrus operator not available in py<38" -) class TestIssue10743: def test_assertion_walrus_operator(self, pytester: Pytester) -> None: pytester.makepyfile( @@ -1441,9 +1437,6 @@ def test_walrus_operator_not_override_value(): assert result.ret == 0 -@pytest.mark.skipif( - sys.version_info < (3, 8), reason="walrus operator not available in py<38" -) class TestIssue11028: def test_assertion_walrus_operator_in_operand(self, pytester: Pytester) -> None: pytester.makepyfile( @@ -1957,16 +1950,10 @@ class TestPyCacheDir: ) def test_get_cache_dir(self, monkeypatch, prefix, source, expected) -> None: monkeypatch.delenv("PYTHONPYCACHEPREFIX", raising=False) - - if prefix is not None and sys.version_info < (3, 8): - pytest.skip("pycache_prefix not available in py<38") monkeypatch.setattr(sys, "pycache_prefix", prefix, raising=False) assert get_cache_dir(Path(source)) == Path(expected) - @pytest.mark.skipif( - sys.version_info < (3, 8), reason="pycache_prefix not available in py<38" - ) @pytest.mark.skipif( sys.version_info[:2] == (3, 9) and sys.platform.startswith("win"), reason="#9298", diff --git a/testing/test_compat.py b/testing/test_compat.py index 8a80fd625dc..27c6db95bbf 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -1,5 +1,6 @@ import enum import sys +from functools import cached_property from functools import partial from functools import wraps from typing import TYPE_CHECKING @@ -8,7 +9,6 @@ import pytest from _pytest.compat import _PytestWrapper from _pytest.compat import assert_never -from _pytest.compat import cached_property from _pytest.compat import get_real_func from _pytest.compat import is_generator from _pytest.compat import safe_getattr diff --git a/testing/test_config.py b/testing/test_config.py index 257d696fa65..9b3fe4af0da 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,4 +1,5 @@ import dataclasses +import importlib.metadata import os import re import sys @@ -13,7 +14,6 @@ import _pytest._code import pytest -from _pytest.compat import importlib_metadata from _pytest.config import _get_plugin_specs_as_list from _pytest.config import _iter_rewritable_modules from _pytest.config import _strtobool @@ -475,7 +475,7 @@ def my_dists(): pytester.makepyfile(myplugin1_module="# my plugin module") pytester.syspathinsert() - monkeypatch.setattr(importlib_metadata, "distributions", my_dists) + monkeypatch.setattr(importlib.metadata, "distributions", my_dists) monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False) pytester.makeini(ini_file_text) @@ -1003,7 +1003,7 @@ class Dist: def my_dists(): return (Dist,) - monkeypatch.setattr(importlib_metadata, "distributions", my_dists) + monkeypatch.setattr(importlib.metadata, "distributions", my_dists) pytester.makeconftest( """ pytest_plugins = "mytestplugin", @@ -1036,7 +1036,7 @@ class Distribution: def distributions(): return (Distribution(),) - monkeypatch.setattr(importlib_metadata, "distributions", distributions) + monkeypatch.setattr(importlib.metadata, "distributions", distributions) with pytest.raises(ImportError): pytester.parseconfig() @@ -1063,7 +1063,7 @@ class Distribution: def distributions(): return (Distribution(),) - monkeypatch.setattr(importlib_metadata, "distributions", distributions) + monkeypatch.setattr(importlib.metadata, "distributions", distributions) pytester.parseconfig() @@ -1091,7 +1091,7 @@ class Distribution: def distributions(): return (Distribution(),) - monkeypatch.setattr(importlib_metadata, "distributions", distributions) + monkeypatch.setattr(importlib.metadata, "distributions", distributions) args = ("-p", "no:mytestplugin") if block_it else () config = pytester.parseconfig(*args) config.pluginmanager.import_plugin("mytestplugin") @@ -1140,7 +1140,7 @@ def distributions(): return (Distribution(),) monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1") - monkeypatch.setattr(importlib_metadata, "distributions", distributions) + monkeypatch.setattr(importlib.metadata, "distributions", distributions) monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin()) # type: ignore[misc] config = pytester.parseconfig(*parse_args) has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None diff --git a/testing/test_entry_points.py b/testing/test_entry_points.py index 5d003127363..dfb3d57d2d8 100644 --- a/testing/test_entry_points.py +++ b/testing/test_entry_points.py @@ -1,7 +1,7 @@ -from _pytest.compat import importlib_metadata +import importlib.metadata def test_pytest_entry_points_are_identical(): - dist = importlib_metadata.distribution("pytest") + dist = importlib.metadata.distribution("pytest") entry_map = {ep.name: ep for ep in dist.entry_points} assert entry_map["pytest"].value == entry_map["py.test"].value diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 6b80346108f..d8b22aa463f 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -1142,12 +1142,10 @@ def test_func(): """ ) result = pytester.runpytest() - markline = " ^" + markline = " ^" pypy_version_info = getattr(sys, "pypy_version_info", None) if pypy_version_info is not None and pypy_version_info < (6,): - markline = markline[5:] - elif sys.version_info >= (3, 8) or hasattr(sys, "pypy_version_info"): - markline = markline[4:] + markline = markline[1:] if sys.version_info[:2] >= (3, 10): expected = [ diff --git a/testing/test_threadexception.py b/testing/test_threadexception.py index 5b7519f27d8..fd9a091ccc9 100644 --- a/testing/test_threadexception.py +++ b/testing/test_threadexception.py @@ -1,13 +1,7 @@ -import sys - import pytest from _pytest.pytester import Pytester -if sys.version_info < (3, 8): - pytest.skip("threadexception plugin needs Python>=3.8", allow_module_level=True) - - @pytest.mark.filterwarnings("default::pytest.PytestUnhandledThreadExceptionWarning") def test_unhandled_thread_exception(pytester: Pytester) -> None: pytester.makepyfile( diff --git a/testing/test_unittest.py b/testing/test_unittest.py index d917d331a03..99a53e0a9af 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1354,9 +1354,6 @@ def test_plain_unittest_does_not_support_async(pytester: Pytester) -> None: result.stdout.fnmatch_lines(expected_lines) -@pytest.mark.skipif( - sys.version_info < (3, 8), reason="Feature introduced in Python 3.8" -) def test_do_class_cleanups_on_success(pytester: Pytester) -> None: testpath = pytester.makepyfile( """ @@ -1382,9 +1379,6 @@ def test_cleanup_called_exactly_once(): assert passed == 3 -@pytest.mark.skipif( - sys.version_info < (3, 8), reason="Feature introduced in Python 3.8" -) def test_do_class_cleanups_on_setupclass_failure(pytester: Pytester) -> None: testpath = pytester.makepyfile( """ @@ -1409,9 +1403,6 @@ def test_cleanup_called_exactly_once(): assert passed == 1 -@pytest.mark.skipif( - sys.version_info < (3, 8), reason="Feature introduced in Python 3.8" -) def test_do_class_cleanups_on_teardownclass_failure(pytester: Pytester) -> None: testpath = pytester.makepyfile( """ diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index f625833dcea..72f620364b7 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -1,13 +1,7 @@ -import sys - import pytest from _pytest.pytester import Pytester -if sys.version_info < (3, 8): - pytest.skip("unraisableexception plugin needs Python>=3.8", allow_module_level=True) - - @pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_unraisable(pytester: Pytester) -> None: pytester.makepyfile( From f617bab0a243dea5ffe6c61ca21f280c56d9280c Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 15:07:07 -0700 Subject: [PATCH 0033/1271] Update pre-commit config --- .pre-commit-config.yaml | 4 ++-- src/_pytest/_code/code.py | 23 ++++++++++------------- src/_pytest/capture.py | 12 +++++------- src/_pytest/compat.py | 5 +---- src/_pytest/legacypath.py | 3 +-- src/_pytest/pytester.py | 6 ++---- 6 files changed, 21 insertions(+), 32 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f1cd674320..94ec6740879 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,12 +40,12 @@ repos: rev: v3.10.0 hooks: - id: reorder-python-imports - args: ['--application-directories=.:src', --py37-plus] + args: ['--application-directories=.:src', --py38-plus] - repo: https://github.com/asottile/pyupgrade rev: v3.7.0 hooks: - id: pyupgrade - args: [--py37-plus] + args: [--py38-plus] - repo: https://github.com/asottile/setup-cfg-fmt rev: v2.3.0 hooks: diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index ddc03d7527c..58483d2a042 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -17,19 +17,21 @@ from typing import Callable from typing import ClassVar from typing import Dict +from typing import Final from typing import final from typing import Generic from typing import Iterable from typing import List +from typing import Literal from typing import Mapping from typing import Optional from typing import overload from typing import Pattern from typing import Sequence from typing import Set +from typing import SupportsIndex from typing import Tuple from typing import Type -from typing import TYPE_CHECKING from typing import TypeVar from typing import Union @@ -48,16 +50,11 @@ from _pytest.pathlib import absolutepath from _pytest.pathlib import bestrelpath -if TYPE_CHECKING: - from typing_extensions import Final - from typing_extensions import Literal - from typing_extensions import SupportsIndex - - _TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] - if sys.version_info[:2] < (3, 11): from exceptiongroup import BaseExceptionGroup +_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] + class Code: """Wrapper around Python code objects.""" @@ -633,7 +630,7 @@ def _getreprcrash(self) -> Optional["ReprFileLocation"]: def getrepr( self, showlocals: bool = False, - style: "_TracebackStyle" = "long", + style: _TracebackStyle = "long", abspath: bool = False, tbfilter: Union[ bool, Callable[["ExceptionInfo[BaseException]"], Traceback] @@ -725,7 +722,7 @@ class FormattedExcinfo: fail_marker: ClassVar = "E" showlocals: bool = False - style: "_TracebackStyle" = "long" + style: _TracebackStyle = "long" abspath: bool = True tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True funcargs: bool = False @@ -1090,7 +1087,7 @@ def toterminal(self, tw: TerminalWriter) -> None: class ReprTraceback(TerminalRepr): reprentries: Sequence[Union["ReprEntry", "ReprEntryNative"]] extraline: Optional[str] - style: "_TracebackStyle" + style: _TracebackStyle entrysep: ClassVar = "_ " @@ -1124,7 +1121,7 @@ def __init__(self, tblines: Sequence[str]) -> None: class ReprEntryNative(TerminalRepr): lines: Sequence[str] - style: ClassVar["_TracebackStyle"] = "native" + style: ClassVar[_TracebackStyle] = "native" def toterminal(self, tw: TerminalWriter) -> None: tw.write("".join(self.lines)) @@ -1136,7 +1133,7 @@ class ReprEntry(TerminalRepr): reprfuncargs: Optional["ReprFuncArgs"] reprlocals: Optional["ReprLocals"] reprfileloc: Optional["ReprFileLocation"] - style: "_TracebackStyle" + style: _TracebackStyle def _write_entry_lines(self, tw: TerminalWriter) -> None: """Write the source code portions of a list of traceback entries with syntax highlighting. diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 3e31e3cb7d6..5c62cf54d9d 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -11,12 +11,14 @@ from typing import Any from typing import AnyStr from typing import BinaryIO +from typing import Final from typing import final from typing import Generator from typing import Generic from typing import Iterable from typing import Iterator from typing import List +from typing import Literal from typing import NamedTuple from typing import Optional from typing import TextIO @@ -35,11 +37,7 @@ from _pytest.nodes import File from _pytest.nodes import Item -if TYPE_CHECKING: - from typing_extensions import Final - from typing_extensions import Literal - - _CaptureMethod = Literal["fd", "sys", "no", "tee-sys"] +_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"] def pytest_addoption(parser: Parser) -> None: @@ -687,7 +685,7 @@ def readouterr(self) -> CaptureResult[AnyStr]: return CaptureResult(out, err) # type: ignore[arg-type] -def _get_multicapture(method: "_CaptureMethod") -> MultiCapture[str]: +def _get_multicapture(method: _CaptureMethod) -> MultiCapture[str]: if method == "fd": return MultiCapture(in_=FDCapture(0), out=FDCapture(1), err=FDCapture(2)) elif method == "sys": @@ -723,7 +721,7 @@ class CaptureManager: needed to ensure the fixtures take precedence over the global capture. """ - def __init__(self, method: "_CaptureMethod") -> None: + def __init__(self, method: _CaptureMethod) -> None: self._method: Final = method self._global_capturing: Optional[MultiCapture[str]] = None self._capture_fixture: Optional[CaptureFixture[Any]] = None diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 4736bf40dbe..998f540f357 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -12,15 +12,12 @@ from pathlib import Path from typing import Any from typing import Callable +from typing import Final from typing import NoReturn -from typing import TYPE_CHECKING from typing import TypeVar import py -if TYPE_CHECKING: - from typing_extensions import Final - _T = TypeVar("_T") _S = TypeVar("_S") diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index 7091f038a3b..8df0a516318 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -3,6 +3,7 @@ import shlex import subprocess from pathlib import Path +from typing import Final from typing import final from typing import List from typing import Optional @@ -32,8 +33,6 @@ from _pytest.tmpdir import TempPathFactory if TYPE_CHECKING: - from typing_extensions import Final - import pexpect diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 0634267ae3e..0129c224f08 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -20,11 +20,13 @@ from typing import Any from typing import Callable from typing import Dict +from typing import Final from typing import final from typing import Generator from typing import IO from typing import Iterable from typing import List +from typing import Literal from typing import Optional from typing import overload from typing import Sequence @@ -68,11 +70,7 @@ from _pytest.tmpdir import TempPathFactory from _pytest.warning_types import PytestWarning - if TYPE_CHECKING: - from typing_extensions import Final - from typing_extensions import Literal - import pexpect From 165fbbd12a74ab639d61ce1f28dfef1511a2c2e2 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 15:19:19 -0700 Subject: [PATCH 0034/1271] Drop py37 from CI --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 55 ++++++++++++------------------ CONTRIBUTING.rst | 16 ++++----- README.rst | 2 +- doc/en/backwards-compatibility.rst | 1 + doc/en/getting-started.rst | 2 +- doc/en/index.rst | 2 +- tox.ini | 9 +++-- 8 files changed, 39 insertions(+), 50 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 25280994687..186adc55a4b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -45,7 +45,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.7" + python-version: "3.11" - name: Install tox run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cf5027223e1..68f05a58ac4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,25 +37,23 @@ jobs: fail-fast: false matrix: name: [ - "windows-py37", - "windows-py37-pluggy", "windows-py38", + "windows-py38-pluggy", "windows-py39", "windows-py310", "windows-py311", "windows-py312", - "ubuntu-py37", - "ubuntu-py37-pluggy", - "ubuntu-py37-freeze", "ubuntu-py38", + "ubuntu-py38-pluggy", + "ubuntu-py38-freeze", "ubuntu-py39", "ubuntu-py310", "ubuntu-py311", "ubuntu-py312", "ubuntu-pypy3", - "macos-py37", + "macos-py38", "macos-py39", "macos-py310", "macos-py312", @@ -66,19 +64,15 @@ jobs: ] include: - - name: "windows-py37" - python: "3.7" - os: windows-latest - tox_env: "py37-numpy" - - name: "windows-py37-pluggy" - python: "3.7" - os: windows-latest - tox_env: "py37-pluggymain-pylib-xdist" - name: "windows-py38" python: "3.8" os: windows-latest tox_env: "py38-unittestextras" use_coverage: true + - name: "windows-py38-pluggy" + python: "3.8" + os: windows-latest + tox_env: "py38-pluggymain-pylib-xdist" - name: "windows-py39" python: "3.9" os: windows-latest @@ -96,23 +90,18 @@ jobs: os: windows-latest tox_env: "py312" - - name: "ubuntu-py37" - python: "3.7" - os: ubuntu-latest - tox_env: "py37-lsof-numpy-pexpect" - use_coverage: true - - name: "ubuntu-py37-pluggy" - python: "3.7" - os: ubuntu-latest - tox_env: "py37-pluggymain-pylib-xdist" - - name: "ubuntu-py37-freeze" - python: "3.7" - os: ubuntu-latest - tox_env: "py37-freeze" - name: "ubuntu-py38" python: "3.8" os: ubuntu-latest tox_env: "py38-xdist" + - name: "ubuntu-py38-pluggy" + python: "3.8" + os: ubuntu-latest + tox_env: "py38-pluggymain-pylib-xdist" + - name: "ubuntu-py38-freeze" + python: "3.8" + os: ubuntu-latest + tox_env: "py38-freeze" - name: "ubuntu-py39" python: "3.9" os: ubuntu-latest @@ -132,14 +121,14 @@ jobs: tox_env: "py312" use_coverage: true - name: "ubuntu-pypy3" - python: "pypy-3.7" + python: "pypy-3.8" os: ubuntu-latest tox_env: "pypy3-xdist" - - name: "macos-py37" - python: "3.7" + - name: "macos-py38" + python: "3.8" os: macos-latest - tox_env: "py37-xdist" + tox_env: "py38-xdist" - name: "macos-py39" python: "3.9" os: macos-latest @@ -160,11 +149,11 @@ jobs: tox_env: "plugins" - name: "docs" - python: "3.7" + python: "3.8" os: ubuntu-latest tox_env: "docs" - name: "doctesting" - python: "3.7" + python: "3.8" os: ubuntu-latest tox_env: "doctesting" use_coverage: true diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 791f988306f..0f6d54351af 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -201,7 +201,7 @@ Short version #. Follow **PEP-8** for naming and `black `_ for formatting. #. Tests are run using ``tox``:: - tox -e linting,py37 + tox -e linting,py39 The test environments above are usually enough to cover most cases locally. @@ -272,24 +272,24 @@ Here is a simple overview, with pytest-specific bits: #. Run all the tests - You need to have Python 3.7 available in your system. Now + You need to have Python 3.8 or later available in your system. Now running tests is as simple as issuing this command:: - $ tox -e linting,py37 + $ tox -e linting,py39 - This command will run tests via the "tox" tool against Python 3.7 + This command will run tests via the "tox" tool against Python 3.9 and also perform "lint" coding-style checks. #. You can now edit your local working copy and run the tests again as necessary. Please follow PEP-8 for naming. - You can pass different options to ``tox``. For example, to run tests on Python 3.7 and pass options to pytest + You can pass different options to ``tox``. For example, to run tests on Python 3.9 and pass options to pytest (e.g. enter pdb on failure) to pytest you can do:: - $ tox -e py37 -- --pdb + $ tox -e py39 -- --pdb - Or to only run tests in a particular test module on Python 3.7:: + Or to only run tests in a particular test module on Python 3.9:: - $ tox -e py37 -- testing/test_config.py + $ tox -e py39 -- testing/test_config.py When committing, ``pre-commit`` will re-format the files if necessary. diff --git a/README.rst b/README.rst index 034034a40b8..e6bb6d4cf7f 100644 --- a/README.rst +++ b/README.rst @@ -100,7 +100,7 @@ Features - Can run `unittest `_ (or trial), `nose `_ test suites out of the box -- Python 3.7+ or PyPy3 +- Python 3.8+ or PyPy3 - Rich plugin architecture, with over 850+ `external plugins `_ and thriving community diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index ea0c6a71a28..4ffb9fe9756 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -87,6 +87,7 @@ Released pytest versions support all Python versions that are actively maintaine ============== =================== pytest version min. Python version ============== =================== +8.0+ 3.8+ 7.1+ 3.7+ 6.2 - 7.0 3.6+ 5.0 - 6.1 3.5+ diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index e295c180454..4a9dc4522f1 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -9,7 +9,7 @@ Get Started Install ``pytest`` ---------------------------------------- -``pytest`` requires: Python 3.7+ or PyPy3. +``pytest`` requires: Python 3.8+ or PyPy3. 1. Run the following command in your command line: diff --git a/doc/en/index.rst b/doc/en/index.rst index de07831ac14..23b6964c9e8 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -77,7 +77,7 @@ Features - Can run :ref:`unittest ` (including trial) and :ref:`nose ` test suites out of the box -- Python 3.7+ or PyPy 3 +- Python 3.8+ or PyPy 3 - Rich plugin architecture, with over 800+ :ref:`external plugins ` and thriving community diff --git a/tox.ini b/tox.ini index 05c1842af8a..9cdbfe3ab81 100644 --- a/tox.ini +++ b/tox.ini @@ -4,17 +4,16 @@ minversion = 3.20.0 distshare = {homedir}/.tox/distshare envlist = linting - py37 py38 py39 py310 py311 py312 pypy3 - py37-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} + py38-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} doctesting plugins - py37-freeze + py38-freeze docs docs-checklinks @@ -43,7 +42,7 @@ setenv = PYTHONWARNDEFAULTENCODING=1 # Configuration to run with coverage similar to CI, e.g. - # "tox -e py37-coverage". + # "tox -e py38-coverage". coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m coverage: _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess coverage: COVERAGE_FILE={toxinidir}/.coverage @@ -136,7 +135,7 @@ commands = pytest pytest_twisted_integration.py pytest simple_integration.py --force-sugar --flakes -[testenv:py37-freeze] +[testenv:py38-freeze] changedir = testing/freeze deps = pyinstaller From 9279ea2882b96be6f7de3f8fbaa38062b1f2353e Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 30 Jun 2023 15:29:02 -0700 Subject: [PATCH 0035/1271] Emit unmatched warnings from pytest.warns() --- AUTHORS | 1 + changelog/9288.breaking.rst | 1 + src/_pytest/recwarn.py | 33 ++++++++++++++++++++++++++++++ testing/test_recwarn.py | 40 +++++++++++++++++++++++++++++++++---- 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 changelog/9288.breaking.rst diff --git a/AUTHORS b/AUTHORS index e0ed531b07b..28116c3c834 100644 --- a/AUTHORS +++ b/AUTHORS @@ -311,6 +311,7 @@ Raphael Pierzina Rafal Semik Raquel Alegre Ravi Chandra +Reagan Lee Robert Holt Roberto Aldera Roberto Polli diff --git a/changelog/9288.breaking.rst b/changelog/9288.breaking.rst new file mode 100644 index 00000000000..7f101123d48 --- /dev/null +++ b/changelog/9288.breaking.rst @@ -0,0 +1 @@ +Set :func:`warns` to re-emit unmatched warnings when the context closes diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index b422f362730..334b3b850df 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -149,6 +149,10 @@ def warns( # noqa: F811 This could be achieved in the same way as with exceptions, see :ref:`parametrizing_conditional_raising` for an example. + .. note:: + Unlike the stdlib :func:`warnings.catch_warnings` context manager, + unmatched warnings will be re-emitted when the context closes. + """ __tracebackhide__ = True if not args: @@ -290,6 +294,32 @@ def __exit__( def found_str(): return pformat([record.message for record in self], indent=2) + def re_emit() -> None: + for r in self: + if matches(r): + continue + + assert issubclass(r.message.__class__, Warning) + + warnings.warn_explicit( + str(r.message), + r.message.__class__, + r.filename, + r.lineno, + module=r.__module__, + source=r.source, + ) + + def matches(warning) -> bool: + if self.expected_warning is not None: + if issubclass(warning.category, self.expected_warning): + if self.match_expr is not None: + if re.compile(self.match_expr).search(str(warning.message)): + return True + return False + return True + return False + # only check if we're not currently handling an exception if exc_type is None and exc_val is None and exc_tb is None: if self.expected_warning is not None: @@ -303,6 +333,7 @@ def found_str(): for r in self: if issubclass(r.category, self.expected_warning): if re.compile(self.match_expr).search(str(r.message)): + re_emit() break else: fail( @@ -311,3 +342,5 @@ def found_str(): Regex: {self.match_expr} Emitted warnings: {found_str()}""" ) + else: + re_emit() diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 7e0f836a634..d9cd1d778e2 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -376,10 +376,12 @@ def test_match_regex(self) -> None: warnings.warn("value must be 42", UserWarning) def test_one_from_multiple_warns(self) -> None: - with pytest.warns(UserWarning, match=r"aaa"): - warnings.warn("cccccccccc", UserWarning) - warnings.warn("bbbbbbbbbb", UserWarning) - warnings.warn("aaaaaaaaaa", UserWarning) + with pytest.raises(pytest.fail.Exception): + with pytest.warns(UserWarning, match=r"aaa"): + with pytest.warns(UserWarning, match=r"aaa"): + warnings.warn("cccccccccc", UserWarning) + warnings.warn("bbbbbbbbbb", UserWarning) + warnings.warn("aaaaaaaaaa", UserWarning) def test_none_of_multiple_warns(self) -> None: with pytest.raises(pytest.fail.Exception): @@ -403,3 +405,33 @@ def test_warns_context_manager_with_kwargs(self) -> None: with pytest.warns(UserWarning, foo="bar"): # type: ignore pass assert "Unexpected keyword arguments" in str(excinfo.value) + + def test_re_emit_single(self) -> None: + with pytest.warns(DeprecationWarning): + with pytest.warns(UserWarning): + warnings.warn("user warning", UserWarning) + warnings.warn("some deprecation warning", DeprecationWarning) + + def test_re_emit_multiple(self) -> None: + with pytest.warns(UserWarning): + warnings.warn("first warning", UserWarning) + warnings.warn("second warning", UserWarning) + + def test_re_emit_match_single(self) -> None: + with pytest.warns(DeprecationWarning): + with pytest.warns(UserWarning, match="user warning"): + warnings.warn("user warning", UserWarning) + warnings.warn("some deprecation warning", DeprecationWarning) + + def test_re_emit_match_multiple(self) -> None: + # with pytest.warns(UserWarning): + with pytest.warns(UserWarning, match="user warning"): + warnings.warn("first user warning", UserWarning) + warnings.warn("second user warning", UserWarning) + + def test_re_emit_non_match_single(self) -> None: + # with pytest.warns(UserWarning): + with pytest.warns(UserWarning, match="v2 warning"): + with pytest.warns(UserWarning, match="v1 warning"): + warnings.warn("v1 warning", UserWarning) + warnings.warn("non-matching v2 warning", UserWarning) From a1b37022afd4aec31009a3e56872c435b05e3c45 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 15:29:02 -0700 Subject: [PATCH 0036/1271] Refactor warns() exit logic --- src/_pytest/recwarn.py | 85 ++++++++++++++++++----------------------- testing/test_recwarn.py | 14 +++---- 2 files changed, 44 insertions(+), 55 deletions(-) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 334b3b850df..5452b7cb9c0 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -281,6 +281,12 @@ def __init__( self.expected_warning = expected_warning_tup self.match_expr = match_expr + def matches(self, warning: warnings.WarningMessage) -> bool: + assert self.expected_warning is not None + return issubclass(warning.category, self.expected_warning) and bool( + self.match_expr is None or re.search(self.match_expr, str(warning.message)) + ) + def __exit__( self, exc_type: Optional[Type[BaseException]], @@ -291,56 +297,39 @@ def __exit__( __tracebackhide__ = True - def found_str(): - return pformat([record.message for record in self], indent=2) + if self.expected_warning is None: + # nothing to do in this deprecated case, see WARNS_NONE_ARG above + return - def re_emit() -> None: - for r in self: - if matches(r): - continue + if not (exc_type is None and exc_val is None and exc_tb is None): + # We currently ignore missing warnings if an exception is active. + # TODO: fix this, because it means things are surprisingly order-sensitive. + return - assert issubclass(r.message.__class__, Warning) + def found_str(): + return pformat([record.message for record in self], indent=2) - warnings.warn_explicit( - str(r.message), - r.message.__class__, - r.filename, - r.lineno, - module=r.__module__, - source=r.source, + try: + if not any(issubclass(w.category, self.expected_warning) for w in self): + fail( + f"DID NOT WARN. No warnings of type {self.expected_warning} were emitted.\n" + f" Emitted warnings: {found_str()}." ) - - def matches(warning) -> bool: - if self.expected_warning is not None: - if issubclass(warning.category, self.expected_warning): - if self.match_expr is not None: - if re.compile(self.match_expr).search(str(warning.message)): - return True - return False - return True - return False - - # only check if we're not currently handling an exception - if exc_type is None and exc_val is None and exc_tb is None: - if self.expected_warning is not None: - if not any(issubclass(r.category, self.expected_warning) for r in self): - __tracebackhide__ = True - fail( - f"DID NOT WARN. No warnings of type {self.expected_warning} were emitted.\n" - f"The list of emitted warnings is: {found_str()}." + elif not any(self.matches(w) for w in self): + fail( + f"DID NOT WARN. No warnings of type {self.expected_warning} matching the regex were emitted.\n" + f" Regex: {self.match_expr}\n" + f" Emitted warnings: {found_str()}." + ) + finally: + # Whether or not any warnings matched, we want to re-emit all unmatched warnings. + for w in self: + if not self.matches(w): + warnings.warn_explicit( + str(w.message), + w.message.__class__, + w.filename, + w.lineno, + module=w.__module__, + source=w.source, ) - elif self.match_expr is not None: - for r in self: - if issubclass(r.category, self.expected_warning): - if re.compile(self.match_expr).search(str(r.message)): - re_emit() - break - else: - fail( - f"""\ -DID NOT WARN. No warnings of type {self.expected_warning} matching the regex were emitted. - Regex: {self.match_expr} - Emitted warnings: {found_str()}""" - ) - else: - re_emit() diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index d9cd1d778e2..a423b20012a 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -376,7 +376,7 @@ def test_match_regex(self) -> None: warnings.warn("value must be 42", UserWarning) def test_one_from_multiple_warns(self) -> None: - with pytest.raises(pytest.fail.Exception): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): with pytest.warns(UserWarning, match=r"aaa"): with pytest.warns(UserWarning, match=r"aaa"): warnings.warn("cccccccccc", UserWarning) @@ -384,7 +384,7 @@ def test_one_from_multiple_warns(self) -> None: warnings.warn("aaaaaaaaaa", UserWarning) def test_none_of_multiple_warns(self) -> None: - with pytest.raises(pytest.fail.Exception): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): with pytest.warns(UserWarning, match=r"aaa"): warnings.warn("bbbbbbbbbb", UserWarning) warnings.warn("cccccccccc", UserWarning) @@ -424,13 +424,13 @@ def test_re_emit_match_single(self) -> None: warnings.warn("some deprecation warning", DeprecationWarning) def test_re_emit_match_multiple(self) -> None: - # with pytest.warns(UserWarning): - with pytest.warns(UserWarning, match="user warning"): - warnings.warn("first user warning", UserWarning) - warnings.warn("second user warning", UserWarning) + with warnings.catch_warnings(): + warnings.simplefilter("error") # if anything is re-emitted + with pytest.warns(UserWarning, match="user warning"): + warnings.warn("first user warning", UserWarning) + warnings.warn("second user warning", UserWarning) def test_re_emit_non_match_single(self) -> None: - # with pytest.warns(UserWarning): with pytest.warns(UserWarning, match="v2 warning"): with pytest.warns(UserWarning, match="v1 warning"): warnings.warn("v1 warning", UserWarning) From 7022fb455d5c5853cb839cd20e53bbbacaa46d28 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 15:29:03 -0700 Subject: [PATCH 0037/1271] Update tests for re-emitted warnings --- src/_pytest/recwarn.py | 7 +-- testing/test_recwarn.py | 103 ++++++++++++++++++++++------------------ 2 files changed, 61 insertions(+), 49 deletions(-) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 5452b7cb9c0..efe2a3dc6ca 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -135,8 +135,9 @@ def warns( # noqa: F811 >>> with pytest.warns(UserWarning, match=r'must be \d+$'): ... warnings.warn("value must be 42", UserWarning) - >>> with pytest.warns(UserWarning, match=r'must be \d+$'): - ... warnings.warn("this is not here", UserWarning) + >>> with pytest.warns(UserWarning): # catch re-emitted warning + ... with pytest.warns(UserWarning, match=r'must be \d+$'): + ... warnings.warn("this is not here", UserWarning) Traceback (most recent call last): ... Failed: DID NOT WARN. No warnings of type ...UserWarning... were emitted... @@ -327,7 +328,7 @@ def found_str(): if not self.matches(w): warnings.warn_explicit( str(w.message), - w.message.__class__, + w.message.__class__, # type: ignore w.filename, w.lineno, module=w.__module__, diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index a423b20012a..6b3856bd924 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -203,19 +203,21 @@ def test_deprecated_call_specificity(self) -> None: def f(): warnings.warn(warning("hi")) - with pytest.raises(pytest.fail.Exception): - pytest.deprecated_call(f) - with pytest.raises(pytest.fail.Exception): - with pytest.deprecated_call(): - f() + with pytest.warns(warning): + with pytest.raises(pytest.fail.Exception): + pytest.deprecated_call(f) + with pytest.raises(pytest.fail.Exception): + with pytest.deprecated_call(): + f() def test_deprecated_call_supports_match(self) -> None: with pytest.deprecated_call(match=r"must be \d+$"): warnings.warn("value must be 42", DeprecationWarning) - with pytest.raises(pytest.fail.Exception): - with pytest.deprecated_call(match=r"must be \d+$"): - warnings.warn("this is not here", DeprecationWarning) + with pytest.deprecated_call(): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): + with pytest.deprecated_call(match=r"must be \d+$"): + warnings.warn("this is not here", DeprecationWarning) class TestWarns: @@ -227,8 +229,9 @@ def test_check_callable(self) -> None: def test_several_messages(self) -> None: # different messages, b/c Python suppresses multiple identical warnings pytest.warns(RuntimeWarning, lambda: warnings.warn("w1", RuntimeWarning)) - with pytest.raises(pytest.fail.Exception): - pytest.warns(UserWarning, lambda: warnings.warn("w2", RuntimeWarning)) + with pytest.warns(RuntimeWarning): + with pytest.raises(pytest.fail.Exception): + pytest.warns(UserWarning, lambda: warnings.warn("w2", RuntimeWarning)) pytest.warns(RuntimeWarning, lambda: warnings.warn("w3", RuntimeWarning)) def test_function(self) -> None: @@ -243,13 +246,14 @@ def test_warning_tuple(self) -> None: pytest.warns( (RuntimeWarning, SyntaxWarning), lambda: warnings.warn("w2", SyntaxWarning) ) - pytest.raises( - pytest.fail.Exception, - lambda: pytest.warns( - (RuntimeWarning, SyntaxWarning), - lambda: warnings.warn("w3", UserWarning), - ), - ) + with pytest.warns(): + pytest.raises( + pytest.fail.Exception, + lambda: pytest.warns( + (RuntimeWarning, SyntaxWarning), + lambda: warnings.warn("w3", UserWarning), + ), + ) def test_as_contextmanager(self) -> None: with pytest.warns(RuntimeWarning): @@ -258,20 +262,22 @@ def test_as_contextmanager(self) -> None: with pytest.warns(UserWarning): warnings.warn("user", UserWarning) - with pytest.raises(pytest.fail.Exception) as excinfo: - with pytest.warns(RuntimeWarning): - warnings.warn("user", UserWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(RuntimeWarning): + warnings.warn("user", UserWarning) excinfo.match( r"DID NOT WARN. No warnings of type \(.+RuntimeWarning.+,\) were emitted.\n" - r"The list of emitted warnings is: \[UserWarning\('user',?\)\]." + r" Emitted warnings: \[UserWarning\('user',?\)\]." ) - with pytest.raises(pytest.fail.Exception) as excinfo: - with pytest.warns(UserWarning): - warnings.warn("runtime", RuntimeWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(UserWarning): + warnings.warn("runtime", RuntimeWarning) excinfo.match( r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) were emitted.\n" - r"The list of emitted warnings is: \[RuntimeWarning\('runtime',?\)]." + r" Emitted warnings: \[RuntimeWarning\('runtime',?\)]." ) with pytest.raises(pytest.fail.Exception) as excinfo: @@ -279,19 +285,20 @@ def test_as_contextmanager(self) -> None: pass excinfo.match( r"DID NOT WARN. No warnings of type \(.+UserWarning.+,\) were emitted.\n" - r"The list of emitted warnings is: \[\]." + r" Emitted warnings: \[\]." ) warning_classes = (UserWarning, FutureWarning) - with pytest.raises(pytest.fail.Exception) as excinfo: - with pytest.warns(warning_classes) as warninfo: - warnings.warn("runtime", RuntimeWarning) - warnings.warn("import", ImportWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception) as excinfo: + with pytest.warns(warning_classes) as warninfo: + warnings.warn("runtime", RuntimeWarning) + warnings.warn("import", ImportWarning) messages = [each.message for each in warninfo] expected_str = ( f"DID NOT WARN. No warnings of type {warning_classes} were emitted.\n" - f"The list of emitted warnings is: {messages}." + f" Emitted warnings: {messages}." ) assert str(excinfo.value) == expected_str @@ -367,27 +374,31 @@ def test_match_regex(self) -> None: with pytest.warns(UserWarning, match=r"must be \d+$"): warnings.warn("value must be 42", UserWarning) - with pytest.raises(pytest.fail.Exception): - with pytest.warns(UserWarning, match=r"must be \d+$"): - warnings.warn("this is not here", UserWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception): + with pytest.warns(UserWarning, match=r"must be \d+$"): + warnings.warn("this is not here", UserWarning) - with pytest.raises(pytest.fail.Exception): - with pytest.warns(FutureWarning, match=r"must be \d+$"): - warnings.warn("value must be 42", UserWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception): + with pytest.warns(FutureWarning, match=r"must be \d+$"): + warnings.warn("value must be 42", UserWarning) def test_one_from_multiple_warns(self) -> None: - with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): - with pytest.warns(UserWarning, match=r"aaa"): + with pytest.warns(): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): with pytest.warns(UserWarning, match=r"aaa"): - warnings.warn("cccccccccc", UserWarning) - warnings.warn("bbbbbbbbbb", UserWarning) - warnings.warn("aaaaaaaaaa", UserWarning) + with pytest.warns(UserWarning, match=r"aaa"): + warnings.warn("cccccccccc", UserWarning) + warnings.warn("bbbbbbbbbb", UserWarning) + warnings.warn("aaaaaaaaaa", UserWarning) def test_none_of_multiple_warns(self) -> None: - with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): - with pytest.warns(UserWarning, match=r"aaa"): - warnings.warn("bbbbbbbbbb", UserWarning) - warnings.warn("cccccccccc", UserWarning) + with pytest.warns(): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): + with pytest.warns(UserWarning, match=r"aaa"): + warnings.warn("bbbbbbbbbb", UserWarning) + warnings.warn("cccccccccc", UserWarning) @pytest.mark.filterwarnings("ignore") def test_can_capture_previously_warned(self) -> None: From 2d48171e88e861bde0e7cf3d3d087ebbe203c103 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 15:29:03 -0700 Subject: [PATCH 0038/1271] Tweak docs on review --- changelog/9288.breaking.rst | 8 +++++++- src/_pytest/recwarn.py | 12 ++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/changelog/9288.breaking.rst b/changelog/9288.breaking.rst index 7f101123d48..053af8013ec 100644 --- a/changelog/9288.breaking.rst +++ b/changelog/9288.breaking.rst @@ -1 +1,7 @@ -Set :func:`warns` to re-emit unmatched warnings when the context closes +:func:`pytest.warns ` now re-emits unmatched warnings when the context +closes -- previously it would consume all warnings, hiding those that were not +matched by the function. + +While this is a new feature, we decided to announce this as a breaking change +because many test suites are configured to error-out on warnings, and will +therefore fail on the newly-re-emitted warnings. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index efe2a3dc6ca..127a7a856a4 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -117,10 +117,10 @@ def warns( # noqa: F811 warning of that class or classes. This helper produces a list of :class:`warnings.WarningMessage` objects, one for - each warning raised (regardless of whether it is an ``expected_warning`` or not). + each warning emitted (regardless of whether it is an ``expected_warning`` or not). + Since pytest 8.0, unmatched warnings are also re-emitted when the context closes. - This function can be used as a context manager, which will capture all the raised - warnings inside it:: + This function can be used as a context manager:: >>> import pytest >>> with pytest.warns(RuntimeWarning): @@ -150,10 +150,6 @@ def warns( # noqa: F811 This could be achieved in the same way as with exceptions, see :ref:`parametrizing_conditional_raising` for an example. - .. note:: - Unlike the stdlib :func:`warnings.catch_warnings` context manager, - unmatched warnings will be re-emitted when the context closes. - """ __tracebackhide__ = True if not args: @@ -328,7 +324,7 @@ def found_str(): if not self.matches(w): warnings.warn_explicit( str(w.message), - w.message.__class__, # type: ignore + w.message.__class__, # type: ignore[arg-type] w.filename, w.lineno, module=w.__module__, From 15524f34d2aa8a0b311ea1ce735d9b6b471b8018 Mon Sep 17 00:00:00 2001 From: Cheukting Date: Thu, 22 Jun 2023 16:48:20 +0100 Subject: [PATCH 0039/1271] capture warning when exception is raised (fix #9036) --- changelog/9036.bugfix.rst | 1 + src/_pytest/recwarn.py | 5 ----- testing/test_recwarn.py | 28 ++++++++++++---------------- 3 files changed, 13 insertions(+), 21 deletions(-) create mode 100644 changelog/9036.bugfix.rst diff --git a/changelog/9036.bugfix.rst b/changelog/9036.bugfix.rst new file mode 100644 index 00000000000..4f25f82e292 --- /dev/null +++ b/changelog/9036.bugfix.rst @@ -0,0 +1 @@ +``pytest.warns`` and similar functions now capture warnings when an exception is raised inside a ``with`` block. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 127a7a856a4..ff8e7082050 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -298,11 +298,6 @@ def __exit__( # nothing to do in this deprecated case, see WARNS_NONE_ARG above return - if not (exc_type is None and exc_val is None and exc_tb is None): - # We currently ignore missing warnings if an exception is active. - # TODO: fix this, because it means things are surprisingly order-sensitive. - return - def found_str(): return pformat([record.message for record in self], indent=2) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 6b3856bd924..16b8d54438f 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -172,22 +172,6 @@ def f(): with pytest.deprecated_call(): assert f() == 10 - @pytest.mark.parametrize("mode", ["context_manager", "call"]) - def test_deprecated_call_exception_is_raised(self, mode) -> None: - """If the block of the code being tested by deprecated_call() raises an exception, - it must raise the exception undisturbed. - """ - - def f(): - raise ValueError("some exception") - - with pytest.raises(ValueError, match="some exception"): - if mode == "call": - pytest.deprecated_call(f) - else: - with pytest.deprecated_call(): - f() - def test_deprecated_call_specificity(self) -> None: other_warnings = [ Warning, @@ -446,3 +430,15 @@ def test_re_emit_non_match_single(self) -> None: with pytest.warns(UserWarning, match="v1 warning"): warnings.warn("v1 warning", UserWarning) warnings.warn("non-matching v2 warning", UserWarning) + + def test_catch_warning_within_raise(self) -> None: + # warns-in-raises works since https://github.com/pytest-dev/pytest/pull/11129 + with pytest.raises(ValueError, match="some exception"): + with pytest.warns(FutureWarning, match="some warning"): + warnings.warn("some warning", category=FutureWarning) + raise ValueError("some exception") + # and raises-in-warns has always worked but we'll check for symmetry. + with pytest.warns(FutureWarning, match="some warning"): + with pytest.raises(ValueError, match="some exception"): + warnings.warn("some warning", category=FutureWarning) + raise ValueError("some exception") From 7fdc8391e2cea79994e20c1ab679e960ce9d9c7c Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 16:23:18 -0700 Subject: [PATCH 0040/1271] Explicit GC for PyPy --- testing/test_unraisableexception.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index 72f620364b7..08e7d6c9538 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -1,11 +1,15 @@ +import sys + import pytest from _pytest.pytester import Pytester +PYPY = hasattr(sys, "pypy_version_info") + @pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_unraisable(pytester: Pytester) -> None: pytester.makepyfile( - test_it=""" + test_it=f""" class BrokenDel: def __del__(self): raise ValueError("del is broken") @@ -13,6 +17,7 @@ def __del__(self): def test_it(): obj = BrokenDel() del obj + {"import gc; gc.collect()" * PYPY} def test_2(): pass """ @@ -37,7 +42,7 @@ def test_2(): pass @pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_unraisable_in_setup(pytester: Pytester) -> None: pytester.makepyfile( - test_it=""" + test_it=f""" import pytest class BrokenDel: @@ -48,6 +53,7 @@ def __del__(self): def broken_del(): obj = BrokenDel() del obj + {"import gc; gc.collect()" * PYPY} def test_it(broken_del): pass def test_2(): pass @@ -73,7 +79,7 @@ def test_2(): pass @pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_unraisable_in_teardown(pytester: Pytester) -> None: pytester.makepyfile( - test_it=""" + test_it=f""" import pytest class BrokenDel: @@ -85,6 +91,7 @@ def broken_del(): yield obj = BrokenDel() del obj + {"import gc; gc.collect()" * PYPY} def test_it(broken_del): pass def test_2(): pass @@ -110,7 +117,7 @@ def test_2(): pass @pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning") def test_unraisable_warning_error(pytester: Pytester) -> None: pytester.makepyfile( - test_it=""" + test_it=f""" class BrokenDel: def __del__(self) -> None: raise ValueError("del is broken") @@ -118,6 +125,7 @@ def __del__(self) -> None: def test_it() -> None: obj = BrokenDel() del obj + {"import gc; gc.collect()" * PYPY} def test_2(): pass """ From 0311fc3384093b3f04e8b25166508e10e3f1d3df Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 20:18:25 -0700 Subject: [PATCH 0041/1271] Apply suggestions from code review Co-authored-by: Bruno Oliveira --- .github/workflows/test.yml | 3 ++- changelog/11151.breaking.rst | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 68f05a58ac4..b3f258f1c21 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -93,7 +93,8 @@ jobs: - name: "ubuntu-py38" python: "3.8" os: ubuntu-latest - tox_env: "py38-xdist" + tox_env: "py38-lsof-numpy-pexpect" + use_coverage: true - name: "ubuntu-py38-pluggy" python: "3.8" os: ubuntu-latest diff --git a/changelog/11151.breaking.rst b/changelog/11151.breaking.rst index d846fc94cb0..2e86c5dfba0 100644 --- a/changelog/11151.breaking.rst +++ b/changelog/11151.breaking.rst @@ -1,2 +1,2 @@ -Drop support for Python 3.7, which `reached end-of-life on 2023-06-27 +Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27 `__. From 0353a94cd1ab1d961aa064235ee038d7a13583dd Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Fri, 30 Jun 2023 20:33:12 -0700 Subject: [PATCH 0042/1271] Explicit GC for PyPy, take 2 --- testing/test_unraisableexception.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index 08e7d6c9538..d255adb2b91 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -6,10 +6,11 @@ PYPY = hasattr(sys, "pypy_version_info") +@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky") @pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_unraisable(pytester: Pytester) -> None: pytester.makepyfile( - test_it=f""" + test_it=""" class BrokenDel: def __del__(self): raise ValueError("del is broken") @@ -17,7 +18,6 @@ def __del__(self): def test_it(): obj = BrokenDel() del obj - {"import gc; gc.collect()" * PYPY} def test_2(): pass """ @@ -39,10 +39,11 @@ def test_2(): pass ) +@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky") @pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_unraisable_in_setup(pytester: Pytester) -> None: pytester.makepyfile( - test_it=f""" + test_it=""" import pytest class BrokenDel: @@ -53,7 +54,6 @@ def __del__(self): def broken_del(): obj = BrokenDel() del obj - {"import gc; gc.collect()" * PYPY} def test_it(broken_del): pass def test_2(): pass @@ -76,10 +76,11 @@ def test_2(): pass ) +@pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky") @pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_unraisable_in_teardown(pytester: Pytester) -> None: pytester.makepyfile( - test_it=f""" + test_it=""" import pytest class BrokenDel: @@ -91,7 +92,6 @@ def broken_del(): yield obj = BrokenDel() del obj - {"import gc; gc.collect()" * PYPY} def test_it(broken_del): pass def test_2(): pass From 2f7415cfbc4b6ca62f9013f1abd27136f46b9653 Mon Sep 17 00:00:00 2001 From: akhilramkee <31619526+akhilramkee@users.noreply.github.com> Date: Sat, 1 Jul 2023 20:42:41 +0530 Subject: [PATCH 0043/1271] Add child modules as attributes of parent modules. (#10338) Failing to add child modules as attributes of parent module will prevent them from being accessible through parent module. Fix #10337 --- changelog/10337.bugfix.rst | 2 ++ src/_pytest/pathlib.py | 14 +++++++++++++- testing/test_pathlib.py | 12 ++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 changelog/10337.bugfix.rst diff --git a/changelog/10337.bugfix.rst b/changelog/10337.bugfix.rst new file mode 100644 index 00000000000..c5eeff19db0 --- /dev/null +++ b/changelog/10337.bugfix.rst @@ -0,0 +1,2 @@ +Fixed but that fake intermediate modules generated by ``--import-mode=importlib`` would not include the +child modules as attributes of the parent modules. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 70383e4b504..e43310ef08b 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -633,6 +633,9 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) -> otherwise "src.tests.test_foo" is not importable by ``__import__``. """ module_parts = module_name.split(".") + child_module: Union[ModuleType, None] = None + module: Union[ModuleType, None] = None + child_name: str = "" while module_name: if module_name not in modules: try: @@ -642,13 +645,22 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) -> # ourselves to fall back to creating a dummy module. if not sys.meta_path: raise ModuleNotFoundError - importlib.import_module(module_name) + module = importlib.import_module(module_name) except ModuleNotFoundError: module = ModuleType( module_name, doc="Empty module created by pytest's importmode=importlib.", ) + else: + module = modules[module_name] + if child_module: + # Add child attribute to the parent that can reference the child + # modules. + if not hasattr(module, child_name): + setattr(module, child_name, child_module) modules[module_name] = module + # Keep track of the child module while moving up the tree. + child_module, child_name = module, module_name.rpartition(".")[-1] module_parts.pop(-1) module_name = ".".join(module_parts) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 56c54e484da..c15a81ea1a3 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -592,3 +592,15 @@ def test_insert_missing_modules( modules = {} insert_missing_modules(modules, "") assert modules == {} + + def test_parent_contains_child_module_attribute( + self, monkeypatch: MonkeyPatch, tmp_path: Path + ): + monkeypatch.chdir(tmp_path) + # Use 'xxx' and 'xxy' as parent names as they are unlikely to exist and + # don't end up being imported. + modules = {"xxx.tests.foo": ModuleType("xxx.tests.foo")} + insert_missing_modules(modules, "xxx.tests.foo") + assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"] + assert modules["xxx"].tests is modules["xxx.tests"] + assert modules["xxx.tests"].foo is modules["xxx.tests.foo"] From b77d0deaf53697630ba534f62dc871f4eb275f14 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 1 Jul 2023 12:37:46 -0300 Subject: [PATCH 0044/1271] Fix duplicated imports with importlib mode and doctest-modules (#11148) The initial implementation (in #7246) introduced the `importlib` mode, which never added the imported module to `sys.modules`, so it included a test to ensure calling `import_path` twice would yield different modules. Not adding modules to `sys.modules` proved problematic, so we began to add the imported module to `sys.modules` in #7870, but failed to realize that given we are now changing `sys.modules`, we might as well avoid importing it more than once. Then #10088 came along, passing `importlib` also when importing application modules (as opposed to only test modules before), which caused problems due to imports having side-effects and the expectation being that they are imported only once. With this PR, `import_path` returns the module immediately if already in `sys.modules`. Fix #10811 Fix #10341 --- changelog/10811.bugfix.rst | 2 ++ src/_pytest/pathlib.py | 2 ++ testing/acceptance_test.py | 35 +++++++++++++++++++++++++++++++++++ testing/test_pathlib.py | 27 +++++++++++++++++++-------- 4 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 changelog/10811.bugfix.rst diff --git a/changelog/10811.bugfix.rst b/changelog/10811.bugfix.rst new file mode 100644 index 00000000000..aa26414e457 --- /dev/null +++ b/changelog/10811.bugfix.rst @@ -0,0 +1,2 @@ +Fixed issue when using ``--import-mode=importlib`` together with ``--doctest-modules`` that caused modules +to be imported more than once, causing problems with modules that have import side effects. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index e43310ef08b..14fb2e3ae2f 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -523,6 +523,8 @@ def import_path( if mode is ImportMode.importlib: module_name = module_name_from_path(path, root) + with contextlib.suppress(KeyError): + return sys.modules[module_name] for meta_importer in sys.meta_path: spec = meta_importer.find_spec(module_name, [str(path.parent)]) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 453e269727c..429fb4e4372 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1315,3 +1315,38 @@ def test_stuff(): ) res = pytester.runpytest() res.stdout.fnmatch_lines(["*Did you mean to use `assert` instead of `return`?*"]) + + +def test_doctest_and_normal_imports_with_importlib(pytester: Pytester) -> None: + """ + Regression test for #10811: previously import_path with ImportMode.importlib would + not return a module if already in sys.modules, resulting in modules being imported + multiple times, which causes problems with modules that have import side effects. + """ + # Uses the exact reproducer form #10811, given it is very minimal + # and illustrates the problem well. + pytester.makepyfile( + **{ + "pmxbot/commands.py": "from . import logging", + "pmxbot/logging.py": "", + "tests/__init__.py": "", + "tests/test_commands.py": """ + import importlib + from pmxbot import logging + + class TestCommands: + def test_boo(self): + assert importlib.import_module('pmxbot.logging') is logging + """, + } + ) + pytester.makeini( + """ + [pytest] + addopts= + --doctest-modules + --import-mode importlib + """ + ) + result = pytester.runpytest_subprocess() + result.stdout.fnmatch_lines("*1 passed*") diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index c15a81ea1a3..3d574e85658 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -7,6 +7,7 @@ from types import ModuleType from typing import Any from typing import Generator +from typing import Iterator import pytest from _pytest.monkeypatch import MonkeyPatch @@ -282,29 +283,36 @@ def test_invalid_path(self, tmp_path: Path) -> None: import_path(tmp_path / "invalid.py", root=tmp_path) @pytest.fixture - def simple_module(self, tmp_path: Path) -> Path: - fn = tmp_path / "_src/tests/mymod.py" + def simple_module( + self, tmp_path: Path, request: pytest.FixtureRequest + ) -> Iterator[Path]: + name = f"mymod_{request.node.name}" + fn = tmp_path / f"_src/tests/{name}.py" fn.parent.mkdir(parents=True) fn.write_text("def foo(x): return 40 + x", encoding="utf-8") - return fn + module_name = module_name_from_path(fn, root=tmp_path) + yield fn + sys.modules.pop(module_name, None) - def test_importmode_importlib(self, simple_module: Path, tmp_path: Path) -> None: + def test_importmode_importlib( + self, simple_module: Path, tmp_path: Path, request: pytest.FixtureRequest + ) -> None: """`importlib` mode does not change sys.path.""" module = import_path(simple_module, mode="importlib", root=tmp_path) assert module.foo(2) == 42 # type: ignore[attr-defined] assert str(simple_module.parent) not in sys.path assert module.__name__ in sys.modules - assert module.__name__ == "_src.tests.mymod" + assert module.__name__ == f"_src.tests.mymod_{request.node.name}" assert "_src" in sys.modules assert "_src.tests" in sys.modules - def test_importmode_twice_is_different_module( + def test_remembers_previous_imports( self, simple_module: Path, tmp_path: Path ) -> None: - """`importlib` mode always returns a new module.""" + """`importlib` mode called remembers previous module (#10341, #10811).""" module1 = import_path(simple_module, mode="importlib", root=tmp_path) module2 = import_path(simple_module, mode="importlib", root=tmp_path) - assert module1 is not module2 + assert module1 is module2 def test_no_meta_path_found( self, simple_module: Path, monkeypatch: MonkeyPatch, tmp_path: Path @@ -317,6 +325,9 @@ def test_no_meta_path_found( # mode='importlib' fails if no spec is found to load the module import importlib.util + # Force module to be re-imported. + del sys.modules[module.__name__] + monkeypatch.setattr( importlib.util, "spec_from_file_location", lambda *args: None ) From 561f1a993bcef74b626a43ec16c79a57b6aa99d9 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Sat, 1 Jul 2023 22:08:21 +0200 Subject: [PATCH 0045/1271] fix #10447 - consider marks in reverse mro order to give base classes priority --- changelog/10447.bugfix.rst | 2 ++ src/_pytest/mark/structures.py | 4 +++- testing/test_mark.py | 37 +++++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 changelog/10447.bugfix.rst diff --git a/changelog/10447.bugfix.rst b/changelog/10447.bugfix.rst new file mode 100644 index 00000000000..fff94b28fb5 --- /dev/null +++ b/changelog/10447.bugfix.rst @@ -0,0 +1,2 @@ +markers are now considered in the reverse mro order to ensure base class markers are considered first +this resolves a regression. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index bc10d3b90ef..d6e426567a6 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -374,7 +374,9 @@ def get_unpacked_marks( if not consider_mro: mark_lists = [obj.__dict__.get("pytestmark", [])] else: - mark_lists = [x.__dict__.get("pytestmark", []) for x in obj.__mro__] + mark_lists = [ + x.__dict__.get("pytestmark", []) for x in reversed(obj.__mro__) + ] mark_list = [] for item in mark_lists: if isinstance(item, list): diff --git a/testing/test_mark.py b/testing/test_mark.py index e2d1a40c38a..2767260df8c 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1130,6 +1130,41 @@ class C(A, B): all_marks = get_unpacked_marks(C) - assert all_marks == [xfail("c").mark, xfail("a").mark, xfail("b").mark] + assert all_marks == [xfail("b").mark, xfail("a").mark, xfail("c").mark] assert get_unpacked_marks(C, consider_mro=False) == [xfail("c").mark] + + +# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/10447") +def test_mark_fixture_order_mro(pytester: Pytester): + """This ensures we walk marks of the mro starting with the base classes + the action at a distance fixtures are taken as minimal example from a real project + + """ + foo = pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def add_attr1(request): + request.instance.attr1 = object() + + + @pytest.fixture + def add_attr2(request): + request.instance.attr2 = request.instance.attr1 + + + @pytest.mark.usefixtures('add_attr1') + class Parent: + pass + + + @pytest.mark.usefixtures('add_attr2') + class TestThings(Parent): + def test_attrs(self): + assert self.attr1 == self.attr2 + """ + ) + result = pytester.runpytest(foo) + result.assert_outcomes(passed=1) From 024e62e6d2b7c19837b567dcc972cabaa0713f16 Mon Sep 17 00:00:00 2001 From: Akhilesh Ramakrishnan <31619526+akhilramkee@users.noreply.github.com> Date: Mon, 3 Jul 2023 17:19:50 +0530 Subject: [PATCH 0046/1271] Added Akhilesh Ramakrishnan to AUTHORS (#11153) * Added Akhilesh Ramakrishnan to AUTHORS PR#10338 * Fix typo in changelog --- AUTHORS | 1 + changelog/10337.bugfix.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 28116c3c834..13ea9469799 100644 --- a/AUTHORS +++ b/AUTHORS @@ -11,6 +11,7 @@ Adam Johnson Adam Stewart Adam Uhlir Ahn Ki-Wook +Akhilesh Ramakrishnan Akiomi Kamakura Alan Velasco Alessio Izzo diff --git a/changelog/10337.bugfix.rst b/changelog/10337.bugfix.rst index c5eeff19db0..629449e8db4 100644 --- a/changelog/10337.bugfix.rst +++ b/changelog/10337.bugfix.rst @@ -1,2 +1,2 @@ -Fixed but that fake intermediate modules generated by ``--import-mode=importlib`` would not include the +Fixed that fake intermediate modules generated by ``--import-mode=importlib`` would not include the child modules as attributes of the parent modules. From b84708422421a1237e0710e0468225d017feeb30 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 3 Jul 2023 11:45:17 -0300 Subject: [PATCH 0047/1271] [automated] Update plugin list (#11159) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 136 +++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 44 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index f4e7570da81..6c7eb6502ed 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -13,7 +13,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1272 plugins. +This list contains 1278 plugins. .. only:: not latex @@ -41,7 +41,7 @@ This list contains 1272 plugins. :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. May 23, 2023 N/A pytest (>=6.0) + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jun 27, 2023 N/A pytest (>=6.0) :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -112,7 +112,7 @@ This list contains 1272 plugins. :pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) :pypi:`pytest-bdd` BDD for pytest Nov 08, 2022 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) - :pypi:`pytest-bdd-ng` BDD for pytest Oct 06, 2022 4 - Beta pytest (>=5.0) + :pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0) :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A @@ -229,7 +229,7 @@ This list contains 1272 plugins. :pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A - :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jan 04, 2021 4 - Beta pytest (>=6.1.0) + :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0) @@ -242,7 +242,7 @@ This list contains 1272 plugins. :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest :pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A :pypi:`pytest-csv` CSV output for pytest. Apr 22, 2021 N/A pytest (>=6.0) - :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Aug 28, 2022 5 - Production/Stable pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Jul 01, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) :pypi:`pytest-curio` Pytest support for curio. Oct 07, 2020 N/A N/A :pypi:`pytest-curl-report` pytest plugin to generate curl command line report Dec 11, 2016 4 - Beta N/A :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A @@ -383,7 +383,7 @@ This list contains 1272 plugins. :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) - :pypi:`pytest-enabler` Enable installed pytest plugins May 12, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-enabler` Enable installed pytest plugins Jun 26, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A @@ -469,7 +469,7 @@ This list contains 1272 plugins. :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest - :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jul 12, 2022 4 - Beta pytest + :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jun 26, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest @@ -494,7 +494,7 @@ This list contains 1272 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jun 14, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jun 28, 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 Jun 22, 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 @@ -512,6 +512,7 @@ This list contains 1272 plugins. :pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest :pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A :pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A + :pypi:`pytest-group-by-class` A Pytest plugin for running a subset of your tests by splitting them in to groups of classes. Jun 27, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-growl` Growl notifications for pytest results. Jan 13, 2014 5 - Production/Stable N/A :pypi:`pytest-grpc` pytest plugin for grpc May 01, 2020 N/A pytest (>=3.6.0) :pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Feb 05, 2023 N/A N/A @@ -581,7 +582,7 @@ This list contains 1272 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. May 09, 2023 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Jun 29, 2023 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 02, 2023 5 - Production/Stable pytest (<7.2.0,>=6) :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A @@ -680,7 +681,7 @@ This list contains 1272 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. May 28, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) + :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Jun 25, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Jun 06, 2023 N/A pytest>=7.2 @@ -714,7 +715,7 @@ This list contains 1272 plugins. :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jun 07, 2021 5 - Production/Stable pytest :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A - :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Oct 22, 2022 5 - Production/Stable pytest + :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A :pypi:`pytest-moto` Fixtures for integration tests of AWS services,uses moto mocking library. Aug 28, 2015 1 - Planning N/A @@ -732,7 +733,7 @@ This list contains 1272 plugins. :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins May 05, 2023 4 - Beta pytest (>=6.2.0) + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jun 29, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) @@ -825,6 +826,7 @@ This list contains 1272 plugins. :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Apr 24, 2023 N/A pytest (<8.0.0,>=6.2.4) + :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jun 26, 2023 N/A N/A :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A @@ -842,6 +844,7 @@ This list contains 1272 plugins. :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest + :pypi:`pytest-porringer` Jun 24, 2023 N/A pytest>=7.1.2 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) @@ -851,7 +854,7 @@ This list contains 1272 plugins. :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A - :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Jun 16, 2023 5 - Production/Stable pytest>=7.3.2 + :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Jun 28, 2023 5 - Production/Stable pytest>=7.3.2 :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A @@ -890,7 +893,7 @@ This list contains 1272 plugins. :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 11, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) :pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0) - :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 09, 2023 5 - Production/Stable pytest (>=6.2.5) + :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 30, 2023 5 - Production/Stable pytest (>=6.2.5) :pypi:`pytest-qml` Run QML Tests with pytest Dec 02, 2020 4 - Beta pytest (>=6.0.0) :pypi:`pytest-qr` pytest plugin to generate test result QR codes Nov 25, 2021 4 - Beta N/A :pypi:`pytest-qt` pytest support for PyQt and PySide applications Oct 25, 2022 5 - Production/Stable pytest (>=3.0.0) @@ -943,7 +946,7 @@ This list contains 1272 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Jun 08, 2023 N/A pytest (>=3.8.0) + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Jun 30, 2023 N/A pytest (>=3.8.0) :pypi:`pytest-reports` An interesting python package Jun 07, 2023 N/A N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) @@ -1002,14 +1005,14 @@ This list contains 1272 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 24, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 30, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 24, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 30, 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 @@ -1049,6 +1052,7 @@ This list contains 1272 plugins. :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest + :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A @@ -1076,7 +1080,7 @@ This list contains 1272 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 Feb 22, 2023 N/A pytest (>5.4.0,<7.3) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jun 30, 2023 N/A pytest (>5.4.0,<8) :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 07, 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 @@ -1124,7 +1128,7 @@ This list contains 1272 plugins. :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Dec 10, 2020 5 - Production/Stable N/A - :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Mar 17, 2023 5 - Production/Stable N/A + :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) :pypi:`pytest-terra-fixt` Terraform and Terragrunt fixtures for pytest Sep 15, 2022 N/A pytest (==6.2.5) :pypi:`pytest-terraform` A pytest plugin for using terraform fixtures Jun 20, 2023 N/A pytest (>=6.0) @@ -1159,6 +1163,7 @@ This list contains 1272 plugins. :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) :pypi:`pytest-tesults` Tesults plugin for pytest Dec 23, 2022 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jun 27, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A @@ -1171,6 +1176,7 @@ This list contains 1272 plugins. :pypi:`pytest-timer` A timer plugin for pytest Jun 02, 2021 N/A N/A :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Apr 01, 2023 N/A pytest (>=5.2) + :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) :pypi:`pytest-tipsi-django` Nov 17, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Nov 04, 2020 4 - Beta pytest (>=3.3.0) :pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0) @@ -1219,7 +1225,7 @@ This list contains 1272 plugins. :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A - :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Jun 15, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Jun 30, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest @@ -1445,7 +1451,7 @@ This list contains 1272 plugins. :pypi:`pytest-alembic` - *last release*: May 23, 2023, + *last release*: Jun 27, 2023, *status*: N/A, *requires*: pytest (>=6.0) @@ -1942,7 +1948,7 @@ This list contains 1272 plugins. pytest plugin to display BDD info in HTML test report :pypi:`pytest-bdd-ng` - *last release*: Oct 06, 2022, + *last release*: Jul 01, 2023, *status*: 4 - Beta, *requires*: pytest (>=5.0) @@ -2761,9 +2767,9 @@ This list contains 1272 plugins. :pypi:`pytest-coverage-context` - *last release*: Jan 04, 2021, + *last release*: Jun 28, 2023, *status*: 4 - Beta, - *requires*: pytest (>=6.1.0) + *requires*: N/A Coverage dynamic context support for PyTest, including sub-processes @@ -2852,9 +2858,9 @@ This list contains 1272 plugins. CSV output for pytest. :pypi:`pytest-csv-params` - *last release*: Aug 28, 2022, + *last release*: Jul 01, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.1.2,<8.0.0) + *requires*: pytest (>=7.4.0,<8.0.0) Pytest plugin for Test Case Parametrization with CSV files @@ -3839,7 +3845,7 @@ This list contains 1272 plugins. Pytest plugin to represent test output with emoji support :pypi:`pytest-enabler` - *last release*: May 12, 2023, + *last release*: Jun 26, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6) ; extra == 'testing' @@ -4441,9 +4447,9 @@ This list contains 1272 plugins. :pypi:`pytest-fluent` - *last release*: Jul 12, 2022, + *last release*: Jun 26, 2023, *status*: 4 - Beta, - *requires*: pytest + *requires*: pytest (>=7.0.0) A pytest plugin in order to provide logs via fluentd @@ -4616,7 +4622,7 @@ This list contains 1272 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jun 14, 2023, + *last release*: Jun 28, 2023, *status*: N/A, *requires*: N/A @@ -4741,6 +4747,13 @@ This list contains 1272 plugins. Green progress dots + :pypi:`pytest-group-by-class` + *last release*: Jun 27, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest (>=2.5) + + A Pytest plugin for running a subset of your tests by splitting them in to groups of classes. + :pypi:`pytest-growl` *last release*: Jan 13, 2014, *status*: 5 - Production/Stable, @@ -5225,7 +5238,7 @@ This list contains 1272 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: May 09, 2023, + *last release*: Jun 29, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5918,7 +5931,7 @@ This list contains 1272 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: May 28, 2023, + *last release*: Jun 25, 2023, *status*: 4 - Beta, *requires*: pytest (!=6.0.0,<8,>=3.3.2) @@ -6156,7 +6169,7 @@ This list contains 1272 plugins. pytest plugin for MongoDB fixtures :pypi:`pytest-monitor` - *last release*: Oct 22, 2022, + *last release*: Jun 25, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -6282,9 +6295,9 @@ This list contains 1272 plugins. Mypy static type checker plugin for Pytest :pypi:`pytest-mypy-plugins` - *last release*: May 05, 2023, + *last release*: Jun 29, 2023, *status*: 4 - Beta, - *requires*: pytest (>=6.2.0) + *requires*: pytest (>=7.0.0) pytest plugin for writing tests for mypy plugins @@ -6932,6 +6945,13 @@ This list contains 1272 plugins. A pytest wrapper with fixtures for Playwright to automate web browsers + :pypi:`pytest-playwright-async` + *last release*: Jun 26, 2023, + *status*: N/A, + *requires*: N/A + + ASYNC Pytest plugin for Playwright + :pypi:`pytest-playwrights` *last release*: Dec 02, 2021, *status*: N/A, @@ -7051,6 +7071,13 @@ This list contains 1272 plugins. A pytest plugin to help with testing pop projects + :pypi:`pytest-porringer` + *last release*: Jun 24, 2023, + *status*: N/A, + *requires*: pytest>=7.1.2 + + + :pypi:`pytest-portion` *last release*: Jan 28, 2021, *status*: 4 - Beta, @@ -7115,7 +7142,7 @@ This list contains 1272 plugins. Minitest-style test colors :pypi:`pytest-print` - *last release*: Jun 16, 2023, + *last release*: Jun 28, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.3.2 @@ -7388,7 +7415,7 @@ This list contains 1272 plugins. Pytest plugin for uploading test results to your QA Touch Testrun. :pypi:`pytest-qgis` - *last release*: Jun 09, 2023, + *last release*: Jun 30, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6.2.5) @@ -7759,7 +7786,7 @@ This list contains 1272 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Jun 08, 2023, + *last release*: Jun 30, 2023, *status*: N/A, *requires*: pytest (>=3.8.0) @@ -8172,7 +8199,7 @@ This list contains 1272 plugins. :pypi:`pytest-sbase` - *last release*: Jun 24, 2023, + *last release*: Jun 30, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8221,7 +8248,7 @@ This list contains 1272 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Jun 24, 2023, + *last release*: Jun 30, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8500,6 +8527,13 @@ This list contains 1272 plugins. Send email with pytest execution result + :pypi:`pytest-smtp4dev` + *last release*: Jun 27, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + Plugin for smtp4dev API + :pypi:`pytest-smtpd` *last release*: May 15, 2023, *status*: N/A, @@ -8690,9 +8724,9 @@ This list contains 1272 plugins. :pypi:`pytest-splunk-addon` - *last release*: Feb 22, 2023, + *last release*: Jun 30, 2023, *status*: N/A, - *requires*: pytest (>5.4.0,<7.3) + *requires*: pytest (>5.4.0,<8) A Dynamic test tool for Splunk Apps and Add-ons @@ -9026,7 +9060,7 @@ This list contains 1272 plugins. Pytest to Telegram reporting plugin :pypi:`pytest-telegram-notifier` - *last release*: Mar 17, 2023, + *last release*: Jun 27, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9270,6 +9304,13 @@ This list contains 1272 plugins. Tesults plugin for pytest + :pypi:`pytest-textual-snapshot` + *last release*: Jun 27, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=7.0.0) + + Snapshot testing for Textual apps + :pypi:`pytest-tezos` *last release*: Jan 16, 2020, *status*: 4 - Beta, @@ -9354,6 +9395,13 @@ This list contains 1272 plugins. A simple plugin to view timestamps for each test + :pypi:`pytest-tinybird` + *last release*: Jun 26, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=3.8.0) + + A pytest plugin to report test results to tinybird + :pypi:`pytest-tipsi-django` *last release*: Nov 17, 2021, *status*: 4 - Beta, @@ -9691,7 +9739,7 @@ This list contains 1272 plugins. Set a test as unstable to return 0 even if it failed :pypi:`pytest-unused-fixtures` - *last release*: Jun 15, 2023, + *last release*: Jun 30, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.3.2,<8.0.0) From bea56b30af3dd7d682993b72d870c8ac7c864460 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 3 Jul 2023 17:52:58 +0200 Subject: [PATCH 0048/1271] Switch to deploy environment and configure for pypi oidc (#10925) Closes #10871 Closes #10870 --- .github/workflows/deploy.yml | 40 ++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 186adc55a4b..166d14a5477 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -13,40 +13,54 @@ on: permissions: {} jobs: - - deploy: - if: github.repository == 'pytest-dev/pytest' - + build: runs-on: ubuntu-latest - timeout-minutes: 30 - permissions: - contents: write - + timeout-minutes: 10 steps: - uses: actions/checkout@v3 with: fetch-depth: 0 persist-credentials: false - - name: Build and Check Package uses: hynek/build-and-inspect-python-package@v1.5 + deploy: + if: github.repository == 'pytest-dev/pytest' + needs: [build] + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + id-token: write + steps: - name: Download Package uses: actions/download-artifact@v3 with: name: Packages path: dist - - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - password: ${{ secrets.pypi_token }} + uses: pypa/gh-action-pypi-publish@v1.8.5 + + release-notes: + # todo: generate the content in the build job + # the goal being of using a github action script to push the release data + # after success instead of creating a complete python/tox env + needs: [deploy] + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + contents: write + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + persist-credentials: false - name: Set up Python uses: actions/setup-python@v4 with: python-version: "3.11" + - name: Install tox run: | python -m pip install --upgrade pip From 6995257cf470d2143ad1683824962de4071c0eb7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Jul 2023 07:00:14 +0000 Subject: [PATCH 0049/1271] [pre-commit.ci] pre-commit autoupdate (#11165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.7.0 → v3.8.0](https://github.com/asottile/pyupgrade/compare/v3.7.0...v3.8.0) - [github.com/asottile/setup-cfg-fmt: v2.3.0 → v2.4.0](https://github.com/asottile/setup-cfg-fmt/compare/v2.3.0...v2.4.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 94ec6740879..33816f0d0eb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,12 +42,12 @@ repos: - id: reorder-python-imports args: ['--application-directories=.:src', --py38-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.7.0 + rev: v3.8.0 hooks: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.3.0 + rev: v2.4.0 hooks: - id: setup-cfg-fmt args: ["--max-py-version=3.12", "--include-version-classifiers"] From 18e87c98319faee46f2becd32cf6518c9efaceaa Mon Sep 17 00:00:00 2001 From: Lesnek Date: Sun, 2 Jul 2023 14:15:50 +0200 Subject: [PATCH 0050/1271] test(warnings-recorder): Add non working subclass behaviour of pop --- testing/test_recwarn.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 16b8d54438f..b15ef2cc111 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -37,6 +37,26 @@ def test_recwarn_captures_deprecation_warning(recwarn: WarningsRecorder) -> None assert recwarn.pop(DeprecationWarning) +class TestSubclassWarningPop: + class ParentWarning(Warning): + pass + + class ChildWarning(ParentWarning): + pass + + def raise_warnings(self): + warnings.warn("Warning Child", self.ChildWarning) + warnings.warn("Warning Parent", self.ParentWarning) + + def test_pop(self): + with pytest.warns((self.ParentWarning, self.ChildWarning)) as record: + self.raise_warnings() + + assert len(record) == 2 + _warn = record.pop(self.ParentWarning) + assert _warn.category is self.ParentWarning + + class TestWarningsRecorderChecker: def test_recording(self) -> None: rec = WarningsRecorder(_ispytest=True) From 8ac3c645fa4a87afb30295d28e8d6fb67166bd01 Mon Sep 17 00:00:00 2001 From: Lesnek Date: Sun, 2 Jul 2023 14:17:06 +0200 Subject: [PATCH 0051/1271] fix(warnings-recorder): Match also subclass of warning in pop --- src/_pytest/recwarn.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index ff8e7082050..ba5a3311ca1 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -206,12 +206,18 @@ def __len__(self) -> int: return len(self._list) def pop(self, cls: Type[Warning] = Warning) -> "warnings.WarningMessage": - """Pop the first recorded warning, raise exception if not exists.""" + """Pop the first recorded warning (or subclass of warning), raise exception if not exists.""" + matches = [] for i, w in enumerate(self._list): - if issubclass(w.category, cls): + if w.category == cls: return self._list.pop(i) - __tracebackhide__ = True - raise AssertionError(f"{cls!r} not found in warning list") + if issubclass(w.category, cls): + matches.append((i, w)) + if not matches: + __tracebackhide__ = True + raise AssertionError(f"{cls!r} not found in warning list") + (idx, best), *rest = matches + return self._list.pop(idx) def clear(self) -> None: """Clear the list of recorded warnings.""" From 2706271f66ea1b8d3e931e6e945bb4dbbd758fea Mon Sep 17 00:00:00 2001 From: Lesnek Date: Sun, 2 Jul 2023 15:03:15 +0200 Subject: [PATCH 0052/1271] test(warnings-recorder): Add another warning --- testing/test_recwarn.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index b15ef2cc111..72dc34b09a5 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -44,7 +44,11 @@ class ParentWarning(Warning): class ChildWarning(ParentWarning): pass + class RandomWarning(Warning): + pass + def raise_warnings(self): + warnings.warn("Warning Random", self.RandomWarning) warnings.warn("Warning Child", self.ChildWarning) warnings.warn("Warning Parent", self.ParentWarning) From 7b7bd304aafcf9287eafc73bb332e4081f8fdf58 Mon Sep 17 00:00:00 2001 From: Lesnek Date: Sun, 2 Jul 2023 15:16:14 +0200 Subject: [PATCH 0053/1271] fix(warnings-recorder): Add handling of rest --- src/_pytest/recwarn.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index ba5a3311ca1..a60f346713d 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -217,6 +217,11 @@ def pop(self, cls: Type[Warning] = Warning) -> "warnings.WarningMessage": __tracebackhide__ = True raise AssertionError(f"{cls!r} not found in warning list") (idx, best), *rest = matches + for i, w in rest: + if issubclass(w.category, best.category) and not issubclass( + best.category, w.category + ): + idx, best = i, w return self._list.pop(idx) def clear(self) -> None: From 3d0dedb5ec7ac56c5f3e8bdbf5b47d7276096151 Mon Sep 17 00:00:00 2001 From: Lesnek Date: Sun, 2 Jul 2023 15:35:04 +0200 Subject: [PATCH 0054/1271] test(warnings-recorder): Add attribute error test --- testing/test_recwarn.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 72dc34b09a5..6c2dc4660b7 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -1,5 +1,7 @@ import warnings +from typing import List from typing import Optional +from typing import Type import pytest from _pytest.pytester import Pytester @@ -44,22 +46,37 @@ class ParentWarning(Warning): class ChildWarning(ParentWarning): pass - class RandomWarning(Warning): + class ChildOfChildWarning(ChildWarning): pass - def raise_warnings(self): - warnings.warn("Warning Random", self.RandomWarning) - warnings.warn("Warning Child", self.ChildWarning) - warnings.warn("Warning Parent", self.ParentWarning) + @staticmethod + def raise_warnings_from_list(_warnings: List[Type[Warning]]): + for warn in _warnings: + warnings.warn(f"Warning {warn().__repr__()}", warn) def test_pop(self): with pytest.warns((self.ParentWarning, self.ChildWarning)) as record: - self.raise_warnings() + self.raise_warnings_from_list( + [self.ChildWarning, self.ParentWarning, self.ChildOfChildWarning] + ) - assert len(record) == 2 + assert len(record) == 3 _warn = record.pop(self.ParentWarning) assert _warn.category is self.ParentWarning + def test_pop_raises(self): + with pytest.raises(AssertionError): + with pytest.warns(self.ParentWarning) as record: + self.raise_warnings_from_list([self.ParentWarning]) + record.pop(self.ChildOfChildWarning) + + def test_pop_most_recent(self): + with pytest.warns(self.ParentWarning) as record: + self.raise_warnings_from_list([self.ChildWarning, self.ChildOfChildWarning]) + + _warn = record.pop(self.ParentWarning) + assert _warn.category is self.ChildOfChildWarning + class TestWarningsRecorderChecker: def test_recording(self) -> None: From 4517af1e28083068cfe6d5d441f151dfd27a98b4 Mon Sep 17 00:00:00 2001 From: Lesnek Date: Sun, 2 Jul 2023 15:35:04 +0200 Subject: [PATCH 0055/1271] test(warnings-recorder): Add attribute error test --- AUTHORS | 1 + changelog/10701.bugfix.rst | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog/10701.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 13ea9469799..062f565c9ce 100644 --- a/AUTHORS +++ b/AUTHORS @@ -263,6 +263,7 @@ Mickey Pashov Mihai Capotă Mike Hoyle (hoylemd) Mike Lundy +Milan Lesnek Miro Hrončok Nathaniel Compton Nathaniel Waisbrot diff --git a/changelog/10701.bugfix.rst b/changelog/10701.bugfix.rst new file mode 100644 index 00000000000..d02ddacab8c --- /dev/null +++ b/changelog/10701.bugfix.rst @@ -0,0 +1 @@ +``pytest.WarningsRecorder.pop`` now also pop most recent subclass of warning. From 6badb6f01e355633eda251d037b48e39a4ed89dc Mon Sep 17 00:00:00 2001 From: Milan Lesnek Date: Tue, 4 Jul 2023 08:59:58 +0200 Subject: [PATCH 0056/1271] Apply suggestions from code review chore(changelog): describe better the fix Co-authored-by: Zac Hatfield-Dodds --- changelog/10701.bugfix.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/changelog/10701.bugfix.rst b/changelog/10701.bugfix.rst index d02ddacab8c..f33fa7fb28b 100644 --- a/changelog/10701.bugfix.rst +++ b/changelog/10701.bugfix.rst @@ -1 +1,2 @@ -``pytest.WarningsRecorder.pop`` now also pop most recent subclass of warning. +:meth:`pytest.WarningsRecorder.pop` will return the most-closely-matched warning in the list, +rather than the first warning which is an instance of the requested type. From c4876c710628b8bd244ae255aef529c369f8dd63 Mon Sep 17 00:00:00 2001 From: Lesnek Date: Tue, 4 Jul 2023 10:20:50 +0200 Subject: [PATCH 0057/1271] chore(CR): Add changes from code review --- pyproject.toml | 2 +- src/_pytest/recwarn.py | 31 +++++++++++++++++-------------- testing/test_recwarn.py | 6 ++++-- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a4139a5c051..8432d5d2bbd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta" write_to = "src/_pytest/_version.py" [tool.pytest.ini_options] -minversion = "2.0" +#minversion = "2.0" addopts = "-rfEX -p pytester --strict-markers" python_files = ["test_*.py", "*_test.py", "testing/python/*.py"] python_classes = ["Test", "Acceptance"] diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index a60f346713d..9d8816556e4 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -206,23 +206,26 @@ def __len__(self) -> int: return len(self._list) def pop(self, cls: Type[Warning] = Warning) -> "warnings.WarningMessage": - """Pop the first recorded warning (or subclass of warning), raise exception if not exists.""" - matches = [] + """Pop the first recorded warning which is an instance of ``cls``. + + But not an instance of a child class of any other match. + Raises ``AssertionError`` if there is no match. + + """ + + best_idx = None for i, w in enumerate(self._list): if w.category == cls: - return self._list.pop(i) - if issubclass(w.category, cls): - matches.append((i, w)) - if not matches: - __tracebackhide__ = True - raise AssertionError(f"{cls!r} not found in warning list") - (idx, best), *rest = matches - for i, w in rest: - if issubclass(w.category, best.category) and not issubclass( - best.category, w.category + return self._list.pop(i) # exact match, stop looking + if issubclass(w.category, cls) and ( + best_idx is None + or not issubclass(w.category, self._list[best_idx].category) # type: ignore[unreachable] ): - idx, best = i, w - return self._list.pop(idx) + best_idx = i + if best_idx is not None: + return self._list.pop(best_idx) + __tracebackhide__ = True + raise AssertionError(f"{cls!r} not found in warning list") def clear(self) -> None: """Clear the list of recorded warnings.""" diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 6c2dc4660b7..3a35c255eaf 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -72,10 +72,12 @@ def test_pop_raises(self): def test_pop_most_recent(self): with pytest.warns(self.ParentWarning) as record: - self.raise_warnings_from_list([self.ChildWarning, self.ChildOfChildWarning]) + self.raise_warnings_from_list( + [self.ChildOfChildWarning, self.ChildWarning, self.ChildOfChildWarning] + ) _warn = record.pop(self.ParentWarning) - assert _warn.category is self.ChildOfChildWarning + assert _warn.category is self.ChildWarning class TestWarningsRecorderChecker: From 6baf9f2d31ce0a7f65a52efbd42038b407a79e9c Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Tue, 4 Jul 2023 17:20:51 +0300 Subject: [PATCH 0058/1271] Update docs and code after dropping EOL 3.7 --- doc/en/index.rst | 2 +- pyproject.toml | 2 +- testing/_py/test_local.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 23b6964c9e8..90b720ea5b9 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -18,7 +18,7 @@ The ``pytest`` framework makes it easy to write small, readable tests, and can scale to support complex functional testing for applications and libraries. -``pytest`` requires: Python 3.7+ or PyPy3. +``pytest`` requires: Python 3.8+ or PyPy3. **PyPI package name**: :pypi:`pytest` diff --git a/pyproject.toml b/pyproject.toml index a4139a5c051..d540773c374 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -113,7 +113,7 @@ template = "changelog/_template.rst" showcontent = true [tool.black] -target-version = ['py37'] +target-version = ['py38'] # check-wheel-contents is executed by the build-and-inspect-python-package action. [tool.check-wheel-contents] diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 348682b5396..895066a9f90 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -1519,9 +1519,9 @@ def test_chown_identity_rec_mayfail(self, path1): path1.chown(owner, group) -class TestUnicodePy2Py3: +class TestUnicode: def test_join_ensure(self, tmpdir, monkeypatch): - if sys.version_info >= (3, 0) and "LANG" not in os.environ: + if "LANG" not in os.environ: pytest.skip("cannot run test without locale") x = local(tmpdir.strpath) part = "hällo" @@ -1529,7 +1529,7 @@ def test_join_ensure(self, tmpdir, monkeypatch): assert x.join(part) == y def test_listdir(self, tmpdir): - if sys.version_info >= (3, 0) and "LANG" not in os.environ: + if "LANG" not in os.environ: pytest.skip("cannot run test without locale") x = local(tmpdir.strpath) part = "hällo" From 1f5058e9722ed59a857d3d568e2560ae0ec96059 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Tue, 4 Jul 2023 17:22:05 +0300 Subject: [PATCH 0059/1271] Use same Black version for blacken-docs as regular Black check --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 33816f0d0eb..d85abe263ec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: rev: 1.14.0 hooks: - id: blacken-docs - additional_dependencies: [black==23.1.0] + additional_dependencies: [black==23.3.0] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: From 7775e494b155176b2c7083bce1e25b236401b638 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Tue, 4 Jul 2023 10:00:29 -0700 Subject: [PATCH 0060/1271] Further tweaks from code review --- pyproject.toml | 2 +- src/_pytest/recwarn.py | 11 ++++------- testing/test_recwarn.py | 6 +++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8432d5d2bbd..a4139a5c051 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta" write_to = "src/_pytest/_version.py" [tool.pytest.ini_options] -#minversion = "2.0" +minversion = "2.0" addopts = "-rfEX -p pytester --strict-markers" python_files = ["test_*.py", "*_test.py", "testing/python/*.py"] python_classes = ["Test", "Acceptance"] diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 9d8816556e4..5484d6f3b33 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -206,20 +206,17 @@ def __len__(self) -> int: return len(self._list) def pop(self, cls: Type[Warning] = Warning) -> "warnings.WarningMessage": - """Pop the first recorded warning which is an instance of ``cls``. - - But not an instance of a child class of any other match. + """Pop the first recorded warning which is an instance of ``cls``, + but not an instance of a child class of any other match. Raises ``AssertionError`` if there is no match. - """ - - best_idx = None + best_idx: Optional[int] = None for i, w in enumerate(self._list): if w.category == cls: return self._list.pop(i) # exact match, stop looking if issubclass(w.category, cls) and ( best_idx is None - or not issubclass(w.category, self._list[best_idx].category) # type: ignore[unreachable] + or not issubclass(w.category, self._list[best_idx].category) ): best_idx = i if best_idx is not None: diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 3a35c255eaf..8b70c8afffa 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -54,7 +54,7 @@ def raise_warnings_from_list(_warnings: List[Type[Warning]]): for warn in _warnings: warnings.warn(f"Warning {warn().__repr__()}", warn) - def test_pop(self): + def test_pop_finds_exact_match(self): with pytest.warns((self.ParentWarning, self.ChildWarning)) as record: self.raise_warnings_from_list( [self.ChildWarning, self.ParentWarning, self.ChildOfChildWarning] @@ -64,13 +64,13 @@ def test_pop(self): _warn = record.pop(self.ParentWarning) assert _warn.category is self.ParentWarning - def test_pop_raises(self): + def test_pop_raises_if_no_match(self): with pytest.raises(AssertionError): with pytest.warns(self.ParentWarning) as record: self.raise_warnings_from_list([self.ParentWarning]) record.pop(self.ChildOfChildWarning) - def test_pop_most_recent(self): + def test_pop_finds_best_inexact_match(self): with pytest.warns(self.ParentWarning) as record: self.raise_warnings_from_list( [self.ChildOfChildWarning, self.ChildWarning, self.ChildOfChildWarning] From b5bc53e441bd52fdb1948739eb0420db3ad6a7ec Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 4 Jul 2023 23:19:24 +0200 Subject: [PATCH 0061/1271] Update open trainings (#11171) --- doc/en/index.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 23b6964c9e8..a2745e98d29 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,8 +2,9 @@ .. sidebar:: Next Open Trainings - - `pytest tips and tricks for a better testsuite `_, at `Europython 2023 `_, July 18th (3h), Prague/Remote - - `Professional Testing with Python `_, via `Python Academy `_, March 5th to 7th 2024 (3 day in-depth training), Leipzig/Remote + - `pytest tips and tricks for a better testsuite `_, at `Europython 2023 `_, **July 18th** (3h), **Prague, Czech Republic / Remote** + - `pytest: Professionelles Testen (nicht nur) für Python `_, at `Workshoptage 2023 `_, **September 5th**, `OST `_ Campus **Rapperswil, Switzerland** + - `Professional Testing with Python `_, via `Python Academy `_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote** Also see :doc:`previous talks and blogposts `. From 119cec02792766e01fe6ad725526679e9bdc69a4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 5 Jul 2023 18:57:40 +0300 Subject: [PATCH 0062/1271] tox: turn off PYTHONWARNDEFAULTENCODING for pre-commit, sphinx etc. Fix #11157. --- tox.ini | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tox.ini b/tox.ini index 9cdbfe3ab81..1b62b98e499 100644 --- a/tox.ini +++ b/tox.ini @@ -74,6 +74,9 @@ skip_install = True basepython = python3 deps = pre-commit>=2.9.3 commands = pre-commit run --all-files --show-diff-on-failure {posargs:} +setenv = + # pre-commit and tools it launches are not clean of this warning. + PYTHONWARNDEFAULTENCODING= [testenv:docs] basepython = python3 @@ -88,6 +91,9 @@ commands = # changelog in the docs; this does not happen on ReadTheDocs because it uses # the standard sphinx command so the 'changelog_towncrier_draft' is never set there sphinx-build -W --keep-going -b html doc/en doc/en/_build/html -t changelog_towncrier_draft {posargs:} +setenv = + # Sphinx is not clean of this warning. + PYTHONWARNDEFAULTENCODING= [testenv:docs-checklinks] basepython = python3 @@ -96,6 +102,9 @@ changedir = doc/en deps = -r{toxinidir}/doc/en/requirements.txt commands = sphinx-build -W -q --keep-going -b linkcheck . _build +setenv = + # Sphinx is not clean of this warning. + PYTHONWARNDEFAULTENCODING= [testenv:regen] changedir = doc/en @@ -110,6 +119,9 @@ allowlist_externals = make commands = make regen +setenv = + # We don't want this warning to reach regen output. + PYTHONWARNDEFAULTENCODING= [testenv:plugins] # use latest versions of all plugins, including pre-releases From 44604f49cdd370682b08e6820a70aab93ce80f8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jul 2023 22:57:45 +0000 Subject: [PATCH 0063/1271] build(deps): Bump django in /testing/plugins_integration Bumps [django](https://github.com/django/django) from 4.2.2 to 4.2.3. - [Commits](https://github.com/django/django/compare/4.2.2...4.2.3) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d56720c0282..efdf837cef8 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==3.7.0 -django==4.2.2 +django==4.2.3 pytest-asyncio==0.21.0 pytest-bdd==6.1.1 pytest-cov==4.1.0 From ddd773ecb1d7631df86de9a09327c7eb003dd627 Mon Sep 17 00:00:00 2001 From: mickeypash Date: Wed, 31 Mar 2021 11:54:33 +0100 Subject: [PATCH 0064/1271] [docs] add table nose x pytest naming comparison --- doc/en/how-to/nose.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/doc/en/how-to/nose.rst b/doc/en/how-to/nose.rst index a736dfa55a7..9ef56c6d799 100644 --- a/doc/en/how-to/nose.rst +++ b/doc/en/how-to/nose.rst @@ -70,6 +70,34 @@ Unsupported idioms / known issues fundamentally incompatible with pytest because they don't support fixtures properly since collection and test execution are separated. +Here is a table comparing the default supported naming conventions for both +nose and pytest. + +========================== ======== ====== +Convention nose pytest +========================== ======== ====== +Ⓜ test*.py ✅ +Ⓜ test_*.py ✅ ✅ +Ⓜ \*_test.py ✅ +Ⓜ \*_tests.py +Ⓒ \*\(unittest.TestCase\) ✅ ✅ +ⓜ test_\* ✅ ✅ +Ⓒ Test\* ✅ +ⓜ test_\* ✅ +ⓕ test_\* ✅ +========================== ======== ====== + +Symbols are described below + +======= ========= +Legend +======= ========= +Ⓜ module +Ⓒ Class +ⓜ method +ⓕ function +======= ========= + Migrating from nose to pytest ------------------------------ From b81003f6fbc4fe540f4e6c2c5ef13c4d52a49964 Mon Sep 17 00:00:00 2001 From: Zac Hatfield-Dodds Date: Thu, 6 Jul 2023 00:04:15 -0700 Subject: [PATCH 0065/1271] Incorporate legend into main table --- doc/en/how-to/nose.rst | 45 ++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/doc/en/how-to/nose.rst b/doc/en/how-to/nose.rst index 9ef56c6d799..45d3357cf39 100644 --- a/doc/en/how-to/nose.rst +++ b/doc/en/how-to/nose.rst @@ -47,8 +47,7 @@ Unsupported idioms / known issues - nose imports test modules with the same import path (e.g. ``tests.test_mode``) but different file system paths (e.g. ``tests/test_mode.py`` and ``other/tests/test_mode.py``) - by extending sys.path/import semantics. pytest does not do that - but there is discussion in :issue:`268` for adding some support. Note that + by extending sys.path/import semantics. pytest does not do that. Note that `nose2 choose to avoid this sys.path/import hackery `_. If you place a conftest.py file in the root directory of your project @@ -66,44 +65,34 @@ Unsupported idioms / known issues - no nose-configuration is recognized. -- ``yield``-based methods are unsupported as of pytest 4.1.0. They are +- ``yield``-based methods are fundamentally incompatible with pytest because they don't support fixtures properly since collection and test execution are separated. Here is a table comparing the default supported naming conventions for both nose and pytest. -========================== ======== ====== -Convention nose pytest -========================== ======== ====== -Ⓜ test*.py ✅ -Ⓜ test_*.py ✅ ✅ -Ⓜ \*_test.py ✅ -Ⓜ \*_tests.py -Ⓒ \*\(unittest.TestCase\) ✅ ✅ -ⓜ test_\* ✅ ✅ -Ⓒ Test\* ✅ -ⓜ test_\* ✅ -ⓕ test_\* ✅ -========================== ======== ====== - -Symbols are described below - -======= ========= -Legend -======= ========= -Ⓜ module -Ⓒ Class -ⓜ method -ⓕ function -======= ========= +========= ========================== ======= ===== +what default naming convention pytest nose +========= ========================== ======= ===== +module ``test*.py`` ✅ +module ``test_*.py`` ✅ ✅ +module ``*_test.py`` ✅ +module ``*_tests.py`` +class ``*(unittest.TestCase)`` ✅ ✅ +method ``test_*`` ✅ ✅ +class ``Test*`` ✅ +method ``test_*`` ✅ +function ``test_*`` ✅ +========= ========================== ======= ===== + Migrating from nose to pytest ------------------------------ `nose2pytest `_ is a Python script and pytest plugin to help convert Nose-based tests into pytest-based tests. -Specifically, the script transforms nose.tools.assert_* function calls into +Specifically, the script transforms ``nose.tools.assert_*`` function calls into raw assert statements, while preserving format of original arguments as much as possible. From c5b13099e6e121e6e9991855136371dbad53fbad Mon Sep 17 00:00:00 2001 From: Kenny Y <24802984+kenny-y-dev@users.noreply.github.com> Date: Fri, 7 Jul 2023 14:42:59 -0400 Subject: [PATCH 0066/1271] Fix error assertion handling in approx when None in dict comparison Dict comparsion in the ApproxMapping class did not check if values were None before attempting to subtract for max_abs_diff stat, which was throwing an TypeError instead of being handled by pytest error assertion. Check for None has been added before these calculations, so that None will properly show as Obtained/Expected in pytest assert message --- changelog/10702.bugfix.rst | 1 + src/_pytest/python_api.py | 25 +++++++++++++------------ testing/python/approx.py | 17 +++++++++++++++++ 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 changelog/10702.bugfix.rst diff --git a/changelog/10702.bugfix.rst b/changelog/10702.bugfix.rst new file mode 100644 index 00000000000..4008cc882ec --- /dev/null +++ b/changelog/10702.bugfix.rst @@ -0,0 +1 @@ +Fixed error assertion handling in :func:`pytest.approx` when ``None`` is an expected or received value when comparing dictionaries. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 0967ae8ece6..35560f16860 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -265,19 +265,20 @@ def _repr_compare(self, other_side: Mapping[object, float]) -> List[str]: approx_side_as_map.items(), other_side.values() ): if approx_value != other_value: - max_abs_diff = max( - max_abs_diff, abs(approx_value.expected - other_value) - ) - if approx_value.expected == 0.0: - max_rel_diff = math.inf - else: - max_rel_diff = max( - max_rel_diff, - abs( - (approx_value.expected - other_value) - / approx_value.expected - ), + if not any((approx_value.expected is None, other_value is None)): + max_abs_diff = max( + max_abs_diff, abs(approx_value.expected - other_value) ) + if approx_value.expected == 0.0: + max_rel_diff = math.inf + else: + max_rel_diff = max( + max_rel_diff, + abs( + (approx_value.expected - other_value) + / approx_value.expected + ), + ) different_ids.append(approx_key) message_data = [ diff --git a/testing/python/approx.py b/testing/python/approx.py index 631e52b56ac..6ad411a3e07 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -122,6 +122,23 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): ], ) + assert_approx_raises_regex( + {"a": 1.0, "b": None, "c": None}, + { + "a": None, + "b": 1000.0, + "c": None, + }, + [ + r" comparison failed. Mismatched elements: 2 / 3:", + r" Max absolute difference: -inf", + r" Max relative difference: -inf", + r" Index \| Obtained\s+\| Expected\s+", + rf" a \| {SOME_FLOAT} \| None", + rf" b \| None\s+\| {SOME_FLOAT} ± {SOME_FLOAT}", + ], + ) + assert_approx_raises_regex( [1.0, 2.0, 3.0, 4.0], [1.0, 3.0, 3.0, 5.0], From d4265448a58434f624c8d1817a7173a168b0f300 Mon Sep 17 00:00:00 2001 From: Kenny Y <24802984+kenny-y-dev@users.noreply.github.com> Date: Sat, 8 Jul 2023 08:41:42 -0400 Subject: [PATCH 0067/1271] Update src/_pytest/python_api.py Co-authored-by: Bruno Oliveira --- src/_pytest/python_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 35560f16860..200b2b3aab6 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -265,7 +265,7 @@ def _repr_compare(self, other_side: Mapping[object, float]) -> List[str]: approx_side_as_map.items(), other_side.values() ): if approx_value != other_value: - if not any((approx_value.expected is None, other_value is None)): + if approx_value.expected is not None and other_value is not None: max_abs_diff = max( max_abs_diff, abs(approx_value.expected - other_value) ) From b73ec8e5d117a244b696ff4f9d2dfb74df078b2f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 8 Jul 2023 21:40:05 +0300 Subject: [PATCH 0068/1271] doc: fix EncodingWarnings in examples (#11158) Otherwise the warnings show in the regen output. --- doc/en/example/nonpython/conftest.py | 2 +- doc/en/example/simple.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/tmp_path.rst | 4 ++-- doc/en/how-to/unittest.rst | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/en/example/nonpython/conftest.py b/doc/en/example/nonpython/conftest.py index dd1ebe88d7e..e969e3e2518 100644 --- a/doc/en/example/nonpython/conftest.py +++ b/doc/en/example/nonpython/conftest.py @@ -12,7 +12,7 @@ def collect(self): # We need a yaml parser, e.g. PyYAML. import yaml - raw = yaml.safe_load(self.path.open()) + raw = yaml.safe_load(self.path.open(encoding="utf-8")) for name, spec in sorted(raw.items()): yield YamlItem.from_parent(self, name=name, spec=spec) diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 97a6dd9f436..32e5188b741 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -817,7 +817,7 @@ case we just write some information out to a ``failures`` file: # we only look at actual failing test calls, not setup/teardown if rep.when == "call" and rep.failed: mode = "a" if os.path.exists("failures") else "w" - with open("failures", mode) as f: + with open("failures", mode, encoding="utf-8") as f: # let's also access a fixture for the fun of it if "tmp_path" in item.fixturenames: extra = " ({})".format(item.funcargs["tmp_path"]) diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index c6047af1231..b2fb24b3fbe 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1698,7 +1698,7 @@ and declare its use in a test module via a ``usefixtures`` marker: class TestDirectoryInit: def test_cwd_starts_empty(self): assert os.listdir(os.getcwd()) == [] - with open("myfile", "w") as f: + with open("myfile", "w", encoding="utf-8") as f: f.write("hello") def test_cwd_again_starts_empty(self): diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index 792933dd87e..d5573f5847d 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -24,8 +24,8 @@ created in the `base temporary directory`_. d = tmp_path / "sub" d.mkdir() p = d / "hello.txt" - p.write_text(CONTENT) - assert p.read_text() == CONTENT + p.write_text(CONTENT, encoding="utf-8") + assert p.read_text(encoding="utf-8") == CONTENT assert len(list(tmp_path.iterdir())) == 1 assert 0 diff --git a/doc/en/how-to/unittest.rst b/doc/en/how-to/unittest.rst index 37caf6e9fb7..7856c1a49c0 100644 --- a/doc/en/how-to/unittest.rst +++ b/doc/en/how-to/unittest.rst @@ -207,10 +207,10 @@ creation of a per-test temporary directory: @pytest.fixture(autouse=True) def initdir(self, tmp_path, monkeypatch): monkeypatch.chdir(tmp_path) # change to pytest-provided temporary directory - tmp_path.joinpath("samplefile.ini").write_text("# testdata") + tmp_path.joinpath("samplefile.ini").write_text("# testdata", encoding="utf-8") def test_method(self): - with open("samplefile.ini") as f: + with open("samplefile.ini", encoding="utf-8") as f: s = f.read() assert "testdata" in s From a3b4220d762ac2afd72577a7cbd4a0a006f89830 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 9 Jul 2023 00:29:15 +0000 Subject: [PATCH 0069/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 144 +++++++++++++++++++------------ 1 file changed, 88 insertions(+), 56 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6c7eb6502ed..f15bc4be59e 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -13,7 +13,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1278 plugins. +This list contains 1282 plugins. .. only:: not latex @@ -41,7 +41,7 @@ This list contains 1278 plugins. :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jun 27, 2023 N/A pytest (>=6.0) + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 06, 2023 N/A pytest (>=6.0) :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -85,6 +85,7 @@ This list contains 1278 plugins. :pypi:`pytest-astropy` Meta-package containing dependencies for testing Apr 12, 2022 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-astropy-header` pytest plugin to add diagnostic information to the header of the test output Sep 06, 2022 3 - Alpha pytest (>=4.6) :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest + :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Mar 19, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. May 31, 2023 N/A N/A :pypi:`pytest-asyncio-network-simulator` pytest-asyncio-network-simulator: Plugin for pytest for simulator the network in tests Jul 31, 2018 3 - Alpha pytest (<3.7.0,>=3.3.2) @@ -118,7 +119,7 @@ This list contains 1278 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A - :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jun 09, 2023 4 - Beta N/A + :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A @@ -206,7 +207,7 @@ This list contains 1278 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Dec 02, 2022 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jul 04, 2023 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A :pypi:`pytest-collector` Python package for collecting pytest. Aug 02, 2022 N/A pytest (>=7.0,<8.0) @@ -346,6 +347,7 @@ This list contains 1278 plugins. :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Jun 08, 2023 3 - Alpha pytest (>=4.6) + :pypi:`pytest-dogu-report` pytest plugin for dogu report Jul 07, 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-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) @@ -373,13 +375,13 @@ This list contains 1278 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. Jun 14, 2023 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jun 14, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jun 14, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jun 14, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jun 14, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jun 14, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jun 14, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jul 05, 2023 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jul 05, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jul 05, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jul 05, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jul 05, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jul 05, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jul 05, 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) @@ -528,7 +530,7 @@ This list contains 1278 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 24, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 07, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -571,7 +573,7 @@ This list contains 1278 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-inline` A pytest plugin for writing inline tests. Feb 08, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Feb 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 12, 2023 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 04, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules May 17, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Jun 16, 2022 4 - Beta N/A :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A @@ -739,7 +741,7 @@ This list contains 1278 plugins. :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jun 19, 2023 N/A pytest (>=3.5.0) + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jul 06, 2023 N/A pytest (>=3.5.0) :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -763,7 +765,7 @@ This list contains 1278 plugins. :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A - :pypi:`pytest-odoo` py.test plugin to run Odoo tests Nov 17, 2022 4 - Beta pytest (>=7.2.0) + :pypi:`pytest-odoo` py.test plugin to run Odoo tests Jul 06, 2023 4 - Beta pytest (>=7.2.0) :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) @@ -809,7 +811,7 @@ This list contains 1278 plugins. :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) :pypi:`pytest-perf` Run performance tests against the mainline code. Jun 02, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) - :pypi:`pytest-persistence` Pytest tool for persistent objects Jun 14, 2023 N/A N/A + :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) @@ -826,7 +828,7 @@ This list contains 1278 plugins. :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Apr 24, 2023 N/A pytest (<8.0.0,>=6.2.4) - :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jun 26, 2023 N/A N/A + :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A @@ -882,7 +884,7 @@ This list contains 1278 plugins. :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Dec 13, 2022 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report May 08, 2023 N/A pytest (>=7.3.1) + :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Jul 02, 2023 N/A pytest (>=7.3.1) :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Nov 20, 2022 4 - Beta pytest (>=7.0.0) :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Mar 12, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. May 07, 2023 N/A pytest (>=3.5.0) @@ -900,7 +902,7 @@ This list contains 1278 plugins. :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) - :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Jun 16, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Jul 05, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-race` Race conditions tester for pytest Jun 07, 2022 4 - Beta N/A :pypi:`pytest-rage` pytest plugin to implement PEP712 Oct 21, 2011 3 - Alpha N/A :pypi:`pytest-rail` pytest plugin for creating TestRail runs and adding results May 02, 2022 N/A pytest (>=3.6) @@ -932,7 +934,7 @@ This list contains 1278 plugins. :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Dec 12, 2022 3 - Alpha pytest (>=4.6) :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) - :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Mar 04, 2020 4 - Beta pytest + :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 31, 2020 5 - Production/Stable pytest (>=3.6) :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jun 09, 2021 4 - Beta pytest (>=3.0.0) @@ -955,7 +957,7 @@ This list contains 1278 plugins. :pypi:`pytest-requires` A pytest plugin to elegantly skip tests with optional requirements Dec 21, 2021 4 - Beta pytest (>=3.5.0) :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-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 09, 2023 5 - Production/Stable pytest (>=5.3) + :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-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Apr 26, 2023 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jun 01, 2023 N/A pytest (~=4.6) ; python_version == "2.7" @@ -1005,14 +1007,14 @@ This list contains 1278 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 30, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 08, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 30, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 08, 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 @@ -1031,7 +1033,7 @@ This list contains 1278 plugins. :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A - :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Sep 23, 2022 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Jul 02, 2023 5 - Production/Stable pytest (>=7.1.0) :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Jan 16, 2023 5 - Production/Stable pytest (>=3.5.1) :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) @@ -1113,6 +1115,7 @@ This list contains 1278 plugins. :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Aug 29, 2017 N/A N/A :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Apr 10, 2023 4 - Beta pytest (>=6.2.0) :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A + :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) @@ -1167,6 +1170,7 @@ This list contains 1278 plugins. :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A + :pypi:`pytest-thread` Jul 07, 2023 N/A N/A :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest @@ -1273,7 +1277,7 @@ This list contains 1278 plugins. :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Mar 01, 2023 N/A pytest>=7.2.0 + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jul 03, 2023 N/A pytest<8,>=7.4.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Jan 05, 2023 4 - Beta pytest (>=2.8) :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A @@ -1283,7 +1287,7 @@ This list contains 1278 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. Jun 18, 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 May 28, 2023 N/A pytest>=7.2.0 + :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Jul 03, 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) @@ -1451,7 +1455,7 @@ This list contains 1278 plugins. :pypi:`pytest-alembic` - *last release*: Jun 27, 2023, + *last release*: Jul 06, 2023, *status*: N/A, *requires*: pytest (>=6.0) @@ -1758,6 +1762,13 @@ This list contains 1278 plugins. + :pypi:`pytest-async-generators` + *last release*: Jul 05, 2023, + *status*: N/A, + *requires*: N/A + + Pytest fixtures for async generators + :pypi:`pytest-asyncio` *last release*: Mar 19, 2023, *status*: 4 - Beta, @@ -1990,7 +2001,7 @@ This list contains 1278 plugins. Fixtures for testing Google Appengine (GAE) apps :pypi:`pytest-beeprint` - *last release*: Jun 09, 2023, + *last release*: Jul 04, 2023, *status*: 4 - Beta, *requires*: N/A @@ -2606,7 +2617,7 @@ This list contains 1278 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Dec 02, 2022, + *last release*: Jul 04, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3585,6 +3596,13 @@ This list contains 1278 plugins. Pytest plugin with advanced doctest features. + :pypi:`pytest-dogu-report` + *last release*: Jul 07, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin for dogu report + :pypi:`pytest-dolphin` *last release*: Nov 30, 2016, *status*: 4 - Beta, @@ -3775,49 +3793,49 @@ This list contains 1278 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jun 14, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jun 14, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jun 14, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jun 14, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jun 14, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jun 14, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jun 14, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4860,7 +4878,7 @@ This list contains 1278 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 24, 2023, + *last release*: Jul 07, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.3.1) @@ -5161,7 +5179,7 @@ This list contains 1278 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Apr 12, 2023, + *last release*: Jul 04, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -6337,7 +6355,7 @@ This list contains 1278 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-netdut` - *last release*: Jun 19, 2023, + *last release*: Jul 06, 2023, *status*: N/A, *requires*: pytest (>=3.5.0) @@ -6505,7 +6523,7 @@ This list contains 1278 plugins. pytest results data-base and HTML reporter :pypi:`pytest-odoo` - *last release*: Nov 17, 2022, + *last release*: Jul 06, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.2.0) @@ -6827,7 +6845,7 @@ This list contains 1278 plugins. A simple plugin to ensure the execution of critical sections of code has not been impacted :pypi:`pytest-persistence` - *last release*: Jun 14, 2023, + *last release*: Jul 04, 2023, *status*: N/A, *requires*: N/A @@ -6946,7 +6964,7 @@ This list contains 1278 plugins. A pytest wrapper with fixtures for Playwright to automate web browsers :pypi:`pytest-playwright-async` - *last release*: Jun 26, 2023, + *last release*: Jul 03, 2023, *status*: N/A, *requires*: N/A @@ -7338,7 +7356,7 @@ This list contains 1278 plugins. Pyramid server fixture for py.test :pypi:`pytest-pyreport` - *last release*: May 08, 2023, + *last release*: Jul 02, 2023, *status*: N/A, *requires*: pytest (>=7.3.1) @@ -7464,7 +7482,7 @@ This list contains 1278 plugins. pytest plugin to generate random data inspired by QuickCheck :pypi:`pytest-rabbitmq` - *last release*: Jun 16, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6.2) @@ -7688,7 +7706,7 @@ This list contains 1278 plugins. Pytest plugin for capturing and mocking connection requests. :pypi:`pytest-remove-stale-bytecode` - *last release*: Mar 04, 2020, + *last release*: Jul 07, 2023, *status*: 4 - Beta, *requires*: pytest @@ -7849,9 +7867,9 @@ This list contains 1278 plugins. Re-run only changed files in specified branch :pypi:`pytest-rerunfailures` - *last release*: Mar 09, 2023, + *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.3) + *requires*: pytest (>=6.2) pytest plugin to re-run tests to eliminate flaky failures @@ -8199,7 +8217,7 @@ This list contains 1278 plugins. :pypi:`pytest-sbase` - *last release*: Jun 30, 2023, + *last release*: Jul 08, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8248,7 +8266,7 @@ This list contains 1278 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Jun 30, 2023, + *last release*: Jul 08, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8381,9 +8399,9 @@ This list contains 1278 plugins. A pytest plugin to help with testing shell scripts / black box commands :pypi:`pytest-shell-utilities` - *last release*: Sep 23, 2022, - *status*: 4 - Beta, - *requires*: pytest (>=6.0.0) + *last release*: Jul 02, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest (>=7.1.0) Pytest plugin to simplify running shell commands against the system @@ -8954,6 +8972,13 @@ This list contains 1278 plugins. A simple plugin to use with pytest + :pypi:`pytest-supercov` + *last release*: Jul 02, 2023, + *status*: N/A, + *requires*: N/A + + Pytest plugin for measuring explicit test-file to source-file coverage + :pypi:`pytest-svn` *last release*: May 28, 2019, *status*: 5 - Production/Stable, @@ -9332,6 +9357,13 @@ This list contains 1278 plugins. Pytest plugin for time travel + :pypi:`pytest-thread` + *last release*: Jul 07, 2023, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-threadleak` *last release*: Jul 03, 2022, *status*: 4 - Beta, @@ -10075,9 +10107,9 @@ This list contains 1278 plugins. Extended logging for test and decorators :pypi:`pytest-xlsx` - *last release*: Mar 01, 2023, + *last release*: Jul 03, 2023, *status*: N/A, - *requires*: pytest>=7.2.0 + *requires*: pytest<8,>=7.4.0 pytest plugin for generating test cases by xlsx(excel) @@ -10145,9 +10177,9 @@ This list contains 1278 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: May 28, 2023, + *last release*: Jul 03, 2023, *status*: N/A, - *requires*: pytest>=7.2.0 + *requires*: pytest>=7.4.0 pytest plugin for generating test cases by yaml From 99ab8ae884a3772adc119e7fba22253b1a82eede Mon Sep 17 00:00:00 2001 From: antosikv <79337398+antosikv@users.noreply.github.com> Date: Sun, 9 Jul 2023 17:30:33 +0200 Subject: [PATCH 0070/1271] Clarify docs for pytest.main default behavior (#11187) Add explicit mentions of the default behavior to both API reference and how-to section about ways to invoke pytest. Co-authored-by: Ran Benita --- doc/en/how-to/usage.rst | 3 ++- src/_pytest/config/__init__.py | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 8e2dd86736f..4ec4459a232 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -173,7 +173,8 @@ You can invoke ``pytest`` from Python code directly: this acts as if you would call "pytest" from the command line. It will not raise :class:`SystemExit` but return the :ref:`exit code ` instead. -You can pass in options and arguments: +If you don't pass it any arguments, ``main`` reads the arguments from the command line arguments of the process (:data:`sys.argv`), which may be undesirable. +You can pass in options and arguments explicitly: .. code-block:: python diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 47651ad9fa4..3e38594a859 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -137,7 +137,9 @@ def main( ) -> Union[int, ExitCode]: """Perform an in-process test run. - :param args: List of command line arguments. + :param args: + List of command line arguments. If `None` or not given, defaults to reading + arguments directly from the process command line (:data:`sys.argv`). :param plugins: List of plugin objects to be auto-registered during initialization. :returns: An exit code. From 4e75bff71a948ffc2e67b1decb00de39a87f1995 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 10:23:12 -0300 Subject: [PATCH 0071/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.8.5 to 1.8.7 (#11189) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.5 to 1.8.7. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.5...v1.8.7) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 166d14a5477..32feb92d5c8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -38,7 +38,7 @@ jobs: name: Packages path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.8.5 + uses: pypa/gh-action-pypi-publish@v1.8.7 release-notes: From b91d5a311289afc5d67ffec80ab1755e6fe6d3a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 10:23:33 -0300 Subject: [PATCH 0072/1271] build(deps): Bump pytest-rerunfailures in /testing/plugins_integration (#11190) Bumps [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) from 11.1.2 to 12.0. - [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/11.1.2...12.0) --- updated-dependencies: - dependency-name: pytest-rerunfailures dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index efdf837cef8..92a64b45292 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -7,7 +7,7 @@ pytest-django==4.5.2 pytest-flakes==4.0.5 pytest-html==3.2.0 pytest-mock==3.11.1 -pytest-rerunfailures==11.1.2 +pytest-rerunfailures==12.0 pytest-sugar==0.9.7 pytest-trio==0.7.0 pytest-twisted==1.14.0 From b20e7f6d0cd85f439d7963b4ae7c3c3fc908452d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jul 2023 10:23:47 -0300 Subject: [PATCH 0073/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#11191) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 3.7.0 to 3.7.1. - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/3.7.0...3.7.1) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 92a64b45292..c99c9f8dc70 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==3.7.0 +anyio[curio,trio]==3.7.1 django==4.2.3 pytest-asyncio==0.21.0 pytest-bdd==6.1.1 From f1c9570a0e3f480c82658cf2a8df4107020c841d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 2 Jul 2023 00:19:04 +0300 Subject: [PATCH 0074/1271] A few more Python>=3.8 simplifications --- doc/en/how-to/failures.rst | 4 ---- src/_pytest/_code/code.py | 10 +++++----- src/_pytest/pathlib.py | 18 ------------------ src/_pytest/pytester.py | 3 +-- 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/doc/en/how-to/failures.rst b/doc/en/how-to/failures.rst index ef87550915a..b3d0c155b48 100644 --- a/doc/en/how-to/failures.rst +++ b/doc/en/how-to/failures.rst @@ -135,10 +135,6 @@ Warning about unraisable exceptions and unhandled thread exceptions .. versionadded:: 6.2 -.. note:: - - These features only work on Python>=3.8. - Unhandled exceptions are exceptions that are raised in a situation in which they cannot propagate to a caller. The most common case is an exception raised in a :meth:`__del__ ` implementation. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 58483d2a042..42c5fa8bd4d 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -393,11 +393,11 @@ def __getitem__( def filter( self, - # TODO(py38): change to positional only. - _excinfo_or_fn: Union[ + excinfo_or_fn: Union[ "ExceptionInfo[BaseException]", Callable[[TracebackEntry], bool], ], + /, ) -> "Traceback": """Return a Traceback instance with certain items removed. @@ -408,10 +408,10 @@ def filter( ``TracebackEntry`` instance, and should return True when the item should be added to the ``Traceback``, False when not. """ - if isinstance(_excinfo_or_fn, ExceptionInfo): - fn = lambda x: not x.ishidden(_excinfo_or_fn) # noqa: E731 + if isinstance(excinfo_or_fn, ExceptionInfo): + fn = lambda x: not x.ishidden(excinfo_or_fn) # noqa: E731 else: - fn = _excinfo_or_fn + fn = excinfo_or_fn return Traceback(filter(fn, self)) def recursionindex(self) -> Optional[int]: diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 14fb2e3ae2f..138a0bdb249 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -769,21 +769,3 @@ def bestrelpath(directory: Path, dest: Path) -> str: # Forward from base to dest. *reldest.parts, ) - - -# Originates from py. path.local.copy(), with siginficant trims and adjustments. -# TODO(py38): Replace with shutil.copytree(..., symlinks=True, dirs_exist_ok=True) -def copytree(source: Path, target: Path) -> None: - """Recursively copy a source directory to target.""" - assert source.is_dir() - for entry in visit(source, recurse=lambda entry: not entry.is_symlink()): - x = Path(entry) - relpath = x.relative_to(source) - newx = target / relpath - newx.parent.mkdir(exist_ok=True) - if x.is_symlink(): - newx.symlink_to(os.readlink(x)) - elif x.is_file(): - shutil.copyfile(x, newx) - elif x.is_dir(): - newx.mkdir(exist_ok=True) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 0129c224f08..d8dd3b9de8b 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -63,7 +63,6 @@ from _pytest.outcomes import importorskip from _pytest.outcomes import skip from _pytest.pathlib import bestrelpath -from _pytest.pathlib import copytree from _pytest.pathlib import make_numbered_dir from _pytest.reports import CollectReport from _pytest.reports import TestReport @@ -971,7 +970,7 @@ def copy_example(self, name: Optional[str] = None) -> Path: example_path = example_dir.joinpath(name) if example_path.is_dir() and not example_path.joinpath("__init__.py").is_file(): - copytree(example_path, self.path) + shutil.copytree(example_path, self.path, symlinks=True, dirs_exist_ok=True) return self.path elif example_path.is_file(): result = self.path.joinpath(example_path.name) From 7967b2e710b5d35a56bb9198410a3987c7f9bb59 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Jul 2023 00:43:45 +0300 Subject: [PATCH 0075/1271] fixtures: change a lambda to partial It makes for a more debuggable repr. Before: . at 0x7fe4ae32d440> After: functools.partial(>, request=>) --- src/_pytest/fixtures.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 6e113492820..319c2a59512 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -698,7 +698,8 @@ def _schedule_finalizers( self, fixturedef: "FixtureDef[object]", subrequest: "SubRequest" ) -> None: # If fixture function failed it might have registered finalizers. - subrequest.node.addfinalizer(lambda: fixturedef.finish(request=subrequest)) + finalizer = functools.partial(fixturedef.finish, request=subrequest) + subrequest.node.addfinalizer(finalizer) def _check_scope( self, From 2c80de532f6501090ccd08a71dbc504af51f3991 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Jul 2023 01:20:01 +0300 Subject: [PATCH 0076/1271] fixtures: replace a `startswith("conftest.py")` with `== "conftest.py"` I can't imagine why we would want to test for a prefix here. --- src/_pytest/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 319c2a59512..04c4c85d30c 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1471,7 +1471,7 @@ def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None: # Construct the base nodeid which is later used to check # what fixtures are visible for particular tests (as denoted # by their test id). - if p.name.startswith("conftest.py"): + if p.name == "conftest.py": try: nodeid = str(p.parent.relative_to(self.config.rootpath)) except ValueError: From ecfab4dc8b6ea33fef7a8f4880cf8e745679bc15 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Jul 2023 23:55:00 +0300 Subject: [PATCH 0077/1271] fixtures: fix a typing ignore TODO From understanding the code better I see this is the correct fix. The fixturedefs can be None if `request.getfixturevalue("doesnotexist")` is used. In practice there is no change in behavior because this mapping is used as `self._arg2fixturedefs.get(argname, None)` which ends up the same. --- src/_pytest/fixtures.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 04c4c85d30c..41a6504ccdd 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -464,12 +464,13 @@ def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": assert self._pyfuncitem.parent is not None parentid = self._pyfuncitem.parent.nodeid fixturedefs = self._fixturemanager.getfixturedefs(argname, parentid) - # TODO: Fix this type ignore. Either add assert or adjust types. - # Can this be None here? - self._arg2fixturedefs[argname] = fixturedefs # type: ignore[assignment] + if fixturedefs is not None: + self._arg2fixturedefs[argname] = fixturedefs + if fixturedefs is None: + raise FixtureLookupError(argname, self) # fixturedefs list is immutable so we maintain a decreasing index. index = self._arg2index.get(argname, 0) - 1 - if fixturedefs is None or (-index > len(fixturedefs)): + if -index > len(fixturedefs): raise FixtureLookupError(argname, self) self._arg2index[argname] = index return fixturedefs[index] From 7008385253939271c7046f37f4008e1b7dcbe75c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:37:07 +0000 Subject: [PATCH 0078/1271] [pre-commit.ci] pre-commit autoupdate (#11195) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/psf/black: 23.3.0 → 23.7.0](https://github.com/psf/black/compare/23.3.0...23.7.0) - [github.com/asottile/blacken-docs: 1.14.0 → 1.15.0](https://github.com/asottile/blacken-docs/compare/1.14.0...1.15.0) - [github.com/asottile/pyupgrade: v3.8.0 → v3.9.0](https://github.com/asottile/pyupgrade/compare/v3.8.0...v3.9.0) * Update .pre-commit-config.yaml * Update .pre-commit-config.yaml --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas Co-authored-by: Bruno Oliveira --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d85abe263ec..4bed8703542 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,14 +1,14 @@ repos: - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 23.7.0 hooks: - id: black args: [--safe, --quiet] - repo: https://github.com/asottile/blacken-docs - rev: 1.14.0 + rev: 1.15.0 hooks: - id: blacken-docs - additional_dependencies: [black==23.3.0] + additional_dependencies: [black==23.7.0] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.4.0 hooks: @@ -42,7 +42,7 @@ repos: - id: reorder-python-imports args: ['--application-directories=.:src', --py38-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.8.0 + rev: v3.9.0 hooks: - id: pyupgrade args: [--py38-plus] From b41acaea1203abd25b83699e12124fed06fa9f9f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 12 Jun 2023 22:30:06 +0300 Subject: [PATCH 0079/1271] Switch to new-style pluggy hook wrappers Fix #11122. --- changelog/11122.improvement.rst | 6 +++ doc/en/example/simple.rst | 14 +++--- doc/en/how-to/writing_hook_functions.rst | 57 ++++++++++++++---------- doc/en/requirements.txt | 2 +- setup.cfg | 2 +- src/_pytest/assertion/__init__.py | 13 +++--- src/_pytest/cacheprovider.py | 33 +++++++------- src/_pytest/capture.py | 49 +++++++++++--------- src/_pytest/config/__init__.py | 12 ++--- src/_pytest/debugging.py | 6 +-- src/_pytest/faulthandler.py | 8 ++-- src/_pytest/helpconfig.py | 10 +++-- src/_pytest/hookspec.py | 8 ++-- src/_pytest/logging.py | 44 +++++++++--------- src/_pytest/pytester.py | 46 ++++++++++--------- src/_pytest/reports.py | 3 ++ src/_pytest/setuponly.py | 32 ++++++------- src/_pytest/skipping.py | 26 ++++++----- src/_pytest/terminal.py | 23 +++++----- src/_pytest/threadexception.py | 32 +++++++------ src/_pytest/tmpdir.py | 16 ++++--- src/_pytest/unittest.py | 13 +++--- src/_pytest/unraisableexception.py | 36 ++++++++------- src/_pytest/warnings.py | 45 ++++++++++--------- testing/conftest.py | 9 ++-- testing/logging/test_reporting.py | 4 +- testing/python/collect.py | 19 ++++---- testing/test_collection.py | 7 ++- testing/test_config.py | 2 +- testing/test_mark.py | 6 +-- testing/test_python_path.py | 12 ++--- testing/test_runner.py | 10 ++--- testing/test_terminal.py | 4 +- testing/test_unittest.py | 2 +- 34 files changed, 335 insertions(+), 276 deletions(-) create mode 100644 changelog/11122.improvement.rst diff --git a/changelog/11122.improvement.rst b/changelog/11122.improvement.rst new file mode 100644 index 00000000000..dedaa7d087b --- /dev/null +++ b/changelog/11122.improvement.rst @@ -0,0 +1,6 @@ +``pluggy>=1.2.0`` is now required. + +pytest now uses "new-style" hook wrappers internally, available since pluggy 1.2.0. +See `pluggy's 1.2.0 changelog `_ and the :ref:`updated docs ` for details. + +Plugins which want to use new-style wrappers can do so if they require this version of pytest or later. diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 32e5188b741..5648aa3834d 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -808,11 +808,10 @@ case we just write some information out to a ``failures`` file: import pytest - @pytest.hookimpl(tryfirst=True, hookwrapper=True) + @pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_makereport(item, call): # execute all other hooks to obtain the report object - outcome = yield - rep = outcome.get_result() + rep = yield # we only look at actual failing test calls, not setup/teardown if rep.when == "call" and rep.failed: @@ -826,6 +825,8 @@ case we just write some information out to a ``failures`` file: f.write(rep.nodeid + extra + "\n") + return rep + if you then have failing tests: @@ -899,16 +900,17 @@ here is a little example implemented via a local plugin: phase_report_key = StashKey[Dict[str, CollectReport]]() - @pytest.hookimpl(tryfirst=True, hookwrapper=True) + @pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_makereport(item, call): # execute all other hooks to obtain the report object - outcome = yield - rep = outcome.get_result() + rep = yield # store test results for each phase of a call, which can # be "setup", "call", "teardown" item.stash.setdefault(phase_report_key, {})[rep.when] = rep + return rep + @pytest.fixture def something(request): diff --git a/doc/en/how-to/writing_hook_functions.rst b/doc/en/how-to/writing_hook_functions.rst index 71379016f2e..527aeec8170 100644 --- a/doc/en/how-to/writing_hook_functions.rst +++ b/doc/en/how-to/writing_hook_functions.rst @@ -56,7 +56,7 @@ The remaining hook functions will not be called in this case. .. _`hookwrapper`: -hookwrapper: executing around other hooks +hook wrappers: executing around other hooks ------------------------------------------------- .. currentmodule:: _pytest.core @@ -69,10 +69,8 @@ which yields exactly once. When pytest invokes hooks it first executes hook wrappers and passes the same arguments as to the regular hooks. At the yield point of the hook wrapper pytest will execute the next hook -implementations and return their result to the yield point in the form of -a :py:class:`Result ` instance which encapsulates a result or -exception info. The yield point itself will thus typically not raise -exceptions (unless there are bugs). +implementations and return their result to the yield point, or will +propagate an exception if they raised. Here is an example definition of a hook wrapper: @@ -81,26 +79,35 @@ Here is an example definition of a hook wrapper: import pytest - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_pyfunc_call(pyfuncitem): do_something_before_next_hook_executes() - outcome = yield - # outcome.excinfo may be None or a (cls, val, tb) tuple + # If the outcome is an exception, will raise the exception. + res = yield - res = outcome.get_result() # will raise if outcome was exception + new_res = post_process_result(res) - post_process_result(res) + # Override the return value to the plugin system. + return new_res - outcome.force_result(new_res) # to override the return value to the plugin system +The hook wrapper needs to return a result for the hook, or raise an exception. -Note that hook wrappers don't return results themselves, they merely -perform tracing or other side effects around the actual hook implementations. -If the result of the underlying hook is a mutable object, they may modify -that result but it's probably better to avoid it. +In many cases, the wrapper only needs to perform tracing or other side effects +around the actual hook implementations, in which case it can return the result +value of the ``yield``. The simplest (though useless) hook wrapper is +``return (yield)``. + +In other cases, the wrapper wants the adjust or adapt the result, in which case +it can return a new value. If the result of the underlying hook is a mutable +object, the wrapper may modify that result, but it's probably better to avoid it. + +If the hook implementation failed with an exception, the wrapper can handle that +exception using a ``try-catch-finally`` around the ``yield``, by propagating it, +supressing it, or raising a different exception entirely. For more information, consult the -:ref:`pluggy documentation about hookwrappers `. +:ref:`pluggy documentation about hook wrappers `. .. _plugin-hookorder: @@ -130,11 +137,14 @@ after others, i.e. the position in the ``N``-sized list of functions: # Plugin 3 - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_collection_modifyitems(items): # will execute even before the tryfirst one above! - outcome = yield - # will execute after all non-hookwrappers executed + try: + return (yield) + finally: + # will execute after all non-wrappers executed + ... Here is the order of execution: @@ -149,12 +159,11 @@ Here is the order of execution: Plugin1). 4. Plugin3's pytest_collection_modifyitems then executing the code after the yield - point. The yield receives a :py:class:`Result ` instance which encapsulates - the result from calling the non-wrappers. Wrappers shall not modify the result. + point. The yield receives the result from calling the non-wrappers, or raises + an exception if the non-wrappers raised. -It's possible to use ``tryfirst`` and ``trylast`` also in conjunction with -``hookwrapper=True`` in which case it will influence the ordering of hookwrappers -among each other. +It's possible to use ``tryfirst`` and ``trylast`` also on hook wrappers +in which case it will influence the ordering of hook wrappers among each other. Declaring new hooks diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index b6059723cd5..0ee999e0faf 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -1,5 +1,5 @@ pallets-sphinx-themes -pluggy>=1.0 +pluggy>=1.2.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 sphinx>=5,<6 diff --git a/setup.cfg b/setup.cfg index f80665f4294..9456353693e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -46,7 +46,7 @@ py_modules = py install_requires = iniconfig packaging - pluggy>=0.12,<2.0 + pluggy>=1.2.0,<2.0 colorama;sys_platform=="win32" exceptiongroup>=1.0.0rc8;python_version<"3.11" tomli>=1.0.0;python_version<"3.11" diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index a46e58136ba..64ad4b0e662 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -112,8 +112,8 @@ def pytest_collection(session: "Session") -> None: assertstate.hook.set_session(session) -@hookimpl(tryfirst=True, hookwrapper=True) -def pytest_runtest_protocol(item: Item) -> Generator[None, None, None]: +@hookimpl(wrapper=True, tryfirst=True) +def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: """Setup the pytest_assertrepr_compare and pytest_assertion_pass hooks. The rewrite module will use util._reprcompare if it exists to use custom @@ -162,10 +162,11 @@ def call_assertion_pass_hook(lineno: int, orig: str, expl: str) -> None: util._assertion_pass = call_assertion_pass_hook - yield - - util._reprcompare, util._assertion_pass = saved_assert_hooks - util._config = None + try: + return (yield) + finally: + util._reprcompare, util._assertion_pass = saved_assert_hooks + util._config = None def pytest_sessionfinish(session: "Session") -> None: diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index a0029d6a08f..f519c974bdd 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -217,12 +217,12 @@ def __init__(self, lfplugin: "LFPlugin") -> None: self.lfplugin = lfplugin self._collected_at_least_one_failure = False - @hookimpl(hookwrapper=True) - def pytest_make_collect_report(self, collector: nodes.Collector): + @hookimpl(wrapper=True) + def pytest_make_collect_report( + self, collector: nodes.Collector + ) -> Generator[None, CollectReport, CollectReport]: + res = yield if isinstance(collector, (Session, Package)): - out = yield - res: CollectReport = out.get_result() - # Sort any lf-paths to the beginning. lf_paths = self.lfplugin._last_failed_paths @@ -240,19 +240,16 @@ def sort_key(node: Union[nodes.Item, nodes.Collector]) -> bool: key=sort_key, reverse=True, ) - return elif isinstance(collector, File): if collector.path in self.lfplugin._last_failed_paths: - out = yield - res = out.get_result() result = res.result lastfailed = self.lfplugin.lastfailed # Only filter with known failures. if not self._collected_at_least_one_failure: if not any(x.nodeid in lastfailed for x in result): - return + return res self.lfplugin.config.pluginmanager.register( LFPluginCollSkipfiles(self.lfplugin), "lfplugin-collskip" ) @@ -268,8 +265,8 @@ def sort_key(node: Union[nodes.Item, nodes.Collector]) -> bool: # Keep all sub-collectors. or isinstance(x, nodes.Collector) ] - return - yield + + return res class LFPluginCollSkipfiles: @@ -342,14 +339,14 @@ def pytest_collectreport(self, report: CollectReport) -> None: else: self.lastfailed[report.nodeid] = True - @hookimpl(hookwrapper=True, tryfirst=True) + @hookimpl(wrapper=True, tryfirst=True) def pytest_collection_modifyitems( self, config: Config, items: List[nodes.Item] ) -> Generator[None, None, None]: - yield + res = yield if not self.active: - return + return res if self.lastfailed: previously_failed = [] @@ -394,6 +391,8 @@ def pytest_collection_modifyitems( else: self._report_status += "not deselecting items." + return res + def pytest_sessionfinish(self, session: Session) -> None: config = self.config if config.getoption("cacheshow") or hasattr(config, "workerinput"): @@ -414,11 +413,11 @@ def __init__(self, config: Config) -> None: assert config.cache is not None self.cached_nodeids = set(config.cache.get("cache/nodeids", [])) - @hookimpl(hookwrapper=True, tryfirst=True) + @hookimpl(wrapper=True, tryfirst=True) def pytest_collection_modifyitems( self, items: List[nodes.Item] ) -> Generator[None, None, None]: - yield + res = yield if self.active: new_items: Dict[str, nodes.Item] = {} @@ -436,6 +435,8 @@ def pytest_collection_modifyitems( else: self.cached_nodeids.update(item.nodeid for item in items) + return res + def _get_increasing_order(self, items: Iterable[nodes.Item]) -> List[nodes.Item]: return sorted(items, key=lambda item: item.path.stat().st_mtime, reverse=True) # type: ignore[no-any-return] diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 5c62cf54d9d..81b8bffbcf7 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -36,6 +36,7 @@ from _pytest.nodes import Collector from _pytest.nodes import File from _pytest.nodes import Item +from _pytest.reports import CollectReport _CaptureMethod = Literal["fd", "sys", "no", "tee-sys"] @@ -130,8 +131,8 @@ def _reopen_stdio(f, mode): sys.stderr = _reopen_stdio(sys.stderr, "wb") -@hookimpl(hookwrapper=True) -def pytest_load_initial_conftests(early_config: Config): +@hookimpl(wrapper=True) +def pytest_load_initial_conftests(early_config: Config) -> Generator[None, None, None]: ns = early_config.known_args_namespace if ns.capture == "fd": _windowsconsoleio_workaround(sys.stdout) @@ -145,12 +146,16 @@ def pytest_load_initial_conftests(early_config: Config): # Finally trigger conftest loading but while capturing (issue #93). capman.start_global_capturing() - outcome = yield - capman.suspend_global_capture() - if outcome.excinfo is not None: + try: + try: + yield + finally: + capman.suspend_global_capture() + except BaseException: out, err = capman.read_global_capture() sys.stdout.write(out) sys.stderr.write(err) + raise # IO Helpers. @@ -841,41 +846,45 @@ def item_capture(self, when: str, item: Item) -> Generator[None, None, None]: self.deactivate_fixture() self.suspend_global_capture(in_=False) - out, err = self.read_global_capture() - item.add_report_section(when, "stdout", out) - item.add_report_section(when, "stderr", err) + out, err = self.read_global_capture() + item.add_report_section(when, "stdout", out) + item.add_report_section(when, "stderr", err) # Hooks - @hookimpl(hookwrapper=True) - def pytest_make_collect_report(self, collector: Collector): + @hookimpl(wrapper=True) + def pytest_make_collect_report( + self, collector: Collector + ) -> Generator[None, CollectReport, CollectReport]: if isinstance(collector, File): self.resume_global_capture() - outcome = yield - self.suspend_global_capture() + try: + rep = yield + finally: + self.suspend_global_capture() out, err = self.read_global_capture() - rep = outcome.get_result() if out: rep.sections.append(("Captured stdout", out)) if err: rep.sections.append(("Captured stderr", err)) else: - yield + rep = yield + return rep - @hookimpl(hookwrapper=True) + @hookimpl(wrapper=True) def pytest_runtest_setup(self, item: Item) -> Generator[None, None, None]: with self.item_capture("setup", item): - yield + return (yield) - @hookimpl(hookwrapper=True) + @hookimpl(wrapper=True) def pytest_runtest_call(self, item: Item) -> Generator[None, None, None]: with self.item_capture("call", item): - yield + return (yield) - @hookimpl(hookwrapper=True) + @hookimpl(wrapper=True) def pytest_runtest_teardown(self, item: Item) -> Generator[None, None, None]: with self.item_capture("teardown", item): - yield + return (yield) @hookimpl(tryfirst=True) def pytest_keyboard_interrupt(self) -> None: diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 3e38594a859..1f4670a560b 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1341,12 +1341,14 @@ def _preparse(self, args: List[str], addopts: bool = True) -> None: else: raise - @hookimpl(hookwrapper=True) - def pytest_collection(self) -> Generator[None, None, None]: + @hookimpl(wrapper=True) + def pytest_collection(self) -> Generator[None, object, object]: # Validate invalid ini keys after collection is done so we take in account # options added by late-loading conftest files. - yield - self._validate_config_options() + try: + return (yield) + finally: + self._validate_config_options() def _checkversion(self) -> None: import pytest @@ -1448,7 +1450,7 @@ def issue_config_time_warning(self, warning: Warning, stacklevel: int) -> None: """Issue and handle a warning during the "configure" stage. During ``pytest_configure`` we can't capture warnings using the ``catch_warnings_for_item`` - function because it is not possible to have hookwrappers around ``pytest_configure``. + function because it is not possible to have hook wrappers around ``pytest_configure``. This function is mainly intended for plugins that need to issue warnings during ``pytest_configure`` (or similar stages). diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index a3f80802cab..69ec58c5b8c 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -304,10 +304,10 @@ def pytest_internalerror(self, excinfo: ExceptionInfo[BaseException]) -> None: class PdbTrace: - @hookimpl(hookwrapper=True) - def pytest_pyfunc_call(self, pyfuncitem) -> Generator[None, None, None]: + @hookimpl(wrapper=True) + def pytest_pyfunc_call(self, pyfuncitem) -> Generator[None, object, object]: wrap_pytest_function_for_tracing(pyfuncitem) - yield + return (yield) def wrap_pytest_function_for_tracing(pyfuncitem): diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index af879aa44cf..2dc672c8d7f 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -62,8 +62,8 @@ def get_timeout_config_value(config: Config) -> float: return float(config.getini("faulthandler_timeout") or 0.0) -@pytest.hookimpl(hookwrapper=True, trylast=True) -def pytest_runtest_protocol(item: Item) -> Generator[None, None, None]: +@pytest.hookimpl(wrapper=True, trylast=True) +def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: timeout = get_timeout_config_value(item.config) if timeout > 0: import faulthandler @@ -71,11 +71,11 @@ def pytest_runtest_protocol(item: Item) -> Generator[None, None, None]: stderr = item.config.stash[fault_handler_stderr_fd_key] faulthandler.dump_traceback_later(timeout, file=stderr) try: - yield + return (yield) finally: faulthandler.cancel_dump_traceback_later() else: - yield + return (yield) @pytest.hookimpl(tryfirst=True) diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 430870608bd..4122d60094a 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -2,6 +2,7 @@ import os import sys from argparse import Action +from typing import Generator from typing import List from typing import Optional from typing import Union @@ -97,10 +98,9 @@ def pytest_addoption(parser: Parser) -> None: ) -@pytest.hookimpl(hookwrapper=True) -def pytest_cmdline_parse(): - outcome = yield - config: Config = outcome.get_result() +@pytest.hookimpl(wrapper=True) +def pytest_cmdline_parse() -> Generator[None, Config, Config]: + config = yield if config.option.debug: # --debug | --debug was provided. @@ -128,6 +128,8 @@ def unset_tracing() -> None: config.add_cleanup(unset_tracing) + return config + def showversion(config: Config) -> None: if config.option.version > 1: diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 1f7c368f792..b01f8ec16b4 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -60,7 +60,7 @@ def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: :param pytest.PytestPluginManager pluginmanager: The pytest plugin manager. .. note:: - This hook is incompatible with ``hookwrapper=True``. + This hook is incompatible with hook wrappers. """ @@ -74,7 +74,7 @@ def pytest_plugin_registered( :param pytest.PytestPluginManager manager: pytest plugin manager. .. note:: - This hook is incompatible with ``hookwrapper=True``. + This hook is incompatible with hook wrappers. """ @@ -113,7 +113,7 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> attribute or can be retrieved as the ``pytestconfig`` fixture. .. note:: - This hook is incompatible with ``hookwrapper=True``. + This hook is incompatible with hook wrappers. """ @@ -128,7 +128,7 @@ def pytest_configure(config: "Config") -> None: imported. .. note:: - This hook is incompatible with ``hookwrapper=True``. + This hook is incompatible with hook wrappers. :param pytest.Config config: The pytest config object. """ diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index ea856837c65..873eb5e4e58 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -738,27 +738,26 @@ def _log_cli_enabled(self): return True - @hookimpl(hookwrapper=True, tryfirst=True) + @hookimpl(wrapper=True, tryfirst=True) def pytest_sessionstart(self) -> Generator[None, None, None]: self.log_cli_handler.set_when("sessionstart") with catching_logs(self.log_cli_handler, level=self.log_cli_level): with catching_logs(self.log_file_handler, level=self.log_file_level): - yield + return (yield) - @hookimpl(hookwrapper=True, tryfirst=True) + @hookimpl(wrapper=True, tryfirst=True) def pytest_collection(self) -> Generator[None, None, None]: self.log_cli_handler.set_when("collection") with catching_logs(self.log_cli_handler, level=self.log_cli_level): with catching_logs(self.log_file_handler, level=self.log_file_level): - yield + return (yield) - @hookimpl(hookwrapper=True) - def pytest_runtestloop(self, session: Session) -> Generator[None, None, None]: + @hookimpl(wrapper=True) + def pytest_runtestloop(self, session: Session) -> Generator[None, object, object]: if session.config.option.collectonly: - yield - return + return (yield) if self._log_cli_enabled() and self._config.getoption("verbose") < 1: # The verbose flag is needed to avoid messy test progress output. @@ -766,7 +765,7 @@ def pytest_runtestloop(self, session: Session) -> Generator[None, None, None]: with catching_logs(self.log_cli_handler, level=self.log_cli_level): with catching_logs(self.log_file_handler, level=self.log_file_level): - yield # Run all the tests. + return (yield) # Run all the tests. @hookimpl def pytest_runtest_logstart(self) -> None: @@ -791,12 +790,13 @@ def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None, None, Non item.stash[caplog_records_key][when] = caplog_handler.records item.stash[caplog_handler_key] = caplog_handler - yield - - log = report_handler.stream.getvalue().strip() - item.add_report_section(when, "log", log) + try: + yield + finally: + log = report_handler.stream.getvalue().strip() + item.add_report_section(when, "log", log) - @hookimpl(hookwrapper=True) + @hookimpl(wrapper=True) def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]: self.log_cli_handler.set_when("setup") @@ -804,31 +804,33 @@ def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]: item.stash[caplog_records_key] = empty yield from self._runtest_for(item, "setup") - @hookimpl(hookwrapper=True) + @hookimpl(wrapper=True) def pytest_runtest_call(self, item: nodes.Item) -> Generator[None, None, None]: self.log_cli_handler.set_when("call") yield from self._runtest_for(item, "call") - @hookimpl(hookwrapper=True) + @hookimpl(wrapper=True) def pytest_runtest_teardown(self, item: nodes.Item) -> Generator[None, None, None]: self.log_cli_handler.set_when("teardown") - yield from self._runtest_for(item, "teardown") - del item.stash[caplog_records_key] - del item.stash[caplog_handler_key] + try: + yield from self._runtest_for(item, "teardown") + finally: + del item.stash[caplog_records_key] + del item.stash[caplog_handler_key] @hookimpl def pytest_runtest_logfinish(self) -> None: self.log_cli_handler.set_when("finish") - @hookimpl(hookwrapper=True, tryfirst=True) + @hookimpl(wrapper=True, tryfirst=True) def pytest_sessionfinish(self) -> Generator[None, None, None]: self.log_cli_handler.set_when("sessionfinish") with catching_logs(self.log_cli_handler, level=self.log_cli_level): with catching_logs(self.log_file_handler, level=self.log_file_level): - yield + return (yield) @hookimpl def pytest_unconfigure(self) -> None: diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index d8dd3b9de8b..b112e6e7000 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -160,29 +160,31 @@ def matching_platform(self) -> bool: else: return True - @hookimpl(hookwrapper=True, tryfirst=True) - def pytest_runtest_protocol(self, item: Item) -> Generator[None, None, None]: + @hookimpl(wrapper=True, tryfirst=True) + def pytest_runtest_protocol(self, item: Item) -> Generator[None, object, object]: lines1 = self.get_open_files() - yield - if hasattr(sys, "pypy_version_info"): - gc.collect() - lines2 = self.get_open_files() - - new_fds = {t[0] for t in lines2} - {t[0] for t in lines1} - leaked_files = [t for t in lines2 if t[0] in new_fds] - if leaked_files: - error = [ - "***** %s FD leakage detected" % len(leaked_files), - *(str(f) for f in leaked_files), - "*** Before:", - *(str(f) for f in lines1), - "*** After:", - *(str(f) for f in lines2), - "***** %s FD leakage detected" % len(leaked_files), - "*** function %s:%s: %s " % item.location, - "See issue #2366", - ] - item.warn(PytestWarning("\n".join(error))) + try: + return (yield) + finally: + if hasattr(sys, "pypy_version_info"): + gc.collect() + lines2 = self.get_open_files() + + new_fds = {t[0] for t in lines2} - {t[0] for t in lines1} + leaked_files = [t for t in lines2 if t[0] in new_fds] + if leaked_files: + error = [ + "***** %s FD leakage detected" % len(leaked_files), + *(str(f) for f in leaked_files), + "*** Before:", + *(str(f) for f in lines1), + "*** After:", + *(str(f) for f in lines2), + "***** %s FD leakage detected" % len(leaked_files), + "*** function %s:%s: %s " % item.location, + "See issue #2366", + ] + item.warn(PytestWarning("\n".join(error))) # used at least by pytest-xdist plugin diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 0a4044ec650..d09a273fca5 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -249,6 +249,9 @@ class TestReport(BaseReport): """ __test__ = False + # Defined by skipping plugin. + # xfail reason if xfailed, otherwise not defined. Use hasattr to distinguish. + wasxfail: str def __init__( self, diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index 583590d6b70..0f8be899af2 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -28,24 +28,26 @@ def pytest_addoption(parser: Parser) -> None: ) -@pytest.hookimpl(hookwrapper=True) +@pytest.hookimpl(wrapper=True) def pytest_fixture_setup( fixturedef: FixtureDef[object], request: SubRequest -) -> Generator[None, None, None]: - yield - if request.config.option.setupshow: - if hasattr(request, "param"): - # Save the fixture parameter so ._show_fixture_action() can - # display it now and during the teardown (in .finish()). - if fixturedef.ids: - if callable(fixturedef.ids): - param = fixturedef.ids(request.param) +) -> Generator[None, object, object]: + try: + return (yield) + finally: + if request.config.option.setupshow: + if hasattr(request, "param"): + # Save the fixture parameter so ._show_fixture_action() can + # display it now and during the teardown (in .finish()). + if fixturedef.ids: + if callable(fixturedef.ids): + param = fixturedef.ids(request.param) + else: + param = fixturedef.ids[request.param_index] else: - param = fixturedef.ids[request.param_index] - else: - param = request.param - fixturedef.cached_param = param # type: ignore[attr-defined] - _show_fixture_action(fixturedef, "SETUP") + param = request.param + fixturedef.cached_param = param # type: ignore[attr-defined] + _show_fixture_action(fixturedef, "SETUP") def pytest_fixture_post_finalizer(fixturedef: FixtureDef[object]) -> None: diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 26ce73758a0..0c5c38f5f1a 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -19,6 +19,7 @@ from _pytest.outcomes import skip from _pytest.outcomes import xfail from _pytest.reports import BaseReport +from _pytest.reports import TestReport from _pytest.runner import CallInfo from _pytest.stash import StashKey @@ -243,7 +244,7 @@ def pytest_runtest_setup(item: Item) -> None: xfail("[NOTRUN] " + xfailed.reason) -@hookimpl(hookwrapper=True) +@hookimpl(wrapper=True) def pytest_runtest_call(item: Item) -> Generator[None, None, None]: xfailed = item.stash.get(xfailed_key, None) if xfailed is None: @@ -252,18 +253,20 @@ def pytest_runtest_call(item: Item) -> Generator[None, None, None]: if xfailed and not item.config.option.runxfail and not xfailed.run: xfail("[NOTRUN] " + xfailed.reason) - yield - - # The test run may have added an xfail mark dynamically. - xfailed = item.stash.get(xfailed_key, None) - if xfailed is None: - item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) + try: + return (yield) + finally: + # The test run may have added an xfail mark dynamically. + xfailed = item.stash.get(xfailed_key, None) + if xfailed is None: + item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) -@hookimpl(hookwrapper=True) -def pytest_runtest_makereport(item: Item, call: CallInfo[None]): - outcome = yield - rep = outcome.get_result() +@hookimpl(wrapper=True) +def pytest_runtest_makereport( + item: Item, call: CallInfo[None] +) -> Generator[None, TestReport, TestReport]: + rep = yield xfailed = item.stash.get(xfailed_key, None) if item.config.option.runxfail: pass # don't interfere @@ -286,6 +289,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]): else: rep.outcome = "passed" rep.wasxfail = xfailed.reason + return rep def pytest_report_teststatus(report: BaseReport) -> Optional[Tuple[str, str, str]]: diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 089314c3e1b..70453f306e8 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -15,7 +15,6 @@ from pathlib import Path from typing import Any from typing import Callable -from typing import cast from typing import ClassVar from typing import Dict from typing import final @@ -849,12 +848,11 @@ def _printcollecteditems(self, items: Sequence[Item]) -> None: for line in doc.splitlines(): self._tw.line("{}{}".format(indent + " ", line)) - @hookimpl(hookwrapper=True) + @hookimpl(wrapper=True) def pytest_sessionfinish( self, session: "Session", exitstatus: Union[int, ExitCode] - ): - outcome = yield - outcome.get_result() + ) -> Generator[None, None, None]: + result = yield self._tw.line("") summary_exit_codes = ( ExitCode.OK, @@ -875,17 +873,20 @@ def pytest_sessionfinish( elif session.shouldstop: self.write_sep("!", str(session.shouldstop), red=True) self.summary_stats() + return result - @hookimpl(hookwrapper=True) + @hookimpl(wrapper=True) def pytest_terminal_summary(self) -> Generator[None, None, None]: self.summary_errors() self.summary_failures() self.summary_warnings() self.summary_passes() - yield - self.short_test_summary() - # Display any extra warnings from teardown here (if any). - self.summary_warnings() + try: + return (yield) + finally: + self.short_test_summary() + # Display any extra warnings from teardown here (if any). + self.summary_warnings() def pytest_keyboard_interrupt(self, excinfo: ExceptionInfo[BaseException]) -> None: self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True) @@ -1466,7 +1467,7 @@ def _get_raw_skip_reason(report: TestReport) -> str: The string is just the part given by the user. """ if hasattr(report, "wasxfail"): - reason = cast(str, report.wasxfail) + reason = report.wasxfail if reason.startswith("reason: "): reason = reason[len("reason: ") :] return reason diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index 43341e739a0..0b5902d66a8 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -59,30 +59,34 @@ def __exit__( def thread_exception_runtest_hook() -> Generator[None, None, None]: with catch_threading_exception() as cm: - yield - if cm.args: - thread_name = "" if cm.args.thread is None else cm.args.thread.name - msg = f"Exception in thread {thread_name}\n\n" - msg += "".join( - traceback.format_exception( - cm.args.exc_type, - cm.args.exc_value, - cm.args.exc_traceback, + try: + yield + finally: + if cm.args: + thread_name = ( + "" if cm.args.thread is None else cm.args.thread.name ) - ) - warnings.warn(pytest.PytestUnhandledThreadExceptionWarning(msg)) + msg = f"Exception in thread {thread_name}\n\n" + msg += "".join( + traceback.format_exception( + cm.args.exc_type, + cm.args.exc_value, + cm.args.exc_traceback, + ) + ) + warnings.warn(pytest.PytestUnhandledThreadExceptionWarning(msg)) -@pytest.hookimpl(hookwrapper=True, trylast=True) +@pytest.hookimpl(wrapper=True, trylast=True) def pytest_runtest_setup() -> Generator[None, None, None]: yield from thread_exception_runtest_hook() -@pytest.hookimpl(hookwrapper=True, tryfirst=True) +@pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_call() -> Generator[None, None, None]: yield from thread_exception_runtest_hook() -@pytest.hookimpl(hookwrapper=True, tryfirst=True) +@pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_teardown() -> Generator[None, None, None]: yield from thread_exception_runtest_hook() diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index fe0855c18b0..5473d95e1ac 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -28,7 +28,7 @@ from _pytest.fixtures import FixtureRequest from _pytest.monkeypatch import MonkeyPatch from _pytest.nodes import Item -from _pytest.reports import CollectReport +from _pytest.reports import TestReport from _pytest.stash import StashKey tmppath_result_key = StashKey[Dict[str, bool]]() @@ -309,10 +309,12 @@ def pytest_sessionfinish(session, exitstatus: Union[int, ExitCode]): cleanup_dead_symlinks(basetemp) -@hookimpl(tryfirst=True, hookwrapper=True) -def pytest_runtest_makereport(item: Item, call): - outcome = yield - result: CollectReport = outcome.get_result() - +@hookimpl(wrapper=True, tryfirst=True) +def pytest_runtest_makereport( + item: Item, call +) -> Generator[None, TestReport, TestReport]: + rep = yield + assert rep.when is not None empty: Dict[str, bool] = {} - item.stash.setdefault(tmppath_result_key, empty)[result.when] = result.passed + item.stash.setdefault(tmppath_result_key, empty)[rep.when] = rep.passed + return rep diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index d42a12a3a9e..27598cbdef6 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -376,8 +376,8 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None: # Twisted trial support. -@hookimpl(hookwrapper=True) -def pytest_runtest_protocol(item: Item) -> Generator[None, None, None]: +@hookimpl(wrapper=True) +def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: if isinstance(item, TestCaseFunction) and "twisted.trial.unittest" in sys.modules: ut: Any = sys.modules["twisted.python.failure"] Failure__init__ = ut.Failure.__init__ @@ -400,10 +400,13 @@ def excstore( Failure__init__(self, exc_value, exc_type, exc_tb) ut.Failure.__init__ = excstore - yield - ut.Failure.__init__ = Failure__init__ + try: + res = yield + finally: + ut.Failure.__init__ = Failure__init__ else: - yield + res = yield + return res def check_testcase_implements_trial_reporter(done: List[int] = []) -> None: diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index fcb5d8237c1..8c0a2d9ae95 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -61,33 +61,35 @@ def __exit__( def unraisable_exception_runtest_hook() -> Generator[None, None, None]: with catch_unraisable_exception() as cm: - yield - if cm.unraisable: - if cm.unraisable.err_msg is not None: - err_msg = cm.unraisable.err_msg - else: - err_msg = "Exception ignored in" - msg = f"{err_msg}: {cm.unraisable.object!r}\n\n" - msg += "".join( - traceback.format_exception( - cm.unraisable.exc_type, - cm.unraisable.exc_value, - cm.unraisable.exc_traceback, + try: + yield + finally: + if cm.unraisable: + if cm.unraisable.err_msg is not None: + err_msg = cm.unraisable.err_msg + else: + err_msg = "Exception ignored in" + msg = f"{err_msg}: {cm.unraisable.object!r}\n\n" + msg += "".join( + traceback.format_exception( + cm.unraisable.exc_type, + cm.unraisable.exc_value, + cm.unraisable.exc_traceback, + ) ) - ) - warnings.warn(pytest.PytestUnraisableExceptionWarning(msg)) + warnings.warn(pytest.PytestUnraisableExceptionWarning(msg)) -@pytest.hookimpl(hookwrapper=True, tryfirst=True) +@pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_setup() -> Generator[None, None, None]: yield from unraisable_exception_runtest_hook() -@pytest.hookimpl(hookwrapper=True, tryfirst=True) +@pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_call() -> Generator[None, None, None]: yield from unraisable_exception_runtest_hook() -@pytest.hookimpl(hookwrapper=True, tryfirst=True) +@pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_teardown() -> Generator[None, None, None]: yield from unraisable_exception_runtest_hook() diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index bb293ec0821..a6af49f916a 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -60,17 +60,18 @@ def catch_warnings_for_item( for arg in mark.args: warnings.filterwarnings(*parse_warning_filter(arg, escape=False)) - yield - - for warning_message in log: - ihook.pytest_warning_recorded.call_historic( - kwargs=dict( - warning_message=warning_message, - nodeid=nodeid, - when=when, - location=None, + try: + yield + finally: + for warning_message in log: + ihook.pytest_warning_recorded.call_historic( + kwargs=dict( + warning_message=warning_message, + nodeid=nodeid, + when=when, + location=None, + ) ) - ) def warning_record_to_str(warning_message: warnings.WarningMessage) -> str: @@ -103,24 +104,24 @@ def warning_record_to_str(warning_message: warnings.WarningMessage) -> str: return msg -@pytest.hookimpl(hookwrapper=True, tryfirst=True) -def pytest_runtest_protocol(item: Item) -> Generator[None, None, None]: +@pytest.hookimpl(wrapper=True, tryfirst=True) +def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: with catch_warnings_for_item( config=item.config, ihook=item.ihook, when="runtest", item=item ): - yield + return (yield) -@pytest.hookimpl(hookwrapper=True, tryfirst=True) -def pytest_collection(session: Session) -> Generator[None, None, None]: +@pytest.hookimpl(wrapper=True, tryfirst=True) +def pytest_collection(session: Session) -> Generator[None, object, object]: config = session.config with catch_warnings_for_item( config=config, ihook=config.hook, when="collect", item=None ): - yield + return (yield) -@pytest.hookimpl(hookwrapper=True) +@pytest.hookimpl(wrapper=True) def pytest_terminal_summary( terminalreporter: TerminalReporter, ) -> Generator[None, None, None]: @@ -128,23 +129,23 @@ def pytest_terminal_summary( with catch_warnings_for_item( config=config, ihook=config.hook, when="config", item=None ): - yield + return (yield) -@pytest.hookimpl(hookwrapper=True) +@pytest.hookimpl(wrapper=True) def pytest_sessionfinish(session: Session) -> Generator[None, None, None]: config = session.config with catch_warnings_for_item( config=config, ihook=config.hook, when="config", item=None ): - yield + return (yield) -@pytest.hookimpl(hookwrapper=True) +@pytest.hookimpl(wrapper=True) def pytest_load_initial_conftests( early_config: "Config", ) -> Generator[None, None, None]: with catch_warnings_for_item( config=early_config, ihook=early_config.hook, when="config", item=None ): - yield + return (yield) diff --git a/testing/conftest.py b/testing/conftest.py index 8e77fcae5ab..926a1d5d364 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -1,6 +1,7 @@ import dataclasses import re import sys +from typing import Generator from typing import List import pytest @@ -21,11 +22,11 @@ def restore_tracing(): sys.settrace(orig_trace) -@pytest.hookimpl(hookwrapper=True, tryfirst=True) -def pytest_collection_modifyitems(items): +@pytest.hookimpl(wrapper=True, tryfirst=True) +def pytest_collection_modifyitems(items) -> Generator[None, None, None]: """Prefer faster tests. - Use a hookwrapper to do this in the beginning, so e.g. --ff still works + Use a hook wrapper to do this in the beginning, so e.g. --ff still works correctly. """ fast_items = [] @@ -62,7 +63,7 @@ def pytest_collection_modifyitems(items): items[:] = fast_items + neutral_items + slow_items + slowest_items - yield + return (yield) @pytest.fixture diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 0c8e3fd08a9..8c1e4f8cc19 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1040,13 +1040,13 @@ def test_log_set_path(pytester: Pytester) -> None: """ import os import pytest - @pytest.hookimpl(hookwrapper=True, tryfirst=True) + @pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_setup(item): config = item.config logging_plugin = config.pluginmanager.get_plugin("logging-plugin") report_file = os.path.join({}, item._request.node.name) logging_plugin.set_log_path(report_file) - yield + return (yield) """.format( repr(report_dir_base) ) diff --git a/testing/python/collect.py b/testing/python/collect.py index 8de216d8f54..0415c3fbe3f 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -827,11 +827,11 @@ def test_customized_pymakemodule_issue205_subdir(self, pytester: Pytester) -> No textwrap.dedent( """\ import pytest - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_pycollect_makemodule(): - outcome = yield - mod = outcome.get_result() + mod = yield mod.obj.hello = "world" + return mod """ ), encoding="utf-8", @@ -855,14 +855,13 @@ def test_customized_pymakeitem(self, pytester: Pytester) -> None: textwrap.dedent( """\ import pytest - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_pycollect_makeitem(): - outcome = yield - if outcome.excinfo is None: - result = outcome.get_result() - if result: - for func in result: - func._some123 = "world" + result = yield + if result: + for func in result: + func._some123 = "world" + return result """ ), encoding="utf-8", diff --git a/testing/test_collection.py b/testing/test_collection.py index c370951b590..ca2e2b7313f 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -334,12 +334,11 @@ def test_collect_report_postprocessing(self, pytester: Pytester) -> None: pytester.makeconftest( """ import pytest - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_make_collect_report(): - outcome = yield - rep = outcome.get_result() + rep = yield rep.headerlines += ["header1"] - outcome.force_result(rep) + return rep """ ) result = pytester.runpytest(p) diff --git a/testing/test_config.py b/testing/test_config.py index 9b3fe4af0da..43561000c91 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1317,7 +1317,7 @@ def pytest_load_initial_conftests(self): hookimpls = [ ( hookimpl.function.__module__, - "wrapper" if hookimpl.hookwrapper else "nonwrapper", + "wrapper" if (hookimpl.wrapper or hookimpl.hookwrapper) else "nonwrapper", ) for hookimpl in hc.get_hookimpls() ] diff --git a/testing/test_mark.py b/testing/test_mark.py index 2767260df8c..7415b393ef2 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -806,12 +806,12 @@ def test_2(self): pytester.makepyfile( conftest=""" import pytest - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_pycollect_makeitem(name): - outcome = yield + item = yield if name == "TestClass": - item = outcome.get_result() item.extra_keyword_matches.add("xxx") + return item """ ) reprec = pytester.inline_run(p.parent, "-s", "-k", keyword) diff --git a/testing/test_python_path.py b/testing/test_python_path.py index e1628feb159..dfef0f3fecf 100644 --- a/testing/test_python_path.py +++ b/testing/test_python_path.py @@ -85,8 +85,8 @@ def test_clean_up(pytester: Pytester) -> None: # This is tough to test behaviorally because the cleanup really runs last. # So the test make several implementation assumptions: # - Cleanup is done in pytest_unconfigure(). - # - Not a hookwrapper. - # So we can add a hookwrapper ourselves to test what it does. + # - Not a hook wrapper. + # So we can add a hook wrapper ourselves to test what it does. pytester.makefile(".ini", pytest="[pytest]\npythonpath=I_SHALL_BE_REMOVED\n") pytester.makepyfile(test_foo="""def test_foo(): pass""") @@ -94,12 +94,14 @@ def test_clean_up(pytester: Pytester) -> None: after: Optional[List[str]] = None class Plugin: - @pytest.hookimpl(hookwrapper=True, tryfirst=True) + @pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_unconfigure(self) -> Generator[None, None, None]: nonlocal before, after before = sys.path.copy() - yield - after = sys.path.copy() + try: + return (yield) + finally: + after = sys.path.copy() result = pytester.runpytest_inprocess(plugins=[Plugin()]) assert result.ret == 0 diff --git a/testing/test_runner.py b/testing/test_runner.py index de3e18184c7..cab631ee12e 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -542,10 +542,10 @@ def pytest_runtest_setup(self, item): @pytest.fixture def mylist(self, request): return request.function.mylist - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_runtest_call(self, item): try: - (yield).get_result() + yield except ValueError: pass def test_hello1(self, mylist): @@ -826,12 +826,12 @@ def test_unicode_in_longrepr(pytester: Pytester) -> None: pytester.makeconftest( """\ import pytest - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_runtest_makereport(): - outcome = yield - rep = outcome.get_result() + rep = yield if rep.when == "call": rep.longrepr = 'ä' + return rep """ ) pytester.makepyfile( diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 7c2f7c94a50..596c3c67ede 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -725,12 +725,12 @@ def test_three(): ) assert result.ret == 0 - def test_deselected_with_hookwrapper(self, pytester: Pytester) -> None: + def test_deselected_with_hook_wrapper(self, pytester: Pytester) -> None: pytester.makeconftest( """ import pytest - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_collection_modifyitems(config, items): yield deselected = items.pop() diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 99a53e0a9af..24f954051d6 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -952,7 +952,7 @@ def test_issue333_result_clearing(pytester: Pytester) -> None: pytester.makeconftest( """ import pytest - @pytest.hookimpl(hookwrapper=True) + @pytest.hookimpl(wrapper=True) def pytest_runtest_call(item): yield assert 0 From 01f38aca440f0fd2a0526c08441e419ee8f34880 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Jul 2023 14:50:25 +0300 Subject: [PATCH 0080/1271] fixtures: expand comments and annotations on fixture internals --- src/_pytest/compat.py | 2 +- src/_pytest/doctest.py | 2 +- src/_pytest/fixtures.py | 106 +++++++++++++++++++++++++------------ testing/python/fixtures.py | 9 ++++ testing/test_legacypath.py | 1 + 5 files changed, 85 insertions(+), 35 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 998f540f357..47ffe47e89b 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -68,7 +68,7 @@ def is_async_function(func: object) -> bool: return iscoroutinefunction(func) or inspect.isasyncgenfunction(func) -def getlocation(function, curdir: str | None = None) -> str: +def getlocation(function, curdir: str | os.PathLike[str] | None = None) -> str: function = get_real_func(function) fn = Path(inspect.getfile(function)) lineno = function.__code__.co_firstlineno diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 455ad62cc9c..a37f1d2ace9 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -582,7 +582,7 @@ def func() -> None: doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined] node=doctest_item, func=func, cls=None, funcargs=False ) - fixture_request = FixtureRequest(doctest_item, _ispytest=True) + fixture_request = FixtureRequest(doctest_item, _ispytest=True) # type: ignore[arg-type] fixture_request._fillfixtures() return fixture_request diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 41a6504ccdd..3ffbc752a41 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -13,6 +13,7 @@ from typing import Callable from typing import cast from typing import Dict +from typing import Final from typing import final from typing import Generator from typing import Generic @@ -73,6 +74,7 @@ from _pytest.scope import _ScopeName from _pytest.main import Session from _pytest.python import CallSpec2 + from _pytest.python import Function from _pytest.python import Metafunc @@ -352,17 +354,24 @@ def get_direct_param_fixture_func(request: "FixtureRequest") -> Any: return request.param -@dataclasses.dataclass +@dataclasses.dataclass(frozen=True) class FuncFixtureInfo: __slots__ = ("argnames", "initialnames", "names_closure", "name2fixturedefs") - # Original function argument names. + # Original function argument names, i.e. fixture names that the function + # requests directly. argnames: Tuple[str, ...] - # Argnames that function immediately requires. These include argnames + - # fixture names specified via usefixtures and via autouse=True in fixture - # definitions. + # Fixture names that the function immediately requires. These include + # argnames + fixture names specified via usefixtures and via autouse=True in + # fixture definitions. initialnames: Tuple[str, ...] + # The transitive closure of the fixture names that the function requires. + # Note: can't include dynamic dependencies (`request.getfixturevalue` calls). names_closure: List[str] + # A map from a fixture name in the transitive closure to the FixtureDefs + # matching the name which are applicable to this function. + # There may be multiple overriding fixtures with the same name. The + # sequence is ordered from furthest to closes to the function. name2fixturedefs: Dict[str, Sequence["FixtureDef[Any]"]] def prune_dependency_tree(self) -> None: @@ -401,17 +410,31 @@ class FixtureRequest: indirectly. """ - def __init__(self, pyfuncitem, *, _ispytest: bool = False) -> None: + def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: check_ispytest(_ispytest) - self._pyfuncitem = pyfuncitem #: Fixture for which this request is being performed. self.fixturename: Optional[str] = None + self._pyfuncitem = pyfuncitem + self._fixturemanager = pyfuncitem.session._fixturemanager self._scope = Scope.Function - self._fixture_defs: Dict[str, FixtureDef[Any]] = {} - fixtureinfo: FuncFixtureInfo = pyfuncitem._fixtureinfo - self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy() + # The FixtureDefs for each fixture name requested by this item. + # Starts from the statically-known fixturedefs resolved during + # collection. Dynamically requested fixtures (using + # `request.getfixturevalue("foo")`) are added dynamically. + self._arg2fixturedefs = pyfuncitem._fixtureinfo.name2fixturedefs.copy() + # A fixture may override another fixture with the same name, e.g. a fixture + # in a module can override a fixture in a conftest, a fixture in a class can + # override a fixture in the module, and so on. + # An overriding fixture can request its own name; in this case it gets + # the value of the fixture it overrides, one level up. + # The _arg2index state keeps the current depth in the overriding chain. + # The fixturedefs list in _arg2fixturedefs for a given name is ordered from + # furthest to closest, so we use negative indexing -1, -2, ... to go from + # last to first. self._arg2index: Dict[str, int] = {} - self._fixturemanager: FixtureManager = pyfuncitem.session._fixturemanager + # The evaluated argnames so far, mapping to the FixtureDef they resolved + # to. + self._fixture_defs: Dict[str, FixtureDef[Any]] = {} # Notes on the type of `param`: # -`request.param` is only defined in parametrized fixtures, and will raise # AttributeError otherwise. Python typing has no notion of "undefined", so @@ -466,10 +489,14 @@ def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": fixturedefs = self._fixturemanager.getfixturedefs(argname, parentid) if fixturedefs is not None: self._arg2fixturedefs[argname] = fixturedefs + # No fixtures defined with this name. if fixturedefs is None: raise FixtureLookupError(argname, self) - # fixturedefs list is immutable so we maintain a decreasing index. + # The are no fixtures with this name applicable for the function. + if not fixturedefs: + raise FixtureLookupError(argname, self) index = self._arg2index.get(argname, 0) - 1 + # The fixture requested its own name, but no remaining to override. if -index > len(fixturedefs): raise FixtureLookupError(argname, self) self._arg2index[argname] = index @@ -503,7 +530,7 @@ def instance(self): """Instance (can be None) on which test function was collected.""" # unittest support hack, see _pytest.unittest.TestCaseFunction. try: - return self._pyfuncitem._testcase + return self._pyfuncitem._testcase # type: ignore[attr-defined] except AttributeError: function = getattr(self, "function", None) return getattr(function, "__self__", None) @@ -513,7 +540,9 @@ def module(self): """Python module object where the test function was collected.""" if self.scope not in ("function", "class", "module"): raise AttributeError(f"module not available in {self.scope}-scoped context") - return self._pyfuncitem.getparent(_pytest.python.Module).obj + mod = self._pyfuncitem.getparent(_pytest.python.Module) + assert mod is not None + return mod.obj @property def path(self) -> Path: @@ -829,7 +858,9 @@ def formatrepr(self) -> "FixtureLookupErrorRepr": if msg is None: fm = self.request._fixturemanager available = set() - parentid = self.request._pyfuncitem.parent.nodeid + parent = self.request._pyfuncitem.parent + assert parent is not None + parentid = parent.nodeid for name, fixturedefs in fm._arg2fixturedefs.items(): faclist = list(fm._matchfactories(fixturedefs, parentid)) if faclist: @@ -976,15 +1007,15 @@ def __init__( # directory path relative to the rootdir. # # For other plugins, the baseid is the empty string (always matches). - self.baseid = baseid or "" + self.baseid: Final = baseid or "" # Whether the fixture was found from a node or a conftest in the # collection tree. Will be false for fixtures defined in non-conftest # plugins. - self.has_location = baseid is not None + self.has_location: Final = baseid is not None # The fixture factory function. - self.func = func + self.func: Final = func # The name by which the fixture may be requested. - self.argname = argname + self.argname: Final = argname if scope is None: scope = Scope.Function elif callable(scope): @@ -993,23 +1024,23 @@ def __init__( scope = Scope.from_user( scope, descr=f"Fixture '{func.__name__}'", where=baseid ) - self._scope = scope + self._scope: Final = scope # If the fixture is directly parametrized, the parameter values. - self.params: Optional[Sequence[object]] = params + self.params: Final = params # If the fixture is directly parametrized, a tuple of explicit IDs to # assign to the parameter values, or a callable to generate an ID given # a parameter value. - self.ids = ids + self.ids: Final = ids # The names requested by the fixtures. - self.argnames = getfuncargnames(func, name=argname, is_method=unittest) + self.argnames: Final = getfuncargnames(func, name=argname, is_method=unittest) # Whether the fixture was collected from a unittest TestCase class. # Note that it really only makes sense to define autouse fixtures in # unittest TestCases. - self.unittest = unittest + self.unittest: Final = unittest # If the fixture was executed, the current value of the fixture. # Can change if the fixture is executed with different parameters. self.cached_result: Optional[_FixtureCachedResult[FixtureValue]] = None - self._finalizers: List[Callable[[], object]] = [] + self._finalizers: Final[List[Callable[[], object]]] = [] @property def scope(self) -> "_ScopeName": @@ -1040,7 +1071,7 @@ def finish(self, request: SubRequest) -> None: # value and remove all finalizers because they may be bound methods # which will keep instances alive. self.cached_result = None - self._finalizers = [] + self._finalizers.clear() def execute(self, request: SubRequest) -> FixtureValue: # Get required arguments and register our own finish() @@ -1417,10 +1448,14 @@ class FixtureManager: def __init__(self, session: "Session") -> None: self.session = session self.config: Config = session.config - self._arg2fixturedefs: Dict[str, List[FixtureDef[Any]]] = {} - self._holderobjseen: Set[object] = set() + # Maps a fixture name (argname) to all of the FixtureDefs in the test + # suite/plugins defined with this name. Populated by parsefactories(). + # TODO: The order of the FixtureDefs list of each arg is significant, + # explain. + self._arg2fixturedefs: Final[Dict[str, List[FixtureDef[Any]]]] = {} + self._holderobjseen: Final[Set[object]] = set() # A mapping from a nodeid to a list of autouse fixtures it defines. - self._nodeid_autousenames: Dict[str, List[str]] = { + self._nodeid_autousenames: Final[Dict[str, List[str]]] = { "": self.config.getini("usefixtures"), } session.config.pluginmanager.register(self, "funcmanage") @@ -1699,11 +1734,16 @@ def parsefactories( # noqa: F811 def getfixturedefs( self, argname: str, nodeid: str ) -> Optional[Sequence[FixtureDef[Any]]]: - """Get a list of fixtures which are applicable to the given node id. + """Get FixtureDefs for a fixture name which are applicable + to a given node. + + Returns None if there are no fixtures at all defined with the given + name. (This is different from the case in which there are fixtures + with the given name, but none applicable to the node. In this case, + an empty result is returned). - :param str argname: Name of the fixture to search for. - :param str nodeid: Full node id of the requesting test. - :rtype: Sequence[FixtureDef] + :param argname: Name of the fixture to search for. + :param nodeid: Full node id of the requesting test. """ try: fixturedefs = self._arg2fixturedefs[argname] diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index e62db8c2653..63c18456a72 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -699,6 +699,7 @@ def test_method(self, something): """ ) (item1,) = pytester.genitems([modcol]) + assert isinstance(item1, Function) assert item1.name == "test_method" arg2fixturedefs = fixtures.FixtureRequest( item1, _ispytest=True @@ -967,6 +968,7 @@ def test_second(): def test_request_getmodulepath(self, pytester: Pytester) -> None: modcol = pytester.getmodulecol("def test_somefunc(): pass") (item,) = pytester.genitems([modcol]) + assert isinstance(item, Function) req = fixtures.FixtureRequest(item, _ispytest=True) assert req.path == modcol.path @@ -1125,6 +1127,7 @@ def test_func2(self, something): pass """ ) + assert isinstance(item1, Function) req1 = fixtures.FixtureRequest(item1, _ispytest=True) assert "xfail" not in item1.keywords req1.applymarker(pytest.mark.xfail) @@ -4009,6 +4012,7 @@ def test_func(m1): """ ) items, _ = pytester.inline_genitems() + assert isinstance(items[0], Function) request = FixtureRequest(items[0], _ispytest=True) assert request.fixturenames == "m1 f1".split() @@ -4057,6 +4061,7 @@ def test_foo(f1, p1, m1, f2, s1): pass """ ) items, _ = pytester.inline_genitems() + assert isinstance(items[0], Function) request = FixtureRequest(items[0], _ispytest=True) # order of fixtures based on their scope and position in the parameter list assert ( @@ -4084,6 +4089,7 @@ def test_func(f1, m1): """ ) items, _ = pytester.inline_genitems() + assert isinstance(items[0], Function) request = FixtureRequest(items[0], _ispytest=True) assert request.fixturenames == "m1 f1".split() @@ -4117,6 +4123,7 @@ def test_func(self, f2, f1, c1, m1, s1): """ ) items, _ = pytester.inline_genitems() + assert isinstance(items[0], Function) request = FixtureRequest(items[0], _ispytest=True) assert request.fixturenames == "s1 m1 c1 f2 f1".split() @@ -4159,6 +4166,7 @@ def test_func(m_test, f1): } ) items, _ = pytester.inline_genitems() + assert isinstance(items[0], Function) request = FixtureRequest(items[0], _ispytest=True) assert request.fixturenames == "p_sub m_conf m_sub m_test f1".split() @@ -4203,6 +4211,7 @@ def test_func(self, f2, f1, m2): """ ) items, _ = pytester.inline_genitems() + assert isinstance(items[0], Function) request = FixtureRequest(items[0], _ispytest=True) assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split() diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index fbfd88b7384..b32036d1413 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -90,6 +90,7 @@ def test_cache_makedir(cache: pytest.Cache) -> None: def test_fixturerequest_getmodulepath(pytester: pytest.Pytester) -> None: modcol = pytester.getmodulecol("def test_somefunc(): pass") (item,) = pytester.genitems([modcol]) + assert isinstance(item, pytest.Function) req = pytest.FixtureRequest(item, _ispytest=True) assert req.path == modcol.path assert req.fspath == modcol.fspath # type: ignore[attr-defined] From 9d0ddb462517fc6c4f6dc7e0f1e14af2e08aeed9 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 14 Jul 2023 10:35:18 +0300 Subject: [PATCH 0081/1271] fixtures: change `FixtureDef.cached_result[2]` from exception triplet to exception Fix #11208. --- changelog/11208.trivial.rst | 2 ++ src/_pytest/fixtures.py | 27 +++++++++++---------------- 2 files changed, 13 insertions(+), 16 deletions(-) create mode 100644 changelog/11208.trivial.rst diff --git a/changelog/11208.trivial.rst b/changelog/11208.trivial.rst new file mode 100644 index 00000000000..fced57b2084 --- /dev/null +++ b/changelog/11208.trivial.rst @@ -0,0 +1,2 @@ +The (internal) ``FixtureDef.cached_result`` type has changed. +Now the third item ``cached_result[2]``, when set, is an exception instance instead of an exception triplet. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 3ffbc752a41..6a263866984 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -2,13 +2,11 @@ import functools import inspect import os -import sys import warnings from collections import defaultdict from collections import deque from contextlib import suppress from pathlib import Path -from types import TracebackType from typing import Any from typing import Callable from typing import cast @@ -27,7 +25,6 @@ from typing import Sequence from typing import Set from typing import Tuple -from typing import Type from typing import TYPE_CHECKING from typing import TypeVar from typing import Union @@ -99,8 +96,8 @@ None, # Cache key. object, - # Exc info if raised. - Tuple[Type[BaseException], BaseException, TracebackType], + # Exception if raised. + BaseException, ], ] @@ -1085,13 +1082,13 @@ def execute(self, request: SubRequest) -> FixtureValue: my_cache_key = self.cache_key(request) if self.cached_result is not None: + cache_key = self.cached_result[1] # note: comparison with `==` can fail (or be expensive) for e.g. # numpy arrays (#6497). - cache_key = self.cached_result[1] if my_cache_key is cache_key: if self.cached_result[2] is not None: - _, val, tb = self.cached_result[2] - raise val.with_traceback(tb) + exc = self.cached_result[2] + raise exc else: result = self.cached_result[0] return result @@ -1156,14 +1153,12 @@ def pytest_fixture_setup( my_cache_key = fixturedef.cache_key(request) try: result = call_fixture_func(fixturefunc, request, kwargs) - except TEST_OUTCOME: - exc_info = sys.exc_info() - assert exc_info[0] is not None - if isinstance( - exc_info[1], skip.Exception - ) and not fixturefunc.__name__.startswith("xunit_setup"): - exc_info[1]._use_item_location = True # type: ignore[attr-defined] - fixturedef.cached_result = (None, my_cache_key, exc_info) + except TEST_OUTCOME as e: + if isinstance(e, skip.Exception) and not fixturefunc.__name__.startswith( + "xunit_setup" + ): + e._use_item_location = True + fixturedef.cached_result = (None, my_cache_key, e) raise fixturedef.cached_result = (result, my_cache_key, None) return result From fb55615d5e999dd44306596f340036c195428ef1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 14 Jul 2023 10:59:00 +0300 Subject: [PATCH 0082/1271] Export `FixtureDef` FixtureDef is used in the `pytest_fixture_setup` hook so needs to be public. However since its current internals are quite dubious (and not all marked with `_` prefix) I've added an explicit note that only documented fields/methods are considered public. Refs #7469. --- changelog/7469.feature.rst | 1 + doc/en/reference/reference.rst | 2 +- src/_pytest/fixtures.py | 11 ++++++++++- src/pytest/__init__.py | 2 ++ 4 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 changelog/7469.feature.rst diff --git a/changelog/7469.feature.rst b/changelog/7469.feature.rst new file mode 100644 index 00000000000..8e9df72697c --- /dev/null +++ b/changelog/7469.feature.rst @@ -0,0 +1 @@ +:class:`~pytest.FixtureDef` is now exported as ``pytest.FixtureDef`` for typing purposes. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index cf83ae05f21..ea008110e4a 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -910,7 +910,7 @@ ExitCode FixtureDef ~~~~~~~~~~ -.. autoclass:: _pytest.fixtures.FixtureDef() +.. autoclass:: pytest.FixtureDef() :members: :show-inheritance: diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 6a263866984..13efca2adb0 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -216,6 +216,7 @@ def add_funcarg_pseudo_fixture_def( params=valuelist, unittest=False, ids=None, + _ispytest=True, ) arg2fixturedefs[argname] = [fixturedef] if name2pseudofixturedef is not None: @@ -974,7 +975,11 @@ def _eval_scope_callable( @final class FixtureDef(Generic[FixtureValue]): - """A container for a fixture definition.""" + """A container for a fixture definition. + + Note: At this time, only explicitly documented fields and methods are + considered public stable API. + """ def __init__( self, @@ -988,7 +993,10 @@ def __init__( ids: Optional[ Union[Tuple[Optional[object], ...], Callable[[Any], Optional[object]]] ] = None, + *, + _ispytest: bool = False, ) -> None: + check_ispytest(_ispytest) self._fixturemanager = fixturemanager # The "base" node ID for the fixture. # @@ -1708,6 +1716,7 @@ def parsefactories( # noqa: F811 params=marker.params, unittest=unittest, ids=marker.ids, + _ispytest=True, ) faclist = self._arg2fixturedefs.setdefault(name, []) diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 58ddb3288eb..831ede1fa1f 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -20,6 +20,7 @@ from _pytest.debugging import pytestPDB as __pytestPDB from _pytest.doctest import DoctestItem from _pytest.fixtures import fixture +from _pytest.fixtures import FixtureDef from _pytest.fixtures import FixtureLookupError from _pytest.fixtures import FixtureRequest from _pytest.fixtures import yield_fixture @@ -102,6 +103,7 @@ "fail", "File", "fixture", + "FixtureDef", "FixtureLookupError", "FixtureRequest", "freeze_includes", From 40ed678885a0be2267f0719bb40b185ee94ba353 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 14 Jul 2023 11:07:42 +0300 Subject: [PATCH 0083/1271] fixtures: remove two unused functions Not used since 310b67b2271cb05f575054c1cdd2ece2412c89a2. --- src/_pytest/fixtures.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 13efca2adb0..1e472cda642 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1172,22 +1172,6 @@ def pytest_fixture_setup( return result -def _ensure_immutable_ids( - ids: Optional[Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]]] -) -> Optional[Union[Tuple[Optional[object], ...], Callable[[Any], Optional[object]]]]: - if ids is None: - return None - if callable(ids): - return ids - return tuple(ids) - - -def _params_converter( - params: Optional[Iterable[object]], -) -> Optional[Tuple[object, ...]]: - return tuple(params) if params is not None else None - - def wrap_function_to_error_out_if_called_directly( function: FixtureFunction, fixture_marker: "FixtureFunctionMarker", From 04e0db7e4895362925df294296d43a50d194ece8 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 16 Jul 2023 01:02:00 +0300 Subject: [PATCH 0084/1271] Use typing.Literal without TYPE_CHECKING checks Literal was added in Python 3.8 which we now require so can use it freely. --- src/_pytest/_py/path.py | 4 +--- src/_pytest/config/argparsing.py | 7 ++----- src/_pytest/fixtures.py | 12 ++++++------ src/_pytest/hookspec.py | 2 +- src/_pytest/logging.py | 3 +-- src/_pytest/main.py | 6 +----- src/_pytest/python.py | 10 +++------- src/_pytest/reports.py | 9 ++++----- src/_pytest/runner.py | 15 +++++++-------- src/_pytest/scope.py | 18 ++++++++---------- src/_pytest/terminal.py | 5 ++--- src/_pytest/tmpdir.py | 4 ++-- src/_pytest/warnings.py | 7 ++----- 13 files changed, 40 insertions(+), 62 deletions(-) diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 73a070d19a8..41a7926c5ed 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -25,14 +25,12 @@ from typing import Any from typing import Callable from typing import cast +from typing import Literal from typing import overload from typing import TYPE_CHECKING from . import error -if TYPE_CHECKING: - from typing import Literal - # Moved from local.py. iswin32 = sys.platform == "win32" or (getattr(os, "_name", False) == "nt") diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 108349f1035..e345de01639 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -9,12 +9,12 @@ from typing import Dict from typing import final from typing import List +from typing import Literal from typing import Mapping from typing import NoReturn from typing import Optional from typing import Sequence from typing import Tuple -from typing import TYPE_CHECKING from typing import Union import _pytest._io @@ -24,9 +24,6 @@ from _pytest.deprecated import ARGUMENT_TYPE_STR_CHOICE from _pytest.deprecated import check_ispytest -if TYPE_CHECKING: - from typing_extensions import Literal - FILE_OR_DIR = "file_or_dir" @@ -177,7 +174,7 @@ def addini( name: str, help: str, type: Optional[ - "Literal['string', 'paths', 'pathlist', 'args', 'linelist', 'bool']" + Literal["string", "paths", "pathlist", "args", "linelist", "bool"] ] = None, default: Any = None, ) -> None: diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 1e472cda642..e81fe9692ad 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -60,6 +60,7 @@ from _pytest.outcomes import TEST_OUTCOME from _pytest.pathlib import absolutepath from _pytest.pathlib import bestrelpath +from _pytest.scope import _ScopeName from _pytest.scope import HIGH_SCOPES from _pytest.scope import Scope from _pytest.stash import StashKey @@ -68,7 +69,6 @@ if TYPE_CHECKING: from typing import Deque - from _pytest.scope import _ScopeName from _pytest.main import Session from _pytest.python import CallSpec2 from _pytest.python import Function @@ -444,7 +444,7 @@ def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: self.param: Any @property - def scope(self) -> "_ScopeName": + def scope(self) -> _ScopeName: """Scope string, one of "function", "class", "module", "package", "session".""" return self._scope.value @@ -949,10 +949,10 @@ def _teardown_yield_fixture(fixturefunc, it) -> None: def _eval_scope_callable( - scope_callable: "Callable[[str, Config], _ScopeName]", + scope_callable: Callable[[str, Config], _ScopeName], fixture_name: str, config: Config, -) -> "_ScopeName": +) -> _ScopeName: try: # Type ignored because there is no typing mechanism to specify # keyword arguments, currently. @@ -987,7 +987,7 @@ def __init__( baseid: Optional[str], argname: str, func: "_FixtureFunc[FixtureValue]", - scope: Union[Scope, "_ScopeName", Callable[[str, Config], "_ScopeName"], None], + scope: Union[Scope, _ScopeName, Callable[[str, Config], _ScopeName], None], params: Optional[Sequence[object]], unittest: bool = False, ids: Optional[ @@ -1048,7 +1048,7 @@ def __init__( self._finalizers: Final[List[Callable[[], object]]] = [] @property - def scope(self) -> "_ScopeName": + def scope(self) -> _ScopeName: """Scope string, one of "function", "class", "module", "package", "session".""" return self._scope.value diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index b01f8ec16b4..11878d1b07c 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -18,7 +18,7 @@ if TYPE_CHECKING: import pdb import warnings - from typing_extensions import Literal + from typing import Literal from _pytest._code.code import ExceptionRepr from _pytest._code.code import ExceptionInfo diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 873eb5e4e58..8de690d9b0e 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -16,6 +16,7 @@ from typing import final from typing import Generator from typing import List +from typing import Literal from typing import Mapping from typing import Optional from typing import Tuple @@ -41,8 +42,6 @@ if TYPE_CHECKING: logging_StreamHandler = logging.StreamHandler[StringIO] - - from typing_extensions import Literal else: logging_StreamHandler = logging.StreamHandler diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 67c52243ee2..f27767cf17c 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -13,13 +13,13 @@ from typing import FrozenSet from typing import Iterator from typing import List +from typing import Literal from typing import Optional from typing import overload from typing import Sequence from typing import Set from typing import Tuple from typing import Type -from typing import TYPE_CHECKING from typing import Union import _pytest._code @@ -43,10 +43,6 @@ from _pytest.runner import SetupState -if TYPE_CHECKING: - from typing_extensions import Literal - - def pytest_addoption(parser: Parser) -> None: parser.addini( "norecursedirs", diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 77912b866f6..cf757533630 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -20,13 +20,13 @@ from typing import Iterable from typing import Iterator from typing import List +from typing import Literal from typing import Mapping from typing import Optional from typing import Pattern from typing import Sequence from typing import Set from typing import Tuple -from typing import TYPE_CHECKING from typing import Union import _pytest @@ -75,16 +75,12 @@ from _pytest.pathlib import ImportPathMismatchError from _pytest.pathlib import parts from _pytest.pathlib import visit +from _pytest.scope import _ScopeName from _pytest.scope import Scope from _pytest.warning_types import PytestCollectionWarning from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning -if TYPE_CHECKING: - from typing_extensions import Literal - - from _pytest.scope import _ScopeName - _PYTEST_DIR = Path(_pytest.__file__).parent @@ -1236,7 +1232,7 @@ def parametrize( ids: Optional[ Union[Iterable[Optional[object]], Callable[[Any], Optional[object]]] ] = None, - scope: "Optional[_ScopeName]" = None, + scope: Optional[_ScopeName] = None, *, _param_mark: Optional[Mark] = None, ) -> None: diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index d09a273fca5..18f1c948afc 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -9,6 +9,7 @@ from typing import Iterable from typing import Iterator from typing import List +from typing import Literal from typing import Mapping from typing import NoReturn from typing import Optional @@ -36,8 +37,6 @@ from _pytest.outcomes import skip if TYPE_CHECKING: - from typing_extensions import Literal - from _pytest.runner import CallInfo @@ -64,7 +63,7 @@ class BaseReport: ] sections: List[Tuple[str, str]] nodeid: str - outcome: "Literal['passed', 'failed', 'skipped']" + outcome: Literal["passed", "failed", "skipped"] def __init__(self, **kw: Any) -> None: self.__dict__.update(kw) @@ -258,11 +257,11 @@ def __init__( nodeid: str, location: Tuple[str, Optional[int], str], keywords: Mapping[str, Any], - outcome: "Literal['passed', 'failed', 'skipped']", + outcome: Literal["passed", "failed", "skipped"], longrepr: Union[ None, ExceptionInfo[BaseException], Tuple[str, int, str], str, TerminalRepr ], - when: "Literal['setup', 'call', 'teardown']", + when: Literal["setup", "call", "teardown"], sections: Iterable[Tuple[str, str]] = (), duration: float = 0, start: float = 0, diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 1f14ff94484..1b39f93cf13 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -9,6 +9,7 @@ from typing import final from typing import Generic from typing import List +from typing import Literal from typing import Optional from typing import Tuple from typing import Type @@ -38,8 +39,6 @@ from exceptiongroup import BaseExceptionGroup if TYPE_CHECKING: - from typing_extensions import Literal - from _pytest.main import Session from _pytest.terminal import TerminalReporter @@ -184,7 +183,7 @@ def pytest_runtest_teardown(item: Item, nextitem: Optional[Item]) -> None: def _update_current_test_var( - item: Item, when: Optional["Literal['setup', 'call', 'teardown']"] + item: Item, when: Optional[Literal["setup", "call", "teardown"]] ) -> None: """Update :envvar:`PYTEST_CURRENT_TEST` to reflect the current item and stage. @@ -217,7 +216,7 @@ def pytest_report_teststatus(report: BaseReport) -> Optional[Tuple[str, str, str def call_and_report( - item: Item, when: "Literal['setup', 'call', 'teardown']", log: bool = True, **kwds + item: Item, when: Literal["setup", "call", "teardown"], log: bool = True, **kwds ) -> TestReport: call = call_runtest_hook(item, when, **kwds) hook = item.ihook @@ -245,7 +244,7 @@ def check_interactive_exception(call: "CallInfo[object]", report: BaseReport) -> def call_runtest_hook( - item: Item, when: "Literal['setup', 'call', 'teardown']", **kwds + item: Item, when: Literal["setup", "call", "teardown"], **kwds ) -> "CallInfo[None]": if when == "setup": ihook: Callable[..., None] = item.ihook.pytest_runtest_setup @@ -281,7 +280,7 @@ class CallInfo(Generic[TResult]): #: The call duration, in seconds. duration: float #: The context of invocation: "collect", "setup", "call" or "teardown". - when: "Literal['collect', 'setup', 'call', 'teardown']" + when: Literal["collect", "setup", "call", "teardown"] def __init__( self, @@ -290,7 +289,7 @@ def __init__( start: float, stop: float, duration: float, - when: "Literal['collect', 'setup', 'call', 'teardown']", + when: Literal["collect", "setup", "call", "teardown"], *, _ispytest: bool = False, ) -> None: @@ -319,7 +318,7 @@ def result(self) -> TResult: def from_call( cls, func: "Callable[[], TResult]", - when: "Literal['collect', 'setup', 'call', 'teardown']", + when: Literal["collect", "setup", "call", "teardown"], reraise: Optional[ Union[Type[BaseException], Tuple[Type[BaseException], ...]] ] = None, diff --git a/src/_pytest/scope.py b/src/_pytest/scope.py index 7a746fb9fa9..98edaf40225 100644 --- a/src/_pytest/scope.py +++ b/src/_pytest/scope.py @@ -9,13 +9,11 @@ """ from enum import Enum from functools import total_ordering +from typing import Literal from typing import Optional -from typing import TYPE_CHECKING -if TYPE_CHECKING: - from typing_extensions import Literal - _ScopeName = Literal["session", "package", "module", "class", "function"] +_ScopeName = Literal["session", "package", "module", "class", "function"] @total_ordering @@ -33,11 +31,11 @@ class Scope(Enum): """ # Scopes need to be listed from lower to higher. - Function: "_ScopeName" = "function" - Class: "_ScopeName" = "class" - Module: "_ScopeName" = "module" - Package: "_ScopeName" = "package" - Session: "_ScopeName" = "session" + Function: _ScopeName = "function" + Class: _ScopeName = "class" + Module: _ScopeName = "module" + Package: _ScopeName = "package" + Session: _ScopeName = "session" def next_lower(self) -> "Scope": """Return the next lower scope.""" @@ -60,7 +58,7 @@ def __lt__(self, other: "Scope") -> bool: @classmethod def from_user( - cls, scope_name: "_ScopeName", descr: str, where: Optional[str] = None + cls, scope_name: _ScopeName, descr: str, where: Optional[str] = None ) -> "Scope": """ Given a scope name from the user, return the equivalent Scope enum. Should be used diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 70453f306e8..ea26d9368dc 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -20,6 +20,7 @@ from typing import final from typing import Generator from typing import List +from typing import Literal from typing import Mapping from typing import NamedTuple from typing import Optional @@ -54,8 +55,6 @@ from _pytest.reports import TestReport if TYPE_CHECKING: - from typing_extensions import Literal - from _pytest.main import Session @@ -366,7 +365,7 @@ def __init__(self, config: Config, file: Optional[TextIO] = None) -> None: self._already_displayed_warnings: Optional[int] = None self._keyboardinterrupt_memo: Optional[ExceptionRepr] = None - def _determine_show_progress_info(self) -> "Literal['progress', 'count', False]": + def _determine_show_progress_info(self) -> Literal["progress", "count", False]: """Return whether we should display progress information based on the current config.""" # do not show progress if we are not capturing output (#3038) unless explicitly # overridden by progress-even-when-capture-no diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 5473d95e1ac..6fa227760a8 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -48,13 +48,13 @@ class TempPathFactory: _trace: Any _basetemp: Optional[Path] _retention_count: int - _retention_policy: "RetentionType" + _retention_policy: RetentionType def __init__( self, given_basetemp: Optional[Path], retention_count: int, - retention_policy: "RetentionType", + retention_policy: RetentionType, trace, basetemp: Optional[Path] = None, *, diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index a6af49f916a..6f20a872cca 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -2,8 +2,8 @@ import warnings from contextlib import contextmanager from typing import Generator +from typing import Literal from typing import Optional -from typing import TYPE_CHECKING import pytest from _pytest.config import apply_warning_filters @@ -13,9 +13,6 @@ from _pytest.nodes import Item from _pytest.terminal import TerminalReporter -if TYPE_CHECKING: - from typing_extensions import Literal - def pytest_configure(config: Config) -> None: config.addinivalue_line( @@ -29,7 +26,7 @@ def pytest_configure(config: Config) -> None: def catch_warnings_for_item( config: Config, ihook, - when: "Literal['config', 'collect', 'runtest']", + when: Literal["config", "collect", "runtest"], item: Optional[Item], ) -> Generator[None, None, None]: """Context manager that catches warnings generated in the contained execution block. From a6687196261b631c41eea7b6f9792b5ff81de00d Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 16 Jul 2023 00:28:56 +0000 Subject: [PATCH 0085/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 140 ++++++++++++++++--------------- 1 file changed, 74 insertions(+), 66 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index f15bc4be59e..82b8286da74 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -13,7 +13,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1282 plugins. +This list contains 1283 plugins. .. only:: not latex @@ -69,7 +69,7 @@ This list contains 1282 plugins. :pypi:`pytest-appium` Pytest plugin for appium Dec 05, 2019 N/A N/A :pypi:`pytest-approvaltests` A plugin to use approvaltests with pytest May 08, 2022 4 - Beta pytest (>=7.0.1) :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Mar 04, 2023 5 - Production/Stable pytest - :pypi:`pytest-archon` Rule your architecture like a real developer Jan 31, 2023 5 - Production/Stable pytest (>=7.2) + :pypi:`pytest-archon` Rule your architecture like a real developer Jul 11, 2023 5 - Production/Stable pytest (>=7.2) :pypi:`pytest-argus` pyest results colection plugin Jun 24, 2021 5 - Production/Stable pytest (>=6.2.4) :pypi:`pytest-arraydiff` pytest plugin to help with comparing array output from tests Jan 13, 2022 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) @@ -86,7 +86,7 @@ This list contains 1282 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 Mar 19, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-asyncio` Pytest support for asyncio Jul 12, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. May 31, 2023 N/A N/A :pypi:`pytest-asyncio-network-simulator` pytest-asyncio-network-simulator: Plugin for pytest for simulator the network in tests Jul 31, 2018 3 - Alpha pytest (<3.7.0,>=3.3.2) :pypi:`pytest-async-mongodb` pytest plugin for async MongoDB Oct 18, 2017 5 - Production/Stable pytest (>=2.5.2) @@ -176,8 +176,8 @@ This list contains 1282 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jun 06, 2023 N/A pytest - :pypi:`pytest-checkdocs` check the README when running tests Oct 09, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jul 14, 2023 N/A pytest + :pypi:`pytest-checkdocs` check the README when running tests Jul 09, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Jul 22, 2020 5 - Production/Stable pytest (>=2.9.2) :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A @@ -301,7 +301,7 @@ This list contains 1282 plugins. :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Jun 23, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Feb 05, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) + :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Jul 15, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) :pypi:`pytest-django` A Django plugin for pytest. Dec 07, 2021 5 - Production/Stable pytest (>=5.4.0) :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest @@ -355,6 +355,7 @@ This list contains 1282 plugins. :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection May 23, 2020 4 - Beta pytest (>=2.7) + :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 11, 2023 N/A pytest (>=7.4.0,<8.0.0) :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jun 25, 2021 N/A N/A @@ -375,17 +376,17 @@ This list contains 1282 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. Jul 05, 2023 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jul 05, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jul 05, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jul 05, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jul 05, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jul 05, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jul 05, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jul 09, 2023 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jul 09, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jul 09, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jul 09, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jul 09, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jul 09, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jul 09, 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) - :pypi:`pytest-enabler` Enable installed pytest plugins Jun 26, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-enabler` Enable installed pytest plugins Jul 14, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A @@ -402,7 +403,7 @@ This list contains 1282 plugins. :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. May 05, 2023 4 - Beta pytest>=7 + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jan 31, 2022 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -461,7 +462,7 @@ This list contains 1282 plugins. :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Mar 18, 2022 4 - Beta pytest (>=7.0) - :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jun 16, 2023 5 - Production/Stable pytest + :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jul 10, 2023 5 - Production/Stable pytest :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) @@ -530,7 +531,7 @@ This list contains 1282 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 07, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 14, 2023 3 - Alpha pytest (==7.3.1) :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -552,7 +553,7 @@ This list contains 1282 plugins. :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Jun 03, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 09, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0) :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -584,14 +585,14 @@ This list contains 1282 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. Jun 29, 2023 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Jul 14, 2023 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 02, 2023 5 - Production/Stable pytest (<7.2.0,>=6) :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Oct 31, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-is-running` pytest plugin providing a function to check if pytest is running. Jun 16, 2023 5 - Production/Stable N/A + :pypi:`pytest-is-running` pytest plugin providing a function to check if pytest is running. Jul 10, 2023 5 - Production/Stable N/A :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 22, 2020 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A @@ -601,7 +602,7 @@ This list contains 1282 plugins. :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Jun 12, 2023 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Jun 06, 2023 4 - Beta pytest + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Jul 11, 2023 4 - Beta pytest :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -707,7 +708,7 @@ This list contains 1282 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jun 09, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jul 12, 2023 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -749,7 +750,7 @@ This list contains 1282 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jun 07, 2023 N/A pytest (==6.2.5) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jul 11, 2023 N/A pytest (==6.2.5) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A @@ -911,7 +912,7 @@ This list contains 1282 plugins. :pypi:`pytest-raisesregexp` Simple pytest plugin to look for regex in Exceptions Dec 18, 2015 N/A N/A :pypi:`pytest-raisin` Plugin enabling the use of exception instances with pytest.raises Feb 06, 2022 N/A pytest :pypi:`pytest-random` py.test plugin to randomize tests Apr 28, 2013 3 - Alpha N/A - :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. May 11, 2022 5 - Production/Stable pytest + :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Jul 10, 2023 5 - Production/Stable pytest :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Dec 03, 2022 5 - Production/Stable pytest (>=3.0.0) @@ -960,14 +961,14 @@ This list contains 1282 plugins. :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-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Apr 26, 2023 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jun 01, 2023 N/A pytest (~=4.6) ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jul 11, 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 :pypi:`pytest-responsemock` Simplified requests calls mocking for pytest Mar 10, 2022 5 - Production/Stable N/A :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jun 16, 2023 5 - Production/Stable pytest + :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jul 10, 2023 5 - Production/Stable pytest :pypi:`pytest-result-log` Write the execution result of the case to the log Apr 17, 2023 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) @@ -975,7 +976,7 @@ This list contains 1282 plugins. :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 16, 2022 N/A pytest (>=7.0.0) :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A - :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jun 16, 2023 5 - Production/Stable pytest + :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) :pypi:`pytest-richtrace` A pytest plugin that displays the names and information of the pytest hook functions as they are executed. Jun 20, 2023 N/A N/A @@ -1007,14 +1008,14 @@ This list contains 1282 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 08, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 13, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 08, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 13, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A @@ -1022,7 +1023,7 @@ This list contains 1282 plugins. :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Apr 15, 2023 3 - Alpha pytest (>=6.2) + :pypi:`pytest-servers` pytest servers Jul 13, 2023 3 - Alpha pytest (>=6.2) :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1124,7 +1125,7 @@ This list contains 1282 plugins. :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) - :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Oct 27, 2021 5 - Production/Stable pytest (>=3.0) + :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Jul 15, 2023 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) @@ -1144,7 +1145,7 @@ This list contains 1282 plugins. :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A :pypi:`pytest-testinfra` Test infrastructures May 21, 2023 5 - Production/Stable pytest (!=3.0.2) :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) - :pypi:`pytest-testmon` selects tests affected by changed files and methods Jun 16, 2023 4 - Beta N/A + :pypi:`pytest-testmon` selects tests affected by changed files and methods Jul 13, 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) @@ -1166,7 +1167,7 @@ This list contains 1282 plugins. :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) :pypi:`pytest-tesults` Tesults plugin for pytest Dec 23, 2022 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jun 27, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 12, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A @@ -1651,7 +1652,7 @@ This list contains 1282 plugins. Extension for ApprovalTests.Python specific to geo data verification :pypi:`pytest-archon` - *last release*: Jan 31, 2023, + *last release*: Jul 11, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=7.2) @@ -1770,7 +1771,7 @@ This list contains 1282 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Mar 19, 2023, + *last release*: Jul 12, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0.0) @@ -2400,14 +2401,14 @@ This list contains 1282 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Jun 06, 2023, + *last release*: Jul 14, 2023, *status*: N/A, *requires*: pytest A pytest plugin that allows multiple failures per test. :pypi:`pytest-checkdocs` - *last release*: Oct 09, 2022, + *last release*: Jul 09, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6) ; extra == 'testing' @@ -3275,7 +3276,7 @@ This list contains 1282 plugins. Disable plugins per test :pypi:`pytest-discord` - *last release*: Feb 05, 2023, + *last release*: Jul 15, 2023, *status*: 4 - Beta, *requires*: pytest (!=6.0.0,<8,>=3.3.2) @@ -3652,6 +3653,13 @@ This list contains 1282 plugins. A Pytest plugin to drop duplicated tests during collection + :pypi:`pytest-dryrun` + *last release*: Jul 11, 2023, + *status*: N/A, + *requires*: pytest (>=7.4.0,<8.0.0) + + A Pytest plugin to ignore tests during collection without reporting them in the test summary. + :pypi:`pytest-dummynet` *last release*: Dec 15, 2021, *status*: 5 - Production/Stable, @@ -3793,49 +3801,49 @@ This list contains 1282 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jul 05, 2023, + *last release*: Jul 09, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jul 05, 2023, + *last release*: Jul 09, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jul 05, 2023, + *last release*: Jul 09, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jul 05, 2023, + *last release*: Jul 09, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jul 05, 2023, + *last release*: Jul 09, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jul 05, 2023, + *last release*: Jul 09, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jul 05, 2023, + *last release*: Jul 09, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -3863,7 +3871,7 @@ This list contains 1282 plugins. Pytest plugin to represent test output with emoji support :pypi:`pytest-enabler` - *last release*: Jun 26, 2023, + *last release*: Jul 14, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6) ; extra == 'testing' @@ -3982,7 +3990,7 @@ This list contains 1282 plugins. Applies eventlet monkey-patch as a pytest plugin. :pypi:`pytest-examples` - *last release*: May 05, 2023, + *last release*: Jul 11, 2023, *status*: 4 - Beta, *requires*: pytest>=7 @@ -4395,7 +4403,7 @@ This list contains 1282 plugins. pytest plugin to check FLAKE8 requirements :pypi:`pytest-flake8-path` - *last release*: Jun 16, 2023, + *last release*: Jul 10, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -4878,7 +4886,7 @@ This list contains 1282 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jul 07, 2023, + *last release*: Jul 14, 2023, *status*: 3 - Alpha, *requires*: pytest (==7.3.1) @@ -5032,7 +5040,7 @@ This list contains 1282 plugins. pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: Jun 03, 2023, + *last release*: Jul 09, 2023, *status*: N/A, *requires*: pytest (>=7.2.0,<8.0.0) @@ -5256,7 +5264,7 @@ This list contains 1282 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Jun 29, 2023, + *last release*: Jul 14, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5305,7 +5313,7 @@ This list contains 1282 plugins. py.test plugin to check import ordering using isort :pypi:`pytest-is-running` - *last release*: Jun 16, 2023, + *last release*: Jul 10, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5375,7 +5383,7 @@ This list contains 1282 plugins. Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: Jun 06, 2023, + *last release*: Jul 11, 2023, *status*: 4 - Beta, *requires*: pytest @@ -6117,7 +6125,7 @@ This list contains 1282 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Jun 09, 2023, + *last release*: Jul 12, 2023, *status*: N/A, *requires*: pytest (>=1.0) @@ -6411,7 +6419,7 @@ This list contains 1282 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Jun 07, 2023, + *last release*: Jul 11, 2023, *status*: N/A, *requires*: pytest (==6.2.5) @@ -7545,7 +7553,7 @@ This list contains 1282 plugins. py.test plugin to randomize tests :pypi:`pytest-randomly` - *last release*: May 11, 2022, + *last release*: Jul 10, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -7888,7 +7896,7 @@ This list contains 1282 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Jun 01, 2023, + *last release*: Jul 11, 2023, *status*: N/A, *requires*: pytest (~=4.6) ; python_version == "2.7" @@ -7937,7 +7945,7 @@ This list contains 1282 plugins. :pypi:`pytest-restrict` - *last release*: Jun 16, 2023, + *last release*: Jul 10, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -7993,7 +8001,7 @@ This list contains 1282 plugins. :pypi:`pytest-reverse` - *last release*: Jun 16, 2023, + *last release*: Jul 10, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -8217,7 +8225,7 @@ This list contains 1282 plugins. :pypi:`pytest-sbase` - *last release*: Jul 08, 2023, + *last release*: Jul 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8266,7 +8274,7 @@ This list contains 1282 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Jul 08, 2023, + *last release*: Jul 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8322,7 +8330,7 @@ This list contains 1282 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Apr 15, 2023, + *last release*: Jul 13, 2023, *status*: 3 - Alpha, *requires*: pytest (>=6.2) @@ -9036,7 +9044,7 @@ This list contains 1282 plugins. A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. :pypi:`pytest-tap` - *last release*: Oct 27, 2021, + *last release*: Jul 15, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=3.0) @@ -9176,9 +9184,9 @@ This list contains 1282 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: Jun 16, 2023, + *last release*: Jul 13, 2023, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest (<8,>=5) selects tests affected by changed files and methods @@ -9330,7 +9338,7 @@ This list contains 1282 plugins. Tesults plugin for pytest :pypi:`pytest-textual-snapshot` - *last release*: Jun 27, 2023, + *last release*: Jul 12, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0.0) From a3fbf2438975d72887ef5b614d529bab893937ca Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 15 Jul 2023 21:35:05 +0300 Subject: [PATCH 0086/1271] unittest: hide access to _request Let the parent class (Function) do this. Tiny bit better abstraction. There seems to be no reason for the `hasattr` bit. --- src/_pytest/unittest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 27598cbdef6..34845cec1c7 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -200,10 +200,10 @@ def setup(self) -> None: assert self.parent is not None self._testcase = self.parent.obj(self.name) # type: ignore[attr-defined] self._obj = getattr(self._testcase, self.name) - if hasattr(self, "_request"): - self._request._fillfixtures() + super().setup() def teardown(self) -> None: + super().teardown() if self._explicit_tearDown is not None: self._explicit_tearDown() self._explicit_tearDown = None From 0e0ed2af950754248dbcedc926a49f55bdb095e0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 15 Jul 2023 22:16:32 +0300 Subject: [PATCH 0087/1271] fixtures: some code comments and minor improvements --- src/_pytest/compat.py | 2 +- src/_pytest/fixtures.py | 56 +++++++++++++++++++++++++++++------------ 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 47ffe47e89b..cead6c3113c 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -102,7 +102,7 @@ def num_mock_patch_args(function) -> int: def getfuncargnames( - function: Callable[..., Any], + function: Callable[..., object], *, name: str = "", is_method: bool = False, diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index e81fe9692ad..5fb8b881d4a 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -354,16 +354,27 @@ def get_direct_param_fixture_func(request: "FixtureRequest") -> Any: @dataclasses.dataclass(frozen=True) class FuncFixtureInfo: + """Fixture-related information for a fixture-requesting item (e.g. test + function). + + This is used to examine the fixtures which an item requests statically + (known during collection). This includes autouse fixtures, fixtures + requested by the `usefixtures` marker, fixtures requested in the function + parameters, and the transitive closure of these. + + An item may also request fixtures dynamically (using `request.getfixturevalue`); + these are not reflected here. + """ + __slots__ = ("argnames", "initialnames", "names_closure", "name2fixturedefs") - # Original function argument names, i.e. fixture names that the function - # requests directly. + # Fixture names that the item requests directly by function parameters. argnames: Tuple[str, ...] - # Fixture names that the function immediately requires. These include + # Fixture names that the item immediately requires. These include # argnames + fixture names specified via usefixtures and via autouse=True in # fixture definitions. initialnames: Tuple[str, ...] - # The transitive closure of the fixture names that the function requires. + # The transitive closure of the fixture names that the item requires. # Note: can't include dynamic dependencies (`request.getfixturevalue` calls). names_closure: List[str] # A map from a fixture name in the transitive closure to the FixtureDefs @@ -547,8 +558,7 @@ def path(self) -> Path: """Path where the test function was collected.""" if self.scope not in ("function", "class", "module", "package"): raise AttributeError(f"path not available in {self.scope}-scoped context") - # TODO: Remove ignore once _pyfuncitem is properly typed. - return self._pyfuncitem.path # type: ignore + return self._pyfuncitem.path @property def keywords(self) -> MutableMapping[str, Any]: @@ -620,9 +630,8 @@ def getfixturevalue(self, argname: str) -> Any: def _get_active_fixturedef( self, argname: str ) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]: - try: - return self._fixture_defs[argname] - except KeyError: + fixturedef = self._fixture_defs.get(argname) + if fixturedef is None: try: fixturedef = self._getnextfixturedef(argname) except FixtureLookupError: @@ -630,10 +639,8 @@ def _get_active_fixturedef( cached_result = (self, [0], None) return PseudoFixtureDef(cached_result, Scope.Function) raise - # Remove indent to prevent the python3 exception - # from leaking into the call. - self._compute_fixture_value(fixturedef) - self._fixture_defs[argname] = fixturedef + self._compute_fixture_value(fixturedef) + self._fixture_defs[argname] = fixturedef return fixturedef def _get_fixturestack(self) -> List["FixtureDef[Any]"]: @@ -1467,8 +1474,26 @@ def _get_direct_parametrize_args(self, node: nodes.Node) -> List[str]: return parametrize_argnames def getfixtureinfo( - self, node: nodes.Node, func, cls, funcargs: bool = True + self, + node: nodes.Item, + func: Callable[..., object], + cls: Optional[type], + funcargs: bool = True, ) -> FuncFixtureInfo: + """Calculate the :class:`FuncFixtureInfo` for an item. + + If ``funcargs`` is false, or if the item sets an attribute + ``nofuncargs = True``, then ``func`` is not examined at all. + + :param node: + The item requesting the fixtures. + :param func: + The item's function. + :param cls: + If the function is a method, the method's class. + :param funcargs: + Whether to look into func's parameters as fixture requests. + """ if funcargs and not getattr(node, "nofuncargs", False): argnames = getfuncargnames(func, name=node.name, cls=cls) else: @@ -1478,8 +1503,7 @@ def getfixtureinfo( arg for mark in node.iter_markers(name="usefixtures") for arg in mark.args ) initialnames = usefixtures + argnames - fm = node.session._fixturemanager - initialnames, names_closure, arg2fixturedefs = fm.getfixtureclosure( + initialnames, names_closure, arg2fixturedefs = self.getfixtureclosure( initialnames, node, ignore_args=self._get_direct_parametrize_args(node) ) return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs) From ff6e110161b83c151d4a2f887c0910311ce35ef1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 15 Jul 2023 22:54:15 +0300 Subject: [PATCH 0088/1271] fixtures: remove inaccurate comment unittest TestCases can also use `usefixtures`. Just remove this comment, it's not very helpful. --- src/_pytest/fixtures.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 5fb8b881d4a..f736b42b19c 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1046,8 +1046,6 @@ def __init__( # The names requested by the fixtures. self.argnames: Final = getfuncargnames(func, name=argname, is_method=unittest) # Whether the fixture was collected from a unittest TestCase class. - # Note that it really only makes sense to define autouse fixtures in - # unittest TestCases. self.unittest: Final = unittest # If the fixture was executed, the current value of the fixture. # Can change if the fixture is executed with different parameters. From c5262b0c42b9d82bb66665c7bbb1599d63bb2634 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 16 Jul 2023 23:05:51 +0300 Subject: [PATCH 0089/1271] fixtures: show test as skip location if skipped from an xunit setup function Fix #11216. --- changelog/11216.improvement.rst | 1 + src/_pytest/fixtures.py | 7 ++++--- testing/test_skipping.py | 21 +++++++++++---------- 3 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 changelog/11216.improvement.rst diff --git a/changelog/11216.improvement.rst b/changelog/11216.improvement.rst new file mode 100644 index 00000000000..80761de5c6e --- /dev/null +++ b/changelog/11216.improvement.rst @@ -0,0 +1 @@ +If a test is skipped from inside an :ref:`xunit setup fixture `, the test summary now shows the test location instead of the fixture location. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index e81fe9692ad..525467192aa 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1162,9 +1162,10 @@ def pytest_fixture_setup( try: result = call_fixture_func(fixturefunc, request, kwargs) except TEST_OUTCOME as e: - if isinstance(e, skip.Exception) and not fixturefunc.__name__.startswith( - "xunit_setup" - ): + if isinstance(e, skip.Exception): + # The test requested a fixture which caused a skip. + # Don't show the fixture as the skip location, as then the user + # wouldn't know which test skipped. e._use_item_location = True fixturedef.cached_result = (None, my_cache_key, e) raise diff --git a/testing/test_skipping.py b/testing/test_skipping.py index d8b22aa463f..b7e448df366 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -989,33 +989,34 @@ def test_skipped_reasons_functional(pytester: Pytester) -> None: pytester.makepyfile( test_one=""" import pytest - from conftest import doskip + from helpers import doskip - def setup_function(func): - doskip() + def setup_function(func): # LINE 4 + doskip("setup function") def test_func(): pass - class TestClass(object): + class TestClass: def test_method(self): - doskip() + doskip("test method") - @pytest.mark.skip("via_decorator") + @pytest.mark.skip("via_decorator") # LINE 14 def test_deco(self): assert 0 """, - conftest=""" + helpers=""" import pytest, sys - def doskip(): + def doskip(reason): assert sys._getframe().f_lineno == 3 - pytest.skip('test') + pytest.skip(reason) # LINE 4 """, ) result = pytester.runpytest("-rs") result.stdout.fnmatch_lines_random( [ - "SKIPPED [[]2[]] conftest.py:4: test", + "SKIPPED [[]1[]] test_one.py:7: setup function", + "SKIPPED [[]1[]] helpers.py:4: test method", "SKIPPED [[]1[]] test_one.py:14: via_decorator", ] ) From cfda801ebf0bb790459fd77148a355c51c9c9d56 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 09:27:38 +0200 Subject: [PATCH 0090/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#11222) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.21.0 to 0.21.1. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.21.0...v0.21.1) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index c99c9f8dc70..cf580b7ccb4 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==3.7.1 django==4.2.3 -pytest-asyncio==0.21.0 +pytest-asyncio==0.21.1 pytest-bdd==6.1.1 pytest-cov==4.1.0 pytest-django==4.5.2 From de1f6f58ba10d31cb5f6657f1b441c4317a97a50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 09:31:06 +0200 Subject: [PATCH 0091/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.8.7 to 1.8.8 (#11221) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.7 to 1.8.8. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.7...v1.8.8) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 32feb92d5c8..ca401f09210 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -38,7 +38,7 @@ jobs: name: Packages path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.8.7 + uses: pypa/gh-action-pypi-publish@v1.8.8 release-notes: From 396bfbf30b1594b6f56528913d6144826060198e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 17 Jul 2023 23:58:35 +0300 Subject: [PATCH 0092/1271] fixtures: add a test for a currently non-covered scope mismatch scenario This test makes clear the need for the `_check_scope()` call in the `pytest_setup_fixture` impl in fixtures.py, which otherwise seems redundant with the one in `_compute_fixture_value`. --- testing/python/fixtures.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 63c18456a72..191689d1c2e 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2464,6 +2464,31 @@ def test_1(arg): ["*ScopeMismatch*You tried*function*session*request*"] ) + def test_scope_mismatch_already_computed_dynamic(self, pytester: Pytester) -> None: + pytester.makepyfile( + test_it=""" + import pytest + + @pytest.fixture(scope="function") + def fixfunc(): pass + + @pytest.fixture(scope="module") + def fixmod(fixfunc): pass + + def test_it(request, fixfunc): + request.getfixturevalue("fixmod") + """, + ) + + result = pytester.runpytest() + assert result.ret == ExitCode.TESTS_FAILED + result.stdout.fnmatch_lines( + [ + "*ScopeMismatch*involved factories*", + "test_it.py:6: def fixmod(fixfunc)", + ] + ) + def test_dynamic_scope(self, pytester: Pytester) -> None: pytester.makeconftest( """ From 1de0923e83e3258709559d86d142adaab65a42d8 Mon Sep 17 00:00:00 2001 From: Isaac Virshup Date: Tue, 18 Jul 2023 13:39:39 +0200 Subject: [PATCH 0093/1271] Have pytest.raises match against exception `__notes__` (#11227) The doctest is skipped because add_note is only available in 3.11, Closes #11223 --- AUTHORS | 1 + changelog/11227.improvement.rst | 1 + src/_pytest/_code/code.py | 7 +++- src/_pytest/python_api.py | 8 +++++ testing/code/test_excinfo.py | 62 +++++++++++++++++++++++++++++---- 5 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 changelog/11227.improvement.rst diff --git a/AUTHORS b/AUTHORS index f507fea75e9..f2b59b7c4db 100644 --- a/AUTHORS +++ b/AUTHORS @@ -168,6 +168,7 @@ Ian Bicking Ian Lesperance Ilya Konstantinov Ionuț Turturică +Isaac Virshup Itxaso Aizpurua Iwan Briquemont Jaap Broekhuizen diff --git a/changelog/11227.improvement.rst b/changelog/11227.improvement.rst new file mode 100644 index 00000000000..3c6748c3d3f --- /dev/null +++ b/changelog/11227.improvement.rst @@ -0,0 +1 @@ +Allow :func:`pytest.raises` ``match`` argument to match against `PEP-678 ` ``__notes__``. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 42c5fa8bd4d..b73c8bbb3da 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -704,7 +704,12 @@ def match(self, regexp: Union[str, Pattern[str]]) -> "Literal[True]": If it matches `True` is returned, otherwise an `AssertionError` is raised. """ __tracebackhide__ = True - value = str(self.value) + value = "\n".join( + [ + str(self.value), + *getattr(self.value, "__notes__", []), + ] + ) msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" if regexp == value: msg += "\n Did you mean to `re.escape()` the regex?" diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 200b2b3aab6..a045da2206b 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -843,6 +843,14 @@ def raises( # noqa: F811 >>> with pytest.raises(ValueError, match=r'must be \d+$'): ... raise ValueError("value must be 42") + The ``match`` argument searches the formatted exception string, which includes any + `PEP-678 ` ``__notes__``: + + >>> with pytest.raises(ValueError, match=r'had a note added'): # doctest: +SKIP + ... e = ValueError("value must be 42") + ... e.add_note("had a note added") + ... raise e + The context manager produces an :class:`ExceptionInfo` object which can be used to inspect the details of the captured exception:: diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index e5c030c4d66..90f81123e01 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1,15 +1,15 @@ +from __future__ import annotations + import importlib import io import operator import queue +import re import sys import textwrap from pathlib import Path from typing import Any -from typing import Dict -from typing import Tuple from typing import TYPE_CHECKING -from typing import Union import _pytest._code import pytest @@ -801,7 +801,7 @@ def entry(): ) excinfo = pytest.raises(ValueError, mod.entry) - styles: Tuple[_TracebackStyle, ...] = ("long", "short") + styles: tuple[_TracebackStyle, ...] = ("long", "short") for style in styles: p = FormattedExcinfo(style=style) reprtb = p.repr_traceback(excinfo) @@ -928,7 +928,7 @@ def entry(): ) excinfo = pytest.raises(ValueError, mod.entry) - styles: Tuple[_TracebackStyle, ...] = ("short", "long", "no") + styles: tuple[_TracebackStyle, ...] = ("short", "long", "no") for style in styles: for showlocals in (True, False): repr = excinfo.getrepr(style=style, showlocals=showlocals) @@ -1090,7 +1090,7 @@ def f(): for funcargs in (True, False) ], ) - def test_format_excinfo(self, reproptions: Dict[str, Any]) -> None: + def test_format_excinfo(self, reproptions: dict[str, Any]) -> None: def bar(): assert False, "some error" @@ -1398,7 +1398,7 @@ def f(): @pytest.mark.parametrize("encoding", [None, "utf8", "utf16"]) def test_repr_traceback_with_unicode(style, encoding): if encoding is None: - msg: Union[str, bytes] = "☹" + msg: str | bytes = "☹" else: msg = "☹".encode(encoding) try: @@ -1648,3 +1648,51 @@ def test(): ], consecutive=True, ) + + +def add_note(err: BaseException, msg: str) -> None: + """Adds a note to an exception inplace.""" + if sys.version_info < (3, 11): + err.__notes__ = getattr(err, "__notes__", []) + [msg] # type: ignore[attr-defined] + else: + err.add_note(msg) + + +@pytest.mark.parametrize( + "error,notes,match", + [ + (Exception("test"), [], "test"), + (AssertionError("foo"), ["bar"], "bar"), + (AssertionError("foo"), ["bar", "baz"], "bar"), + (AssertionError("foo"), ["bar", "baz"], "baz"), + (ValueError("foo"), ["bar", "baz"], re.compile(r"bar\nbaz", re.MULTILINE)), + (ValueError("foo"), ["bar", "baz"], re.compile(r"BAZ", re.IGNORECASE)), + ], +) +def test_check_error_notes_success( + error: Exception, notes: list[str], match: str +) -> None: + for note in notes: + add_note(error, note) + + with pytest.raises(Exception, match=match): + raise error + + +@pytest.mark.parametrize( + "error, notes, match", + [ + (Exception("test"), [], "foo"), + (AssertionError("foo"), ["bar"], "baz"), + (AssertionError("foo"), ["bar"], "foo\nbaz"), + ], +) +def test_check_error_notes_failure( + error: Exception, notes: list[str], match: str +) -> None: + for note in notes: + add_note(error, note) + + with pytest.raises(AssertionError): + with pytest.raises(type(error), match=match): + raise error From 497a1d798ae9918d647707328c0b40f299430aa3 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 20 Jul 2023 09:41:16 +0300 Subject: [PATCH 0094/1271] doc/example/parametrize: a few fixes/improvements Remove "Indirect" from a few section names -- not actually indirect. Also few minor updates to the related multipython.py example. --- doc/en/example/multipython.py | 13 ++++++------- doc/en/example/parametrize.rst | 8 ++++---- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/doc/en/example/multipython.py b/doc/en/example/multipython.py index 9005d31addd..8d76ed483e8 100644 --- a/doc/en/example/multipython.py +++ b/doc/en/example/multipython.py @@ -1,14 +1,13 @@ -""" -module containing a parametrized tests testing cross-python -serialization via the pickle module. -""" +"""Module containing a parametrized tests testing cross-python serialization +via the pickle module.""" import shutil import subprocess import textwrap import pytest -pythonlist = ["python3.5", "python3.6", "python3.7"] + +pythonlist = ["python3.9", "python3.10", "python3.11"] @pytest.fixture(params=pythonlist) @@ -43,7 +42,7 @@ def dumps(self, obj): ) ) ) - subprocess.check_call((self.pythonpath, str(dumpfile))) + subprocess.run((self.pythonpath, str(dumpfile)), check=True) def load_and_is_true(self, expression): loadfile = self.picklefile.with_name("load.py") @@ -63,7 +62,7 @@ def load_and_is_true(self, expression): ) ) print(loadfile) - subprocess.check_call((self.pythonpath, str(loadfile))) + subprocess.run((self.pythonpath, str(loadfile)), check=True) @pytest.mark.parametrize("obj", [42, {}, {1: 3}]) diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index df2859b14e0..f771e5da4e0 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -483,8 +483,8 @@ argument sets to use for each test function. Let's run it: FAILED test_parametrize.py::TestClass::test_equals[1-2] - assert 1 == 2 1 failed, 2 passed in 0.12s -Indirect parametrization with multiple fixtures --------------------------------------------------------------- +Parametrization with multiple fixtures +-------------------------------------- Here is a stripped down real-life example of using parametrized testing for testing serialization of objects between different python @@ -509,8 +509,8 @@ Running it results in some skips if we don't have all the python interpreters in SKIPPED [9] multipython.py:69: 'python3.7' not found 27 skipped in 0.12s -Indirect parametrization of optional implementations/imports --------------------------------------------------------------------- +Parametrization of optional implementations/imports +--------------------------------------------------- If you want to compare the outcomes of several implementations of a given API, you can write test functions that receive the already imported implementations From 1ded74739b4d6be9dd9a20537296312685e683b1 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 24 Apr 2023 17:12:25 +0200 Subject: [PATCH 0095/1271] update-plugin-list: use json, use http caching, use gh action caches this change * switches from html index usage to json index usage * adds using requests-cache as http cache to trim down runtime * adds gh action caches for pip and the new http cache --- .github/workflows/update-plugin-list.yml | 12 ++- doc/en/reference/plugin_list.rst | 102 +++++++++++++++++------ scripts/update-plugin-list.py | 63 ++++++++++---- 3 files changed, 135 insertions(+), 42 deletions(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index e7cbc4e96be..b278f633fba 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -27,12 +27,20 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: 3.8 + python-version: "3.8" + cache: pip + - name: requests-cache + uses: actions/cache@v3 + with: + path: ~/.cache/pytest-plugin-list/ + key: plugins-http-cache-${{ github.run_id }} # Can use time based key as well + restore-keys: plugins-http-cache- - name: Install dependencies run: | python -m pip install --upgrade pip - pip install packaging requests tabulate[widechars] tqdm + pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs + - name: Update Plugin List run: python scripts/update-plugin-list.py diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 82b8286da74..0a333976ec2 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -1,4 +1,6 @@ +.. Note this file is autogenerated by scripts/update-plugin-list.py - usually weekly via github action + .. _plugin-list: Plugin List @@ -13,7 +15,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1283 plugins. +This list contains 1289 plugins. .. only:: not latex @@ -198,7 +200,7 @@ This list contains 1283 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Jan 21, 2023 N/A pytest<8,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Jul 19, 2023 N/A pytest<8,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest @@ -301,7 +303,7 @@ This list contains 1283 plugins. :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Jun 23, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Jul 15, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) + :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Jul 16, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) :pypi:`pytest-django` A Django plugin for pytest. Dec 07, 2021 5 - Production/Stable pytest (>=5.4.0) :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest @@ -325,7 +327,7 @@ This list contains 1283 plugins. :pypi:`pytest-doc` A documentation plugin for py.test. Jun 28, 2015 5 - Production/Stable N/A :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A - :pypi:`pytest-docker` Simple pytest fixtures for Docker and docker-compose based tests Sep 14, 2022 N/A pytest (<8.0,>=4.0) + :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Jul 19, 2023 N/A pytest (<8.0,>=4.0) :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Feb 16, 2022 4 - Beta pytest :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) @@ -355,7 +357,7 @@ This list contains 1283 plugins. :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection May 23, 2020 4 - Beta pytest (>=2.7) - :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 11, 2023 N/A pytest (>=7.4.0,<8.0.0) + :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 18, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jun 25, 2021 N/A N/A @@ -651,7 +653,7 @@ This list contains 1283 plugins. :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 04, 2022 5 - Production/Stable pytest - :pypi:`pytest-localserver` pytest plugin to test server connections locally. Jan 30, 2023 4 - Beta N/A + :pypi:`pytest-localserver` pytest plugin to test server connections locally. Jul 16, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lockable` lockable resource plugin for pytest Jul 20, 2022 5 - Production/Stable pytest :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) @@ -662,7 +664,7 @@ This list contains 1283 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Jun 22, 2023 5 - Production/Stable pytest (==7.3.1) + :pypi:`pytest-logikal` Common testing environment Jul 17, 2023 5 - Production/Stable pytest (==7.4.0) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) @@ -684,7 +686,7 @@ This list contains 1283 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Jun 25, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) + :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Jul 16, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Jun 06, 2023 N/A pytest>=7.2 @@ -716,6 +718,7 @@ This list contains 1283 plugins. :pypi:`pytest-modifyjunit` Utility for adding additional properties to junit xml for IDM QE Jan 10, 2019 N/A N/A :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) + :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jun 07, 2021 5 - Production/Stable pytest :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest @@ -740,6 +743,7 @@ This list contains 1283 plugins. :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-ndb` Open Source Software Health Report Jul 19, 2023 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jul 06, 2023 N/A pytest (>=3.5.0) @@ -766,6 +770,7 @@ This list contains 1283 plugins. :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A + :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Jul 18, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-odoo` py.test plugin to run Odoo tests Jul 06, 2023 4 - Beta pytest (>=7.2.0) :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A @@ -864,6 +869,7 @@ This list contains 1283 plugins. :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest :pypi:`pytest-prosper` Test helpers for Prosper projects Sep 24, 2018 N/A N/A + :pypi:`pytest-prysk` Pytest plugin for prysk Jul 18, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) @@ -949,7 +955,7 @@ This list contains 1283 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Jun 30, 2023 N/A pytest (>=3.8.0) + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Jul 18, 2023 N/A pytest (>=3.8.0) :pypi:`pytest-reports` An interesting python package Jun 07, 2023 N/A N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) @@ -1008,14 +1014,15 @@ This list contains 1283 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 20, 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 18, 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-seleniumbase` A complete web automation framework for end-to-end testing. Jul 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 20, 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 @@ -1067,6 +1074,7 @@ This list contains 1283 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) + :pypi:`pytest-sort` Tools for sorting test cases Jul 17, 2023 N/A pytest (>=7.0.0) :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Feb 14, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest @@ -1167,7 +1175,7 @@ This list contains 1283 plugins. :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) :pypi:`pytest-tesults` Tesults plugin for pytest Dec 23, 2022 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 12, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 18, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A @@ -2555,7 +2563,7 @@ This list contains 1283 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Jan 21, 2023, + *last release*: Jul 19, 2023, *status*: N/A, *requires*: pytest<8,>=4 @@ -3276,7 +3284,7 @@ This list contains 1283 plugins. Disable plugins per test :pypi:`pytest-discord` - *last release*: Jul 15, 2023, + *last release*: Jul 16, 2023, *status*: 4 - Beta, *requires*: pytest (!=6.0.0,<8,>=3.3.2) @@ -3444,11 +3452,11 @@ This list contains 1283 plugins. An RST Documentation Generator for pytest-based test suites :pypi:`pytest-docker` - *last release*: Sep 14, 2022, + *last release*: Jul 19, 2023, *status*: N/A, *requires*: pytest (<8.0,>=4.0) - Simple pytest fixtures for Docker and docker-compose based tests + Simple pytest fixtures for Docker and Docker Compose based tests :pypi:`pytest-docker-apache-fixtures` *last release*: Feb 16, 2022, @@ -3654,8 +3662,8 @@ This list contains 1283 plugins. A Pytest plugin to drop duplicated tests during collection :pypi:`pytest-dryrun` - *last release*: Jul 11, 2023, - *status*: N/A, + *last release*: Jul 18, 2023, + *status*: 5 - Production/Stable, *requires*: pytest (>=7.4.0,<8.0.0) A Pytest plugin to ignore tests during collection without reporting them in the test summary. @@ -5726,7 +5734,7 @@ This list contains 1283 plugins. A PyTest plugin which provides an FTP fixture for your tests :pypi:`pytest-localserver` - *last release*: Jan 30, 2023, + *last release*: Jul 16, 2023, *status*: 4 - Beta, *requires*: N/A @@ -5803,9 +5811,9 @@ This list contains 1283 plugins. :pypi:`pytest-logikal` - *last release*: Jun 22, 2023, + *last release*: Jul 17, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (==7.3.1) + *requires*: pytest (==7.4.0) Common testing environment @@ -5957,7 +5965,7 @@ This list contains 1283 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: Jun 25, 2023, + *last release*: Jul 16, 2023, *status*: 4 - Beta, *requires*: pytest (!=6.0.0,<8,>=3.3.2) @@ -6180,6 +6188,13 @@ This list contains 1283 plugins. PyTest Molecule Plugin :: discover and run molecule tests + :pypi:`pytest-molecule-JC` + *last release*: Jul 18, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest (>=7.0.0) + + PyTest Molecule Plugin :: discover and run molecule tests + :pypi:`pytest-mongo` *last release*: Jun 07, 2021, *status*: 5 - Production/Stable, @@ -6348,6 +6363,13 @@ This list contains 1283 plugins. MySQL process and client fixtures for pytest + :pypi:`pytest-ndb` + *last release*: Jul 19, 2023, + *status*: N/A, + *requires*: pytest + + Open Source Software Health Report + :pypi:`pytest-needle` *last release*: Dec 10, 2018, *status*: 4 - Beta, @@ -6530,6 +6552,13 @@ This list contains 1283 plugins. pytest results data-base and HTML reporter + :pypi:`pytest-odc` + *last release*: Jul 18, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=3.5.0) + + A pytest plugin for simplifying ODC database tests + :pypi:`pytest-odoo` *last release*: Jul 06, 2023, *status*: 4 - Beta, @@ -7216,6 +7245,13 @@ This list contains 1283 plugins. Test helpers for Prosper projects + :pypi:`pytest-prysk` + *last release*: Jul 18, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=7.3.2,<8.0.0) + + Pytest plugin for prysk + :pypi:`pytest-pspec` *last release*: Jun 02, 2020, *status*: 4 - Beta, @@ -7812,7 +7848,7 @@ This list contains 1283 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Jun 30, 2023, + *last release*: Jul 18, 2023, *status*: N/A, *requires*: pytest (>=3.8.0) @@ -8225,7 +8261,7 @@ This list contains 1283 plugins. :pypi:`pytest-sbase` - *last release*: Jul 13, 2023, + *last release*: Jul 20, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8252,6 +8288,13 @@ This list contains 1283 plugins. 👍 Validate return values against a schema-like object in testing + :pypi:`pytest-screenshot-on-failure` + *last release*: Jul 18, 2023, + *status*: 4 - Beta, + *requires*: N/A + + Saves a screenshot when a test case from a pytest execution fails + :pypi:`pytest-securestore` *last release*: Nov 08, 2021, *status*: 4 - Beta, @@ -8274,7 +8317,7 @@ This list contains 1283 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Jul 13, 2023, + *last release*: Jul 20, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8637,6 +8680,13 @@ This list contains 1283 plugins. Solr process and client fixtures for py.test. + :pypi:`pytest-sort` + *last release*: Jul 17, 2023, + *status*: N/A, + *requires*: pytest (>=7.0.0) + + Tools for sorting test cases + :pypi:`pytest-sorter` *last release*: Apr 20, 2021, *status*: 4 - Beta, @@ -9338,7 +9388,7 @@ This list contains 1283 plugins. Tesults plugin for pytest :pypi:`pytest-textual-snapshot` - *last release*: Jul 12, 2023, + *last release*: Jul 18, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0.0) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index ea7e7986e15..eaf5619207c 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -5,12 +5,19 @@ from textwrap import indent import packaging.version -import requests +import platformdirs import tabulate import wcwidth +from requests_cache import CachedResponse +from requests_cache import CachedSession +from requests_cache import OriginalResponse +from requests_cache import SQLiteCache from tqdm import tqdm + FILE_HEAD = r""" +.. Note this file is autogenerated by scripts/update-plugin-list.py - usually weekly via github action + .. _plugin-list: Plugin List @@ -53,19 +60,47 @@ def escape_rst(text: str) -> str: return text +def project_response_with_refresh( + session: CachedSession, name: str, last_serial: int +) -> OriginalResponse | CachedResponse: + """Get a http cached pypi project + + force refresh in case of last serial mismatch + """ + + response = session.get(f"https://pypi.org/pypi/{name}/json") + if int(response.headers.get("X-PyPI-Last-Serial", -1)) != last_serial: + response = session.get(f"https://pypi.org/pypi/{name}/json", refresh=True) + return response + + +def get_session() -> CachedSession: + """Configures the requests-cache session""" + cache_path = platformdirs.user_cache_path("pytest-plugin-list") + cache_path.mkdir(exist_ok=True, parents=True) + cache_file = cache_path.joinpath("http_cache.sqlite3") + return CachedSession(backend=SQLiteCache(cache_file)) + + +def pytest_plugin_projects_from_pypi(session: CachedSession) -> dict[str, int]: + response = session.get( + "https://pypi.org/simple", + headers={"Accept": "application/vnd.pypi.simple.v1+json"}, + refresh=True, + ) + return { + name: p["_last-serial"] + for p in response.json()["projects"] + if (name := p["name"]).startswith("pytest-") or name in ADDITIONAL_PROJECTS + } + + def iter_plugins(): - regex = r">([\d\w-]*)" - response = requests.get("https://pypi.org/simple") - - match_names = (match.groups()[0] for match in re.finditer(regex, response.text)) - plugin_names = [ - name - for name in match_names - if name.startswith("pytest-") or name in ADDITIONAL_PROJECTS - ] - - for name in tqdm(plugin_names, smoothing=0): - response = requests.get(f"https://pypi.org/pypi/{name}/json") + session = get_session() + name_2_serial = pytest_plugin_projects_from_pypi(session) + + for name, last_serial in tqdm(name_2_serial.items(), smoothing=0): + response = project_response_with_refresh(session, name, last_serial) if response.status_code == 404: # Some packages, like pytest-azurepipelines42, are included in https://pypi.org/simple # but return 404 on the JSON API. Skip. @@ -136,7 +171,7 @@ def plugin_definitions(plugins): def main(): - plugins = list(iter_plugins()) + plugins = [*iter_plugins()] reference_dir = pathlib.Path("doc", "en", "reference") From 0b4a557087b7d90f4db44a893470545656730d2a Mon Sep 17 00:00:00 2001 From: bowugit Date: Fri, 21 Jul 2023 00:29:29 +0800 Subject: [PATCH 0096/1271] Extend pytest.raises to support Exception having __repr__ method and initialized with kwargs (#11073) Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + src/_pytest/python_api.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index f2b59b7c4db..4c42de21f5b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -57,6 +57,7 @@ Ben Gartner Ben Webb Benjamin Peterson Bernard Pratz +Bo Wu Bob Ippolito Brian Dorsey Brian Larsen diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index a045da2206b..27826863ead 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -812,7 +812,8 @@ def raises( # noqa: F811 :kwparam str | typing.Pattern[str] | None match: If specified, a string containing a regular expression, or a regular expression object, that is tested against the string - representation of the exception using :func:`re.search`. + representation of the exception and its `PEP-678 ` `__notes__` + using :func:`re.search`. To match a literal string that may contain :ref:`special characters `, the pattern can first be escaped with :func:`re.escape`. From e3247834e2797461ce155ff730d4b4b67c04ebc6 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 22 Jul 2023 20:16:59 +0200 Subject: [PATCH 0097/1271] Remove ep2023 training (#11241) --- doc/en/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index e64b5b311a0..73bf2e4d8df 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,6 @@ .. sidebar:: Next Open Trainings - - `pytest tips and tricks for a better testsuite `_, at `Europython 2023 `_, **July 18th** (3h), **Prague, Czech Republic / Remote** - `pytest: Professionelles Testen (nicht nur) für Python `_, at `Workshoptage 2023 `_, **September 5th**, `OST `_ Campus **Rapperswil, Switzerland** - `Professional Testing with Python `_, via `Python Academy `_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote** From 161ba87300ab5b49efa2833cd0e39bba301c2712 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 23 Jul 2023 13:36:42 +0300 Subject: [PATCH 0098/1271] doc/usage: clarify "Run tests by node ids" Fix #11107, #11235. --- doc/en/how-to/usage.rst | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 4ec4459a232..03afb22d675 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -46,21 +46,28 @@ Use ``""`` instead of ``''`` in expression when running this on Windows **Run tests by node ids** -Each collected test is assigned a unique ``nodeid`` which consist of the module filename followed -by specifiers like class names, function names and parameters from parametrization, separated by ``::`` characters. +Each collected test is assigned a unique ``nodeid`` which consist of the module file path followed +by specifiers like class names and function names separated by ``::`` characters, +and parameters from parametrization in ``[...]``. +You can use the same syntax to match tests relative to the working directory. To run a specific test within a module: .. code-block:: bash - pytest test_mod.py::test_func + pytest tests/test_mod.py::test_func +To run all tests in a class: -Another example specifying a test method in the command line: +.. code-block:: bash + + pytest tests/test_mod.py::TestClass + +Specifying a specific test method: .. code-block:: bash - pytest test_mod.py::TestClass::test_method + pytest tests/test_mod.py::TestClass::test_method **Run tests by marker expressions** From 4e42421ebf2938bfac01e271afb195c2323566fd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 23 Jul 2023 13:54:03 +0300 Subject: [PATCH 0099/1271] config: fix an incorrect type Was a mistake in d97d44a97af2303eb3f3aea1f16fd834f5415509. --- src/_pytest/config/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 1f4670a560b..88b23f1a46f 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1243,7 +1243,7 @@ def _decide_args( self, *, args: List[str], - pyargs: List[str], + pyargs: bool, testpaths: List[str], invocation_dir: Path, rootpath: Path, From 13e2b002583b0f3e8541b4b1201c10b8c330a865 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 23 Jul 2023 14:10:26 +0300 Subject: [PATCH 0100/1271] config: don't pass the entire Config to `determine_setup()` Seems better to make the function a bit more pure, and avoids the circular import. --- src/_pytest/config/__init__.py | 2 +- src/_pytest/config/findpaths.py | 23 ++++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 88b23f1a46f..be62fe9995d 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1170,7 +1170,7 @@ def _initini(self, args: Sequence[str]) -> None: ns.inifilename, ns.file_or_dir + unknown_args, rootdir_cmd_arg=ns.rootdir or None, - config=self, + invocation_dir=self.invocation_params.dir, ) self._rootpath = rootpath self._inipath = inipath diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 234b9e12906..9c76947a466 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -7,7 +7,6 @@ from typing import Optional from typing import Sequence from typing import Tuple -from typing import TYPE_CHECKING from typing import Union import iniconfig @@ -17,9 +16,6 @@ from _pytest.pathlib import absolutepath from _pytest.pathlib import commonpath -if TYPE_CHECKING: - from . import Config - def _parse_ini_config(path: Path) -> iniconfig.IniConfig: """Parse the given generic '.ini' file using legacy IniConfig parser, returning @@ -176,8 +172,21 @@ def determine_setup( inifile: Optional[str], args: Sequence[str], rootdir_cmd_arg: Optional[str] = None, - config: Optional["Config"] = None, + invocation_dir: Optional[Path] = None, ) -> Tuple[Path, Optional[Path], Dict[str, Union[str, List[str]]]]: + """Determine the rootdir, inifile and ini configuration values from the + command line arguments. + + :param inifile: + The `--inifile` command line argument, if given. + :param args: + The free command line arguments. + :param rootdir_cmd_arg: + The `--rootdir` command line argument, if given. + :param invocation_dir: + The working directory when pytest was invoked, if known. + If not known, the current working directory is used. + """ rootdir = None dirs = get_dirs_from_args(args) if inifile: @@ -198,8 +207,8 @@ def determine_setup( if dirs != [ancestor]: rootdir, inipath, inicfg = locate_config(dirs) if rootdir is None: - if config is not None: - cwd = config.invocation_params.dir + if invocation_dir is not None: + cwd = invocation_dir else: cwd = Path.cwd() rootdir = get_common_ancestor([cwd, ancestor]) From 12054a49722eee2b12e3b9106f3cf878bcb13648 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Thu, 27 Jul 2023 09:32:23 +0300 Subject: [PATCH 0101/1271] config: avoid list[], set[], dict[] Should wait with this until Python 3.8 is dropped. --- src/_pytest/config/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index be62fe9995d..2b6f250f316 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -353,9 +353,9 @@ def _get_legacy_hook_marks( if TYPE_CHECKING: # abuse typeguard from importlib to avoid massive method type union thats lacking a alias assert inspect.isroutine(method) - known_marks: set[str] = {m.name for m in getattr(method, "pytestmark", [])} - must_warn: list[str] = [] - opts: dict[str, bool] = {} + known_marks: Set[str] = {m.name for m in getattr(method, "pytestmark", [])} + must_warn: List[str] = [] + opts: Dict[str, bool] = {} for opt_name in opt_names: opt_attr = getattr(method, opt_name, AttributeError) if opt_attr is not AttributeError: From e8aa906e06f696f28d2ae4ce205e099aab18a7a8 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Thu, 27 Jul 2023 09:36:30 +0300 Subject: [PATCH 0102/1271] fixtures: move _get_direct_parametrize_args to a standalone function So it can be used independently of the FixtureManager. --- AUTHORS | 1 + src/_pytest/fixtures.py | 41 +++++++++++++++++++++-------------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/AUTHORS b/AUTHORS index 4c42de21f5b..313e507f204 100644 --- a/AUTHORS +++ b/AUTHORS @@ -327,6 +327,7 @@ Ross Lawley Ruaridh Williamson Russel Winder Ryan Wooden +Sadra Barikbin Saiprasad Kale Samuel Colvin Samuel Dion-Girardeau diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 650e934b3f1..516a595efee 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1404,6 +1404,26 @@ def pytest_addoption(parser: Parser) -> None: ) +def _get_direct_parametrize_args(node: nodes.Node) -> List[str]: + """Return all direct parametrization arguments of a node, so we don't + mistake them for fixtures. + + Check https://github.com/pytest-dev/pytest/issues/5036. + + These things are done later as well when dealing with parametrization + so this could be improved. + """ + parametrize_argnames: List[str] = [] + for marker in node.iter_markers(name="parametrize"): + if not marker.kwargs.get("indirect", False): + p_argnames, _ = ParameterSet._parse_parametrize_args( + *marker.args, **marker.kwargs + ) + parametrize_argnames.extend(p_argnames) + + return parametrize_argnames + + class FixtureManager: """pytest fixture definitions and information is stored and managed from this class. @@ -1453,25 +1473,6 @@ def __init__(self, session: "Session") -> None: } session.config.pluginmanager.register(self, "funcmanage") - def _get_direct_parametrize_args(self, node: nodes.Node) -> List[str]: - """Return all direct parametrization arguments of a node, so we don't - mistake them for fixtures. - - Check https://github.com/pytest-dev/pytest/issues/5036. - - These things are done later as well when dealing with parametrization - so this could be improved. - """ - parametrize_argnames: List[str] = [] - for marker in node.iter_markers(name="parametrize"): - if not marker.kwargs.get("indirect", False): - p_argnames, _ = ParameterSet._parse_parametrize_args( - *marker.args, **marker.kwargs - ) - parametrize_argnames.extend(p_argnames) - - return parametrize_argnames - def getfixtureinfo( self, node: nodes.Item, @@ -1503,7 +1504,7 @@ def getfixtureinfo( ) initialnames = usefixtures + argnames initialnames, names_closure, arg2fixturedefs = self.getfixtureclosure( - initialnames, node, ignore_args=self._get_direct_parametrize_args(node) + initialnames, node, ignore_args=_get_direct_parametrize_args(node) ) return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs) From d3552ef4c0770fe90e8a583d8fae9fd9280bca96 Mon Sep 17 00:00:00 2001 From: Uday Kumar Date: Fri, 28 Jul 2023 12:36:38 +0530 Subject: [PATCH 0103/1271] Clarify doc for running tests by nodeid section (#11249) --- doc/en/how-to/usage.rst | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 03afb22d675..65f9debd852 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -44,12 +44,10 @@ Use ``""`` instead of ``''`` in expression when running this on Windows .. _nodeids: -**Run tests by node ids** +**Run tests by collection arguments** -Each collected test is assigned a unique ``nodeid`` which consist of the module file path followed -by specifiers like class names and function names separated by ``::`` characters, -and parameters from parametrization in ``[...]``. -You can use the same syntax to match tests relative to the working directory. +Pass the module filename relative to the working directory, followed by specifiers like the class name and function name +separated by ``::`` characters, and parameters from parameterization enclosed in ``[]``. To run a specific test within a module: @@ -69,6 +67,12 @@ Specifying a specific test method: pytest tests/test_mod.py::TestClass::test_method +Specifying a specific parametrization of a test: + +.. code-block:: bash + + pytest tests/test_mod.py::test_func[x1,y2] + **Run tests by marker expressions** .. code-block:: bash From 71e627aa8f4eecb9f13e69285069480f063dd118 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 28 Jul 2023 13:54:11 +0300 Subject: [PATCH 0104/1271] fixtures: fix crash when `parametrize(scope="package")` is used without a Package There as handling for `scope="class"` without a class, but not for `scope="package"` without a package. It would fail the assert. --- changelog/11255.bugfix.rst | 1 + src/_pytest/fixtures.py | 18 +++++++++++++----- testing/python/metafunc.py | 17 +++++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 changelog/11255.bugfix.rst diff --git a/changelog/11255.bugfix.rst b/changelog/11255.bugfix.rst new file mode 100644 index 00000000000..2a2a42667a3 --- /dev/null +++ b/changelog/11255.bugfix.rst @@ -0,0 +1 @@ +Fixed crash on `parametrize(..., scope="package")` without a package present. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 516a595efee..c35f842db59 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -155,6 +155,8 @@ def get_scope_node( def add_funcarg_pseudo_fixture_def( collector: nodes.Collector, metafunc: "Metafunc", fixturemanager: "FixtureManager" ) -> None: + import _pytest.python + # This function will transform all collected calls to functions # if they use direct funcargs (i.e. direct parametrization) # because we want later test execution to be able to rely on @@ -192,11 +194,17 @@ def add_funcarg_pseudo_fixture_def( if scope is not Scope.Function: node = get_scope_node(collector, scope) if node is None: - assert scope is Scope.Class and isinstance( - collector, _pytest.python.Module - ) - # Use module-level collector for class-scope (for now). - node = collector + # If used class scope and there is no class, use module-level + # collector (for now). + if scope is Scope.Class: + assert isinstance(collector, _pytest.python.Module) + node = collector + # If used package scope and there is no package, use session + # (for now). + elif scope is Scope.Package: + node = collector.session + else: + assert False, f"Unhandled missing scope: {scope}" if node is None: name2pseudofixturedef = None else: diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 08ea8f9107f..bb4ae9d9af3 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1486,6 +1486,23 @@ def test_foo(x): ] ) + @pytest.mark.parametrize("scope", ["class", "package"]) + def test_parametrize_missing_scope_doesnt_crash( + self, pytester: Pytester, scope: str + ) -> None: + """Doesn't crash when parametrize(scope=) is used without a + corresponding node.""" + pytester.makepyfile( + f""" + import pytest + + @pytest.mark.parametrize("x", [0], scope="{scope}") + def test_it(x): pass + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + class TestMetafuncFunctionalAuto: """Tests related to automatically find out the correct scope for From a21fb87a90974189c1b8b26189959507189bb3a1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 2 Jun 2023 16:02:09 +0300 Subject: [PATCH 0105/1271] python: change `Package` to no longer be a `Module`/`File` Fix #11137. --- changelog/11137.breaking.rst | 11 +++ doc/en/deprecations.rst | 16 +++++ src/_pytest/cacheprovider.py | 11 +-- src/_pytest/fixtures.py | 5 +- src/_pytest/main.py | 110 +++++++++++++--------------- src/_pytest/python.py | 136 +++++++++++++++++------------------ 6 files changed, 149 insertions(+), 140 deletions(-) create mode 100644 changelog/11137.breaking.rst diff --git a/changelog/11137.breaking.rst b/changelog/11137.breaking.rst new file mode 100644 index 00000000000..a92df326a49 --- /dev/null +++ b/changelog/11137.breaking.rst @@ -0,0 +1,11 @@ +:class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File`. + +The ``Package`` collector node designates a Python package, that is, a directory with an `__init__.py` file. +Previously ``Package`` was a subtype of ``pytest.Module`` (which represents a single Python module), +the module being the `__init__.py` file. +This has been deemed a design mistake (see :issue:`11137` and :issue:`7777` for details). + +The ``path`` property of ``Package`` nodes now points to the package directory instead of the ``__init__.py`` file. + +Note that a ``Module`` node for ``__init__.py`` (which is not a ``Package``) may still exist, +if it is picked up during collection (e.g. if you configured :confval:`python_files` to include ``__init__.py`` files). diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index e73c1a18e5d..7b4e9996526 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -495,6 +495,22 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +:class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionchanged:: 8.0 + +The ``Package`` collector node designates a Python package, that is, a directory with an `__init__.py` file. +Previously ``Package`` was a subtype of ``pytest.Module`` (which represents a single Python module), +the module being the `__init__.py` file. +This has been deemed a design mistake (see :issue:`11137` and :issue:`7777` for details). + +The ``path`` property of ``Package`` nodes now points to the package directory instead of the ``__init__.py`` file. + +Note that a ``Module`` node for ``__init__.py`` (which is not a ``Package``) may still exist, +if it is picked up during collection (e.g. if you configured :confval:`python_files` to include ``__init__.py`` files). + + Collecting ``__init__.py`` files no longer collects package ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index f519c974bdd..67dee6add03 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -228,12 +228,7 @@ def pytest_make_collect_report( # Use stable sort to priorize last failed. def sort_key(node: Union[nodes.Item, nodes.Collector]) -> bool: - # Package.path is the __init__.py file, we need the directory. - if isinstance(node, Package): - path = node.path.parent - else: - path = node.path - return path in lf_paths + return node.path in lf_paths res.result = sorted( res.result, @@ -277,9 +272,7 @@ def __init__(self, lfplugin: "LFPlugin") -> None: def pytest_make_collect_report( self, collector: nodes.Collector ) -> Optional[CollectReport]: - # Packages are Files, but we only want to skip test-bearing Files, - # so don't filter Packages. - if isinstance(collector, File) and not isinstance(collector, Package): + if isinstance(collector, File): if collector.path not in self.lfplugin._last_failed_paths: self.lfplugin._skipped_files += 1 diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index c35f842db59..f2bf5320cd4 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -119,9 +119,8 @@ def get_scope_package( from _pytest.python import Package current: Optional[Union[nodes.Item, nodes.Collector]] = node - fixture_package_name = "{}/{}".format(fixturedef.baseid, "__init__.py") while current and ( - not isinstance(current, Package) or fixture_package_name != current.nodeid + not isinstance(current, Package) or current.nodeid != fixturedef.baseid ): current = current.parent # type: ignore[assignment] if current is None: @@ -263,7 +262,7 @@ def get_parametrized_fixture_keys(item: nodes.Item, scope: Scope) -> Iterator[_K if scope is Scope.Session: key: _Key = (argname, param_index) elif scope is Scope.Package: - key = (argname, param_index, item.path.parent) + key = (argname, param_index, item.path) elif scope is Scope.Module: key = (argname, param_index, item.path) elif scope is Scope.Class: diff --git a/src/_pytest/main.py b/src/_pytest/main.py index f27767cf17c..4c3c9aed439 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -17,9 +17,9 @@ from typing import Optional from typing import overload from typing import Sequence -from typing import Set from typing import Tuple from typing import Type +from typing import TYPE_CHECKING from typing import Union import _pytest._code @@ -43,6 +43,10 @@ from _pytest.runner import SetupState +if TYPE_CHECKING: + from _pytest.python import Package + + def pytest_addoption(parser: Parser) -> None: parser.addini( "norecursedirs", @@ -572,6 +576,17 @@ def _recurse(self, direntry: "os.DirEntry[str]") -> bool: return False return True + def _collectpackage(self, fspath: Path) -> Optional["Package"]: + from _pytest.python import Package + + ihook = self.gethookproxy(fspath) + if not self.isinitpath(fspath): + if ihook.pytest_ignore_collect(collection_path=fspath, config=self.config): + return None + + pkg: Package = Package.from_parent(self, path=fspath) + return pkg + def _collectfile( self, fspath: Path, handle_dupes: bool = True ) -> Sequence[nodes.Collector]: @@ -680,8 +695,6 @@ def perform_collect( # noqa: F811 return items def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: - from _pytest.python import Package - # Keep track of any collected nodes in here, so we don't duplicate fixtures. node_cache1: Dict[Path, Sequence[nodes.Collector]] = {} node_cache2: Dict[Tuple[Type[nodes.Collector], Path], nodes.Collector] = {} @@ -691,7 +704,9 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: matchnodes_cache: Dict[Tuple[Type[nodes.Collector], str], CollectReport] = {} # Directories of pkgs with dunder-init files. - pkg_roots: Dict[Path, Package] = {} + pkg_roots: Dict[Path, "Package"] = {} + + pm = self.config.pluginmanager for argpath, names in self._initial_parts: self.trace("processing argument", (argpath, names)) @@ -699,55 +714,47 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: # Start with a Session root, and delve to argpath item (dir or file) # and stack all Packages found on the way. - # No point in finding packages when collecting doctests. - if not self.config.getoption("doctestmodules", False): - pm = self.config.pluginmanager - for parent in (argpath, *argpath.parents): - if not pm._is_in_confcutdir(argpath): - break - - if parent.is_dir(): - pkginit = parent / "__init__.py" - if pkginit.is_file() and pkginit not in node_cache1: - col = self._collectfile(pkginit, handle_dupes=False) - if col: - if isinstance(col[0], Package): - pkg_roots[parent] = col[0] - node_cache1[col[0].path] = [col[0]] + for parent in (argpath, *argpath.parents): + if not pm._is_in_confcutdir(argpath): + break + + if parent.is_dir(): + pkginit = parent / "__init__.py" + if pkginit.is_file() and parent not in node_cache1: + pkg = self._collectpackage(parent) + if pkg is not None: + pkg_roots[parent] = pkg + node_cache1[pkg.path] = [pkg] # If it's a directory argument, recurse and look for any Subpackages. # Let the Package collector deal with subnodes, don't collect here. if argpath.is_dir(): assert not names, f"invalid arg {(argpath, names)!r}" - seen_dirs: Set[Path] = set() - for direntry in visit(argpath, self._recurse): - if not direntry.is_file(): - continue + if argpath in pkg_roots: + yield pkg_roots[argpath] + for direntry in visit(argpath, self._recurse): path = Path(direntry.path) - dirpath = path.parent - - if dirpath not in seen_dirs: - # Collect packages first. - seen_dirs.add(dirpath) - pkginit = dirpath / "__init__.py" - if pkginit.exists(): - for x in self._collectfile(pkginit): + if direntry.is_dir() and self._recurse(direntry): + pkginit = path / "__init__.py" + if pkginit.is_file(): + pkg = self._collectpackage(path) + if pkg is not None: + yield pkg + pkg_roots[path] = pkg + + elif direntry.is_file(): + if path.parent in pkg_roots: + # Package handles this file. + continue + for x in self._collectfile(path): + key2 = (type(x), x.path) + if key2 in node_cache2: + yield node_cache2[key2] + else: + node_cache2[key2] = x yield x - if isinstance(x, Package): - pkg_roots[dirpath] = x - if dirpath in pkg_roots: - # Do not collect packages here. - continue - - for x in self._collectfile(path): - key2 = (type(x), x.path) - if key2 in node_cache2: - yield node_cache2[key2] - else: - node_cache2[key2] = x - yield x else: assert argpath.is_file() @@ -806,21 +813,6 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: self._notfound.append((report_arg, col)) continue - # If __init__.py was the only file requested, then the matched - # node will be the corresponding Package (by default), and the - # first yielded item will be the __init__ Module itself, so - # just use that. If this special case isn't taken, then all the - # files in the package will be yielded. - if argpath.name == "__init__.py" and isinstance(matching[0], Package): - try: - yield next(iter(matching[0].collect())) - except StopIteration: - # The package collects nothing with only an __init__.py - # file in it, which gets ignored by the default - # "python_files" option. - pass - continue - yield from matching self.trace.root.indent -= 1 diff --git a/src/_pytest/python.py b/src/_pytest/python.py index cf757533630..c0c16d4d0d8 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -204,7 +204,7 @@ def pytest_collect_file(file_path: Path, parent: nodes.Collector) -> Optional["M if file_path.suffix == ".py": if not parent.session.isinitpath(file_path): if not path_matches_patterns( - file_path, parent.config.getini("python_files") + ["__init__.py"] + file_path, parent.config.getini("python_files") ): return None ihook = parent.session.gethookproxy(file_path) @@ -221,9 +221,6 @@ def path_matches_patterns(path: Path, patterns: Iterable[str]) -> bool: def pytest_pycollect_makemodule(module_path: Path, parent) -> "Module": - if module_path.name == "__init__.py": - pkg: Package = Package.from_parent(parent, path=module_path) - return pkg mod: Module = Module.from_parent(parent, path=module_path) return mod @@ -517,11 +514,62 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]: ) +def importtestmodule( + path: Path, + config: Config, +): + # We assume we are only called once per module. + importmode = config.getoption("--import-mode") + try: + mod = import_path(path, mode=importmode, root=config.rootpath) + except SyntaxError as e: + raise nodes.Collector.CollectError( + ExceptionInfo.from_current().getrepr(style="short") + ) from e + except ImportPathMismatchError as e: + raise nodes.Collector.CollectError( + "import file mismatch:\n" + "imported module %r has this __file__ attribute:\n" + " %s\n" + "which is not the same as the test file we want to collect:\n" + " %s\n" + "HINT: remove __pycache__ / .pyc files and/or use a " + "unique basename for your test file modules" % e.args + ) from e + except ImportError as e: + exc_info = ExceptionInfo.from_current() + if config.getoption("verbose") < 2: + exc_info.traceback = exc_info.traceback.filter(filter_traceback) + exc_repr = ( + exc_info.getrepr(style="short") + if exc_info.traceback + else exc_info.exconly() + ) + formatted_tb = str(exc_repr) + raise nodes.Collector.CollectError( + "ImportError while importing test module '{path}'.\n" + "Hint: make sure your test modules/packages have valid Python names.\n" + "Traceback:\n" + "{traceback}".format(path=path, traceback=formatted_tb) + ) from e + except skip.Exception as e: + if e.allow_module_level: + raise + raise nodes.Collector.CollectError( + "Using pytest.skip outside of a test will skip the entire module. " + "If that's your intention, pass `allow_module_level=True`. " + "If you want to skip a specific test or an entire class, " + "use the @pytest.mark.skip or @pytest.mark.skipif decorators." + ) from e + config.pluginmanager.consider_module(mod) + return mod + + class Module(nodes.File, PyCollector): """Collector for test classes and functions in a Python module.""" def _getobj(self): - return self._importtestmodule() + return importtestmodule(self.path, self.config) def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: self._inject_setup_module_fixture() @@ -606,55 +654,8 @@ def xunit_setup_function_fixture(request) -> Generator[None, None, None]: self.obj.__pytest_setup_function = xunit_setup_function_fixture - def _importtestmodule(self): - # We assume we are only called once per module. - importmode = self.config.getoption("--import-mode") - try: - mod = import_path(self.path, mode=importmode, root=self.config.rootpath) - except SyntaxError as e: - raise self.CollectError( - ExceptionInfo.from_current().getrepr(style="short") - ) from e - except ImportPathMismatchError as e: - raise self.CollectError( - "import file mismatch:\n" - "imported module %r has this __file__ attribute:\n" - " %s\n" - "which is not the same as the test file we want to collect:\n" - " %s\n" - "HINT: remove __pycache__ / .pyc files and/or use a " - "unique basename for your test file modules" % e.args - ) from e - except ImportError as e: - exc_info = ExceptionInfo.from_current() - if self.config.getoption("verbose") < 2: - exc_info.traceback = exc_info.traceback.filter(filter_traceback) - exc_repr = ( - exc_info.getrepr(style="short") - if exc_info.traceback - else exc_info.exconly() - ) - formatted_tb = str(exc_repr) - raise self.CollectError( - "ImportError while importing test module '{path}'.\n" - "Hint: make sure your test modules/packages have valid Python names.\n" - "Traceback:\n" - "{traceback}".format(path=self.path, traceback=formatted_tb) - ) from e - except skip.Exception as e: - if e.allow_module_level: - raise - raise self.CollectError( - "Using pytest.skip outside of a test will skip the entire module. " - "If that's your intention, pass `allow_module_level=True`. " - "If you want to skip a specific test or an entire class, " - "use the @pytest.mark.skip or @pytest.mark.skipif decorators." - ) from e - self.config.pluginmanager.consider_module(mod) - return mod - - -class Package(Module): + +class Package(nodes.FSCollector): """Collector for files and directories in a Python packages -- directories with an `__init__.py` file.""" @@ -680,22 +681,24 @@ def __init__( session=session, nodeid=nodeid, ) - self.name = self.path.parent.name + self.name = self.path.name def setup(self) -> None: + init_mod = importtestmodule(self.path / "__init__.py", self.config) + # Not using fixtures to call setup_module here because autouse fixtures # from packages are not called automatically (#4085). setup_module = _get_first_non_fixture_func( - self.obj, ("setUpModule", "setup_module") + init_mod, ("setUpModule", "setup_module") ) if setup_module is not None: - _call_with_optional_argument(setup_module, self.obj) + _call_with_optional_argument(setup_module, init_mod) teardown_module = _get_first_non_fixture_func( - self.obj, ("tearDownModule", "teardown_module") + init_mod, ("tearDownModule", "teardown_module") ) if teardown_module is not None: - func = partial(_call_with_optional_argument, teardown_module, self.obj) + func = partial(_call_with_optional_argument, teardown_module, init_mod) self.addfinalizer(func) def _recurse(self, direntry: "os.DirEntry[str]") -> bool: @@ -732,21 +735,16 @@ def _collectfile( return ihook.pytest_collect_file(file_path=fspath, parent=self) # type: ignore[no-any-return] def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: - this_path = self.path.parent - # Always collect the __init__ first. - if self.session.isinitpath(self.path) or path_matches_patterns( - self.path, self.config.getini("python_files") - ): - yield Module.from_parent(self, path=self.path) + yield from self._collectfile(self.path / "__init__.py") pkg_prefixes: Set[Path] = set() - for direntry in visit(str(this_path), recurse=self._recurse): + for direntry in visit(self.path, recurse=self._recurse): path = Path(direntry.path) - # We will visit our own __init__.py file, in which case we skip it. + # Already handled above. if direntry.is_file(): - if direntry.name == "__init__.py" and path.parent == this_path: + if direntry.name == "__init__.py" and path.parent == self.path: continue parts_ = parts(direntry.path) @@ -761,7 +759,7 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: elif not direntry.is_dir(): # Broken symlink or invalid/missing file. continue - elif path.joinpath("__init__.py").is_file(): + elif self._recurse(direntry) and path.joinpath("__init__.py").is_file(): pkg_prefixes.add(path) From 01ac13a77d6cd56a5ac20756542e59a7b14129a0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 9 Jan 2022 13:58:29 +0200 Subject: [PATCH 0106/1271] config: split _getconftestmodules and _loadconftestmodules Previously, the `_getconftestmodules` function was used both to load conftest modules for a path (during `pytest_load_initial_conftests`), and to retrieve conftest modules for a path (during hook dispatch and for fetching `collect_ignore`). This made things muddy - it is usually nicer to have clear separation between "command" and "query" functions, when they occur in separate phases. So split into "load" and "get". Currently, `gethookproxy` still loads conftest itself. I hope to change this in the future. --- src/_pytest/config/__init__.py | 32 +++++++--------- src/_pytest/main.py | 11 ++++-- testing/python/fixtures.py | 4 +- testing/test_config.py | 17 +++------ testing/test_conftest.py | 70 +++++++++++----------------------- 5 files changed, 50 insertions(+), 84 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 2b6f250f316..8dbaf7c70e5 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -581,26 +581,25 @@ def _is_in_confcutdir(self, path: Path) -> bool: def _try_load_conftest( self, anchor: Path, importmode: Union[str, ImportMode], rootpath: Path ) -> None: - self._getconftestmodules(anchor, importmode, rootpath) + self._loadconftestmodules(anchor, importmode, rootpath) # let's also consider test* subdirs if anchor.is_dir(): for x in anchor.glob("test*"): if x.is_dir(): - self._getconftestmodules(x, importmode, rootpath) + self._loadconftestmodules(x, importmode, rootpath) - def _getconftestmodules( + def _loadconftestmodules( self, path: Path, importmode: Union[str, ImportMode], rootpath: Path - ) -> Sequence[types.ModuleType]: + ) -> None: if self._noconftest: - return [] + return directory = self._get_directory(path) # Optimization: avoid repeated searches in the same directory. # Assumes always called with same importmode and rootpath. - existing_clist = self._dirpath2confmods.get(directory) - if existing_clist is not None: - return existing_clist + if directory in self._dirpath2confmods: + return # XXX these days we may rather want to use config.rootpath # and allow users to opt into looking into the rootdir parent @@ -613,16 +612,17 @@ def _getconftestmodules( mod = self._importconftest(conftestpath, importmode, rootpath) clist.append(mod) self._dirpath2confmods[directory] = clist - return clist + + def _getconftestmodules(self, path: Path) -> Sequence[types.ModuleType]: + directory = self._get_directory(path) + return self._dirpath2confmods.get(directory, ()) def _rget_with_confmod( self, name: str, path: Path, - importmode: Union[str, ImportMode], - rootpath: Path, ) -> Tuple[types.ModuleType, Any]: - modules = self._getconftestmodules(path, importmode, rootpath=rootpath) + modules = self._getconftestmodules(path) for mod in reversed(modules): try: return mod, getattr(mod, name) @@ -1562,13 +1562,9 @@ def _getini(self, name: str): else: return self._getini_unknown_type(name, type, value) - def _getconftest_pathlist( - self, name: str, path: Path, rootpath: Path - ) -> Optional[List[Path]]: + def _getconftest_pathlist(self, name: str, path: Path) -> Optional[List[Path]]: try: - mod, relroots = self.pluginmanager._rget_with_confmod( - name, path, self.getoption("importmode"), rootpath - ) + mod, relroots = self.pluginmanager._rget_with_confmod(name, path) except KeyError: return None assert mod.__file__ is not None diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 4c3c9aed439..fd3836736ed 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -376,7 +376,7 @@ def _in_venv(path: Path) -> bool: def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[bool]: ignore_paths = config._getconftest_pathlist( - "collect_ignore", path=collection_path.parent, rootpath=config.rootpath + "collect_ignore", path=collection_path.parent ) ignore_paths = ignore_paths or [] excludeopt = config.getoption("ignore") @@ -387,7 +387,7 @@ def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[boo return True ignore_globs = config._getconftest_pathlist( - "collect_ignore_glob", path=collection_path.parent, rootpath=config.rootpath + "collect_ignore_glob", path=collection_path.parent ) ignore_globs = ignore_globs or [] excludeglobopt = config.getoption("ignore_glob") @@ -551,11 +551,16 @@ def gethookproxy(self, fspath: "os.PathLike[str]"): pm = self.config.pluginmanager # Check if we have the common case of running # hooks with all conftest.py files. - my_conftestmodules = pm._getconftestmodules( + # + # TODO: pytest relies on this call to load non-initial conftests. This + # is incidental. It will be better to load conftests at a more + # well-defined place. + pm._loadconftestmodules( path, self.config.getoption("importmode"), rootpath=self.config.rootpath, ) + my_conftestmodules = pm._getconftestmodules(path) remove_mods = pm._conftest_plugins.difference(my_conftestmodules) if remove_mods: # One or more conftests are not in use at this fspath. diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 191689d1c2e..7c028277253 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2103,9 +2103,7 @@ def test_2(self): reprec = pytester.inline_run("-v", "-s", "--confcutdir", pytester.path) reprec.assertoutcome(passed=8) config = reprec.getcalls("pytest_unconfigure")[0].config - values = config.pluginmanager._getconftestmodules( - p, importmode="prepend", rootpath=pytester.path - )[0].values + values = config.pluginmanager._getconftestmodules(p)[0].values assert values == ["fin_a1", "fin_a2", "fin_b1", "fin_b2"] * 2 def test_scope_ordering(self, pytester: Pytester) -> None: diff --git a/testing/test_config.py b/testing/test_config.py index 43561000c91..04161f238d8 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -642,18 +642,11 @@ def test_getconftest_pathlist(self, pytester: Pytester, tmp_path: Path) -> None: p = tmp_path.joinpath("conftest.py") p.write_text(f"mylist = {['.', str(somepath)]}", encoding="utf-8") config = pytester.parseconfigure(p) - assert ( - config._getconftest_pathlist("notexist", path=tmp_path, rootpath=tmp_path) - is None - ) - pl = ( - config._getconftest_pathlist("mylist", path=tmp_path, rootpath=tmp_path) - or [] - ) - print(pl) - assert len(pl) == 2 - assert pl[0] == tmp_path - assert pl[1] == somepath + assert config._getconftest_pathlist("notexist", path=tmp_path) is None + assert config._getconftest_pathlist("mylist", path=tmp_path) == [ + tmp_path, + somepath, + ] @pytest.mark.parametrize("maybe_type", ["not passed", "None", '"string"']) def test_addini(self, pytester: Pytester, maybe_type: str) -> None: diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 4278315078f..cfc2d577b53 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -62,28 +62,22 @@ def basedir( def test_basic_init(self, basedir: Path) -> None: conftest = PytestPluginManager() p = basedir / "adir" - assert ( - conftest._rget_with_confmod("a", p, importmode="prepend", rootpath=basedir)[ - 1 - ] - == 1 - ) + conftest._loadconftestmodules(p, importmode="prepend", rootpath=basedir) + assert conftest._rget_with_confmod("a", p)[1] == 1 def test_immediate_initialiation_and_incremental_are_the_same( self, basedir: Path ) -> None: conftest = PytestPluginManager() assert not len(conftest._dirpath2confmods) - conftest._getconftestmodules( - basedir, importmode="prepend", rootpath=Path(basedir) - ) + conftest._loadconftestmodules(basedir, importmode="prepend", rootpath=basedir) snap1 = len(conftest._dirpath2confmods) assert snap1 == 1 - conftest._getconftestmodules( + conftest._loadconftestmodules( basedir / "adir", importmode="prepend", rootpath=basedir ) assert len(conftest._dirpath2confmods) == snap1 + 1 - conftest._getconftestmodules( + conftest._loadconftestmodules( basedir / "b", importmode="prepend", rootpath=basedir ) assert len(conftest._dirpath2confmods) == snap1 + 2 @@ -91,33 +85,23 @@ def test_immediate_initialiation_and_incremental_are_the_same( def test_value_access_not_existing(self, basedir: Path) -> None: conftest = ConftestWithSetinitial(basedir) with pytest.raises(KeyError): - conftest._rget_with_confmod( - "a", basedir, importmode="prepend", rootpath=Path(basedir) - ) + conftest._rget_with_confmod("a", basedir) def test_value_access_by_path(self, basedir: Path) -> None: conftest = ConftestWithSetinitial(basedir) adir = basedir / "adir" - assert ( - conftest._rget_with_confmod( - "a", adir, importmode="prepend", rootpath=basedir - )[1] - == 1 - ) - assert ( - conftest._rget_with_confmod( - "a", adir / "b", importmode="prepend", rootpath=basedir - )[1] - == 1.5 + conftest._loadconftestmodules(adir, importmode="prepend", rootpath=basedir) + assert conftest._rget_with_confmod("a", adir)[1] == 1 + conftest._loadconftestmodules( + adir / "b", importmode="prepend", rootpath=basedir ) + assert conftest._rget_with_confmod("a", adir / "b")[1] == 1.5 def test_value_access_with_confmod(self, basedir: Path) -> None: startdir = basedir / "adir" / "b" startdir.joinpath("xx").mkdir() conftest = ConftestWithSetinitial(startdir) - mod, value = conftest._rget_with_confmod( - "a", startdir, importmode="prepend", rootpath=Path(basedir) - ) + mod, value = conftest._rget_with_confmod("a", startdir) assert value == 1.5 assert mod.__file__ is not None path = Path(mod.__file__) @@ -143,9 +127,7 @@ def test_doubledash_considered(pytester: Pytester) -> None: conf.joinpath("conftest.py").touch() conftest = PytestPluginManager() conftest_setinitial(conftest, [conf.name, conf.name]) - values = conftest._getconftestmodules( - conf, importmode="prepend", rootpath=pytester.path - ) + values = conftest._getconftestmodules(conf) assert len(values) == 1 @@ -192,26 +174,22 @@ def test_conftestcutdir(pytester: Pytester) -> None: p = pytester.mkdir("x") conftest = PytestPluginManager() conftest_setinitial(conftest, [pytester.path], confcutdir=p) - values = conftest._getconftestmodules( - p, importmode="prepend", rootpath=pytester.path - ) + conftest._loadconftestmodules(p, importmode="prepend", rootpath=pytester.path) + values = conftest._getconftestmodules(p) assert len(values) == 0 - values = conftest._getconftestmodules( + conftest._loadconftestmodules( conf.parent, importmode="prepend", rootpath=pytester.path ) + values = conftest._getconftestmodules(conf.parent) assert len(values) == 0 assert not conftest.has_plugin(str(conf)) # but we can still import a conftest directly conftest._importconftest(conf, importmode="prepend", rootpath=pytester.path) - values = conftest._getconftestmodules( - conf.parent, importmode="prepend", rootpath=pytester.path - ) + values = conftest._getconftestmodules(conf.parent) assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf)) # and all sub paths get updated properly - values = conftest._getconftestmodules( - p, importmode="prepend", rootpath=pytester.path - ) + values = conftest._getconftestmodules(p) assert len(values) == 1 assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf)) @@ -221,9 +199,7 @@ def test_conftestcutdir_inplace_considered(pytester: Pytester) -> None: conf = pytester.makeconftest("") conftest = PytestPluginManager() conftest_setinitial(conftest, [conf.parent], confcutdir=conf.parent) - values = conftest._getconftestmodules( - conf.parent, importmode="prepend", rootpath=pytester.path - ) + values = conftest._getconftestmodules(conf.parent) assert len(values) == 1 assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf)) @@ -433,10 +409,8 @@ def impct(p, importmode, root): conftest = PytestPluginManager() conftest._confcutdir = pytester.path monkeypatch.setattr(conftest, "_importconftest", impct) - mods = cast( - List[Path], - conftest._getconftestmodules(sub, importmode="prepend", rootpath=pytester.path), - ) + conftest._loadconftestmodules(sub, importmode="prepend", rootpath=pytester.path) + mods = cast(List[Path], conftest._getconftestmodules(sub)) expected = [ct1, ct2] assert mods == expected From c9163402e046c25ad86ff94fd6606a451102efdc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 23:52:09 +0200 Subject: [PATCH 0107/1271] [pre-commit.ci] pre-commit autoupdate (#11269) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/PyCQA/flake8: 6.0.0 → 6.1.0](https://github.com/PyCQA/flake8/compare/6.0.0...6.1.0) - [github.com/asottile/pyupgrade: v3.9.0 → v3.10.1](https://github.com/asottile/pyupgrade/compare/v3.9.0...v3.10.1) * Use is instead of type comparison with equal to appease the linter --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 4 ++-- src/_pytest/assertion/util.py | 2 +- testing/_py/test_local.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4bed8703542..be6d0822106 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ repos: language: python files: \.py$ - repo: https://github.com/PyCQA/flake8 - rev: 6.0.0 + rev: 6.1.0 hooks: - id: flake8 language_version: python3 @@ -42,7 +42,7 @@ repos: - id: reorder-python-imports args: ['--application-directories=.:src', --py38-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.9.0 + rev: v3.10.1 hooks: - id: pyupgrade args: [--py38-plus] diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index fc5dfdbd5ba..268f714baac 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -222,7 +222,7 @@ def _compare_eq_any(left: Any, right: Any, verbose: int = 0) -> List[str]: other_side = right if isinstance(left, ApproxBase) else left explanation = approx_side._repr_compare(other_side) - elif type(left) == type(right) and ( + elif type(left) is type(right) and ( isdatacls(left) or isattrs(left) or isnamedtuple(left) ): # Note: unlike dataclasses/attrs, namedtuples compare only the diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 895066a9f90..91b14aa2e0e 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -1573,4 +1573,4 @@ def test_default_encoding(self, tmpdir): x.write_text(part, "ascii") s = x.read_text("ascii") assert s == part - assert type(s) == type(part) + assert type(s) is type(part) From 4797deab998622d2fda34e96920f6d672d30e8b0 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Wed, 2 Aug 2023 14:58:31 +0330 Subject: [PATCH 0108/1271] Add `FixtureArgKey` class to represent fixture deps in `fixtures.py` (#11231) --- src/_pytest/fixtures.py | 48 +++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index f2bf5320cd4..00c2a8ef432 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -239,11 +239,17 @@ def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]: ) -# Parametrized fixture key, helper alias for code below. -_Key = Tuple[object, ...] +@dataclasses.dataclass(frozen=True) +class FixtureArgKey: + argname: str + param_index: int + scoped_item_path: Optional[Path] + item_cls: Optional[type] -def get_parametrized_fixture_keys(item: nodes.Item, scope: Scope) -> Iterator[_Key]: +def get_parametrized_fixture_keys( + item: nodes.Item, scope: Scope +) -> Iterator[FixtureArgKey]: """Return list of keys for all parametrized arguments which match the specified scope.""" assert scope is not Scope.Function @@ -253,24 +259,28 @@ def get_parametrized_fixture_keys(item: nodes.Item, scope: Scope) -> Iterator[_K pass else: cs: CallSpec2 = callspec - # cs.indices.items() is random order of argnames. Need to + # cs.indices is random order of argnames. Need to # sort this so that different calls to # get_parametrized_fixture_keys will be deterministic. - for argname, param_index in sorted(cs.indices.items()): + for argname in sorted(cs.indices): if cs._arg2scope[argname] != scope: continue + + item_cls = None if scope is Scope.Session: - key: _Key = (argname, param_index) + scoped_item_path = None elif scope is Scope.Package: - key = (argname, param_index, item.path) + scoped_item_path = item.path elif scope is Scope.Module: - key = (argname, param_index, item.path) + scoped_item_path = item.path elif scope is Scope.Class: + scoped_item_path = item.path item_cls = item.cls # type: ignore[attr-defined] - key = (argname, param_index, item.path, item_cls) else: assert_never(scope) - yield key + + param_index = cs.indices[argname] + yield FixtureArgKey(argname, param_index, scoped_item_path, item_cls) # Algorithm for sorting on a per-parametrized resource setup basis. @@ -280,12 +290,12 @@ def get_parametrized_fixture_keys(item: nodes.Item, scope: Scope) -> Iterator[_K def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]: - argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[_Key, None]]] = {} - items_by_argkey: Dict[Scope, Dict[_Key, Deque[nodes.Item]]] = {} + argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]] = {} + items_by_argkey: Dict[Scope, Dict[FixtureArgKey, Deque[nodes.Item]]] = {} for scope in HIGH_SCOPES: - d: Dict[nodes.Item, Dict[_Key, None]] = {} + d: Dict[nodes.Item, Dict[FixtureArgKey, None]] = {} argkeys_cache[scope] = d - item_d: Dict[_Key, Deque[nodes.Item]] = defaultdict(deque) + item_d: Dict[FixtureArgKey, Deque[nodes.Item]] = defaultdict(deque) items_by_argkey[scope] = item_d for item in items: keys = dict.fromkeys(get_parametrized_fixture_keys(item, scope), None) @@ -301,8 +311,8 @@ def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]: def fix_cache_order( item: nodes.Item, - argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[_Key, None]]], - items_by_argkey: Dict[Scope, Dict[_Key, "Deque[nodes.Item]"]], + argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]], + items_by_argkey: Dict[Scope, Dict[FixtureArgKey, "Deque[nodes.Item]"]], ) -> None: for scope in HIGH_SCOPES: for key in argkeys_cache[scope].get(item, []): @@ -311,13 +321,13 @@ def fix_cache_order( def reorder_items_atscope( items: Dict[nodes.Item, None], - argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[_Key, None]]], - items_by_argkey: Dict[Scope, Dict[_Key, "Deque[nodes.Item]"]], + argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]], + items_by_argkey: Dict[Scope, Dict[FixtureArgKey, "Deque[nodes.Item]"]], scope: Scope, ) -> Dict[nodes.Item, None]: if scope is Scope.Function or len(items) < 3: return items - ignore: Set[Optional[_Key]] = set() + ignore: Set[Optional[FixtureArgKey]] = set() items_deque = deque(items) items_done: Dict[nodes.Item, None] = {} scoped_items_by_argkey = items_by_argkey[scope] From b8b74331b420bc465892ce56c03e3614819f47f0 Mon Sep 17 00:00:00 2001 From: Christoph Anton Mitterer Date: Thu, 3 Aug 2023 18:31:17 +0200 Subject: [PATCH 0109/1271] Improve docs for Parametrizing conditional raising (#11279) What one typically actually wants in such a case is both, checking for some resulting values *and* checking for some expected exception. Since this is easily possible with the `nullcontext` context manager, adapt the example accordingly (needlessly using a different name rather just confuses people). Signed-off-by: Christoph Anton Mitterer --- doc/en/example/parametrize.rst | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index f771e5da4e0..4ea6f6e6512 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -657,13 +657,16 @@ Use :func:`pytest.raises` with the :ref:`pytest.mark.parametrize ref` decorator to write parametrized tests in which some tests raise exceptions and others do not. -It may be helpful to use ``nullcontext`` as a complement to ``raises``. +``contextlib.nullcontext`` can be used to test cases that are not expected to +raise exceptions but that should result in some value. The value is given as the +``enter_result`` parameter, which will be available as the ``with`` statement’s +target (``e`` in the example below). For example: .. code-block:: python - from contextlib import nullcontext as does_not_raise + from contextlib import nullcontext import pytest @@ -671,16 +674,17 @@ For example: @pytest.mark.parametrize( "example_input,expectation", [ - (3, does_not_raise()), - (2, does_not_raise()), - (1, does_not_raise()), + (3, nullcontext(2)), + (2, nullcontext(3)), + (1, nullcontext(6)), (0, pytest.raises(ZeroDivisionError)), ], ) def test_division(example_input, expectation): """Test how much I know division.""" - with expectation: - assert (6 / example_input) is not None + with expectation as e: + assert (6 / example_input) == e -In the example above, the first three test cases should run unexceptionally, -while the fourth should raise ``ZeroDivisionError``. +In the example above, the first three test cases should run without any +exceptions, while the fourth should raise a``ZeroDivisionError`` exception, +which is expected by pytest. From cc0adf6bf3c9f356e3473ff8a21004b9c1fb2b93 Mon Sep 17 00:00:00 2001 From: Christoph Anton Mitterer Date: Sat, 5 Aug 2023 21:30:41 +0200 Subject: [PATCH 0110/1271] doc: update information about assertion messages (#11285) It was pointed out[0] that the previous behaviour has been obsoleted by commit 37bd1e03cb77a26ae80873a8725c87d57fda987c. [0] https://github.com/pytest-dev/pytest/issues/11265#issuecomment-1666581197 Signed-off-by: Christoph Anton Mitterer --- doc/en/how-to/assert.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 1b10c131389..d99a1ce5c97 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -54,14 +54,13 @@ operators. (See :ref:`tbreportdemo`). This allows you to use the idiomatic python constructs without boilerplate code while not losing introspection information. -However, if you specify a message with the assertion like this: +If a message is specified with the assertion like this: .. code-block:: python assert a % 2 == 0, "value was odd, should be even" -then no assertion introspection takes places at all and the message -will be simply shown in the traceback. +it is printed alongside the assertion introspection in the traceback. See :ref:`assert-details` for more information on assertion introspection. From 1c04a925039a528a996bf0433ef604086d6c432e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 6 Aug 2023 12:39:11 +0200 Subject: [PATCH 0111/1271] doc: Link pytest.main to how-to guide (#11287) --- doc/en/reference/reference.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index ea008110e4a..a6d7cfdd40b 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -82,6 +82,8 @@ pytest.exit pytest.main ~~~~~~~~~~~ +**Tutorial**: :ref:`pytest.main-usage` + .. autofunction:: pytest.main pytest.param From e8a8a5f320ad7a9fc1d58ab74c2425e923634f60 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Sun, 6 Aug 2023 17:29:54 +0330 Subject: [PATCH 0112/1271] python: fix scope assignment for indirect parameter sets (#11277) Previously, when assigning a scope for a fully-indirect parameter set, when there are multiple fixturedefs for a param (i.e. same-name fixture chain), the highest scope was used, but it should be the lowest scope, since that's the effective scope of the fixture. --- changelog/11277.bugfix.rst | 2 ++ src/_pytest/fixtures.py | 2 +- src/_pytest/python.py | 4 +-- testing/python/metafunc.py | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 changelog/11277.bugfix.rst diff --git a/changelog/11277.bugfix.rst b/changelog/11277.bugfix.rst new file mode 100644 index 00000000000..43370561e3b --- /dev/null +++ b/changelog/11277.bugfix.rst @@ -0,0 +1,2 @@ +Fixed a bug that when there are multiple fixtures for an indirect parameter, +the scope of the highest-scope fixture is picked for the parameter set, instead of that of the one with the narrowest scope. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 00c2a8ef432..6e99ec18895 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -492,7 +492,7 @@ def node(self): node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem elif scope is Scope.Package: # FIXME: _fixturedef is not defined on FixtureRequest (this class), - # but on FixtureRequest (a subclass). + # but on SubRequest (a subclass). node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] else: node = get_scope_node(self._pyfuncitem, scope) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index c0c16d4d0d8..ae42e390f56 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1516,7 +1516,7 @@ def _find_parametrized_scope( if all_arguments_are_fixtures: fixturedefs = arg2fixturedefs or {} used_scopes = [ - fixturedef[0]._scope + fixturedef[-1]._scope for name, fixturedef in fixturedefs.items() if name in argnames ] @@ -1682,7 +1682,7 @@ class Function(PyobjMixin, nodes.Item): :param config: The pytest Config object. :param callspec: - If given, this is function has been parametrized and the callspec contains + If given, this function has been parametrized and the callspec contains meta information about the parametrization. :param callobj: If given, the object which will be called when the Function is invoked, diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index bb4ae9d9af3..4c066a89d79 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -151,6 +151,7 @@ class DummyFixtureDef: module_fix=[DummyFixtureDef(Scope.Module)], class_fix=[DummyFixtureDef(Scope.Class)], func_fix=[DummyFixtureDef(Scope.Function)], + mixed_fix=[DummyFixtureDef(Scope.Module), DummyFixtureDef(Scope.Class)], ), ) @@ -187,6 +188,7 @@ def find_scope(argnames, indirect): ) == Scope.Module ) + assert find_scope(["mixed_fix"], indirect=True) == Scope.Class def test_parametrize_and_id(self) -> None: def func(x, y): @@ -1503,6 +1505,66 @@ def test_it(x): pass result = pytester.runpytest() assert result.ret == 0 + def test_reordering_with_scopeless_and_just_indirect_parametrization( + self, pytester: Pytester + ) -> None: + pytester.makeconftest( + """ + import pytest + + @pytest.fixture(scope="package") + def fixture1(): + pass + """ + ) + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="module") + def fixture0(): + pass + + @pytest.fixture(scope="module") + def fixture1(fixture0): + pass + + @pytest.mark.parametrize("fixture1", [0], indirect=True) + def test_0(fixture1): + pass + + @pytest.fixture(scope="module") + def fixture(): + pass + + @pytest.mark.parametrize("fixture", [0], indirect=True) + def test_1(fixture): + pass + + def test_2(): + pass + + class Test: + @pytest.fixture(scope="class") + def fixture(self, fixture): + pass + + @pytest.mark.parametrize("fixture", [0], indirect=True) + def test_3(self, fixture): + pass + """ + ) + result = pytester.runpytest("-v") + assert result.ret == 0 + result.stdout.fnmatch_lines( + [ + "*test_0*", + "*test_1*", + "*test_2*", + "*test_3*", + ] + ) + class TestMetafuncFunctionalAuto: """Tests related to automatically find out the correct scope for From 84a342e27c1b3ba218b9c31ed9aeddba843ef36c Mon Sep 17 00:00:00 2001 From: Christoph Anton Mitterer Date: Sun, 6 Aug 2023 17:39:31 +0200 Subject: [PATCH 0113/1271] doc: parametrize() can be called multiple times only on different args Signed-off-by: Christoph Anton Mitterer --- src/_pytest/python.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index c0c16d4d0d8..b3f7d408b47 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1239,8 +1239,9 @@ def parametrize( during the collection phase. If you need to setup expensive resources see about setting indirect to do it rather than at test setup time. - Can be called multiple times, in which case each call parametrizes all - previous parametrizations, e.g. + Can be called multiple times per test function (but only on different + argument names), in which case each call parametrizes all previous + parametrizations, e.g. :: From 1cc58ed67ff9e9c90b6b39154763138779ebceaf Mon Sep 17 00:00:00 2001 From: Christoph Anton Mitterer Date: Sun, 6 Aug 2023 17:43:37 +0200 Subject: [PATCH 0114/1271] improve exception message on duplicate parametrization Signed-off-by: Christoph Anton Mitterer --- src/_pytest/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index b3f7d408b47..fef952b6604 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1148,7 +1148,7 @@ def setmulti( arg2scope = self._arg2scope.copy() for arg, val in zip(argnames, valset): if arg in params or arg in funcargs: - raise ValueError(f"duplicate {arg!r}") + raise ValueError(f"duplicate parametrization of {arg!r}") valtype_for_arg = valtypes[arg] if valtype_for_arg == "params": params[arg] = val From 9c67b7aeb60d7abbea782018e73a93d6c8bbef16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 03:39:31 +0000 Subject: [PATCH 0115/1271] build(deps): Bump django in /testing/plugins_integration Bumps [django](https://github.com/django/django) from 4.2.3 to 4.2.4. - [Commits](https://github.com/django/django/compare/4.2.3...4.2.4) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index cf580b7ccb4..d46300fe0d8 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==3.7.1 -django==4.2.3 +django==4.2.4 pytest-asyncio==0.21.1 pytest-bdd==6.1.1 pytest-cov==4.1.0 From 09b78737a5bde23eb488d5d6649bf966c5809176 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Wed, 9 Aug 2023 20:43:45 +0330 Subject: [PATCH 0116/1271] Move `fixtures.py::add_funcarg_pseudo_fixture_def` to `Metafunc.parametrize` (#11220) To remove fixtures.py::add_funcargs_pseudo_fixture_def and add its logic i.e. registering funcargs as params and making corresponding fixturedefs, right to Metafunc.parametrize in which parametrization takes place. To remove funcargs from metafunc attributes as we populate metafunc params and make pseudo fixturedefs simultaneously and there's no need to keep funcargs separately. --- src/_pytest/fixtures.py | 88 ----------------------- src/_pytest/python.py | 102 +++++++++++++++++++------- testing/example_scripts/issue_519.py | 4 +- testing/python/metafunc.py | 103 +++++++++++++++++++++++---- 4 files changed, 167 insertions(+), 130 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 6e99ec18895..be0dce17c43 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -63,7 +63,6 @@ from _pytest.scope import _ScopeName from _pytest.scope import HIGH_SCOPES from _pytest.scope import Scope -from _pytest.stash import StashKey if TYPE_CHECKING: @@ -147,89 +146,6 @@ def get_scope_node( assert_never(scope) -# Used for storing artificial fixturedefs for direct parametrization. -name2pseudofixturedef_key = StashKey[Dict[str, "FixtureDef[Any]"]]() - - -def add_funcarg_pseudo_fixture_def( - collector: nodes.Collector, metafunc: "Metafunc", fixturemanager: "FixtureManager" -) -> None: - import _pytest.python - - # This function will transform all collected calls to functions - # if they use direct funcargs (i.e. direct parametrization) - # because we want later test execution to be able to rely on - # an existing FixtureDef structure for all arguments. - # XXX we can probably avoid this algorithm if we modify CallSpec2 - # to directly care for creating the fixturedefs within its methods. - if not metafunc._calls[0].funcargs: - # This function call does not have direct parametrization. - return - # Collect funcargs of all callspecs into a list of values. - arg2params: Dict[str, List[object]] = {} - arg2scope: Dict[str, Scope] = {} - for callspec in metafunc._calls: - for argname, argvalue in callspec.funcargs.items(): - assert argname not in callspec.params - callspec.params[argname] = argvalue - arg2params_list = arg2params.setdefault(argname, []) - callspec.indices[argname] = len(arg2params_list) - arg2params_list.append(argvalue) - if argname not in arg2scope: - scope = callspec._arg2scope.get(argname, Scope.Function) - arg2scope[argname] = scope - callspec.funcargs.clear() - - # Register artificial FixtureDef's so that later at test execution - # time we can rely on a proper FixtureDef to exist for fixture setup. - arg2fixturedefs = metafunc._arg2fixturedefs - for argname, valuelist in arg2params.items(): - # If we have a scope that is higher than function, we need - # to make sure we only ever create an according fixturedef on - # a per-scope basis. We thus store and cache the fixturedef on the - # node related to the scope. - scope = arg2scope[argname] - node = None - if scope is not Scope.Function: - node = get_scope_node(collector, scope) - if node is None: - # If used class scope and there is no class, use module-level - # collector (for now). - if scope is Scope.Class: - assert isinstance(collector, _pytest.python.Module) - node = collector - # If used package scope and there is no package, use session - # (for now). - elif scope is Scope.Package: - node = collector.session - else: - assert False, f"Unhandled missing scope: {scope}" - if node is None: - name2pseudofixturedef = None - else: - default: Dict[str, FixtureDef[Any]] = {} - name2pseudofixturedef = node.stash.setdefault( - name2pseudofixturedef_key, default - ) - if name2pseudofixturedef is not None and argname in name2pseudofixturedef: - arg2fixturedefs[argname] = [name2pseudofixturedef[argname]] - else: - fixturedef = FixtureDef( - fixturemanager=fixturemanager, - baseid="", - argname=argname, - func=get_direct_param_fixture_func, - scope=arg2scope[argname], - params=valuelist, - unittest=False, - ids=None, - _ispytest=True, - ) - arg2fixturedefs[argname] = [fixturedef] - if name2pseudofixturedef is not None: - name2pseudofixturedef[argname] = fixturedef - - def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]: """Return fixturemarker or None if it doesn't exist or raised exceptions.""" @@ -365,10 +281,6 @@ def reorder_items_atscope( return items_done -def get_direct_param_fixture_func(request: "FixtureRequest") -> Any: - return request.param - - @dataclasses.dataclass(frozen=True) class FuncFixtureInfo: """Fixture-related information for a fixture-requesting item (e.g. test diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 02d6c174993..eb4512fe5ee 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -40,7 +40,6 @@ from _pytest._io import TerminalWriter from _pytest._io.saferepr import saferepr from _pytest.compat import ascii_escaped -from _pytest.compat import assert_never from _pytest.compat import get_default_arg_names from _pytest.compat import get_real_func from _pytest.compat import getimfunc @@ -59,7 +58,10 @@ from _pytest.deprecated import check_ispytest from _pytest.deprecated import INSTANCE_COLLECTOR from _pytest.deprecated import NOSE_SUPPORT_METHOD +from _pytest.fixtures import FixtureDef +from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FuncFixtureInfo +from _pytest.fixtures import get_scope_node from _pytest.main import Session from _pytest.mark import MARK_GEN from _pytest.mark import ParameterSet @@ -77,6 +79,7 @@ from _pytest.pathlib import visit from _pytest.scope import _ScopeName from _pytest.scope import Scope +from _pytest.stash import StashKey from _pytest.warning_types import PytestCollectionWarning from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning @@ -493,13 +496,11 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]: if not metafunc._calls: yield Function.from_parent(self, name=name, fixtureinfo=fixtureinfo) else: - # Add funcargs() as fixturedefs to fixtureinfo.arg2fixturedefs. - fm = self.session._fixturemanager - fixtures.add_funcarg_pseudo_fixture_def(self, metafunc, fm) - - # Add_funcarg_pseudo_fixture_def may have shadowed some fixtures - # with direct parametrization, so make sure we update what the - # function really needs. + # Direct parametrizations taking place in module/class-specific + # `metafunc.parametrize` calls may have shadowed some fixtures, so make sure + # we update what the function really needs a.k.a its fixture closure. Note that + # direct parametrizations using `@pytest.mark.parametrize` have already been considered + # into making the closure using `ignore_args` arg to `getfixtureclosure`. fixtureinfo.prune_dependency_tree() for callspec in metafunc._calls: @@ -1116,11 +1117,8 @@ class CallSpec2: and stored in item.callspec. """ - # arg name -> arg value which will be passed to the parametrized test - # function (direct parameterization). - funcargs: Dict[str, object] = dataclasses.field(default_factory=dict) - # arg name -> arg value which will be passed to a fixture of the same name - # (indirect parametrization). + # arg name -> arg value which will be passed to a fixture or pseudo-fixture + # of the same name. (indirect or direct parametrization respectively) params: Dict[str, object] = dataclasses.field(default_factory=dict) # arg name -> arg index. indices: Dict[str, int] = dataclasses.field(default_factory=dict) @@ -1134,7 +1132,6 @@ class CallSpec2: def setmulti( self, *, - valtypes: Mapping[str, "Literal['params', 'funcargs']"], argnames: Iterable[str], valset: Iterable[object], id: str, @@ -1142,24 +1139,16 @@ def setmulti( scope: Scope, param_index: int, ) -> "CallSpec2": - funcargs = self.funcargs.copy() params = self.params.copy() indices = self.indices.copy() arg2scope = self._arg2scope.copy() for arg, val in zip(argnames, valset): - if arg in params or arg in funcargs: + if arg in params: raise ValueError(f"duplicate parametrization of {arg!r}") - valtype_for_arg = valtypes[arg] - if valtype_for_arg == "params": - params[arg] = val - elif valtype_for_arg == "funcargs": - funcargs[arg] = val - else: - assert_never(valtype_for_arg) + params[arg] = val indices[arg] = param_index arg2scope[arg] = scope return CallSpec2( - funcargs=funcargs, params=params, indices=indices, _arg2scope=arg2scope, @@ -1178,6 +1167,14 @@ def id(self) -> str: return "-".join(self._idlist) +def get_direct_param_fixture_func(request: FixtureRequest) -> Any: + return request.param + + +# Used for storing pseudo fixturedefs for direct parametrization. +name2pseudofixturedef_key = StashKey[Dict[str, FixtureDef[Any]]]() + + @final class Metafunc: """Objects passed to the :hook:`pytest_generate_tests` hook. @@ -1320,8 +1317,6 @@ def parametrize( self._validate_if_using_arg_names(argnames, indirect) - arg_values_types = self._resolve_arg_value_types(argnames, indirect) - # Use any already (possibly) generated ids with parametrize Marks. if _param_mark and _param_mark._param_ids_from: generated_ids = _param_mark._param_ids_from._param_ids_generated @@ -1336,6 +1331,60 @@ def parametrize( if _param_mark and _param_mark._param_ids_from and generated_ids is None: object.__setattr__(_param_mark._param_ids_from, "_param_ids_generated", ids) + # Add funcargs as fixturedefs to fixtureinfo.arg2fixturedefs by registering + # artificial "pseudo" FixtureDef's so that later at test execution time we can + # rely on a proper FixtureDef to exist for fixture setup. + arg2fixturedefs = self._arg2fixturedefs + node = None + # If we have a scope that is higher than function, we need + # to make sure we only ever create an according fixturedef on + # a per-scope basis. We thus store and cache the fixturedef on the + # node related to the scope. + if scope_ is not Scope.Function: + collector = self.definition.parent + assert collector is not None + node = get_scope_node(collector, scope_) + if node is None: + # If used class scope and there is no class, use module-level + # collector (for now). + if scope_ is Scope.Class: + assert isinstance(collector, _pytest.python.Module) + node = collector + # If used package scope and there is no package, use session + # (for now). + elif scope_ is Scope.Package: + node = collector.session + else: + assert False, f"Unhandled missing scope: {scope}" + if node is None: + name2pseudofixturedef = None + else: + default: Dict[str, FixtureDef[Any]] = {} + name2pseudofixturedef = node.stash.setdefault( + name2pseudofixturedef_key, default + ) + arg_values_types = self._resolve_arg_value_types(argnames, indirect) + for argname in argnames: + if arg_values_types[argname] == "params": + continue + if name2pseudofixturedef is not None and argname in name2pseudofixturedef: + fixturedef = name2pseudofixturedef[argname] + else: + fixturedef = FixtureDef( + fixturemanager=self.definition.session._fixturemanager, + baseid="", + argname=argname, + func=get_direct_param_fixture_func, + scope=scope_, + params=None, + unittest=False, + ids=None, + _ispytest=True, + ) + if name2pseudofixturedef is not None: + name2pseudofixturedef[argname] = fixturedef + arg2fixturedefs[argname] = [fixturedef] + # Create the new calls: if we are parametrize() multiple times (by applying the decorator # more than once) then we accumulate those calls generating the cartesian product # of all calls. @@ -1345,7 +1394,6 @@ def parametrize( zip(ids, parametersets) ): newcallspec = callspec.setmulti( - valtypes=arg_values_types, argnames=argnames, valset=param_set.values, id=param_id, diff --git a/testing/example_scripts/issue_519.py b/testing/example_scripts/issue_519.py index e44367fca04..73437ef7bdb 100644 --- a/testing/example_scripts/issue_519.py +++ b/testing/example_scripts/issue_519.py @@ -22,13 +22,13 @@ def checked_order(): assert order == [ ("issue_519.py", "fix1", "arg1v1"), ("test_one[arg1v1-arg2v1]", "fix2", "arg2v1"), - ("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"), ("test_one[arg1v1-arg2v2]", "fix2", "arg2v2"), + ("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"), ("test_two[arg1v1-arg2v2]", "fix2", "arg2v2"), ("issue_519.py", "fix1", "arg1v2"), ("test_one[arg1v2-arg2v1]", "fix2", "arg2v1"), - ("test_two[arg1v2-arg2v1]", "fix2", "arg2v1"), ("test_one[arg1v2-arg2v2]", "fix2", "arg2v2"), + ("test_two[arg1v2-arg2v1]", "fix2", "arg2v1"), ("test_two[arg1v2-arg2v2]", "fix2", "arg2v2"), ] diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 4c066a89d79..4ee9e32d6e9 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -23,6 +23,7 @@ from _pytest.compat import NOTSET from _pytest.outcomes import fail from _pytest.pytester import Pytester +from _pytest.python import Function from _pytest.python import IdMaker from _pytest.scope import Scope @@ -33,11 +34,19 @@ def Metafunc(self, func, config=None) -> python.Metafunc: # on the funcarg level, so we don't need a full blown # initialization. class FuncFixtureInfoMock: - name2fixturedefs = None + name2fixturedefs: Dict[str, List[fixtures.FixtureDef[object]]] = {} def __init__(self, names): self.names_closure = names + @dataclasses.dataclass + class FixtureManagerMock: + config: Any + + @dataclasses.dataclass + class SessionMock: + _fixturemanager: FixtureManagerMock + @dataclasses.dataclass class DefinitionMock(python.FunctionDefinition): _nodeid: str @@ -46,6 +55,8 @@ class DefinitionMock(python.FunctionDefinition): names = getfuncargnames(func) fixtureinfo: Any = FuncFixtureInfoMock(names) definition: Any = DefinitionMock._create(obj=func, _nodeid="mock::nodeid") + definition._fixtureinfo = fixtureinfo + definition.session = SessionMock(FixtureManagerMock({})) return python.Metafunc(definition, fixtureinfo, config, _ispytest=True) def test_no_funcargs(self) -> None: @@ -98,7 +109,7 @@ def gen() -> Iterator[Union[int, None, Exc]]: # When the input is an iterator, only len(args) are taken, # so the bad Exc isn't reached. metafunc.parametrize("x", [1, 2], ids=gen()) # type: ignore[arg-type] - assert [(x.funcargs, x.id) for x in metafunc._calls] == [ + assert [(x.params, x.id) for x in metafunc._calls] == [ ({"x": 1}, "0"), ({"x": 2}, "2"), ] @@ -714,8 +725,6 @@ def func(x, y): metafunc.parametrize("x", [1], indirect=True) metafunc.parametrize("y", [2, 3], indirect=True) assert len(metafunc._calls) == 2 - assert metafunc._calls[0].funcargs == {} - assert metafunc._calls[1].funcargs == {} assert metafunc._calls[0].params == dict(x=1, y=2) assert metafunc._calls[1].params == dict(x=1, y=3) @@ -727,8 +736,10 @@ def func(x, y): metafunc = self.Metafunc(func) metafunc.parametrize("x, y", [("a", "b")], indirect=["x"]) - assert metafunc._calls[0].funcargs == dict(y="b") - assert metafunc._calls[0].params == dict(x="a") + assert metafunc._calls[0].params == dict(x="a", y="b") + # Since `y` is a direct parameter, its pseudo-fixture would + # be registered. + assert list(metafunc._arg2fixturedefs.keys()) == ["y"] def test_parametrize_indirect_list_all(self) -> None: """#714""" @@ -738,8 +749,8 @@ def func(x, y): metafunc = self.Metafunc(func) metafunc.parametrize("x, y", [("a", "b")], indirect=["x", "y"]) - assert metafunc._calls[0].funcargs == {} assert metafunc._calls[0].params == dict(x="a", y="b") + assert list(metafunc._arg2fixturedefs.keys()) == [] def test_parametrize_indirect_list_empty(self) -> None: """#714""" @@ -749,8 +760,8 @@ def func(x, y): metafunc = self.Metafunc(func) metafunc.parametrize("x, y", [("a", "b")], indirect=[]) - assert metafunc._calls[0].funcargs == dict(x="a", y="b") - assert metafunc._calls[0].params == {} + assert metafunc._calls[0].params == dict(x="a", y="b") + assert list(metafunc._arg2fixturedefs.keys()) == ["x", "y"] def test_parametrize_indirect_wrong_type(self) -> None: def func(x, y): @@ -944,9 +955,9 @@ def test_parametrize_onearg(self) -> None: metafunc = self.Metafunc(lambda x: None) metafunc.parametrize("x", [1, 2]) assert len(metafunc._calls) == 2 - assert metafunc._calls[0].funcargs == dict(x=1) + assert metafunc._calls[0].params == dict(x=1) assert metafunc._calls[0].id == "1" - assert metafunc._calls[1].funcargs == dict(x=2) + assert metafunc._calls[1].params == dict(x=2) assert metafunc._calls[1].id == "2" def test_parametrize_onearg_indirect(self) -> None: @@ -961,11 +972,45 @@ def test_parametrize_twoargs(self) -> None: metafunc = self.Metafunc(lambda x, y: None) metafunc.parametrize(("x", "y"), [(1, 2), (3, 4)]) assert len(metafunc._calls) == 2 - assert metafunc._calls[0].funcargs == dict(x=1, y=2) + assert metafunc._calls[0].params == dict(x=1, y=2) assert metafunc._calls[0].id == "1-2" - assert metafunc._calls[1].funcargs == dict(x=3, y=4) + assert metafunc._calls[1].params == dict(x=3, y=4) assert metafunc._calls[1].id == "3-4" + def test_high_scoped_parametrize_reordering(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("arg2", [3, 4]) + @pytest.mark.parametrize("arg1", [0, 1, 2], scope='module') + def test1(arg1, arg2): + pass + + def test2(): + pass + + @pytest.mark.parametrize("arg1", [0, 1, 2], scope='module') + def test3(arg1): + pass + """ + ) + result = pytester.runpytest("--collect-only") + result.stdout.re_match_lines( + [ + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + ] + ) + def test_parametrize_multiple_times(self, pytester: Pytester) -> None: pytester.makepyfile( """ @@ -1505,6 +1550,38 @@ def test_it(x): pass result = pytester.runpytest() assert result.ret == 0 + def test_parametrize_module_level_test_with_class_scope( + self, pytester: Pytester + ) -> None: + """ + Test that a class-scoped parametrization without a corresponding `Class` + gets module scope, i.e. we only create a single FixtureDef for it per module. + """ + module = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("x", [0, 1], scope="class") + def test_1(x): + pass + + @pytest.mark.parametrize("x", [1, 2], scope="module") + def test_2(x): + pass + """ + ) + test_1_0, _, test_2_0, _ = pytester.genitems((pytester.getmodulecol(module),)) + + assert isinstance(test_1_0, Function) + assert test_1_0.name == "test_1[0]" + test_1_fixture_x = test_1_0._fixtureinfo.name2fixturedefs["x"][-1] + + assert isinstance(test_2_0, Function) + assert test_2_0.name == "test_2[1]" + test_2_fixture_x = test_2_0._fixtureinfo.name2fixturedefs["x"][-1] + + assert test_1_fixture_x is test_2_fixture_x + def test_reordering_with_scopeless_and_just_indirect_parametrization( self, pytester: Pytester ) -> None: From 3ad3fc6b8f480656e727ce7e89ad84eb9a6735e7 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 9 Aug 2023 20:34:16 +0300 Subject: [PATCH 0117/1271] python: use clearer terminology for `_resolve_arg_value_types` --- src/_pytest/python.py | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index eb4512fe5ee..c3097b863c2 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1363,9 +1363,9 @@ def parametrize( name2pseudofixturedef = node.stash.setdefault( name2pseudofixturedef_key, default ) - arg_values_types = self._resolve_arg_value_types(argnames, indirect) + arg_directness = self._resolve_args_directness(argnames, indirect) for argname in argnames: - if arg_values_types[argname] == "params": + if arg_directness[argname] == "indirect": continue if name2pseudofixturedef is not None and argname in name2pseudofixturedef: fixturedef = name2pseudofixturedef[argname] @@ -1470,28 +1470,30 @@ def _validate_ids( return list(itertools.islice(ids, num_ids)) - def _resolve_arg_value_types( + def _resolve_args_directness( self, argnames: Sequence[str], indirect: Union[bool, Sequence[str]], - ) -> Dict[str, "Literal['params', 'funcargs']"]: - """Resolve if each parametrized argument must be considered a - parameter to a fixture or a "funcarg" to the function, based on the - ``indirect`` parameter of the parametrized() call. + ) -> Dict[str, Literal["indirect", "direct"]]: + """Resolve if each parametrized argument must be considered an indirect + parameter to a fixture of the same name, or a direct parameter to the + parametrized function, based on the ``indirect`` parameter of the + parametrized() call. - :param List[str] argnames: List of argument names passed to ``parametrize()``. - :param indirect: Same as the ``indirect`` parameter of ``parametrize()``. - :rtype: Dict[str, str] - A dict mapping each arg name to either: - * "params" if the argname should be the parameter of a fixture of the same name. - * "funcargs" if the argname should be a parameter to the parametrized test function. + :param argnames: + List of argument names passed to ``parametrize()``. + :param indirect: + Same as the ``indirect`` parameter of ``parametrize()``. + :returns + A dict mapping each arg name to either "indirect" or "direct". """ + arg_directness: Dict[str, Literal["indirect", "direct"]] if isinstance(indirect, bool): - valtypes: Dict[str, Literal["params", "funcargs"]] = dict.fromkeys( - argnames, "params" if indirect else "funcargs" + arg_directness = dict.fromkeys( + argnames, "indirect" if indirect else "direct" ) elif isinstance(indirect, Sequence): - valtypes = dict.fromkeys(argnames, "funcargs") + arg_directness = dict.fromkeys(argnames, "direct") for arg in indirect: if arg not in argnames: fail( @@ -1500,7 +1502,7 @@ def _resolve_arg_value_types( ), pytrace=False, ) - valtypes[arg] = "params" + arg_directness[arg] = "indirect" else: fail( "In {func}: expected Sequence or boolean for indirect, got {type}".format( @@ -1508,7 +1510,7 @@ def _resolve_arg_value_types( ), pytrace=False, ) - return valtypes + return arg_directness def _validate_if_using_arg_names( self, From 47c0fc3d78a6db8bbe6c298dec76084142f59171 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Thu, 10 Aug 2023 16:36:22 -0700 Subject: [PATCH 0118/1271] tests --- testing/test_assertrewrite.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index e1b71ded69c..d85c8bed6d6 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -685,6 +685,21 @@ def myany(x) -> bool: assert msg is not None assert " < 0" in msg + def test_assert_handling_raise_in__iter__(self) -> None: + def f() -> None: + class A: + def __iter__(self): + raise TypeError("user message") + + def __eq__(self, o: object) -> bool: + return self is o + + assert A() == A() + + msg = getmsg(f) + assert msg is not None + assert "Unexpected exception" in msg + def test_formatchar(self) -> None: def f() -> None: assert "%test" == "test" # type: ignore[comparison-overlap] From e938580257e8120dabbea789d5b7a3dd3354d0a3 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:37:48 -0700 Subject: [PATCH 0119/1271] check for user-generated exceptions --- src/_pytest/assertion/util.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index fc5dfdbd5ba..47244b688ac 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -132,8 +132,14 @@ def isiterable(obj: Any) -> bool: try: iter(obj) return not istext(obj) - except TypeError: - return False + except Exception as e: + if ( + isinstance(e, TypeError) + and (len(e.args) == 1) + and "iter() returned non-iterator of type" in str(e.args[0]) + ): + return False + raise ValueError(f"Unexpected exception {e!r} while testing object {obj!r}") def has_default_eq( @@ -195,13 +201,20 @@ def assertrepr_compare( explanation = _notin_text(left, right, verbose) except outcomes.Exit: raise - except Exception: - explanation = [ - "(pytest_assertion plugin: representation of details failed: {}.".format( - _pytest._code.ExceptionInfo.from_current()._getreprcrash() - ), - " Probably an object has a faulty __repr__.)", - ] + except Exception as e: + if ( + isinstance(e, ValueError) + and (len(e.args) == 1) + and ("Unexpected exception" in str(e.args[0])) + ): + explanation = [e.args[0]] + else: + explanation = [ + "(pytest_assertion plugin: representation of details failed: {}.".format( + _pytest._code.ExceptionInfo.from_current()._getreprcrash() + ), + " Probably an object has a faulty __repr__.)", + ] if not explanation: return None From b9cb87d862bb3f841d67723ac5717ce90b219dc2 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Thu, 10 Aug 2023 17:43:01 -0700 Subject: [PATCH 0120/1271] simplify code / take out user-gen typeerror case --- src/_pytest/assertion/util.py | 8 ++------ testing/test_assertrewrite.py | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 47244b688ac..22eec180961 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -132,13 +132,9 @@ def isiterable(obj: Any) -> bool: try: iter(obj) return not istext(obj) + except TypeError: + return False except Exception as e: - if ( - isinstance(e, TypeError) - and (len(e.args) == 1) - and "iter() returned non-iterator of type" in str(e.args[0]) - ): - return False raise ValueError(f"Unexpected exception {e!r} while testing object {obj!r}") diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index d85c8bed6d6..b4e3e5d53d2 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -689,7 +689,7 @@ def test_assert_handling_raise_in__iter__(self) -> None: def f() -> None: class A: def __iter__(self): - raise TypeError("user message") + raise ValueError() def __eq__(self, o: object) -> bool: return self is o From d2dc8a70b593b61a013ae3eba99bb3f10e82eb65 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 11 Aug 2023 09:48:53 -0700 Subject: [PATCH 0121/1271] changelog --- changelog/7966.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/7966.bugfix.rst diff --git a/changelog/7966.bugfix.rst b/changelog/7966.bugfix.rst new file mode 100644 index 00000000000..40cad46c69d --- /dev/null +++ b/changelog/7966.bugfix.rst @@ -0,0 +1 @@ +Assertion rewrite mechanism now gives a seperate, more detailed error message from failures within __iter__. From ec1053cc162250e42ae220ebe91c3bf00b22b084 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 11 Aug 2023 10:03:19 -0700 Subject: [PATCH 0122/1271] error msg --- src/_pytest/assertion/util.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 22eec180961..613a40b9785 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -135,7 +135,9 @@ def isiterable(obj: Any) -> bool: except TypeError: return False except Exception as e: - raise ValueError(f"Unexpected exception {e!r} while testing object {obj!r}") + raise ValueError( + f"Unexpected exception {e!r} while testing object {obj!r}. Probably an issue with __iter__" + ) def has_default_eq( From c0cf822ca1d5d6ac74f46ddccbe377c254c6084a Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 11 Aug 2023 10:03:19 -0700 Subject: [PATCH 0123/1271] improve error msg and test --- src/_pytest/assertion/util.py | 9 ++++++--- testing/test_assertrewrite.py | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 613a40b9785..d20c2363eb3 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -136,7 +136,10 @@ def isiterable(obj: Any) -> bool: return False except Exception as e: raise ValueError( - f"Unexpected exception {e!r} while testing object {obj!r}. Probably an issue with __iter__" + [ + f"pytest_assertion plugin: unexpected exception {e!r} while testing object {obj!r}", + ", probably from __iter__", + ] ) @@ -203,9 +206,9 @@ def assertrepr_compare( if ( isinstance(e, ValueError) and (len(e.args) == 1) - and ("Unexpected exception" in str(e.args[0])) + and ("__iter__" in str(e.args[0])) ): - explanation = [e.args[0]] + explanation = e.args[0] else: explanation = [ "(pytest_assertion plugin: representation of details failed: {}.".format( diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index b4e3e5d53d2..62c6bb8d4bc 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -698,7 +698,7 @@ def __eq__(self, o: object) -> bool: msg = getmsg(f) assert msg is not None - assert "Unexpected exception" in msg + assert "__iter__" in msg and "__repr__" not in msg def test_formatchar(self) -> None: def f() -> None: From 9e164fc4fe46bbd43ac87fc30d0d6935f7e4d28b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 16 Jul 2023 00:37:33 +0300 Subject: [PATCH 0124/1271] fixtures: make FixtureRequest abstract, add TopRequest subclass Fix #11218. --- changelog/11218.trivial.rst | 5 + src/_pytest/doctest.py | 8 +- src/_pytest/fixtures.py | 201 ++++++++++++++++++++++-------------- src/_pytest/python.py | 2 +- testing/python/fixtures.py | 25 ++--- testing/test_legacypath.py | 3 +- 6 files changed, 148 insertions(+), 96 deletions(-) create mode 100644 changelog/11218.trivial.rst diff --git a/changelog/11218.trivial.rst b/changelog/11218.trivial.rst new file mode 100644 index 00000000000..772054856d2 --- /dev/null +++ b/changelog/11218.trivial.rst @@ -0,0 +1,5 @@ +(This entry is meant to assist plugins which access private pytest internals to instantiate ``FixtureRequest`` objects.) + +:class:`~pytest.FixtureRequest` is now an abstract class which can't be instantiated directly. +A new concrete ``TopRequest`` subclass of ``FixtureRequest`` has been added for the ``request`` fixture in test functions, +as counterpart to the existing ``SubRequest`` subclass for the ``request`` fixture in fixture functions. diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index a37f1d2ace9..e6f666dda03 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -32,7 +32,7 @@ from _pytest.config import Config from _pytest.config.argparsing import Parser from _pytest.fixtures import fixture -from _pytest.fixtures import FixtureRequest +from _pytest.fixtures import TopRequest from _pytest.nodes import Collector from _pytest.nodes import Item from _pytest.outcomes import OutcomeException @@ -261,7 +261,7 @@ def __init__( self.runner = runner self.dtest = dtest self.obj = None - self.fixture_request: Optional[FixtureRequest] = None + self.fixture_request: Optional[TopRequest] = None @classmethod def from_parent( # type: ignore @@ -571,7 +571,7 @@ def _find( ) -def _setup_fixtures(doctest_item: DoctestItem) -> FixtureRequest: +def _setup_fixtures(doctest_item: DoctestItem) -> TopRequest: """Used by DoctestTextfile and DoctestItem to setup fixture information.""" def func() -> None: @@ -582,7 +582,7 @@ def func() -> None: doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined] node=doctest_item, func=func, cls=None, funcargs=False ) - fixture_request = FixtureRequest(doctest_item, _ispytest=True) # type: ignore[arg-type] + fixture_request = TopRequest(doctest_item, _ispytest=True) # type: ignore[arg-type] fixture_request._fillfixtures() return fixture_request diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index be0dce17c43..c7fc28adbbc 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1,3 +1,4 @@ +import abc import dataclasses import functools import inspect @@ -340,26 +341,32 @@ def prune_dependency_tree(self) -> None: self.names_closure[:] = sorted(closure, key=self.names_closure.index) -class FixtureRequest: - """A request for a fixture from a test or fixture function. +class FixtureRequest(abc.ABC): + """The type of the ``request`` fixture. - A request object gives access to the requesting test context and has - an optional ``param`` attribute in case the fixture is parametrized - indirectly. + A request object gives access to the requesting test context and has a + ``param`` attribute in case the fixture is parametrized. """ - def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: + def __init__( + self, + pyfuncitem: "Function", + fixturename: Optional[str], + arg2fixturedefs: Dict[str, Sequence["FixtureDef[Any]"]], + arg2index: Dict[str, int], + fixture_defs: Dict[str, "FixtureDef[Any]"], + *, + _ispytest: bool = False, + ) -> None: check_ispytest(_ispytest) #: Fixture for which this request is being performed. - self.fixturename: Optional[str] = None - self._pyfuncitem = pyfuncitem - self._fixturemanager = pyfuncitem.session._fixturemanager - self._scope = Scope.Function + self.fixturename: Final = fixturename + self._pyfuncitem: Final = pyfuncitem # The FixtureDefs for each fixture name requested by this item. # Starts from the statically-known fixturedefs resolved during # collection. Dynamically requested fixtures (using # `request.getfixturevalue("foo")`) are added dynamically. - self._arg2fixturedefs = pyfuncitem._fixtureinfo.name2fixturedefs.copy() + self._arg2fixturedefs: Final = arg2fixturedefs # A fixture may override another fixture with the same name, e.g. a fixture # in a module can override a fixture in a conftest, a fixture in a class can # override a fixture in the module, and so on. @@ -369,10 +376,10 @@ def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: # The fixturedefs list in _arg2fixturedefs for a given name is ordered from # furthest to closest, so we use negative indexing -1, -2, ... to go from # last to first. - self._arg2index: Dict[str, int] = {} + self._arg2index: Final = arg2index # The evaluated argnames so far, mapping to the FixtureDef they resolved # to. - self._fixture_defs: Dict[str, FixtureDef[Any]] = {} + self._fixture_defs: Final = fixture_defs # Notes on the type of `param`: # -`request.param` is only defined in parametrized fixtures, and will raise # AttributeError otherwise. Python typing has no notion of "undefined", so @@ -383,6 +390,15 @@ def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: # for now just using Any. self.param: Any + @property + def _fixturemanager(self) -> "FixtureManager": + return self._pyfuncitem.session._fixturemanager + + @property + @abc.abstractmethod + def _scope(self) -> Scope: + raise NotImplementedError() + @property def scope(self) -> _ScopeName: """Scope string, one of "function", "class", "module", "package", "session".""" @@ -396,25 +412,10 @@ def fixturenames(self) -> List[str]: return result @property + @abc.abstractmethod def node(self): """Underlying collection node (depends on current request scope).""" - scope = self._scope - if scope is Scope.Function: - # This might also be a non-function Item despite its attribute name. - node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem - elif scope is Scope.Package: - # FIXME: _fixturedef is not defined on FixtureRequest (this class), - # but on SubRequest (a subclass). - node = get_scope_package(self._pyfuncitem, self._fixturedef) # type: ignore[attr-defined] - else: - node = get_scope_node(self._pyfuncitem, scope) - if node is None and scope is Scope.Class: - # Fallback to function item itself. - node = self._pyfuncitem - assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format( - scope, self._pyfuncitem - ) - return node + raise NotImplementedError() def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": fixturedefs = self._arg2fixturedefs.get(argname, None) @@ -500,11 +501,11 @@ def session(self) -> "Session": """Pytest session object.""" return self._pyfuncitem.session # type: ignore[no-any-return] + @abc.abstractmethod def addfinalizer(self, finalizer: Callable[[], object]) -> None: """Add finalizer/teardown function to be called without arguments after the last test within the requesting test context finished execution.""" - # XXX usually this method is shadowed by fixturedef specific ones. - self.node.addfinalizer(finalizer) + raise NotImplementedError() def applymarker(self, marker: Union[str, MarkDecorator]) -> None: """Apply a marker to a single test function invocation. @@ -525,13 +526,6 @@ def raiseerror(self, msg: Optional[str]) -> NoReturn: """ raise self._fixturemanager.FixtureLookupError(None, self, msg) - def _fillfixtures(self) -> None: - item = self._pyfuncitem - fixturenames = getattr(item, "fixturenames", self.fixturenames) - for argname in fixturenames: - if argname not in item.funcargs: - item.funcargs[argname] = self.getfixturevalue(argname) - def getfixturevalue(self, argname: str) -> Any: """Dynamically run a named fixture function. @@ -665,6 +659,98 @@ def _schedule_finalizers( finalizer = functools.partial(fixturedef.finish, request=subrequest) subrequest.node.addfinalizer(finalizer) + +@final +class TopRequest(FixtureRequest): + """The type of the ``request`` fixture in a test function.""" + + def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: + super().__init__( + fixturename=None, + pyfuncitem=pyfuncitem, + arg2fixturedefs=pyfuncitem._fixtureinfo.name2fixturedefs.copy(), + arg2index={}, + fixture_defs={}, + _ispytest=_ispytest, + ) + + @property + def _scope(self) -> Scope: + return Scope.Function + + @property + def node(self): + return self._pyfuncitem + + def __repr__(self) -> str: + return "" % (self.node) + + def _fillfixtures(self) -> None: + item = self._pyfuncitem + fixturenames = getattr(item, "fixturenames", self.fixturenames) + for argname in fixturenames: + if argname not in item.funcargs: + item.funcargs[argname] = self.getfixturevalue(argname) + + def addfinalizer(self, finalizer: Callable[[], object]) -> None: + self.node.addfinalizer(finalizer) + + +@final +class SubRequest(FixtureRequest): + """The type of the ``request`` fixture in a fixture function requested + (transitively) by a test function.""" + + def __init__( + self, + request: FixtureRequest, + scope: Scope, + param: Any, + param_index: int, + fixturedef: "FixtureDef[object]", + *, + _ispytest: bool = False, + ) -> None: + super().__init__( + pyfuncitem=request._pyfuncitem, + fixturename=fixturedef.argname, + fixture_defs=request._fixture_defs, + arg2fixturedefs=request._arg2fixturedefs, + arg2index=request._arg2index, + _ispytest=_ispytest, + ) + self._parent_request: Final[FixtureRequest] = request + self._scope_field: Final = scope + self._fixturedef: Final = fixturedef + if param is not NOTSET: + self.param = param + self.param_index: Final = param_index + + def __repr__(self) -> str: + return f"" + + @property + def _scope(self) -> Scope: + return self._scope_field + + @property + def node(self): + scope = self._scope + if scope is Scope.Function: + # This might also be a non-function Item despite its attribute name. + node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem + elif scope is Scope.Package: + node = get_scope_package(self._pyfuncitem, self._fixturedef) + else: + node = get_scope_node(self._pyfuncitem, scope) + if node is None and scope is Scope.Class: + # Fallback to function item itself. + node = self._pyfuncitem + assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format( + scope, self._pyfuncitem + ) + return node + def _check_scope( self, argname: str, @@ -699,44 +785,7 @@ def _factorytraceback(self) -> List[str]: ) return lines - def __repr__(self) -> str: - return "" % (self.node) - - -@final -class SubRequest(FixtureRequest): - """A sub request for handling getting a fixture from a test function/fixture.""" - - def __init__( - self, - request: "FixtureRequest", - scope: Scope, - param: Any, - param_index: int, - fixturedef: "FixtureDef[object]", - *, - _ispytest: bool = False, - ) -> None: - check_ispytest(_ispytest) - self._parent_request = request - self.fixturename = fixturedef.argname - if param is not NOTSET: - self.param = param - self.param_index = param_index - self._scope = scope - self._fixturedef = fixturedef - self._pyfuncitem = request._pyfuncitem - self._fixture_defs = request._fixture_defs - self._arg2fixturedefs = request._arg2fixturedefs - self._arg2index = request._arg2index - self._fixturemanager = request._fixturemanager - - def __repr__(self) -> str: - return f"" - def addfinalizer(self, finalizer: Callable[[], object]) -> None: - """Add finalizer/teardown function to be called without arguments after - the last test within the requesting test context finished execution.""" self._fixturedef.addfinalizer(finalizer) def _schedule_finalizers( diff --git a/src/_pytest/python.py b/src/_pytest/python.py index c3097b863c2..df1eb854dd4 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1812,7 +1812,7 @@ def from_parent(cls, parent, **kw): # todo: determine sound type limitations def _initrequest(self) -> None: self.funcargs: Dict[str, object] = {} - self._request = fixtures.FixtureRequest(self, _ispytest=True) + self._request = fixtures.TopRequest(self, _ispytest=True) @property def function(self): diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 7c028277253..a8f36cb9fae 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4,10 +4,9 @@ from pathlib import Path import pytest -from _pytest import fixtures from _pytest.compat import getfuncargnames from _pytest.config import ExitCode -from _pytest.fixtures import FixtureRequest +from _pytest.fixtures import TopRequest from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import get_public_names from _pytest.pytester import Pytester @@ -659,7 +658,7 @@ def test_func(something): pass """ ) assert isinstance(item, Function) - req = fixtures.FixtureRequest(item, _ispytest=True) + req = TopRequest(item, _ispytest=True) assert req.function == item.obj assert req.keywords == item.keywords assert hasattr(req.module, "test_func") @@ -701,9 +700,7 @@ def test_method(self, something): (item1,) = pytester.genitems([modcol]) assert isinstance(item1, Function) assert item1.name == "test_method" - arg2fixturedefs = fixtures.FixtureRequest( - item1, _ispytest=True - )._arg2fixturedefs + arg2fixturedefs = TopRequest(item1, _ispytest=True)._arg2fixturedefs assert len(arg2fixturedefs) == 1 assert arg2fixturedefs["something"][0].argname == "something" @@ -969,7 +966,7 @@ def test_request_getmodulepath(self, pytester: Pytester) -> None: modcol = pytester.getmodulecol("def test_somefunc(): pass") (item,) = pytester.genitems([modcol]) assert isinstance(item, Function) - req = fixtures.FixtureRequest(item, _ispytest=True) + req = TopRequest(item, _ispytest=True) assert req.path == modcol.path def test_request_fixturenames(self, pytester: Pytester) -> None: @@ -1128,7 +1125,7 @@ def test_func2(self, something): """ ) assert isinstance(item1, Function) - req1 = fixtures.FixtureRequest(item1, _ispytest=True) + req1 = TopRequest(item1, _ispytest=True) assert "xfail" not in item1.keywords req1.applymarker(pytest.mark.xfail) assert "xfail" in item1.keywords @@ -4036,7 +4033,7 @@ def test_func(m1): ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "m1 f1".split() def test_func_closure_with_native_fixtures( @@ -4085,7 +4082,7 @@ def test_foo(f1, p1, m1, f2, s1): pass ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) # order of fixtures based on their scope and position in the parameter list assert ( request.fixturenames @@ -4113,7 +4110,7 @@ def test_func(f1, m1): ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "m1 f1".split() def test_func_closure_scopes_reordered(self, pytester: Pytester) -> None: @@ -4147,7 +4144,7 @@ def test_func(self, f2, f1, c1, m1, s1): ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "s1 m1 c1 f2 f1".split() def test_func_closure_same_scope_closer_root_first( @@ -4190,7 +4187,7 @@ def test_func(m_test, f1): ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "p_sub m_conf m_sub m_test f1".split() def test_func_closure_all_scopes_complex(self, pytester: Pytester) -> None: @@ -4235,7 +4232,7 @@ def test_func(self, f2, f1, m2): ) items, _ = pytester.inline_genitems() assert isinstance(items[0], Function) - request = FixtureRequest(items[0], _ispytest=True) + request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split() def test_multiple_packages(self, pytester: Pytester) -> None: diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index b32036d1413..b4fd1bf2c22 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -2,6 +2,7 @@ import pytest from _pytest.compat import LEGACY_PATH +from _pytest.fixtures import TopRequest from _pytest.legacypath import TempdirFactory from _pytest.legacypath import Testdir @@ -91,7 +92,7 @@ def test_fixturerequest_getmodulepath(pytester: pytest.Pytester) -> None: modcol = pytester.getmodulecol("def test_somefunc(): pass") (item,) = pytester.genitems([modcol]) assert isinstance(item, pytest.Function) - req = pytest.FixtureRequest(item, _ispytest=True) + req = TopRequest(item, _ispytest=True) assert req.path == modcol.path assert req.fspath == modcol.fspath # type: ignore[attr-defined] From 1827d8d5f9164da3cf8a7f0a22ea6c36814fdfd4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 12 Aug 2023 18:02:13 +0300 Subject: [PATCH 0125/1271] doc: fix a few `pytest.mark.xfail` nits Refs #9027, #10094. --- doc/en/reference/reference.rst | 8 +++++--- src/_pytest/mark/structures.py | 4 +++- src/_pytest/outcomes.py | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index a6d7cfdd40b..5a2458bcb01 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -237,7 +237,7 @@ pytest.mark.xfail Marks a test function as *expected to fail*. -.. py:function:: pytest.mark.xfail(condition=None, *, reason=None, raises=None, run=True, strict=False) +.. py:function:: pytest.mark.xfail(condition=None, *, reason=None, raises=None, run=True, strict=xfail_strict) :type condition: bool or str :param condition: @@ -249,10 +249,10 @@ Marks a test function as *expected to fail*. :keyword Type[Exception] raises: Exception subclass (or tuple of subclasses) expected to be raised by the test function; other exceptions will fail the test. :keyword bool run: - If the test function should actually be executed. If ``False``, the function will always xfail and will + Whether the test function should actually be executed. If ``False``, the function will always xfail and will not be executed (useful if a function is segfaulting). :keyword bool strict: - * If ``False`` (the default) the function will be shown in the terminal output as ``xfailed`` if it fails + * If ``False`` the function will be shown in the terminal output as ``xfailed`` if it fails and as ``xpass`` if it passes. In both cases this will not cause the test suite to fail as a whole. This is particularly useful to mark *flaky* tests (tests that fail at random) to be tackled later. * If ``True``, the function will be shown in the terminal output as ``xfailed`` if it fails, but if it @@ -260,6 +260,8 @@ Marks a test function as *expected to fail*. that are always failing and there should be a clear indication if they unexpectedly start to pass (for example a new release of a library fixes a known bug). + Defaults to :confval:`xfail_strict`, which is ``False`` by default. + Custom marks ~~~~~~~~~~~~ diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index d6e426567a6..bbde6864486 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -461,7 +461,9 @@ def __call__( *conditions: Union[str, bool], reason: str = ..., run: bool = ..., - raises: Union[Type[BaseException], Tuple[Type[BaseException], ...]] = ..., + raises: Union[ + None, Type[BaseException], Tuple[Type[BaseException], ...] + ] = ..., strict: bool = ..., ) -> MarkDecorator: ... diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 7dab4499b56..a8984c5b97b 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -233,6 +233,9 @@ def xfail(reason: str = "") -> NoReturn: This function should be called only during testing (setup, call or teardown). + No other code is executed after using ``xfail()`` (it is implemented + internally by raising an exception). + :param reason: The message to show the user as reason for the xfail. From 73d754bd74ae8ddf86eb90cda29545cef495e927 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 15 Aug 2023 07:56:42 +0000 Subject: [PATCH 0126/1271] [pre-commit.ci] pre-commit autoupdate (#11313) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.4.1 → v1.5.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.4.1...v1.5.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index be6d0822106..d9d488dd168 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.4.1 + rev: v1.5.0 hooks: - id: mypy files: ^(src/|testing/) From d4fb6ac9f7875b762a6bd1f179ef5df4997d6182 Mon Sep 17 00:00:00 2001 From: Tyler Smart Date: Wed, 16 Aug 2023 00:54:38 -0600 Subject: [PATCH 0127/1271] Fix doctest collection of `functools.cached_property` objects. --- AUTHORS | 1 + changelog/11237.bugfix.rst | 1 + src/_pytest/doctest.py | 18 +++++++++++++++++- testing/test_doctest.py | 18 ++++++++++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 changelog/11237.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 313e507f204..18db7808f13 100644 --- a/AUTHORS +++ b/AUTHORS @@ -379,6 +379,7 @@ Tor Colvin Trevor Bekolay Tushar Sadhwani Tyler Goodlet +Tyler Smart Tzu-ping Chung Vasily Kuznetsov Victor Maryama diff --git a/changelog/11237.bugfix.rst b/changelog/11237.bugfix.rst new file mode 100644 index 00000000000..d054fc18d1c --- /dev/null +++ b/changelog/11237.bugfix.rst @@ -0,0 +1 @@ +Fix doctest collection of `functools.cached_property` objects. diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index e6f666dda03..e8bf92d95ec 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -1,5 +1,6 @@ """Discover and run doctests in modules and test files.""" import bdb +import functools import inspect import os import platform @@ -536,6 +537,21 @@ def _find( tests, obj, name, module, source_lines, globs, seen ) + class CachedPropertyAwareDocTestFinder(MockAwareDocTestFinder): + def _from_module(self, module, object): + """Doctest code does not take into account `@cached_property`, + this is a hackish way to fix it. https://github.com/python/cpython/issues/107995 + + Wrap Doctest finder so that when it calls `_from_module` for + a cached_property it uses the underlying function instead of the + wrapped cached_property object. + """ + if isinstance(object, functools.cached_property): + object = object.func + + # Type ignored because this is a private function. + return super()._from_module(module, object) # type: ignore[misc] + if self.path.name == "conftest.py": module = self.config.pluginmanager._importconftest( self.path, @@ -555,7 +571,7 @@ def _find( else: raise # Uses internal doctest module parsing mechanism. - finder = MockAwareDocTestFinder() + finder = CachedPropertyAwareDocTestFinder() optionflags = get_optionflags(self) runner = _get_runner( verbose=False, diff --git a/testing/test_doctest.py b/testing/test_doctest.py index f189e8645fa..f4d3155c435 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -482,6 +482,24 @@ def test_doctestmodule(self, pytester: Pytester): reprec = pytester.inline_run(p, "--doctest-modules") reprec.assertoutcome(failed=1) + def test_doctest_cached_property(self, pytester: Pytester): + p = pytester.makepyfile( + """ + import functools + + class Foo: + @functools.cached_property + def foo(self): + ''' + >>> assert False, "Tacos!" + ''' + ... + """ + ) + result = pytester.runpytest(p, "--doctest-modules") + result.assert_outcomes(failed=1) + assert "Tacos!" in result.stdout.str() + def test_doctestmodule_external_and_issue116(self, pytester: Pytester): p = pytester.mkpydir("hello") p.joinpath("__init__.py").write_text( From 176d728b7b351fd967be1ff63deee042d5c234e2 Mon Sep 17 00:00:00 2001 From: ubaumann Date: Fri, 18 Aug 2023 23:34:40 +0200 Subject: [PATCH 0128/1271] add nuts to plugin list Adding https://github.com/network-unit-testing-system/nuts to the plugin list. --- scripts/update-plugin-list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index eaf5619207c..f345e1f7cd6 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -44,6 +44,7 @@ ) ADDITIONAL_PROJECTS = { # set of additional projects to consider as plugins "logassert", + "nuts", } From ebd571bb18d2cf00ebc70db8090217fc62d00e98 Mon Sep 17 00:00:00 2001 From: Tyler Smart Date: Sat, 19 Aug 2023 12:04:59 -0600 Subject: [PATCH 0129/1271] Move _from_module override to pre-existsing DocTestFinder subclass --- src/_pytest/doctest.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index e8bf92d95ec..c99ccbbb1c8 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -537,14 +537,11 @@ def _find( tests, obj, name, module, source_lines, globs, seen ) - class CachedPropertyAwareDocTestFinder(MockAwareDocTestFinder): def _from_module(self, module, object): - """Doctest code does not take into account `@cached_property`, - this is a hackish way to fix it. https://github.com/python/cpython/issues/107995 - - Wrap Doctest finder so that when it calls `_from_module` for - a cached_property it uses the underlying function instead of the - wrapped cached_property object. + """`cached_property` objects will are never considered a part + of the 'current module'. As such they are skipped by doctest. + Here we override `_from_module` to check the underlying + function instead. https://github.com/python/cpython/issues/107995 """ if isinstance(object, functools.cached_property): object = object.func @@ -571,7 +568,7 @@ def _from_module(self, module, object): else: raise # Uses internal doctest module parsing mechanism. - finder = CachedPropertyAwareDocTestFinder() + finder = MockAwareDocTestFinder() optionflags = get_optionflags(self) runner = _get_runner( verbose=False, From 87bfc83aa0d9fbc8f8e95180805a1a58cdf43fd6 Mon Sep 17 00:00:00 2001 From: Tyler Smart Date: Sat, 19 Aug 2023 12:18:17 -0600 Subject: [PATCH 0130/1271] Add doctesting-coverage to envlist --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 1b62b98e499..c52a43fd7a7 100644 --- a/tox.ini +++ b/tox.ini @@ -12,6 +12,7 @@ envlist = pypy3 py38-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} doctesting + doctesting-coverage plugins py38-freeze docs From 7a625481dae2380d8f9d1cf53f6a59a2977b49c8 Mon Sep 17 00:00:00 2001 From: Tyler Smart Date: Sat, 19 Aug 2023 22:20:40 -0600 Subject: [PATCH 0131/1271] PR suggestions --- src/_pytest/doctest.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index c99ccbbb1c8..fcd48f8939e 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -537,17 +537,19 @@ def _find( tests, obj, name, module, source_lines, globs, seen ) - def _from_module(self, module, object): - """`cached_property` objects will are never considered a part - of the 'current module'. As such they are skipped by doctest. - Here we override `_from_module` to check the underlying - function instead. https://github.com/python/cpython/issues/107995 - """ - if isinstance(object, functools.cached_property): - object = object.func + if sys.version_info < (3, 13): - # Type ignored because this is a private function. - return super()._from_module(module, object) # type: ignore[misc] + def _from_module(self, module, object): + """`cached_property` objects are never considered a part + of the 'current module'. As such they are skipped by doctest. + Here we override `_from_module` to check the underlying + function instead. https://github.com/python/cpython/issues/107995 + """ + if isinstance(object, functools.cached_property): + object = object.func + + # Type ignored because this is a private function. + return super()._from_module(module, object) # type: ignore[misc] if self.path.name == "conftest.py": module = self.config.pluginmanager._importconftest( From 3cb3cd1a081dd1bcccedbfdee652e667427fdb87 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 20 Aug 2023 00:16:31 +0300 Subject: [PATCH 0132/1271] testing: add `.*` to `norecursedirs` Setting `norecursedirs` overrides the default, so we end up scanning dot-directories and such which slows down collection unnecessarily (150ms on my working directory). --- pyproject.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index d540773c374..cdbdd3880e4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,12 @@ python_classes = ["Test", "Acceptance"] python_functions = ["test"] # NOTE: "doc" is not included here, but gets tested explicitly via "doctesting". testpaths = ["testing"] -norecursedirs = ["testing/example_scripts"] +norecursedirs = [ + "testing/example_scripts", + ".*", + "build", + "dist", +] xfail_strict = true filterwarnings = [ "error", From 049eec8474d3238b056a42fa07558c4293a97f05 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Sun, 20 Aug 2023 14:04:20 -0700 Subject: [PATCH 0133/1271] Revert iter raises checks This reverts commit e938580257e8120dabbea789d5b7a3dd3354d0a3. Revert "improve error msg and test" This reverts commit c0cf822ca1d5d6ac74f46ddccbe377c254c6084a. Revert "error msg" This reverts commit ec1053cc162250e42ae220ebe91c3bf00b22b084. Revert "changelog" This reverts commit d2dc8a70b593b61a013ae3eba99bb3f10e82eb65. Revert "simplify code / take out user-gen typeerror case" This reverts commit b9cb87d862bb3f841d67723ac5717ce90b219dc2. --- changelog/7966.bugfix.rst | 1 - src/_pytest/assertion/util.py | 28 +++++++--------------------- testing/test_assertrewrite.py | 4 ++-- 3 files changed, 9 insertions(+), 24 deletions(-) delete mode 100644 changelog/7966.bugfix.rst diff --git a/changelog/7966.bugfix.rst b/changelog/7966.bugfix.rst deleted file mode 100644 index 40cad46c69d..00000000000 --- a/changelog/7966.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Assertion rewrite mechanism now gives a seperate, more detailed error message from failures within __iter__. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index d20c2363eb3..fc5dfdbd5ba 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -134,13 +134,6 @@ def isiterable(obj: Any) -> bool: return not istext(obj) except TypeError: return False - except Exception as e: - raise ValueError( - [ - f"pytest_assertion plugin: unexpected exception {e!r} while testing object {obj!r}", - ", probably from __iter__", - ] - ) def has_default_eq( @@ -202,20 +195,13 @@ def assertrepr_compare( explanation = _notin_text(left, right, verbose) except outcomes.Exit: raise - except Exception as e: - if ( - isinstance(e, ValueError) - and (len(e.args) == 1) - and ("__iter__" in str(e.args[0])) - ): - explanation = e.args[0] - else: - explanation = [ - "(pytest_assertion plugin: representation of details failed: {}.".format( - _pytest._code.ExceptionInfo.from_current()._getreprcrash() - ), - " Probably an object has a faulty __repr__.)", - ] + except Exception: + explanation = [ + "(pytest_assertion plugin: representation of details failed: {}.".format( + _pytest._code.ExceptionInfo.from_current()._getreprcrash() + ), + " Probably an object has a faulty __repr__.)", + ] if not explanation: return None diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 62c6bb8d4bc..d85c8bed6d6 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -689,7 +689,7 @@ def test_assert_handling_raise_in__iter__(self) -> None: def f() -> None: class A: def __iter__(self): - raise ValueError() + raise TypeError("user message") def __eq__(self, o: object) -> bool: return self is o @@ -698,7 +698,7 @@ def __eq__(self, o: object) -> bool: msg = getmsg(f) assert msg is not None - assert "__iter__" in msg and "__repr__" not in msg + assert "Unexpected exception" in msg def test_formatchar(self) -> None: def f() -> None: From 61133ba83d0f24c40aa6b0c1473919c7aff3b16f Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Sun, 20 Aug 2023 14:46:09 -0700 Subject: [PATCH 0134/1271] un-iterable fix --- changelog/7966.bugfix.rst | 1 + src/_pytest/assertion/util.py | 2 +- testing/test_assertrewrite.py | 7 +++++-- 3 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 changelog/7966.bugfix.rst diff --git a/changelog/7966.bugfix.rst b/changelog/7966.bugfix.rst new file mode 100644 index 00000000000..de055768066 --- /dev/null +++ b/changelog/7966.bugfix.rst @@ -0,0 +1 @@ +Removes unhelpful error message from assertion rewrite mechanism when exceptions raised in __iter__ methods, and instead treats them as un-iterable. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index fc5dfdbd5ba..39ca5403e04 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -132,7 +132,7 @@ def isiterable(obj: Any) -> bool: try: iter(obj) return not istext(obj) - except TypeError: + except Exception: return False diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index d85c8bed6d6..2c908133d39 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -689,16 +689,19 @@ def test_assert_handling_raise_in__iter__(self) -> None: def f() -> None: class A: def __iter__(self): - raise TypeError("user message") + raise ValueError() def __eq__(self, o: object) -> bool: return self is o + def __repr__(self): + return "" + assert A() == A() msg = getmsg(f) assert msg is not None - assert "Unexpected exception" in msg + assert " == " in msg def test_formatchar(self) -> None: def f() -> None: From a357c7abc84e0382894a9b53d88ebb7ed2680686 Mon Sep 17 00:00:00 2001 From: Tyler Smart Date: Sun, 20 Aug 2023 20:55:30 -0600 Subject: [PATCH 0135/1271] Ignore dip in branch coverage (since py3.13+ isn't tested in CI) --- src/_pytest/doctest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index fcd48f8939e..49f8c9bfe7c 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -551,6 +551,9 @@ def _from_module(self, module, object): # Type ignored because this is a private function. return super()._from_module(module, object) # type: ignore[misc] + else: # pragma: no cover + pass + if self.path.name == "conftest.py": module = self.config.pluginmanager._importconftest( self.path, From fc653d0d12fb43aa7fa843cb801d33854e1033b6 Mon Sep 17 00:00:00 2001 From: DetachHead <57028336+DetachHead@users.noreply.github.com> Date: Mon, 21 Aug 2023 18:00:28 +1000 Subject: [PATCH 0136/1271] use `if not TYPE_CHECKING` on `pytest.__getattr__` to prevent type checkers from using it --- src/pytest/__init__.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 831ede1fa1f..8d7cf520b35 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -1,5 +1,7 @@ # PYTHON_ARGCOMPLETE_OK """pytest: unit and functional testing with Python.""" +from typing import TYPE_CHECKING + from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo @@ -165,11 +167,12 @@ "yield_fixture", ] +if not TYPE_CHECKING: -def __getattr__(name: str) -> object: - if name == "Instance": - # The import emits a deprecation warning. - from _pytest.python import Instance - - return Instance - raise AttributeError(f"module {__name__} has no attribute {name}") + def __getattr__(name: str) -> object: + if name == "Instance": + # The import emits a deprecation warning. + from _pytest.python import Instance + + return Instance + raise AttributeError(f"module {__name__} has no attribute {name}") From dd5ae0c3b88058c4488fe1411c53e874e79bd7b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 08:03:06 +0000 Subject: [PATCH 0137/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pytest/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 8d7cf520b35..0aa496a2fa7 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -173,6 +173,6 @@ def __getattr__(name: str) -> object: if name == "Instance": # The import emits a deprecation warning. from _pytest.python import Instance - + return Instance raise AttributeError(f"module {__name__} has no attribute {name}") From 010e1742d8f8c1526c417a871d4f82ddf6e5e7de Mon Sep 17 00:00:00 2001 From: DetachHead <57028336+DetachHead@users.noreply.github.com> Date: Mon, 21 Aug 2023 22:29:41 +1000 Subject: [PATCH 0138/1271] use python 3.11 for update-plugin-list (#11328) --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index b278f633fba..bbce63f7b78 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -27,7 +27,7 @@ jobs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: "3.8" + python-version: "3.11" cache: pip - name: requests-cache uses: actions/cache@v3 From 370eacd3ca8addb5a8eb3f1291feff4304181042 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 21 Aug 2023 15:40:03 +0300 Subject: [PATCH 0139/1271] doc/reference: replace Unicode dashes with ascii `-` in cli flags (#11323) --- doc/en/reference/reference.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 5a2458bcb01..d578fc285ef 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1640,11 +1640,11 @@ passed multiple times. The expected format is ``name=value``. For example:: Additionally, ``pytest`` will attempt to intelligently identify and ignore a virtualenv by the presence of an activation script. Any directory deemed to be the root of a virtual environment will not be considered during test - collection unless ``‑‑collect‑in‑virtualenv`` is given. Note also that - ``norecursedirs`` takes precedence over ``‑‑collect‑in‑virtualenv``; e.g. if + collection unless ``--collect-in-virtualenv`` is given. Note also that + ``norecursedirs`` takes precedence over ``--collect-in-virtualenv``; e.g. if you intend to run tests in a virtualenv with a base directory that matches ``'.*'`` you *must* override ``norecursedirs`` in addition to using the - ``‑‑collect‑in‑virtualenv`` flag. + ``--collect-in-virtualenv`` flag. .. confval:: python_classes From 4deb38b2edc97e559df067c4d3e4d2b70d2e5f53 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 13:19:58 +0000 Subject: [PATCH 0140/1271] [automated] Update plugin list (#11329) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 440 +++++++++++++++++++++---------- 1 file changed, 308 insertions(+), 132 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 0a333976ec2..9d5728352de 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -15,7 +15,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1289 plugins. +This list contains 1311 plugins. .. only:: not latex @@ -23,10 +23,12 @@ This list contains 1289 plugins. name summary last release status requires =============================================== ======================================================================================================================================================================================================== ============== ===================== ================================================ :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A + :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) + :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Aug 15, 2023 N/A N/A :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-adf` Pytest plugin for writing Azure Data Factory integration tests May 10, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) @@ -52,10 +54,11 @@ This list contains 1289 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Aug 21, 2023 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures May 15, 2023 5 - Production/Stable pytest (<8.0.0,>=6) + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Aug 09, 2023 5 - Production/Stable pytest <8.0.0,>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -89,7 +92,7 @@ This list contains 1289 plugins. :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 Jul 12, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. May 31, 2023 N/A N/A + :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Aug 06, 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) @@ -107,6 +110,7 @@ This list contains 1289 plugins. :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) + :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest :pypi:`pytest-azure-devops` Simplifies using azure devops parallel strategy (https://docs.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner) with pytest. Jun 20, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-azurepipelines` Formatting PyTest output for Azure Pipelines UI Oct 20, 2022 5 - Production/Stable pytest (>=5.0.0) @@ -116,6 +120,7 @@ This list contains 1289 plugins. :pypi:`pytest-bdd` BDD for pytest Nov 08, 2022 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0) + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 20, 2023 N/A N/A :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A @@ -132,7 +137,7 @@ This list contains 1289 plugins. :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) :pypi:`pytest-blame` A pytest plugin helps developers to debug by providing useful commits history. May 04, 2019 N/A pytest (>=4.4.0) - :pypi:`pytest-blender` Blender Pytest plugin. Jan 04, 2023 N/A pytest ; extra == 'dev' + :pypi:`pytest-blender` Blender Pytest plugin. Aug 10, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-blink1` Pytest plugin to emit notifications via the Blink(1) RGB LED Jan 07, 2018 4 - Beta N/A :pypi:`pytest-blockage` Disable network requests during a test run. Dec 21, 2021 N/A pytest :pypi:`pytest-blocker` pytest plugin to mark a test as blocker and skip all other tests Sep 07, 2015 4 - Beta N/A @@ -157,7 +162,7 @@ This list contains 1289 plugins. :pypi:`pytest-builtin-types` Nov 17, 2021 N/A pytest :pypi:`pytest-bwrap` Run your tests in Bubblewrap sandboxes Oct 26, 2018 3 - Alpha N/A :pypi:`pytest-cache` pytest plugin with mechanisms for caching across test runs Jun 04, 2013 3 - Alpha N/A - :pypi:`pytest-cache-assert` Cache assertion data to simplify regression testing of complex serializable data Feb 26, 2023 5 - Production/Stable pytest (>=5.0.0) + :pypi:`pytest-cache-assert` Cache assertion data to simplify regression testing of complex serializable data Aug 14, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-cagoule` Pytest plugin to only run tests affected by changes Jan 01, 2020 3 - Alpha N/A :pypi:`pytest-cairo` Pytest support for cairo-lang and starknet Apr 17, 2022 N/A pytest :pypi:`pytest-call-checker` Small pytest utility to easily create test doubles Oct 16, 2022 4 - Beta pytest (>=7.1.3,<8.0.0) @@ -178,8 +183,8 @@ This list contains 1289 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jul 14, 2023 N/A pytest - :pypi:`pytest-checkdocs` check the README when running tests Jul 09, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Aug 11, 2023 N/A pytest + :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Jul 22, 2020 5 - Production/Stable pytest (>=2.9.2) :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A @@ -209,7 +214,8 @@ This list contains 1289 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jul 04, 2023 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jul 27, 2023 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A :pypi:`pytest-collector` Python package for collecting pytest. Aug 02, 2022 N/A pytest (>=7.0,<8.0) @@ -279,10 +285,12 @@ This list contains 1289 plugins. :pypi:`pytest-dbt` Unit test dbt models with standard python tooling Jun 08, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-dbt-core` Pytest extension for dbt. May 03, 2023 N/A pytest (>=6.2.5) ; extra == 'test' + :pypi:`pytest-dbt-core` Pytest extension for dbt. Aug 09, 2023 N/A pytest >=6.2.5 ; extra == 'test' :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) + :pypi:`pytest-dc` Manages Docker containers during your integration tests Aug 16, 2023 5 - Production/Stable pytest >=3.3 :pypi:`pytest-deadfixtures` A simple plugin to list unused fixtures in pytest Jul 23, 2020 5 - Production/Stable N/A + :pypi:`pytest-deduplicate` Identifies duplicate unit tests Aug 12, 2023 4 - Beta pytest :pypi:`pytest-deepcov` deepcov Mar 30, 2021 N/A N/A :pypi:`pytest-defer` Aug 24, 2021 N/A N/A :pypi:`pytest-demo-plugin` pytest示例插件 May 15, 2021 N/A N/A @@ -309,6 +317,7 @@ This list contains 1289 plugins. :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A + :pypi:`pytest-django-class` A pytest plugin for running django in class-scoped fixtures Aug 08, 2023 4 - Beta N/A :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) :pypi:`pytest-django-factories` Factories for your Django models that can be used as Pytest fixtures. Nov 12, 2020 4 - Beta N/A :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 @@ -348,8 +357,9 @@ This list contains 1289 plugins. :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Jun 08, 2023 3 - Alpha pytest (>=4.6) + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Aug 11, 2023 3 - Alpha pytest >=4.6 :pypi:`pytest-dogu-report` pytest plugin for dogu report Jul 07, 2023 N/A N/A + :pypi:`pytest-dogu-sdk` pytest plugin for the Dogu Aug 04, 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-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) @@ -373,7 +383,7 @@ This list contains 1289 plugins. :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Jan 08, 2020 5 - Production/Stable N/A :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest - :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 01, 2022 5 - Production/Stable pytest (>=6.2.0) + :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Aug 03, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) @@ -391,6 +401,7 @@ This list contains 1289 plugins. :pypi:`pytest-enabler` Enable installed pytest plugins Jul 14, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest + :pypi:`pytest-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` py.test plugin that allows you to add environment variables. Jun 15, 2023 5 - Production/Stable pytest>=7.3.1 @@ -406,7 +417,7 @@ This list contains 1289 plugins. :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 - :pypi:`pytest-excel` pytest plugin for generating excel reports Jan 31, 2022 5 - Production/Stable N/A + :pypi:`pytest-excel` pytest plugin for generating excel reports Jul 20, 2023 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest :pypi:`pytest-executable` pytest plugin for testing executables Mar 25, 2023 N/A pytest (<8,>=4.3) @@ -418,7 +429,8 @@ This list contains 1289 plugins. :pypi:`pytest-expect-test` A fixture to support expect tests in pytest Apr 10, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-experiments` A pytest plugin to help developers of research-oriented software projects keep track of the results of their numerical experiments. Dec 13, 2021 4 - Beta pytest (>=6.2.5,<7.0.0) :pypi:`pytest-explicit` A Pytest plugin to ignore certain marked tests by default Jun 15, 2021 5 - Production/Stable pytest - :pypi:`pytest-exploratory` Interactive console for pytest. Feb 21, 2022 N/A pytest (>=6.2) + :pypi:`pytest-exploratory` Interactive console for pytest. Aug 18, 2023 N/A pytest (>=6.2) + :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) @@ -482,7 +494,7 @@ This list contains 1289 plugins. :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A - :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications May 03, 2023 4 - Beta pytest>=7.0.0 + :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Aug 07, 2023 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -499,7 +511,7 @@ This list contains 1289 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jun 28, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jul 24, 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 Jun 22, 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 @@ -533,7 +545,7 @@ This list contains 1289 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 14, 2023 3 - Alpha pytest (==7.3.1) + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 19, 2023 3 - Alpha pytest ==7.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -541,7 +553,8 @@ This list contains 1289 plugins. :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Apr 08, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) + :pypi:`pytest-html` pytest plugin for generating HTML reports Aug 13, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) + :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Apr 03, 2022 N/A N/A :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Mar 04, 2022 5 - Production/Stable N/A @@ -555,18 +568,20 @@ This list contains 1289 plugins. :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 09, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Apr 12, 2023 5 - Production/Stable pytest (<8.0,>=6.0) + :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-httpx` Send responses to httpx. Aug 02, 2023 5 - Production/Stable pytest (<8.0,>=6.0) :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Aug 21, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Aug 09, 2022 4 - Beta N/A :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 23, 2021 5 - Production/Stable N/A + :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-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 @@ -575,7 +590,7 @@ This list contains 1289 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. Feb 08, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Feb 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Aug 03, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 04, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules May 17, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Jun 16, 2022 4 - Beta N/A @@ -645,17 +660,18 @@ This list contains 1289 plugins. :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest - :pypi:`pytest-line-profiler` Profile code executed by pytest May 03, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-line-profiler` Profile code executed by pytest Aug 10, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-line-profiler-apn` Profile code executed by pytest Dec 05, 2022 N/A pytest (>=3.5.0) :pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-listener` A simple network listener May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-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-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 04, 2022 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Jul 16, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-lockable` lockable resource plugin for pytest Jul 20, 2022 5 - Production/Stable pytest + :pypi:`pytest-lockable` lockable resource plugin for pytest Aug 09, 2023 5 - Production/Stable pytest :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) :pypi:`pytest-log` print log Aug 15, 2021 N/A pytest (>=3.8) :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) @@ -710,7 +726,7 @@ This list contains 1289 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jul 12, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jul 24, 2023 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -719,7 +735,7 @@ This list contains 1289 plugins. :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jun 07, 2021 5 - Production/Stable pytest + :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jul 20, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A @@ -731,7 +747,7 @@ This list contains 1289 plugins. :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Jul 23, 2022 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Mar 15, 2023 4 - Beta pytest (<8) ; extra == 'test' + :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Aug 03, 2023 4 - Beta pytest (<8) ; extra == 'test' :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A @@ -739,7 +755,7 @@ This list contains 1289 plugins. :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jun 29, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jul 25, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) @@ -754,13 +770,14 @@ This list contains 1289 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jul 11, 2023 N/A pytest (==6.2.5) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Aug 02, 2023 N/A pytest (==6.2.5) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A :pypi:`pytest-nocustom` Run all tests without custom markers Jul 07, 2021 5 - Production/Stable N/A :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A :pypi:`pytest-notice` Send pytest execution result email Nov 05, 2020 N/A N/A :pypi:`pytest-notification` A pytest plugin for sending a desktop notification and playing a sound upon completion of tests Jun 19, 2020 N/A pytest (>=4) :pypi:`pytest-notifier` A pytest plugin to notify test result Jun 12, 2020 3 - Alpha pytest @@ -770,7 +787,7 @@ This list contains 1289 plugins. :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A - :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Jul 18, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-odoo` py.test plugin to run Odoo tests Jul 06, 2023 4 - Beta pytest (>=7.2.0) :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A @@ -821,7 +838,7 @@ This list contains 1289 plugins. :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) - :pypi:`pytest-picked` Run the tests related to the changed files Dec 23, 2020 N/A pytest (>=3.5.0) + :pypi:`pytest-picked` Run the tests related to the changed files Jul 27, 2023 N/A pytest (>=3.7.0) :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) :pypi:`pytest-pikachu` Show surprise when tests are passing Aug 05, 2021 5 - Production/Stable pytest :pypi:`pytest-pilot` Slice in your test base thanks to powerful markers. Oct 09, 2020 5 - Production/Stable N/A @@ -833,7 +850,7 @@ This list contains 1289 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Apr 24, 2023 N/A pytest (<8.0.0,>=6.2.4) + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Aug 07, 2023 N/A pytest (<8.0.0,>=6.2.4) :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A @@ -852,17 +869,17 @@ This list contains 1289 plugins. :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-porringer` Jun 24, 2023 N/A pytest>=7.1.2 + :pypi:`pytest-porringer` Aug 19, 2023 N/A pytest>=7.4.0 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) - :pypi:`pytest-pot` A package for enhancing pytest Nov 20, 2022 N/A N/A :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Jun 28, 2023 5 - Production/Stable pytest>=7.3.2 + :pypi:`pytest-priority` pytest plugin for add priority for tests Jul 23, 2023 N/A N/A :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A @@ -892,7 +909,7 @@ This list contains 1289 plugins. :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Dec 13, 2022 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Jul 02, 2023 N/A pytest (>=7.3.1) - :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Nov 20, 2022 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Aug 20, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Mar 12, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. May 07, 2023 N/A pytest (>=3.5.0) :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) @@ -918,14 +935,14 @@ This list contains 1289 plugins. :pypi:`pytest-raisesregexp` Simple pytest plugin to look for regex in Exceptions Dec 18, 2015 N/A N/A :pypi:`pytest-raisin` Plugin enabling the use of exception instances with pytest.raises Feb 06, 2022 N/A pytest :pypi:`pytest-random` py.test plugin to randomize tests Apr 28, 2013 3 - Alpha N/A - :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Jul 10, 2023 5 - Production/Stable pytest + :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Aug 15, 2023 5 - Production/Stable pytest :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Dec 03, 2022 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A - :pypi:`pytest-reana` Pytest fixtures for REANA. Dec 13, 2022 3 - Alpha N/A + :pypi:`pytest-reana` Pytest fixtures for REANA. Aug 04, 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-recording` A pytest plugin that allows you recording of network interactions via VCR.py Feb 16, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-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) :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest @@ -935,7 +952,7 @@ This list contains 1289 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 13, 2023 5 - Production/Stable pytest (>=6.2.0) - :pypi:`pytest-regtest` pytest plugin for regression tests Jul 08, 2022 N/A N/A + :pypi:`pytest-regtest` pytest plugin for regression tests Aug 17, 2023 N/A N/A :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A @@ -979,7 +996,7 @@ This list contains 1289 plugins. :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 16, 2022 N/A pytest (>=7.0.0) + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 02, 2023 N/A pytest (>=7.0.0) :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest @@ -990,13 +1007,14 @@ This list contains 1289 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest + :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 19, 2023 N/A N/A :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jun 08, 2023 4 - Beta N/A + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 31, 2023 4 - Beta N/A :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-runner` Invoke py.test as distutils command with dependency resolution Feb 25, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' @@ -1008,29 +1026,30 @@ This list contains 1289 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 Dec 15, 2022 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-salt-factories` Pytest Salt Plugin Jul 31, 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. Jul 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 18, 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 18, 2023 4 - Beta N/A + :pypi:`pytest-screenshot-on-failure` Saves a screenshot when a test case from a pytest execution fails Jul 21, 2023 4 - Beta N/A :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 18, 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-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 20, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Jul 13, 2023 3 - Alpha pytest (>=6.2) + :pypi:`pytest-servers` pytest servers Jul 26, 2023 3 - Alpha pytest (>=6.2) :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1043,14 +1062,14 @@ This list contains 1289 plugins. :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Jul 02, 2023 5 - Production/Stable pytest (>=7.1.0) :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest - :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Jan 16, 2023 5 - Production/Stable pytest (>=3.5.1) + :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-simplehttpserver` Simple pytest fixture to spin up an HTTP server Jun 24, 2021 4 - Beta N/A :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest :pypi:`pytest-single-file-logging` Allow for multiple processes to log to a single file May 05, 2016 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-skip-markers` Pytest Salt Plugin Dec 20, 2022 5 - Production/Stable pytest (>=7.1.0) + :pypi:`pytest-skip-markers` Pytest Salt Plugin Jul 31, 2023 5 - Production/Stable pytest (>=7.1.0) :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 @@ -1067,6 +1086,7 @@ This list contains 1289 plugins. :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-snapshot-with-message-generator` A plugin for snapshot testing with pytest. Jul 25, 2023 4 - Beta pytest (>=3.0.0) :pypi:`pytest-snmpserver` May 12, 2021 N/A N/A :pypi:`pytest-snowflake-bdd` Setup test data and run tests on snowflake in BDD style! Jan 05, 2022 4 - Beta pytest (>=6.2.0) :pypi:`pytest-socket` Pytest Plugin to disable socket calls during tests Feb 03, 2023 4 - Beta pytest (>=3.6.3) @@ -1074,9 +1094,9 @@ This list contains 1289 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Jul 17, 2023 N/A pytest (>=7.0.0) + :pypi:`pytest-sort` Tools for sorting test cases Aug 12, 2023 N/A pytest >=7.0.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) - :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Feb 14, 2023 2 - Pre-Alpha pytest + :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest :pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A @@ -1091,7 +1111,7 @@ This list contains 1289 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 Jun 30, 2023 N/A pytest (>5.4.0,<8) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jul 25, 2023 N/A pytest (>5.4.0,<8) :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 07, 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 @@ -1110,7 +1130,7 @@ This list contains 1289 plugins. :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A - :pypi:`pytest-stf` pytest plugin for openSTF Dec 04, 2022 N/A pytest (>=5.0) + :pypi:`pytest-stf` pytest plugin for openSTF Aug 16, 2023 N/A pytest >=5.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-structlog` Structured logging assertions Dec 18, 2022 N/A pytest @@ -1138,6 +1158,7 @@ This list contains 1289 plugins. :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) + :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Dec 10, 2020 5 - Production/Stable N/A :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A @@ -1148,7 +1169,7 @@ This list contains 1289 plugins. :pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A :pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest - :pypi:`pytest-testdox` A testdox format reporter for pytest Apr 19, 2022 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A :pypi:`pytest-testinfra` Test infrastructures May 21, 2023 5 - Production/Stable pytest (!=3.0.2) @@ -1174,7 +1195,7 @@ This list contains 1289 plugins. :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) - :pypi:`pytest-tesults` Tesults plugin for pytest Dec 23, 2022 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-tesults` Tesults plugin for pytest Jul 21, 2023 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 18, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A @@ -1226,7 +1247,7 @@ This list contains 1289 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-xray` Typhoon HIL plugin for pytest Jun 10, 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 :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest @@ -1238,7 +1259,7 @@ This list contains 1289 plugins. :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A - :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Jun 30, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest @@ -1282,9 +1303,10 @@ This list contains 1289 plugins. :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) - :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Jun 19, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A + :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jul 03, 2023 N/A pytest<8,>=7.4.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest @@ -1294,7 +1316,7 @@ This list contains 1289 plugins. :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (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. Jun 18, 2023 4 - Beta pytest (>=7.1.0) + :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Jul 30, 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-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) @@ -1323,6 +1345,13 @@ This list contains 1289 plugins. Simple but powerful assertion and verification of logged lines. + :pypi:`nuts` + *last release*: Aug 11, 2023, + *status*: N/A, + *requires*: pytest (>=7.3.0,<8.0.0) + + Network Unit Testing System + :pypi:`pytest-abq` *last release*: Apr 07, 2023, *status*: N/A, @@ -1351,6 +1380,13 @@ This list contains 1289 plugins. pytest plugin for generating test execution results within Jira Test Management (tm4j) + :pypi:`pytest-adaptavist-fixed` + *last release*: Aug 15, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin for generating test execution results within Jira Test Management (tm4j) + :pypi:`pytest-addons-test` *last release*: Aug 02, 2021, *status*: N/A, @@ -1526,6 +1562,13 @@ This list contains 1289 plugins. Static code checks used at Alphamoon + :pypi:`pytest-analyzer` + *last release*: Aug 21, 2023, + *status*: N/A, + *requires*: pytest >=7.3.1 + + this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system + :pypi:`pytest-android` *last release*: Feb 21, 2019, *status*: 3 - Alpha, @@ -1548,9 +1591,9 @@ This list contains 1289 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: May 15, 2023, + *last release*: Aug 09, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (<8.0.0,>=6) + *requires*: pytest <8.0.0,>=6 Plugin for pytest to simplify calling ansible modules from tests or fixtures @@ -1786,7 +1829,7 @@ This list contains 1289 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-cooperative` - *last release*: May 31, 2023, + *last release*: Aug 06, 2023, *status*: N/A, *requires*: N/A @@ -1911,6 +1954,13 @@ This list contains 1289 plugins. pytest plugin for axe-selenium-python + :pypi:`pytest-axe-playwright-snapshot` + *last release*: Jul 25, 2023, + *status*: N/A, + *requires*: pytest + + A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. + :pypi:`pytest-azure` *last release*: Jan 18, 2023, *status*: 3 - Alpha, @@ -1974,6 +2024,13 @@ This list contains 1289 plugins. BDD for pytest + :pypi:`pytest-bdd-report` + *last release*: Aug 20, 2023, + *status*: N/A, + *requires*: N/A + + A pytest-bdd plugin for generating useful and informative BDD test reports + :pypi:`pytest-bdd-splinter` *last release*: Aug 12, 2019, *status*: 5 - Production/Stable, @@ -2087,7 +2144,7 @@ This list contains 1289 plugins. A pytest plugin helps developers to debug by providing useful commits history. :pypi:`pytest-blender` - *last release*: Jan 04, 2023, + *last release*: Aug 10, 2023, *status*: N/A, *requires*: pytest ; extra == 'dev' @@ -2262,9 +2319,9 @@ This list contains 1289 plugins. pytest plugin with mechanisms for caching across test runs :pypi:`pytest-cache-assert` - *last release*: Feb 26, 2023, + *last release*: Aug 14, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.0.0) + *requires*: pytest (>=6.0.0) Cache assertion data to simplify regression testing of complex serializable data @@ -2409,14 +2466,14 @@ This list contains 1289 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Jul 14, 2023, + *last release*: Aug 11, 2023, *status*: N/A, *requires*: pytest A pytest plugin that allows multiple failures per test. :pypi:`pytest-checkdocs` - *last release*: Jul 09, 2023, + *last release*: Jul 30, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=6) ; extra == 'testing' @@ -2626,12 +2683,19 @@ This list contains 1289 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Jul 04, 2023, + *last release*: Jul 27, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 Pytest plugin to create CodSpeed benchmarks + :pypi:`pytest-collect-appoint-info` + *last release*: Aug 03, 2023, + *status*: N/A, + *requires*: pytest + + set your encoding + :pypi:`pytest-collect-formatter` *last release*: Mar 29, 2021, *status*: 5 - Production/Stable, @@ -3116,9 +3180,9 @@ This list contains 1289 plugins. A pytest plugin for linting a dbt project's conventions :pypi:`pytest-dbt-core` - *last release*: May 03, 2023, + *last release*: Aug 09, 2023, *status*: N/A, - *requires*: pytest (>=6.2.5) ; extra == 'test' + *requires*: pytest >=6.2.5 ; extra == 'test' Pytest extension for dbt. @@ -3136,6 +3200,13 @@ This list contains 1289 plugins. Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code + :pypi:`pytest-dc` + *last release*: Aug 16, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest >=3.3 + + Manages Docker containers during your integration tests + :pypi:`pytest-deadfixtures` *last release*: Jul 23, 2020, *status*: 5 - Production/Stable, @@ -3143,6 +3214,13 @@ This list contains 1289 plugins. A simple plugin to list unused fixtures in pytest + :pypi:`pytest-deduplicate` + *last release*: Aug 12, 2023, + *status*: 4 - Beta, + *requires*: pytest + + Identifies duplicate unit tests + :pypi:`pytest-deepcov` *last release*: Mar 30, 2021, *status*: N/A, @@ -3325,6 +3403,13 @@ This list contains 1289 plugins. Integrate CasperJS with your django tests as a pytest fixture. + :pypi:`pytest-django-class` + *last release*: Aug 08, 2023, + *status*: 4 - Beta, + *requires*: N/A + + A pytest plugin for running django in class-scoped fixtures + :pypi:`pytest-django-dotenv` *last release*: Nov 26, 2019, *status*: 4 - Beta, @@ -3599,9 +3684,9 @@ This list contains 1289 plugins. A simple pytest plugin to import names and add them to the doctest namespace. :pypi:`pytest-doctestplus` - *last release*: Jun 08, 2023, + *last release*: Aug 11, 2023, *status*: 3 - Alpha, - *requires*: pytest (>=4.6) + *requires*: pytest >=4.6 Pytest plugin with advanced doctest features. @@ -3612,6 +3697,13 @@ This list contains 1289 plugins. pytest plugin for dogu report + :pypi:`pytest-dogu-sdk` + *last release*: Aug 04, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin for the Dogu + :pypi:`pytest-dolphin` *last release*: Nov 30, 2016, *status*: 4 - Beta, @@ -3774,9 +3866,9 @@ This list contains 1289 plugins. Pytest plugin to select test using Ekstazi algorithm :pypi:`pytest-elasticsearch` - *last release*: Mar 01, 2022, + *last release*: Aug 03, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.0) + *requires*: pytest (>=6.2) Elasticsearch fixtures and fixture factories for Pytest. @@ -3899,6 +3991,13 @@ This list contains 1289 plugins. set your encoding and logger + :pypi:`pytest-encoding` + *last release*: Aug 11, 2023, + *status*: N/A, + *requires*: pytest + + set your encoding and logger + :pypi:`pytest-enhanced-reports` *last release*: Dec 15, 2022, *status*: N/A, @@ -4005,7 +4104,7 @@ This list contains 1289 plugins. Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-excel` - *last release*: Jan 31, 2022, + *last release*: Jul 20, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4089,12 +4188,19 @@ This list contains 1289 plugins. A Pytest plugin to ignore certain marked tests by default :pypi:`pytest-exploratory` - *last release*: Feb 21, 2022, + *last release*: Aug 18, 2023, *status*: N/A, *requires*: pytest (>=6.2) Interactive console for pytest. + :pypi:`pytest-explorer` + *last release*: Aug 01, 2023, + *status*: N/A, + *requires*: N/A + + terminal ui for exploring and running tests + :pypi:`pytest-extensions` *last release*: Aug 17, 2022, *status*: 4 - Beta, @@ -4537,7 +4643,7 @@ This list contains 1289 plugins. A pytest plugin to shim pytest commandline options for fowards compatibility :pypi:`pytest-frappe` - *last release*: May 03, 2023, + *last release*: Aug 07, 2023, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -4656,7 +4762,7 @@ This list contains 1289 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jun 28, 2023, + *last release*: Jul 24, 2023, *status*: N/A, *requires*: N/A @@ -4894,9 +5000,9 @@ This list contains 1289 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jul 14, 2023, + *last release*: Aug 19, 2023, *status*: 3 - Alpha, - *requires*: pytest (==7.3.1) + *requires*: pytest ==7.3.1 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -4950,12 +5056,19 @@ This list contains 1289 plugins. Helpers for testing hpfeeds in your python project :pypi:`pytest-html` - *last release*: Apr 08, 2023, + *last release*: Aug 13, 2023, *status*: 5 - Production/Stable, *requires*: pytest (!=6.0.0,>=5.0) pytest plugin for generating HTML reports + :pypi:`pytest-html-cn` + *last release*: Aug 01, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + pytest plugin for generating HTML reports + :pypi:`pytest-html-lee` *last release*: Jun 30, 2020, *status*: 5 - Production/Stable, @@ -5048,14 +5161,14 @@ This list contains 1289 plugins. pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: Jul 09, 2023, + *last release*: Jul 24, 2023, *status*: N/A, *requires*: pytest (>=7.2.0,<8.0.0) http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Apr 12, 2023, + *last release*: Aug 02, 2023, *status*: 5 - Production/Stable, *requires*: pytest (<8.0,>=6.0) @@ -5089,6 +5202,13 @@ This list contains 1289 plugins. help hypo module for pytest + :pypi:`pytest-iam` + *last release*: Aug 21, 2023, + *status*: 3 - Alpha, + *requires*: pytest (>=7.0.0,<8.0.0) + + A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite + :pypi:`pytest-ibutsu` *last release*: Aug 05, 2022, *status*: 4 - Beta, @@ -5131,6 +5251,13 @@ This list contains 1289 plugins. ignore failures from flaky tests (pytest plugin) + :pypi:`pytest-ignore-test-results` + *last release*: Aug 17, 2023, + *status*: 2 - Pre-Alpha, + *requires*: pytest>=7.0 + + A pytest plugin to ignore test results. + :pypi:`pytest-image-diff` *last release*: Mar 09, 2023, *status*: 3 - Alpha, @@ -5188,7 +5315,7 @@ This list contains 1289 plugins. A pytest plugin for writing inline tests. :pypi:`pytest-inmanta` - *last release*: Feb 23, 2023, + *last release*: Aug 03, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5678,9 +5805,9 @@ This list contains 1289 plugins. A pytest plugin to show the line numbers of test functions :pypi:`pytest-line-profiler` - *last release*: May 03, 2021, + *last release*: Aug 10, 2023, *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *requires*: pytest >=3.5.0 Profile code executed by pytest @@ -5712,6 +5839,13 @@ This list contains 1289 plugins. A pytest plugin that stream output in LITF format + :pypi:`pytest-litter` + *last release*: Aug 08, 2023, + *status*: 4 - Beta, + *requires*: pytest >=6.1 + + Pytest plugin which verifies that tests do not modify file trees. + :pypi:`pytest-live` *last release*: Mar 08, 2020, *status*: N/A, @@ -5748,7 +5882,7 @@ This list contains 1289 plugins. Pytest plugin for AWS integration tests :pypi:`pytest-lockable` - *last release*: Jul 20, 2022, + *last release*: Aug 09, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -6133,7 +6267,7 @@ This list contains 1289 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Jul 12, 2023, + *last release*: Jul 24, 2023, *status*: N/A, *requires*: pytest (>=1.0) @@ -6196,9 +6330,9 @@ This list contains 1289 plugins. PyTest Molecule Plugin :: discover and run molecule tests :pypi:`pytest-mongo` - *last release*: Jun 07, 2021, + *last release*: Jul 20, 2023, *status*: 5 - Production/Stable, - *requires*: pytest + *requires*: pytest (>=6.2) MongoDB process and client fixtures plugin for Pytest. @@ -6280,7 +6414,7 @@ This list contains 1289 plugins. low-startup-overhead, scalable, distributed-testing pytest plugin :pypi:`pytest-mqtt` - *last release*: Mar 15, 2023, + *last release*: Aug 03, 2023, *status*: 4 - Beta, *requires*: pytest (<8) ; extra == 'test' @@ -6336,7 +6470,7 @@ This list contains 1289 plugins. Mypy static type checker plugin for Pytest :pypi:`pytest-mypy-plugins` - *last release*: Jun 29, 2023, + *last release*: Jul 25, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0.0) @@ -6441,7 +6575,7 @@ This list contains 1289 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Jul 11, 2023, + *last release*: Aug 02, 2023, *status*: N/A, *requires*: pytest (==6.2.5) @@ -6489,6 +6623,13 @@ This list contains 1289 plugins. Ensure a test produces no garbage + :pypi:`pytest-nose-attrib` + *last release*: Aug 13, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach + :pypi:`pytest-notice` *last release*: Nov 05, 2020, *status*: N/A, @@ -6553,7 +6694,7 @@ This list contains 1289 plugins. pytest results data-base and HTML reporter :pypi:`pytest-odc` - *last release*: Jul 18, 2023, + *last release*: Aug 04, 2023, *status*: 4 - Beta, *requires*: pytest (>=3.5.0) @@ -6910,9 +7051,9 @@ This list contains 1289 plugins. pytest plugin to test Python examples in Markdown using phmdoctest. :pypi:`pytest-picked` - *last release*: Dec 23, 2020, + *last release*: Jul 27, 2023, *status*: N/A, - *requires*: pytest (>=3.5.0) + *requires*: pytest (>=3.7.0) Run the tests related to the changed files @@ -6994,7 +7135,7 @@ This list contains 1289 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Apr 24, 2023, + *last release*: Aug 07, 2023, *status*: N/A, *requires*: pytest (<8.0.0,>=6.2.4) @@ -7127,9 +7268,9 @@ This list contains 1289 plugins. A pytest plugin to help with testing pop projects :pypi:`pytest-porringer` - *last release*: Jun 24, 2023, + *last release*: Aug 19, 2023, *status*: N/A, - *requires*: pytest>=7.1.2 + *requires*: pytest>=7.4.0 @@ -7154,13 +7295,6 @@ This list contains 1289 plugins. Postgresql fixtures and fixture factories for Pytest. - :pypi:`pytest-pot` - *last release*: Nov 20, 2022, - *status*: N/A, - *requires*: N/A - - A package for enhancing pytest - :pypi:`pytest-power` *last release*: Dec 31, 2020, *status*: N/A, @@ -7203,6 +7337,13 @@ This list contains 1289 plugins. pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) + :pypi:`pytest-priority` + *last release*: Jul 23, 2023, + *status*: N/A, + *requires*: N/A + + pytest plugin for add priority for tests + :pypi:`pytest-profiles` *last release*: Dec 09, 2021, *status*: 4 - Beta, @@ -7407,9 +7548,9 @@ This list contains 1289 plugins. PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report :pypi:`pytest-pyright` - *last release*: Nov 20, 2022, + *last release*: Aug 20, 2023, *status*: 4 - Beta, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 Pytest plugin for type checking code with Pyright @@ -7589,7 +7730,7 @@ This list contains 1289 plugins. py.test plugin to randomize tests :pypi:`pytest-randomly` - *last release*: Jul 10, 2023, + *last release*: Aug 15, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -7624,7 +7765,7 @@ This list contains 1289 plugins. Test your README.md file :pypi:`pytest-reana` - *last release*: Dec 13, 2022, + *last release*: Aug 04, 2023, *status*: 3 - Alpha, *requires*: N/A @@ -7638,9 +7779,9 @@ This list contains 1289 plugins. Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. :pypi:`pytest-recording` - *last release*: Feb 16, 2023, + *last release*: Jul 31, 2023, *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *requires*: pytest>=3.5.0 A pytest plugin that allows you recording of network interactions via VCR.py @@ -7708,7 +7849,7 @@ This list contains 1289 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Jul 08, 2022, + *last release*: Aug 17, 2023, *status*: N/A, *requires*: N/A @@ -8016,7 +8157,7 @@ This list contains 1289 plugins. A RethinkDB plugin for pytest. :pypi:`pytest-retry` - *last release*: Aug 16, 2022, + *last release*: Aug 02, 2023, *status*: N/A, *requires*: pytest (>=7.0.0) @@ -8092,6 +8233,13 @@ This list contains 1289 plugins. pytest plugin for ROAST configuration override and fixtures + :pypi:`pytest-robotframework` + *last release*: Aug 19, 2023, + *status*: N/A, + *requires*: N/A + + a pytest plugin that can run both python and robotframework tests while generating robot reports for them + :pypi:`pytest-rocketchat` *last release*: Apr 18, 2021, *status*: 5 - Production/Stable, @@ -8135,7 +8283,7 @@ This list contains 1289 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Jun 08, 2023, + *last release*: Jul 31, 2023, *status*: 4 - Beta, *requires*: N/A @@ -8219,7 +8367,7 @@ This list contains 1289 plugins. A Pytest plugin that builds and creates docker containers :pypi:`pytest-salt-factories` - *last release*: Dec 15, 2022, + *last release*: Jul 31, 2023, *status*: 4 - Beta, *requires*: pytest (>=6.0.0) @@ -8261,7 +8409,7 @@ This list contains 1289 plugins. :pypi:`pytest-sbase` - *last release*: Jul 20, 2023, + *last release*: Aug 18, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8289,7 +8437,7 @@ This list contains 1289 plugins. 👍 Validate return values against a schema-like object in testing :pypi:`pytest-screenshot-on-failure` - *last release*: Jul 18, 2023, + *last release*: Jul 21, 2023, *status*: 4 - Beta, *requires*: N/A @@ -8317,7 +8465,7 @@ This list contains 1289 plugins. pytest plugin for Selenium :pypi:`pytest-seleniumbase` - *last release*: Jul 20, 2023, + *last release*: Aug 18, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8337,6 +8485,13 @@ This list contains 1289 plugins. A pytest package implementing perceptualdiff for Selenium tests. + :pypi:`pytest-selenium-screenshot` + *last release*: Aug 20, 2023, + *status*: N/A, + *requires*: pytest >= 7.0.0 + + pytest plugin to automatically capture screenshots upon selenium webdriver events + :pypi:`pytest-send-email` *last release*: Dec 04, 2019, *status*: N/A, @@ -8373,7 +8528,7 @@ This list contains 1289 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Jul 13, 2023, + *last release*: Jul 26, 2023, *status*: 3 - Alpha, *requires*: pytest (>=6.2) @@ -8464,9 +8619,9 @@ This list contains 1289 plugins. Versatile ZODB abstraction layer - pytest fixtures :pypi:`pytest-sherlock` - *last release*: Jan 16, 2023, + *last release*: Aug 14, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.5.1) + *requires*: pytest >=3.5.1 pytest plugin help to find coupled tests @@ -8513,7 +8668,7 @@ This list contains 1289 plugins. Allow for multiple processes to log to a single file :pypi:`pytest-skip-markers` - *last release*: Dec 20, 2022, + *last release*: Jul 31, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=7.1.0) @@ -8631,6 +8786,13 @@ This list contains 1289 plugins. A plugin for snapshot testing with pytest. + :pypi:`pytest-snapshot-with-message-generator` + *last release*: Jul 25, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=3.0.0) + + A plugin for snapshot testing with pytest. + :pypi:`pytest-snmpserver` *last release*: May 12, 2021, *status*: N/A, @@ -8681,9 +8843,9 @@ This list contains 1289 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Jul 17, 2023, + *last release*: Aug 12, 2023, *status*: N/A, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 Tools for sorting test cases @@ -8695,7 +8857,7 @@ This list contains 1289 plugins. A simple plugin to first execute tests that historically failed more :pypi:`pytest-sosu` - *last release*: Feb 14, 2023, + *last release*: Aug 04, 2023, *status*: 2 - Pre-Alpha, *requires*: pytest @@ -8800,7 +8962,7 @@ This list contains 1289 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jun 30, 2023, + *last release*: Jul 25, 2023, *status*: N/A, *requires*: pytest (>5.4.0,<8) @@ -8933,9 +9095,9 @@ This list contains 1289 plugins. Run a test suite one failing test at a time. :pypi:`pytest-stf` - *last release*: Dec 04, 2022, + *last release*: Aug 16, 2023, *status*: N/A, - *requires*: pytest (>=5.0) + *requires*: pytest >=5.0 pytest plugin for openSTF @@ -9128,6 +9290,13 @@ This list contains 1289 plugins. A pytest plugin for testing TCP clients + :pypi:`pytest-tdd` + *last release*: Aug 18, 2023, + *status*: 4 - Beta, + *requires*: N/A + + run pytest on a python module + :pypi:`pytest-teamcity-logblock` *last release*: May 15, 2018, *status*: 4 - Beta, @@ -9199,7 +9368,7 @@ This list contains 1289 plugins. A py.test plugin providing temporary directories in unit tests. :pypi:`pytest-testdox` - *last release*: Apr 19, 2022, + *last release*: Jul 22, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=4.6.0) @@ -9381,7 +9550,7 @@ This list contains 1289 plugins. :pypi:`pytest-tesults` - *last release*: Dec 23, 2022, + *last release*: Jul 21, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=3.5.0) @@ -9745,7 +9914,7 @@ This list contains 1289 plugins. A Typhoon HIL plugin that facilitates test parameter configuration at runtime :pypi:`pytest-typhoon-xray` - *last release*: Jun 10, 2023, + *last release*: Aug 15, 2023, *status*: 4 - Beta, *requires*: N/A @@ -9829,7 +9998,7 @@ This list contains 1289 plugins. Set a test as unstable to return 0 even if it failed :pypi:`pytest-unused-fixtures` - *last release*: Jun 30, 2023, + *last release*: Aug 08, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.3.2,<8.0.0) @@ -10137,7 +10306,7 @@ This list contains 1289 plugins. pytest plugin helps to reproduce failures for particular xdist node :pypi:`pytest-xdist-worker-stats` - *last release*: Jun 19, 2023, + *last release*: Aug 08, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.3.2,<8.0.0) @@ -10157,6 +10326,13 @@ This list contains 1289 plugins. Pytest fixtures providing data read from function, module or package related (x)files. + :pypi:`pytest-xiuyu` + *last release*: Jul 25, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + This is a pytest plugin + :pypi:`pytest-xlog` *last release*: May 31, 2020, *status*: 4 - Beta, @@ -10221,7 +10397,7 @@ This list contains 1289 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-xvirt` - *last release*: Jun 18, 2023, + *last release*: Jul 30, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.1.0) From d1722d5c189ff7a1baccadfb514d05402104ccee Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:49:39 -0700 Subject: [PATCH 0141/1271] fix test for codecov --- testing/test_assertrewrite.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 2c908133d39..08813c4dcf0 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -685,8 +685,9 @@ def myany(x) -> bool: assert msg is not None assert " < 0" in msg - def test_assert_handling_raise_in__iter__(self) -> None: - def f() -> None: + def test_assert_handling_raise_in__iter__(self, pytester: Pytester) -> None: + pytester.makepyfile( + """\ class A: def __iter__(self): raise ValueError() @@ -698,10 +699,10 @@ def __repr__(self): return "" assert A() == A() - - msg = getmsg(f) - assert msg is not None - assert " == " in msg + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines(["*E*assert == "]) def test_formatchar(self) -> None: def f() -> None: From 3f446b68fdbd8f1e0e0d9af3960e1da90f58f1b3 Mon Sep 17 00:00:00 2001 From: WarrenTheRabbit <37808734+WarrenTheRabbit@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:36:39 +1000 Subject: [PATCH 0142/1271] doc: fix docstring spelling in pytester --- src/_pytest/pytester.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index b112e6e7000..649338599da 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -829,7 +829,7 @@ def makefile(self, ext: str, *args: str, **kwargs: str) -> Path: return self._makefile(ext, args, kwargs) def makeconftest(self, source: str) -> Path: - """Write a contest.py file. + """Write a conftest.py file. :param source: The contents. :returns: The conftest.py file. From cada6c105a7f9e22d5519c0e9355cc44df2a58b8 Mon Sep 17 00:00:00 2001 From: DetachHead <57028336+DetachHead@users.noreply.github.com> Date: Tue, 22 Aug 2023 17:57:59 +1000 Subject: [PATCH 0143/1271] ignore mypy error on deprecated `Instance` usage --- testing/deprecated_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index f4197a1f618..08e193b5cec 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -272,7 +272,7 @@ def test_importing_instance_is_deprecated(pytester: Pytester) -> None: pytest.PytestDeprecationWarning, match=re.escape("The pytest.Instance collector type is deprecated"), ): - pytest.Instance + pytest.Instance # type:ignore[attr-defined] with pytest.warns( pytest.PytestDeprecationWarning, From 8f36fd5454f6d3c9fa33ecb7403641bfa713ab87 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 22 Aug 2023 08:10:48 +0000 Subject: [PATCH 0144/1271] [pre-commit.ci] pre-commit autoupdate (#11335) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/blacken-docs: 1.15.0 → 1.16.0](https://github.com/asottile/blacken-docs/compare/1.15.0...1.16.0) - [github.com/pre-commit/mirrors-mypy: v1.5.0 → v1.5.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.5.0...v1.5.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d9d488dd168..82dc5dae700 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,7 @@ repos: - id: black args: [--safe, --quiet] - repo: https://github.com/asottile/blacken-docs - rev: 1.15.0 + rev: 1.16.0 hooks: - id: blacken-docs additional_dependencies: [black==23.7.0] @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.0 + rev: v1.5.1 hooks: - id: mypy files: ^(src/|testing/) From 23b899f31f91a05a75d06bcc5e8c99891b210541 Mon Sep 17 00:00:00 2001 From: Ha Pam Date: Wed, 23 Aug 2023 15:17:09 +0700 Subject: [PATCH 0145/1271] Fix a typo in anatomy.rst (#11341) --- doc/en/explanation/anatomy.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/explanation/anatomy.rst b/doc/en/explanation/anatomy.rst index e86dd74251e..93d3400dae2 100644 --- a/doc/en/explanation/anatomy.rst +++ b/doc/en/explanation/anatomy.rst @@ -34,7 +34,7 @@ a function/method call. **Assert** is where we look at that resulting state and check if it looks how we'd expect after the dust has settled. It's where we gather evidence to say the -behavior does or does not aligns with what we expect. The ``assert`` in our test +behavior does or does not align with what we expect. The ``assert`` in our test is where we take that measurement/observation and apply our judgement to it. If something should be green, we'd say ``assert thing == "green"``. From 7500fe44b2aed9fec71251b7826f726d9b403428 Mon Sep 17 00:00:00 2001 From: Jon Parise Date: Wed, 23 Aug 2023 02:21:17 -0700 Subject: [PATCH 0146/1271] Correct the spelling of ArgSource.INVOCATION_DIR (#11333) Config.ArgsSource.INCOVATION_DIR remains as a backwards compatibility alias. --- changelog/11333.trivial.rst | 2 ++ src/_pytest/config/__init__.py | 5 +++-- testing/test_config.py | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 changelog/11333.trivial.rst diff --git a/changelog/11333.trivial.rst b/changelog/11333.trivial.rst new file mode 100644 index 00000000000..846f79e34a7 --- /dev/null +++ b/changelog/11333.trivial.rst @@ -0,0 +1,2 @@ +Corrected the spelling of ``Config.ArgsSource.INVOCATION_DIR``. +The previous spelling ``INCOVATION_DIR`` remains as an alias. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 8dbaf7c70e5..1d9c49aa111 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -953,7 +953,8 @@ class ArgsSource(enum.Enum): #: Command line arguments. ARGS = enum.auto() #: Invocation directory. - INCOVATION_DIR = enum.auto() + INVOCATION_DIR = enum.auto() + INCOVATION_DIR = INVOCATION_DIR # backwards compatibility alias #: 'testpaths' configuration value. TESTPATHS = enum.auto() @@ -1278,7 +1279,7 @@ def _decide_args( else: result = [] if not result: - source = Config.ArgsSource.INCOVATION_DIR + source = Config.ArgsSource.INVOCATION_DIR result = [str(invocation_dir)] return result, source diff --git a/testing/test_config.py b/testing/test_config.py index 04161f238d8..ded30790188 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -507,6 +507,24 @@ def pytest_load_initial_conftests(early_config, parser, args): result = pytester.runpytest("--foo=1") result.stdout.fnmatch_lines("* no tests ran in *") + def test_args_source_args(self, pytester: Pytester): + config = pytester.parseconfig("--", "test_filename.py") + assert config.args_source == Config.ArgsSource.ARGS + + def test_args_source_invocation_dir(self, pytester: Pytester): + config = pytester.parseconfig() + assert config.args_source == Config.ArgsSource.INVOCATION_DIR + + def test_args_source_testpaths(self, pytester: Pytester): + pytester.makeini( + """ + [pytest] + testpaths=* + """ + ) + config = pytester.parseconfig() + assert config.args_source == Config.ArgsSource.TESTPATHS + class TestConfigCmdlineParsing: def test_parsing_again_fails(self, pytester: Pytester) -> None: From 77f7f59b2a7058d75c2d4fd8fc15ee6858dc5dc3 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 26 Aug 2023 09:53:45 +0300 Subject: [PATCH 0147/1271] Fixes for typed pluggy Since version 1.3 pluggy added typing, which requires some fixes to please mypy. --- changelog/11353.trivial.rst | 1 + doc/en/reference/reference.rst | 4 ++-- setup.cfg | 2 +- src/_pytest/config/__init__.py | 21 +++++++++++++-------- src/_pytest/helpconfig.py | 6 +++++- src/_pytest/logging.py | 2 ++ src/_pytest/pytester.py | 2 +- testing/test_pluginmanager.py | 10 ++++++++-- 8 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 changelog/11353.trivial.rst diff --git a/changelog/11353.trivial.rst b/changelog/11353.trivial.rst new file mode 100644 index 00000000000..10a6b46927f --- /dev/null +++ b/changelog/11353.trivial.rst @@ -0,0 +1 @@ +pluggy>=1.3.0 is now required. This adds typing to :class:`~pytest.PytestPluginManager`. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index d578fc285ef..b172c3e9cb8 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -980,10 +980,10 @@ TestShortLogReport .. autoclass:: pytest.TestShortLogReport() :members: -_Result +Result ~~~~~~~ -Result object used within :ref:`hook wrappers `, see :py:class:`_Result in the pluggy documentation ` for more information. +Result object used within :ref:`hook wrappers `, see :py:class:`Result in the pluggy documentation ` for more information. Stash ~~~~~ diff --git a/setup.cfg b/setup.cfg index 9456353693e..3b1c627de06 100644 --- a/setup.cfg +++ b/setup.cfg @@ -46,7 +46,7 @@ py_modules = py install_requires = iniconfig packaging - pluggy>=1.2.0,<2.0 + pluggy>=1.3.0,<2.0 colorama;sys_platform=="win32" exceptiongroup>=1.0.0rc8;python_version<"3.11" tomli>=1.0.0;python_version<"3.11" diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 1d9c49aa111..cde230fdbd9 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -38,7 +38,9 @@ from typing import Union from pluggy import HookimplMarker +from pluggy import HookimplOpts from pluggy import HookspecMarker +from pluggy import HookspecOpts from pluggy import PluginManager import _pytest._code @@ -440,15 +442,17 @@ def __init__(self) -> None: # Used to know when we are importing conftests after the pytest_configure stage. self._configured = False - def parse_hookimpl_opts(self, plugin: _PluggyPlugin, name: str): + def parse_hookimpl_opts( + self, plugin: _PluggyPlugin, name: str + ) -> Optional[HookimplOpts]: # pytest hooks are always prefixed with "pytest_", # so we avoid accessing possibly non-readable attributes # (see issue #1073). if not name.startswith("pytest_"): - return + return None # Ignore names which can not be hooks. if name == "pytest_plugins": - return + return None opts = super().parse_hookimpl_opts(plugin, name) if opts is not None: @@ -457,18 +461,18 @@ def parse_hookimpl_opts(self, plugin: _PluggyPlugin, name: str): method = getattr(plugin, name) # Consider only actual functions for hooks (#3775). if not inspect.isroutine(method): - return + return None # Collect unmarked hooks as long as they have the `pytest_' prefix. - return _get_legacy_hook_marks( + return _get_legacy_hook_marks( # type: ignore[return-value] method, "impl", ("tryfirst", "trylast", "optionalhook", "hookwrapper") ) - def parse_hookspec_opts(self, module_or_class, name: str): + def parse_hookspec_opts(self, module_or_class, name: str) -> Optional[HookspecOpts]: opts = super().parse_hookspec_opts(module_or_class, name) if opts is None: method = getattr(module_or_class, name) if name.startswith("pytest_"): - opts = _get_legacy_hook_marks( + opts = _get_legacy_hook_marks( # type: ignore[assignment] method, "spec", ("firstresult", "historic"), @@ -1067,9 +1071,10 @@ def _ensure_unconfigure(self) -> None: fin() def get_terminal_writer(self) -> TerminalWriter: - terminalreporter: TerminalReporter = self.pluginmanager.get_plugin( + terminalreporter: Optional[TerminalReporter] = self.pluginmanager.get_plugin( "terminalreporter" ) + assert terminalreporter is not None return terminalreporter._tw def pytest_cmdline_parse( diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 4122d60094a..364bf4c4276 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -12,6 +12,7 @@ from _pytest.config import ExitCode from _pytest.config import PrintHelp from _pytest.config.argparsing import Parser +from _pytest.terminal import TerminalReporter class HelpAction(Action): @@ -161,7 +162,10 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: def showhelp(config: Config) -> None: import textwrap - reporter = config.pluginmanager.get_plugin("terminalreporter") + reporter: Optional[TerminalReporter] = config.pluginmanager.get_plugin( + "terminalreporter" + ) + assert reporter is not None tw = reporter._tw tw.write(config._parser.optparser.format_help()) tw.line() diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 8de690d9b0e..245b7aed06c 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -659,6 +659,8 @@ def __init__(self, config: Config) -> None: ) if self._log_cli_enabled(): terminal_reporter = config.pluginmanager.get_plugin("terminalreporter") + # Guaranteed by `_log_cli_enabled()`. + assert terminal_reporter is not None capture_manager = config.pluginmanager.get_plugin("capturemanager") # if capturemanager plugin is disabled, live logging still works. self.log_cli_handler: Union[ diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 649338599da..854ee6834aa 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -751,7 +751,7 @@ def preserve_module(name): def make_hook_recorder(self, pluginmanager: PytestPluginManager) -> HookRecorder: """Create a new :class:`HookRecorder` for a :class:`PytestPluginManager`.""" - pluginmanager.reprec = reprec = HookRecorder(pluginmanager, _ispytest=True) + pluginmanager.reprec = reprec = HookRecorder(pluginmanager, _ispytest=True) # type: ignore[attr-defined] self._request.addfinalizer(reprec.finish_recording) return reprec diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index c6f518b1da2..e5773412fbf 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -242,8 +242,12 @@ def test_consider_module( mod = types.ModuleType("temp") mod.__dict__["pytest_plugins"] = ["pytest_p1", "pytest_p2"] pytestpm.consider_module(mod) - assert pytestpm.get_plugin("pytest_p1").__name__ == "pytest_p1" - assert pytestpm.get_plugin("pytest_p2").__name__ == "pytest_p2" + p1 = pytestpm.get_plugin("pytest_p1") + assert p1 is not None + assert p1.__name__ == "pytest_p1" + p2 = pytestpm.get_plugin("pytest_p2") + assert p2 is not None + assert p2.__name__ == "pytest_p2" def test_consider_module_import_module( self, pytester: Pytester, _config_for_test: Config @@ -336,6 +340,7 @@ def test_import_plugin_importname( len2 = len(pytestpm.get_plugins()) assert len1 == len2 plugin1 = pytestpm.get_plugin("pytest_hello") + assert plugin1 is not None assert plugin1.__name__.endswith("pytest_hello") plugin2 = pytestpm.get_plugin("pytest_hello") assert plugin2 is plugin1 @@ -351,6 +356,7 @@ def test_import_plugin_dotted_name( pluginname = "pkg.plug" pytestpm.import_plugin(pluginname) mod = pytestpm.get_plugin("pkg.plug") + assert mod is not None assert mod.x == 3 def test_consider_conftest_deps( From ff23347f1f050d2544cfb89ff6aa9af885c27375 Mon Sep 17 00:00:00 2001 From: Warren Markham Date: Sun, 27 Aug 2023 22:40:24 +1000 Subject: [PATCH 0148/1271] Fix platform-dependent type-check errors (#11345) Use more explicit `sys.platform` checks, instead of the previous check using `in`, which mypy understands. Fixes #11343 --- src/_pytest/compat.py | 25 +++++++++++++++++-------- testing/test_parseopt.py | 3 ++- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index cead6c3113c..73d77f978f7 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -314,15 +314,24 @@ def safe_isclass(obj: object) -> bool: def get_user_id() -> int | None: - """Return the current user id, or None if we cannot get it reliably on the current platform.""" - # win32 does not have a getuid() function. - # On Emscripten, getuid() is a stub that always returns 0. - if sys.platform in ("win32", "emscripten"): + """Return the current process's real user id or None if it could not be + determined. + + :return: The user id or None if it could not be determined. + """ + # mypy follows the version and platform checking expectation of PEP 484: + # https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks + # Containment checks are too complex for mypy v1.5.0 and cause failure. + if sys.platform == "win32" or sys.platform == "emscripten": + # win32 does not have a getuid() function. + # Emscripten has a return 0 stub. return None - # getuid shouldn't fail, but cpython defines such a case. - # Let's hope for the best. - uid = os.getuid() - return uid if uid != -1 else None + else: + # On other platforms, a return value of -1 is assumed to indicate that + # the current process's real user id could not be determined. + ERROR = -1 + uid = os.getuid() + return uid if uid != ERROR else None # Perform exhaustiveness checking. diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 1899abe153f..b6df035aacf 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -291,7 +291,8 @@ def test_multiple_metavar_help(self, parser: parseopt.Parser) -> None: def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: try: - encoding = locale.getencoding() # New in Python 3.11, ignores utf-8 mode + # New in Python 3.11, ignores utf-8 mode + encoding = locale.getencoding() # type: ignore[attr-defined] except AttributeError: encoding = locale.getpreferredencoding(False) try: From 17e8f2b3fcbc347939215f100d5e4911a6a3c80b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 27 Aug 2023 11:29:17 -0300 Subject: [PATCH 0149/1271] [automated] Update plugin list (#11358) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 94 +++++++++++++++++++------------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 9d5728352de..a1aef9d1cba 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -15,7 +15,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1311 plugins. +This list contains 1313 plugins. .. only:: not latex @@ -54,7 +54,7 @@ This list contains 1311 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Aug 21, 2023 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Aug 24, 2023 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -242,7 +242,7 @@ This list contains 1311 plugins. :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0) - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Jun 19, 2023 N/A N/A + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 26, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -285,7 +285,7 @@ This list contains 1311 plugins. :pypi:`pytest-dbt` Unit test dbt models with standard python tooling Jun 08, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-dbt-core` Pytest extension for dbt. Aug 09, 2023 N/A pytest >=6.2.5 ; extra == 'test' + :pypi:`pytest-dbt-core` Pytest extension for dbt. Aug 25, 2023 N/A pytest >=6.2.5 ; extra == 'test' :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-dc` Manages Docker containers during your integration tests Aug 16, 2023 5 - Production/Stable pytest >=3.3 @@ -404,7 +404,7 @@ This list contains 1311 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` py.test plugin that allows you to add environment variables. Jun 15, 2023 5 - Production/Stable pytest>=7.3.1 + :pypi:`pytest-env` py.test plugin that allows you to add environment variables. Aug 24, 2023 5 - Production/Stable pytest>=7.3.1 :pypi:`pytest-envfiles` A py.test plugin that parses environment files before running tests Oct 08, 2015 3 - Alpha N/A :pypi:`pytest-env-info` Push information about the running pytest into envvars Nov 25, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-envraw` py.test plugin that allows you to add environment variables. Aug 27, 2020 4 - Beta pytest (>=2.6.0) @@ -545,7 +545,7 @@ This list contains 1311 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 19, 2023 3 - Alpha pytest ==7.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 25, 2023 3 - Alpha pytest ==7.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -553,7 +553,7 @@ This list contains 1311 plugins. :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Aug 13, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) + :pypi:`pytest-html` pytest plugin for generating HTML reports Aug 25, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Apr 03, 2022 N/A N/A @@ -705,7 +705,7 @@ This list contains 1311 plugins. :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Jul 16, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A - :pypi:`pytest-memray` A simple plugin to use with pytest Jun 06, 2023 N/A pytest>=7.2 + :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) @@ -869,7 +869,7 @@ This list contains 1311 plugins. :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-porringer` Aug 19, 2023 N/A pytest>=7.4.0 + :pypi:`pytest-porringer` Aug 26, 2023 N/A pytest>=7.4.0 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) @@ -878,7 +878,7 @@ This list contains 1311 plugins. :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A - :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Jun 28, 2023 5 - Production/Stable pytest>=7.3.2 + :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Aug 25, 2023 5 - Production/Stable pytest>=7.4 :pypi:`pytest-priority` pytest plugin for add priority for tests Jul 23, 2023 N/A N/A :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest @@ -996,7 +996,7 @@ This list contains 1311 plugins. :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 02, 2023 N/A pytest (>=7.0.0) + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 23, 2023 N/A pytest >=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest @@ -1007,7 +1007,7 @@ This list contains 1311 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 19, 2023 N/A N/A + :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 24, 2023 N/A N/A :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1032,7 +1032,7 @@ This list contains 1311 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 18, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 23, 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) @@ -1040,10 +1040,11 @@ This list contains 1311 plugins. :pypi:`pytest-securestore` An encrypted password store for use within pytest cases Nov 08, 2021 4 - Beta N/A :pypi:`pytest-select` A pytest plugin which allows to (de-)select tests from a file. Jan 18, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-selenium` pytest plugin for Selenium May 28, 2023 5 - Production/Stable pytest>=6.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 18, 2023 5 - Production/Stable N/A + :pypi:`pytest-selenium-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 23, 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-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 20, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A @@ -1147,6 +1148,7 @@ This list contains 1311 plugins. :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A + :pypi:`pytest-synodic` Synodic Pytest utilities Aug 26, 2023 N/A pytest>=7.4.0 :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A :pypi:`pytest-tagging` a pytest plugin to tag tests Apr 01, 2023 N/A pytest (>=7.1.3,<8.0.0) @@ -1172,7 +1174,7 @@ This list contains 1311 plugins. :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A - :pypi:`pytest-testinfra` Test infrastructures May 21, 2023 5 - Production/Stable pytest (!=3.0.2) + :pypi:`pytest-testinfra` Test infrastructures Aug 24, 2023 5 - Production/Stable pytest !=3.0.2 :pypi:`pytest-testlink-adaptor` pytest reporting plugin for testlink Dec 20, 2018 4 - Beta pytest (>=2.6) :pypi:`pytest-testmon` selects tests affected by changed files and methods Jul 13, 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) @@ -1196,7 +1198,7 @@ This list contains 1311 plugins. :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) :pypi:`pytest-tesults` Tesults plugin for pytest Jul 21, 2023 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 18, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A @@ -1316,7 +1318,7 @@ This list contains 1311 plugins. :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (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. Jul 30, 2023 4 - Beta pytest (>=7.1.0) + :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Aug 24, 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-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) @@ -1563,7 +1565,7 @@ This list contains 1311 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Aug 21, 2023, + *last release*: Aug 24, 2023, *status*: N/A, *requires*: pytest >=7.3.1 @@ -2879,7 +2881,7 @@ This list contains 1311 plugins. Use pytest's runner to discover and execute C++ tests :pypi:`pytest-cppython` - *last release*: Jun 19, 2023, + *last release*: Aug 26, 2023, *status*: N/A, *requires*: N/A @@ -3180,7 +3182,7 @@ This list contains 1311 plugins. A pytest plugin for linting a dbt project's conventions :pypi:`pytest-dbt-core` - *last release*: Aug 09, 2023, + *last release*: Aug 25, 2023, *status*: N/A, *requires*: pytest >=6.2.5 ; extra == 'test' @@ -4013,7 +4015,7 @@ This list contains 1311 plugins. Improvements for pytest (rejected upstream) :pypi:`pytest-env` - *last release*: Jun 15, 2023, + *last release*: Aug 24, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.3.1 @@ -5000,7 +5002,7 @@ This list contains 1311 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Aug 19, 2023, + *last release*: Aug 25, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.3.1 @@ -5056,7 +5058,7 @@ This list contains 1311 plugins. Helpers for testing hpfeeds in your python project :pypi:`pytest-html` - *last release*: Aug 13, 2023, + *last release*: Aug 25, 2023, *status*: 5 - Production/Stable, *requires*: pytest (!=6.0.0,>=5.0) @@ -6120,7 +6122,7 @@ This list contains 1311 plugins. Estimates memory consumption of test functions :pypi:`pytest-memray` - *last release*: Jun 06, 2023, + *last release*: Aug 23, 2023, *status*: N/A, *requires*: pytest>=7.2 @@ -7268,7 +7270,7 @@ This list contains 1311 plugins. A pytest plugin to help with testing pop projects :pypi:`pytest-porringer` - *last release*: Aug 19, 2023, + *last release*: Aug 26, 2023, *status*: N/A, *requires*: pytest>=7.4.0 @@ -7331,9 +7333,9 @@ This list contains 1311 plugins. Minitest-style test colors :pypi:`pytest-print` - *last release*: Jun 28, 2023, + *last release*: Aug 25, 2023, *status*: 5 - Production/Stable, - *requires*: pytest>=7.3.2 + *requires*: pytest>=7.4 pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) @@ -8157,9 +8159,9 @@ This list contains 1311 plugins. A RethinkDB plugin for pytest. :pypi:`pytest-retry` - *last release*: Aug 02, 2023, + *last release*: Aug 23, 2023, *status*: N/A, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 Adds the ability to retry flaky tests in CI environments @@ -8234,7 +8236,7 @@ This list contains 1311 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest-robotframework` - *last release*: Aug 19, 2023, + *last release*: Aug 24, 2023, *status*: N/A, *requires*: N/A @@ -8409,7 +8411,7 @@ This list contains 1311 plugins. :pypi:`pytest-sbase` - *last release*: Aug 18, 2023, + *last release*: Aug 23, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8464,8 +8466,15 @@ This list contains 1311 plugins. pytest plugin for Selenium + :pypi:`pytest-selenium-auto` + *last release*: Aug 22, 2023, + *status*: N/A, + *requires*: pytest >= 7.0.0 + + pytest plugin to automatically capture screenshots upon selenium webdriver events + :pypi:`pytest-seleniumbase` - *last release*: Aug 18, 2023, + *last release*: Aug 23, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8486,7 +8495,7 @@ This list contains 1311 plugins. A pytest package implementing perceptualdiff for Selenium tests. :pypi:`pytest-selenium-screenshot` - *last release*: Aug 20, 2023, + *last release*: Aug 22, 2023, *status*: N/A, *requires*: pytest >= 7.0.0 @@ -9213,6 +9222,13 @@ This list contains 1311 plugins. pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. + :pypi:`pytest-synodic` + *last release*: Aug 26, 2023, + *status*: N/A, + *requires*: pytest>=7.4.0 + + Synodic Pytest utilities + :pypi:`pytest-system-statistics` *last release*: Feb 16, 2022, *status*: 5 - Production/Stable, @@ -9389,9 +9405,9 @@ This list contains 1311 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-testinfra` - *last release*: May 21, 2023, + *last release*: Aug 24, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (!=3.0.2) + *requires*: pytest !=3.0.2 Test infrastructures @@ -9557,7 +9573,7 @@ This list contains 1311 plugins. Tesults plugin for pytest :pypi:`pytest-textual-snapshot` - *last release*: Jul 18, 2023, + *last release*: Aug 23, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0.0) @@ -10397,9 +10413,9 @@ This list contains 1311 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-xvirt` - *last release*: Jul 30, 2023, + *last release*: Aug 24, 2023, *status*: 4 - Beta, - *requires*: pytest (>=7.1.0) + *requires*: pytest >=7.1.0 A pytest plugin to virtualize test. For example to transparently running them on a remote box. From 19d6b12b2a98f273a082f83cc8d469ab5db4e155 Mon Sep 17 00:00:00 2001 From: Sean Malloy Date: Sun, 27 Aug 2023 15:03:42 -0700 Subject: [PATCH 0150/1271] fix: fixing an issue with pre-commit with mypy and flake8 --- AUTHORS | 1 + testing/_py/test_local.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 313e507f204..6fa7a41eb8c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -336,6 +336,7 @@ Samuele Pedroni Sanket Duthade Sankt Petersbug Saravanan Padmanaban +Sean Malloy Segev Finer Serhii Mozghovyi Seth Junot diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 91b14aa2e0e..57e2d91f900 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -15,7 +15,7 @@ def ignore_encoding_warning(): with warnings.catch_warnings(): with contextlib.suppress(NameError): # new in 3.10 - warnings.simplefilter("ignore", EncodingWarning) + warnings.simplefilter("ignore", EncodingWarning) # type: ignore [name-defined] # noqa: F821 yield From 76ba7db6ce57846af4b82e0dabd9c5fbcd7c6b44 Mon Sep 17 00:00:00 2001 From: Sean Patrick Malloy Date: Mon, 28 Aug 2023 17:14:45 -0700 Subject: [PATCH 0151/1271] Improve docs for last-failed-no-failures Improve documentation for last-failed-no-failures to make the different options and the functionality more clear. Closes #11354 --- doc/en/how-to/cache.rst | 17 ++++++++++++----- doc/en/reference/reference.rst | 7 +++++-- src/_pytest/cacheprovider.py | 6 +++++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index 8554a984c72..03ab0c77780 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -176,14 +176,21 @@ with more recent files coming first. Behavior when no tests failed in the last run --------------------------------------------- -When no tests failed in the last run, or when no cached ``lastfailed`` data was -found, ``pytest`` can be configured either to run all of the tests or no tests, -using the ``--last-failed-no-failures`` option, which takes one of the following values: +The ``--lfnf/--last-failed-no-failures`` option governs the behavior of ``--last-failed``. +Determines whether to execute tests when there are no previously (known) +failures or when no cached ``lastfailed`` data was found. + +There are two options: + +* ``all``: when there are no known test failures, runs all tests (the full test suite). This is the default. +* ``none``: when there are no known test failures, just emits a message stating this and exit successfully. + +Example: .. code-block:: bash - pytest --last-failed --last-failed-no-failures all # run all tests (default behavior) - pytest --last-failed --last-failed-no-failures none # run no tests and exit + pytest --last-failed --last-failed-no-failures all # runs the full test suite (default behavior) + pytest --last-failed --last-failed-no-failures none # runs no tests and exits successfully The new config.cache object -------------------------------- diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index b172c3e9cb8..514a74aa5cd 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1892,8 +1892,11 @@ All the command-line flags can be obtained by running ``pytest --help``:: tests. Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run --lfnf={all,none}, --last-failed-no-failures={all,none} - Which tests to run with no previously (known) - failures + With ``--lf``, determines whether to execute tests when there + are no previously (known) failures or when no + cached ``lastfailed`` data was found. + ``all`` (the default) runs the full test suite again. + ``none`` just emits a message about no known failures and exits successfully. --sw, --stepwise Exit on test failure and continue from last failing test next time --sw-skip, --stepwise-skip diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 67dee6add03..50a474a2920 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -499,7 +499,11 @@ def pytest_addoption(parser: Parser) -> None: dest="last_failed_no_failures", choices=("all", "none"), default="all", - help="Which tests to run with no previously (known) failures", + help="With ``--lf``, determines whether to execute tests when there " + "are no previously (known) failures or when no " + "cached ``lastfailed`` data was found. " + "``all`` (the default) runs the full test suite again. " + "``none`` just emits a message about no known failures and exits successfully.", ) From afb8d66e42a3449476cf9bf4526705b1e36ff5a5 Mon Sep 17 00:00:00 2001 From: Sourabh Beniwal Date: Wed, 30 Aug 2023 21:52:14 +1000 Subject: [PATCH 0152/1271] Update CONTRIBUTING.rst (#11368) Chnaged Status: easy to good first issue, and updated the URL --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 0f6d54351af..bcfd205b107 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -50,7 +50,7 @@ Fix bugs -------- Look through the `GitHub issues for bugs `_. -See also the `"status: easy" issues `_ +See also the `"good first issue" issues `_ that are friendly to new contributors. :ref:`Talk ` to developers to find out how you can fix specific bugs. To indicate that you are going From ab6cae21262dff2581d5ce6e69be6c79abddc7ab Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 2 Sep 2023 08:13:00 -0300 Subject: [PATCH 0153/1271] Improve CI workflow * Build the package only once, and test on all platforms. * Deploy is now triggered manually via an Action, which is then responsible for tagging the repository after the package has been uploaded successfully. * Drop 'docs': we nowadays rely on readthedocs preview PR builds. --- .github/workflows/deploy.yml | 31 ++++++++++++++++++++++--------- .github/workflows/test.yml | 36 ++++++++++++++++++++++-------------- RELEASING.rst | 11 ++++------- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ca401f09210..01cc4c6e3a9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,33 +1,38 @@ name: deploy on: - push: - tags: - # These tags are protected, see: - # https://github.com/pytest-dev/pytest/settings/tag_protection - - "[0-9]+.[0-9]+.[0-9]+" - - "[0-9]+.[0-9]+.[0-9]+rc[0-9]+" + workflow_dispatch: + inputs: + version: + description: 'Release version' + required: true + default: '1.2.3' # Set permissions at the job level. permissions: {} jobs: - build: + package: runs-on: ubuntu-latest + env: + SETUPTOOLS_SCM_PRETEND_VERSION: ${{ github.event.inputs.version }} timeout-minutes: 10 + steps: - uses: actions/checkout@v3 with: fetch-depth: 0 persist-credentials: false + - name: Build and Check Package uses: hynek/build-and-inspect-python-package@v1.5 deploy: if: github.repository == 'pytest-dev/pytest' - needs: [build] + needs: [package] runs-on: ubuntu-latest + environment: deploy timeout-minutes: 30 permissions: id-token: write @@ -37,9 +42,17 @@ jobs: with: name: Packages path: dist + - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@v1.8.8 + - name: Push tag + run: | + git config user.name "pytest bot" + git config user.email "pytestbot@gmail.com" + git tag --annotate --message=v${{ github.event.inputs.version }} v${{ github.event.inputs.version }} ${{ github.sha }} + git push origin v${{ github.event.inputs.version }} + release-notes: # todo: generate the content in the build job @@ -55,12 +68,12 @@ jobs: with: fetch-depth: 0 persist-credentials: false + - name: Set up Python uses: actions/setup-python@v4 with: python-version: "3.11" - - name: Install tox run: | python -m pip install --upgrade pip diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b3f258f1c21..726dbf0f8cd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,7 +27,19 @@ concurrency: permissions: {} jobs: + package: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + persist-credentials: false + - name: Build and Check Package + uses: hynek/build-and-inspect-python-package@v1.5 + build: + needs: [package] + runs-on: ${{ matrix.os }} timeout-minutes: 45 permissions: @@ -58,7 +70,6 @@ jobs: "macos-py310", "macos-py312", - "docs", "doctesting", "plugins", ] @@ -149,10 +160,6 @@ jobs: os: ubuntu-latest tox_env: "plugins" - - name: "docs" - python: "3.8" - os: ubuntu-latest - tox_env: "docs" - name: "doctesting" python: "3.8" os: ubuntu-latest @@ -165,6 +172,12 @@ jobs: fetch-depth: 0 persist-credentials: false + - name: Download Package + uses: actions/download-artifact@v3 + with: + name: Packages + path: dist + - name: Set up Python ${{ matrix.python }} uses: actions/setup-python@v4 with: @@ -178,11 +191,13 @@ jobs: - name: Test without coverage if: "! matrix.use_coverage" - run: "tox -e ${{ matrix.tox_env }}" + shell: bash + run: tox run -e ${{ matrix.tox_env }} --installpkg `find dist/*.tar.gz` - name: Test with coverage if: "matrix.use_coverage" - run: "tox -e ${{ matrix.tox_env }}-coverage" + shell: bash + run: tox run -e ${{ matrix.tox_env }}-coverage --installpkg `find dist/*.tar.gz` - name: Generate coverage report if: "matrix.use_coverage" @@ -196,10 +211,3 @@ jobs: fail_ci_if_error: true files: ./coverage.xml verbose: true - - check-package: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v1.5 diff --git a/RELEASING.rst b/RELEASING.rst index b018dc48932..5d49fb5d6d9 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -133,14 +133,11 @@ Releasing Both automatic and manual processes described above follow the same steps from this point onward. -#. After all tests pass and the PR has been approved, tag the release commit - in the ``release-MAJOR.MINOR.PATCH`` branch and push it. This will publish to PyPI:: +#. After all tests pass and the PR has been approved, trigger the ``deploy`` job + in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml. - git fetch upstream - git tag MAJOR.MINOR.PATCH upstream/release-MAJOR.MINOR.PATCH - git push upstream MAJOR.MINOR.PATCH - - Wait for the deploy to complete, then make sure it is `available on PyPI `_. + This job will require approval from ``pytest-dev/core``, after which it will publish to PyPI + and tag the repository. #. Merge the PR. **Make sure it's not squash-merged**, so that the tagged commit ends up in the main branch. From 5b528bd1317f6268a93e9ada3bb5f6a190eb257c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 2 Sep 2023 12:04:30 -0300 Subject: [PATCH 0154/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.8.8 to 1.8.10 (#11310) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.8 to 1.8.10. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.8...v1.8.10) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 01cc4c6e3a9..1773c05462a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -44,7 +44,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.8.8 + uses: pypa/gh-action-pypi-publish@v1.8.10 - name: Push tag run: | From f08782d8d0e793fbd2c565556938d41b2d8d4b62 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 2 Sep 2023 12:41:32 -0300 Subject: [PATCH 0155/1271] Merge pull request #11377 from pytest-dev/release-7.4.1 Prepare release 7.4.1 (cherry picked from commit 82eb86f707cac79f33d0ff69723ccf1cea7e75f7) --- .github/workflows/deploy.yml | 1 + changelog/10337.bugfix.rst | 2 -- changelog/10702.bugfix.rst | 1 - changelog/10811.bugfix.rst | 2 -- doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.1.rst | 20 ++++++++++++++++++++ doc/en/builtin.rst | 2 +- doc/en/changelog.rst | 17 +++++++++++++++++ doc/en/example/reportingdemo.rst | 20 ++++++++++---------- doc/en/getting-started.rst | 2 +- doc/en/how-to/tmp_path.rst | 4 ++-- doc/en/reference/reference.rst | 11 ++++++----- 12 files changed, 59 insertions(+), 24 deletions(-) delete mode 100644 changelog/10337.bugfix.rst delete mode 100644 changelog/10702.bugfix.rst delete mode 100644 changelog/10811.bugfix.rst create mode 100644 doc/en/announce/release-7.4.1.rst diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1773c05462a..dd3d5eeb481 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -37,6 +37,7 @@ jobs: permissions: id-token: write steps: + - uses: actions/checkout@v3 - name: Download Package uses: actions/download-artifact@v3 with: diff --git a/changelog/10337.bugfix.rst b/changelog/10337.bugfix.rst deleted file mode 100644 index 629449e8db4..00000000000 --- a/changelog/10337.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed that fake intermediate modules generated by ``--import-mode=importlib`` would not include the -child modules as attributes of the parent modules. diff --git a/changelog/10702.bugfix.rst b/changelog/10702.bugfix.rst deleted file mode 100644 index 4008cc882ec..00000000000 --- a/changelog/10702.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed error assertion handling in :func:`pytest.approx` when ``None`` is an expected or received value when comparing dictionaries. diff --git a/changelog/10811.bugfix.rst b/changelog/10811.bugfix.rst deleted file mode 100644 index aa26414e457..00000000000 --- a/changelog/10811.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed issue when using ``--import-mode=importlib`` together with ``--doctest-modules`` that caused modules -to be imported more than once, causing problems with modules that have import side effects. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 914e763bd9e..85dfa0894fe 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.1 release-7.4.0 release-7.3.2 release-7.3.1 diff --git a/doc/en/announce/release-7.4.1.rst b/doc/en/announce/release-7.4.1.rst new file mode 100644 index 00000000000..efadcf919e8 --- /dev/null +++ b/doc/en/announce/release-7.4.1.rst @@ -0,0 +1,20 @@ +pytest-7.4.1 +======================================= + +pytest 7.4.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Florian Bruhin +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 53305eecded..0d673d0426e 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:528 + cache -- .../_pytest/cacheprovider.py:532 Return a cache object that can persist state between testing sessions. cache.get(key, default) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 391721df34d..be7e7fabaef 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,23 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.1 (2023-09-02) +========================= + +Bug Fixes +--------- + +- `#10337 `_: Fixed bug where fake intermediate modules generated by ``--import-mode=importlib`` would not include the + child modules as attributes of the parent modules. + + +- `#10702 `_: Fixed error assertion handling in :func:`pytest.approx` when ``None`` is an expected or received value when comparing dictionaries. + + +- `#10811 `_: Fixed issue when using ``--import-mode=importlib`` together with ``--doctest-modules`` that caused modules + to be imported more than once, causing problems with modules that have import side effects. + + pytest 7.4.0 (2023-06-23) ========================= diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index cb59c4b42e1..d4d3d3ce202 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -554,13 +554,13 @@ Here is a nice run of several failures and how ``pytest`` presents things: E AssertionError: assert False E + where False = ('456') E + where = '123'.startswith - E + where '123' = .f at 0xdeadbeef0029>() - E + and '456' = .g at 0xdeadbeef002a>() + E + where '123' = .f at 0xdeadbeef0006>() + E + and '456' = .g at 0xdeadbeef0029>() failure_demo.py:235: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -571,18 +571,18 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:238: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - self = + self = def test_instance(self): self.x = 6 * 7 > assert self.x != 42 E assert 42 != 42 - E + where 42 = .x + E + where 42 = .x failure_demo.py:242: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -592,7 +592,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:245: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -603,7 +603,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:250: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -618,7 +618,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:261: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -637,7 +637,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:268: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 4a9dc4522f1..c7a1ee54087 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 7.4.0 + pytest 7.4.1 .. _`simpletest`: diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index d5573f5847d..3b49d63a5be 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -51,8 +51,8 @@ Running this would result in a passed test except for the last d = tmp_path / "sub" d.mkdir() p = d / "hello.txt" - p.write_text(CONTENT) - assert p.read_text() == CONTENT + p.write_text(CONTENT, encoding="utf-8") + assert p.read_text(encoding="utf-8") == CONTENT assert len(list(tmp_path.iterdir())) == 1 > assert 0 E assert 0 diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 514a74aa5cd..d8efbbbaadc 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1892,11 +1892,12 @@ All the command-line flags can be obtained by running ``pytest --help``:: tests. Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run --lfnf={all,none}, --last-failed-no-failures={all,none} - With ``--lf``, determines whether to execute tests when there - are no previously (known) failures or when no - cached ``lastfailed`` data was found. - ``all`` (the default) runs the full test suite again. - ``none`` just emits a message about no known failures and exits successfully. + With ``--lf``, determines whether to execute tests + when there are no previously (known) failures or + when no cached ``lastfailed`` data was found. + ``all`` (the default) runs the full test suite + again. ``none`` just emits a message about no known + failures and exits successfully. --sw, --stepwise Exit on test failure and continue from last failing test next time --sw-skip, --stepwise-skip From 4e3a0874dfc1061070b677492543a1a77d1c6d8c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 2 Sep 2023 22:13:17 -0300 Subject: [PATCH 0156/1271] [automated] Update plugin list (#11380) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 108 ++++++++++++++++++------------- 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index a1aef9d1cba..7dae208a08d 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -15,7 +15,7 @@ Packages classified as inactive are excluded. creating a PDF, because otherwise the table gets far too wide for the page. -This list contains 1313 plugins. +This list contains 1315 plugins. .. only:: not latex @@ -214,7 +214,7 @@ This list contains 1313 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jul 27, 2023 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Sep 01, 2023 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -276,7 +276,7 @@ This list contains 1313 plugins. :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jan 08, 2023 5 - Production/Stable pytest - :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files May 01, 2023 5 - Production/Stable N/A + :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A :pypi:`pytest-data-suites` Class-based pytest parametrization Jul 24, 2022 N/A pytest (>=6.0,<8.0) :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Dec 04, 2019 N/A N/A @@ -323,7 +323,7 @@ This list contains 1313 plugins. :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 :pypi:`pytest-django-gcir` A Django plugin for pytest. Mar 06, 2018 5 - Production/Stable N/A :pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4) - :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Jun 06, 2023 5 - Production/Stable N/A + :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Aug 27, 2023 5 - Production/Stable N/A :pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A :pypi:`pytest-django-liveserver-ssl` Jan 20, 2022 3 - Alpha N/A :pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A @@ -336,7 +336,7 @@ This list contains 1313 plugins. :pypi:`pytest-doc` A documentation plugin for py.test. Jun 28, 2015 5 - Production/Stable N/A :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A - :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Jul 19, 2023 N/A pytest (<8.0,>=4.0) + :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Sep 01, 2023 N/A pytest <8.0,>=4.0 :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Feb 16, 2022 4 - Beta pytest :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) @@ -511,7 +511,7 @@ This list contains 1313 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jul 24, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Aug 30, 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 Jun 22, 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 @@ -541,6 +541,7 @@ This list contains 1313 plugins. :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) + :pypi:`pytest-henry` Aug 29, 2023 N/A N/A :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 @@ -553,7 +554,7 @@ This list contains 1313 plugins. :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Aug 25, 2023 5 - Production/Stable pytest (!=6.0.0,>=5.0) + :pypi:`pytest-html` pytest plugin for generating HTML reports Sep 01, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Apr 03, 2022 N/A N/A @@ -574,7 +575,7 @@ This list contains 1313 plugins. :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Aug 21, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Aug 31, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Aug 09, 2022 4 - Beta N/A :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A @@ -713,7 +714,7 @@ This list contains 1313 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 Jun 08, 2023 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Sep 01, 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) @@ -852,6 +853,7 @@ This list contains 1313 plugins. :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Aug 07, 2023 N/A pytest (<8.0.0,>=6.2.4) :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A + :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A @@ -901,14 +903,14 @@ This list contains 1313 plugins. :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A :pypi:`pytest-pylint` pytest plugin to check source code with pylint Sep 10, 2022 5 - Production/Stable pytest (>=5.4) :pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A - :pypi:`pytest-pyodide` "Pytest plugin for testing applications that use Pyodide" Jun 19, 2023 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Aug 29, 2023 N/A pytest :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Dec 13, 2022 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Jul 02, 2023 N/A pytest (>=7.3.1) + :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Aug 27, 2023 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Aug 20, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Mar 12, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. May 07, 2023 N/A pytest (>=3.5.0) @@ -951,7 +953,7 @@ This list contains 1313 plugins. :pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest - :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 13, 2023 5 - Production/Stable pytest (>=6.2.0) + :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 :pypi:`pytest-regtest` pytest plugin for regression tests Aug 17, 2023 N/A N/A :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) @@ -983,8 +985,8 @@ This list contains 1313 plugins. :pypi:`pytest-rerun` Re-run only changed files in specified branch Jul 08, 2019 N/A pytest (>=3.6) :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Jul 05, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-rerunfailures-all-logs` pytest plugin to re-run tests to eliminate flaky failures Mar 07, 2022 5 - Production/Stable N/A - :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Apr 26, 2023 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jul 11, 2023 N/A pytest (~=4.6) ; python_version == "2.7" + :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 Aug 31, 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 @@ -1007,7 +1009,7 @@ This list contains 1313 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 24, 2023 N/A N/A + :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 30, 2023 N/A pytest (>=7,<8) :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1032,7 +1034,7 @@ This list contains 1313 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 02, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) @@ -1040,8 +1042,8 @@ This list contains 1313 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-selenium-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 29, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 02, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 @@ -1286,7 +1288,7 @@ This list contains 1313 plugins. :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-wake` May 11, 2023 N/A pytest + :pypi:`pytest-wake` Aug 30, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 24, 2023 4 - Beta N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A @@ -1318,7 +1320,7 @@ This list contains 1313 plugins. :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (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. Aug 24, 2023 4 - Beta pytest >=7.1.0 + :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Aug 27, 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-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) @@ -2685,7 +2687,7 @@ This list contains 1313 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Jul 27, 2023, + *last release*: Sep 01, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3119,7 +3121,7 @@ This list contains 1313 plugins. A py.test plugin recording and comparing test output. :pypi:`pytest-dataset` - *last release*: May 01, 2023, + *last release*: Sep 01, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -3448,7 +3450,7 @@ This list contains 1313 plugins. Cleanup your Haystack indexes between tests :pypi:`pytest-django-ifactory` - *last release*: Jun 06, 2023, + *last release*: Aug 27, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -3539,9 +3541,9 @@ This list contains 1313 plugins. An RST Documentation Generator for pytest-based test suites :pypi:`pytest-docker` - *last release*: Jul 19, 2023, + *last release*: Sep 01, 2023, *status*: N/A, - *requires*: pytest (<8.0,>=4.0) + *requires*: pytest <8.0,>=4.0 Simple pytest fixtures for Docker and Docker Compose based tests @@ -4764,7 +4766,7 @@ This list contains 1313 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jul 24, 2023, + *last release*: Aug 30, 2023, *status*: N/A, *requires*: N/A @@ -4973,6 +4975,13 @@ This list contains 1313 plugins. Pytest Helpers Namespace Plugin + :pypi:`pytest-henry` + *last release*: Aug 29, 2023, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-hidecaptured` *last release*: May 04, 2018, *status*: 4 - Beta, @@ -5058,9 +5067,9 @@ This list contains 1313 plugins. Helpers for testing hpfeeds in your python project :pypi:`pytest-html` - *last release*: Aug 25, 2023, + *last release*: Sep 01, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (!=6.0.0,>=5.0) + *requires*: pytest>=7.0.0 pytest plugin for generating HTML reports @@ -5205,7 +5214,7 @@ This list contains 1313 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Aug 21, 2023, + *last release*: Aug 31, 2023, *status*: 3 - Alpha, *requires*: pytest (>=7.0.0,<8.0.0) @@ -6178,7 +6187,7 @@ This list contains 1313 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Jun 08, 2023, + *last release*: Sep 01, 2023, *status*: N/A, *requires*: pytest @@ -7150,6 +7159,13 @@ This list contains 1313 plugins. ASYNC Pytest plugin for Playwright + :pypi:`pytest-playwright-asyncio` + *last release*: Aug 29, 2023, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-playwrights` *last release*: Dec 02, 2021, *status*: N/A, @@ -7494,11 +7510,11 @@ This list contains 1313 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Jun 19, 2023, + *last release*: Aug 29, 2023, *status*: N/A, *requires*: pytest - "Pytest plugin for testing applications that use Pyodide" + Pytest plugin for testing applications that use Pyodide :pypi:`pytest-pypi` *last release*: Mar 04, 2018, @@ -7543,9 +7559,9 @@ This list contains 1313 plugins. Pyramid server fixture for py.test :pypi:`pytest-pyreport` - *last release*: Jul 02, 2023, + *last release*: Aug 27, 2023, *status*: N/A, - *requires*: pytest (>=7.3.1) + *requires*: pytest PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report @@ -7844,9 +7860,9 @@ This list contains 1313 plugins. Management of Pytest dependencies via regex patterns :pypi:`pytest-regressions` - *last release*: Jan 13, 2023, + *last release*: Aug 31, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.0) + *requires*: pytest >=6.2.0 Easy to use fixtures to write regression tests. @@ -8068,16 +8084,16 @@ This list contains 1313 plugins. pytest plugin to re-run tests to eliminate flaky failures :pypi:`pytest-reserial` - *last release*: Apr 26, 2023, + *last release*: Aug 31, 2023, *status*: 4 - Beta, *requires*: pytest Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Jul 11, 2023, + *last release*: Aug 31, 2023, *status*: N/A, - *requires*: pytest (~=4.6) ; python_version == "2.7" + *requires*: pytest ~=4.6 ; python_version == "2.7" Resilient Circuits fixtures for PyTest @@ -8236,9 +8252,9 @@ This list contains 1313 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest-robotframework` - *last release*: Aug 24, 2023, + *last release*: Aug 30, 2023, *status*: N/A, - *requires*: N/A + *requires*: pytest (>=7,<8) a pytest plugin that can run both python and robotframework tests while generating robot reports for them @@ -8411,7 +8427,7 @@ This list contains 1313 plugins. :pypi:`pytest-sbase` - *last release*: Aug 23, 2023, + *last release*: Sep 02, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8467,14 +8483,14 @@ This list contains 1313 plugins. pytest plugin for Selenium :pypi:`pytest-selenium-auto` - *last release*: Aug 22, 2023, + *last release*: Aug 29, 2023, *status*: N/A, *requires*: pytest >= 7.0.0 pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Aug 23, 2023, + *last release*: Sep 02, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -10189,7 +10205,7 @@ This list contains 1313 plugins. Pytest plugin for testing whatsapp bots with end to end tests :pypi:`pytest-wake` - *last release*: May 11, 2023, + *last release*: Aug 30, 2023, *status*: N/A, *requires*: pytest @@ -10413,7 +10429,7 @@ This list contains 1313 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-xvirt` - *last release*: Aug 24, 2023, + *last release*: Aug 27, 2023, *status*: 4 - Beta, *requires*: pytest >=7.1.0 From 917ce9aa0102c7f0ec8fdac118058c41ffb603e6 Mon Sep 17 00:00:00 2001 From: Israel Fruchter Date: Sun, 3 Sep 2023 20:33:54 +0300 Subject: [PATCH 0157/1271] Fix user_properties not saved to XML if fixture errors during teardown Move handling of user_properties to `finalize()`. Previously if a fixture failed during teardown, `pytest_runtest_logreport` would not be called with "teardown", resulting in the user properties not being saved on the JUnit XML file. Fixes: #11367 --- AUTHORS | 1 + changelog/11367.bugfix.rst | 1 + src/_pytest/junitxml.py | 7 ++++--- testing/test_junitxml.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 changelog/11367.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 6fa7a41eb8c..52157cc0a36 100644 --- a/AUTHORS +++ b/AUTHORS @@ -170,6 +170,7 @@ Ian Lesperance Ilya Konstantinov Ionuț Turturică Isaac Virshup +Israel Fruchter Itxaso Aizpurua Iwan Briquemont Jaap Broekhuizen diff --git a/changelog/11367.bugfix.rst b/changelog/11367.bugfix.rst new file mode 100644 index 00000000000..dda40db0fc9 --- /dev/null +++ b/changelog/11367.bugfix.rst @@ -0,0 +1 @@ +Fixed bug where `user_properties` where not being saved in the JUnit XML file if a fixture failed during teardown. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 9242d46d9df..ed259e4c41d 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -502,6 +502,10 @@ def finalize(self, report: TestReport) -> None: # Local hack to handle xdist report order. workernode = getattr(report, "node", None) reporter = self.node_reporters.pop((nodeid, workernode)) + + for propname, propvalue in report.user_properties: + reporter.add_property(propname, str(propvalue)) + if reporter is not None: reporter.finalize() @@ -599,9 +603,6 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: reporter = self._opentestcase(report) reporter.write_captured_output(report) - for propname, propvalue in report.user_properties: - reporter.add_property(propname, str(propvalue)) - self.finalize(report) report_wid = getattr(report, "worker_id", None) report_ii = getattr(report, "item_index", None) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 690830329c0..3f88c21e2b7 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1228,6 +1228,36 @@ def test_record(record_property, other): result.stdout.fnmatch_lines(["*= 1 passed in *"]) +def test_record_property_on_test_and_teardown_failure( + pytester: Pytester, run_and_parse: RunAndParse +) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def other(record_property): + record_property("bar", 1) + yield + assert 0 + + def test_record(record_property, other): + record_property("foo", "<1") + assert 0 + """ + ) + result, dom = run_and_parse() + node = dom.find_first_by_tag("testsuite") + tnodes = node.find_by_tag("testcase") + for tnode in tnodes: + psnode = tnode.find_first_by_tag("properties") + assert psnode, f"testcase didn't had expected properties:\n{tnode}" + pnodes = psnode.find_by_tag("property") + pnodes[0].assert_attr(name="bar", value="1") + pnodes[1].assert_attr(name="foo", value="<1") + result.stdout.fnmatch_lines(["*= 1 failed, 1 error *"]) + + def test_record_property_same_name( pytester: Pytester, run_and_parse: RunAndParse ) -> None: From 65c73a09e7b95e98f4f7a63bd2ec7b3161a0a781 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 08:07:56 -0300 Subject: [PATCH 0158/1271] build(deps): Bump twisted in /testing/plugins_integration (#11385) Bumps [twisted](https://github.com/twisted/twisted) from 22.8.0 to 23.8.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-22.8.0...twisted-23.8.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d46300fe0d8..42ec0f509a8 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -11,5 +11,5 @@ pytest-rerunfailures==12.0 pytest-sugar==0.9.7 pytest-trio==0.7.0 pytest-twisted==1.14.0 -twisted==22.8.0 +twisted==23.8.0 pytest-xvfb==3.0.0 From 0d8b87f161156cf4cdf356814078de58dcbe7b91 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 08:08:01 -0300 Subject: [PATCH 0159/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#11383) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 3.7.1 to 4.0.0. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/3.7.1...4.0.0) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 42ec0f509a8..4106abda3bc 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==3.7.1 +anyio[curio,trio]==4.0.0 django==4.2.4 pytest-asyncio==0.21.1 pytest-bdd==6.1.1 From 9c8937b4800c72bb511a45f4548f0c58823ec30b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 08:08:10 -0300 Subject: [PATCH 0160/1271] build(deps): Bump pytest-html in /testing/plugins_integration (#11384) Bumps [pytest-html](https://github.com/pytest-dev/pytest-html) from 3.2.0 to 4.0.0. - [Release notes](https://github.com/pytest-dev/pytest-html/releases) - [Changelog](https://github.com/pytest-dev/pytest-html/blob/master/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-html/compare/v3.2.0...4.0.0) --- updated-dependencies: - dependency-name: pytest-html dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 4106abda3bc..4850adf9b12 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -5,7 +5,7 @@ pytest-bdd==6.1.1 pytest-cov==4.1.0 pytest-django==4.5.2 pytest-flakes==4.0.5 -pytest-html==3.2.0 +pytest-html==4.0.0 pytest-mock==3.11.1 pytest-rerunfailures==12.0 pytest-sugar==0.9.7 From 8032d212715108c5187e57b5fccdd2502e716410 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 10:09:33 -0300 Subject: [PATCH 0161/1271] [pre-commit.ci] pre-commit autoupdate (#11389) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/autoflake: v2.2.0 → v2.2.1](https://github.com/PyCQA/autoflake/compare/v2.2.0...v2.2.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 82dc5dae700..509ac5212f3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: exclude: _pytest/(debugging|hookspec).py language_version: python3 - repo: https://github.com/PyCQA/autoflake - rev: v2.2.0 + rev: v2.2.1 hooks: - id: autoflake name: autoflake From 8d815ca55b054c556e4bed7e5d3d51b67db43d3e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 2 Aug 2023 22:48:30 +0300 Subject: [PATCH 0162/1271] python: type some CallSpec2 fields as immutable Knowing that a field is immutable makes it easier to understand the code. --- src/_pytest/python.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index df1eb854dd4..87990548666 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1123,9 +1123,9 @@ class CallSpec2: # arg name -> arg index. indices: Dict[str, int] = dataclasses.field(default_factory=dict) # Used for sorting parametrized resources. - _arg2scope: Dict[str, Scope] = dataclasses.field(default_factory=dict) + _arg2scope: Mapping[str, Scope] = dataclasses.field(default_factory=dict) # Parts which will be added to the item's name in `[..]` separated by "-". - _idlist: List[str] = dataclasses.field(default_factory=list) + _idlist: Sequence[str] = dataclasses.field(default_factory=tuple) # Marks which will be applied to the item. marks: List[Mark] = dataclasses.field(default_factory=list) @@ -1141,7 +1141,7 @@ def setmulti( ) -> "CallSpec2": params = self.params.copy() indices = self.indices.copy() - arg2scope = self._arg2scope.copy() + arg2scope = dict(self._arg2scope) for arg, val in zip(argnames, valset): if arg in params: raise ValueError(f"duplicate parametrization of {arg!r}") From d4872f5df75cc4a8a875fe783ae1e0307b2b8b47 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 2 Aug 2023 22:50:13 +0300 Subject: [PATCH 0163/1271] fixtures: tiny code cleanup --- src/_pytest/fixtures.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index c7fc28adbbc..88ee50adf6c 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -210,16 +210,14 @@ def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]: argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]] = {} items_by_argkey: Dict[Scope, Dict[FixtureArgKey, Deque[nodes.Item]]] = {} for scope in HIGH_SCOPES: - d: Dict[nodes.Item, Dict[FixtureArgKey, None]] = {} - argkeys_cache[scope] = d - item_d: Dict[FixtureArgKey, Deque[nodes.Item]] = defaultdict(deque) - items_by_argkey[scope] = item_d + scoped_argkeys_cache = argkeys_cache[scope] = {} + scoped_items_by_argkey = items_by_argkey[scope] = defaultdict(deque) for item in items: keys = dict.fromkeys(get_parametrized_fixture_keys(item, scope), None) if keys: - d[item] = keys + scoped_argkeys_cache[item] = keys for key in keys: - item_d[key].append(item) + scoped_items_by_argkey[key].append(item) items_dict = dict.fromkeys(items, None) return list( reorder_items_atscope(items_dict, argkeys_cache, items_by_argkey, Scope.Session) From 82bd63d318dd46e877b51beaf80c9758603aa0b1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Sep 2023 14:49:34 +0300 Subject: [PATCH 0164/1271] doctest: add `fixturenames` field to `DoctestItem` The field is used in `_fillfixtures`, in preference to `request.fixturenames`, which also includes already-computed which is not needed. --- src/_pytest/doctest.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index e6f666dda03..c3dbf84c290 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -579,9 +579,11 @@ def func() -> None: doctest_item.funcargs = {} # type: ignore[attr-defined] fm = doctest_item.session._fixturemanager - doctest_item._fixtureinfo = fm.getfixtureinfo( # type: ignore[attr-defined] + fixtureinfo = fm.getfixtureinfo( node=doctest_item, func=func, cls=None, funcargs=False ) + doctest_item._fixtureinfo = fixtureinfo # type: ignore[attr-defined] + doctest_item.fixturenames = fixtureinfo.names_closure # type: ignore[attr-defined] fixture_request = TopRequest(doctest_item, _ispytest=True) # type: ignore[arg-type] fixture_request._fillfixtures() return fixture_request From 65c01f531b45bd62c5a28a910645dbfb878d8017 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Sep 2023 14:53:36 +0300 Subject: [PATCH 0165/1271] fixtures: use the item `fixturenames` in `request.fixturenames` `_pyfuncitem.fixturenames` is just an alias for `_pyfuncitem._fixtureinfo.names_closure` (at least in core pytest), so let's do the less abstraction-breaking thing. --- src/_pytest/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 88ee50adf6c..0fefaa0d07e 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -405,7 +405,7 @@ def scope(self) -> _ScopeName: @property def fixturenames(self) -> List[str]: """Names of all active fixtures in this request.""" - result = list(self._pyfuncitem._fixtureinfo.names_closure) + result = list(self._pyfuncitem.fixturenames) result.extend(set(self._fixture_defs).difference(result)) return result From d2b5177dd666d034e982db1dd69e411fcff123dd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Sep 2023 15:01:05 +0300 Subject: [PATCH 0166/1271] fixtures: avoid some redundant work in `_fillfixtures` --- src/_pytest/fixtures.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 0fefaa0d07e..7d3c8da1114 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -685,7 +685,10 @@ def __repr__(self) -> str: def _fillfixtures(self) -> None: item = self._pyfuncitem - fixturenames = getattr(item, "fixturenames", self.fixturenames) + fixturenames = getattr(item, "fixturenames", None) + if fixturenames is None: + # Mildly expensive so don't move into the getattr! + fixturenames = self.fixturenames for argname in fixturenames: if argname not in item.funcargs: item.funcargs[argname] = self.getfixturevalue(argname) From b8906b29a758faebba775b1ad544bba537c99d69 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Sep 2023 15:13:15 +0300 Subject: [PATCH 0167/1271] fixtures: require `item.fixturenames` to exist in `_fillfixtures` I could find 2 plugins that would be broken by this (pytest-play and pytest-wdl), but they will be better served by just copying `_fillfixtures` instead of use the private function. --- src/_pytest/fixtures.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 7d3c8da1114..dee34c34871 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -685,11 +685,7 @@ def __repr__(self) -> str: def _fillfixtures(self) -> None: item = self._pyfuncitem - fixturenames = getattr(item, "fixturenames", None) - if fixturenames is None: - # Mildly expensive so don't move into the getattr! - fixturenames = self.fixturenames - for argname in fixturenames: + for argname in item.fixturenames: if argname not in item.funcargs: item.funcargs[argname] = self.getfixturevalue(argname) From 574e0f45d908cd51f81538543e9aedcaeaac6900 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Sep 2023 15:36:41 +0300 Subject: [PATCH 0168/1271] fixtures: avoid using the mildly expensive `fixturenames` property Avoid creating a list copy + 2 sets + a linear search through the list (in the common case). --- src/_pytest/fixtures.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index dee34c34871..e692c9489d2 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -791,7 +791,10 @@ def _schedule_finalizers( # If the executing fixturedef was not explicitly requested in the argument list (via # getfixturevalue inside the fixture call) then ensure this fixture def will be finished # first. - if fixturedef.argname not in self.fixturenames: + if ( + fixturedef.argname not in self._fixture_defs + and fixturedef.argname not in self._pyfuncitem.fixturenames + ): fixturedef.addfinalizer( functools.partial(self._fixturedef.finish, request=self) ) From bc71561ad9bb5d7a68f0d0da3a3ba79c5c327892 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 5 Sep 2023 08:59:44 +0300 Subject: [PATCH 0169/1271] python: avoid an Any --- src/_pytest/python.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 87990548666..e8d55c92915 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -473,7 +473,9 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]: clscol = self.getparent(Class) cls = clscol and clscol.obj or None - definition = FunctionDefinition.from_parent(self, name=name, callobj=funcobj) + definition: FunctionDefinition = FunctionDefinition.from_parent( + self, name=name, callobj=funcobj + ) fixtureinfo = definition._fixtureinfo # pytest_generate_tests impls call metafunc.parametrize() which fills From 194a782e3817ee9f4f77a7a61ec68d25b3b08250 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 5 Sep 2023 19:42:40 -0300 Subject: [PATCH 0170/1271] Fix import_path for packages (#11390) For packages, `import_path` receives the path to the package's `__init__.py` file, however module names (as they live in `sys.modules`) should not include the `__init__` part. For example, `app/core/__init__.py` should be imported as `app.core`, not as `app.core.__init__`. Fix #11306 --- changelog/11306.bugfix.rst | 1 + src/_pytest/pathlib.py | 4 ++++ testing/test_pathlib.py | 45 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 changelog/11306.bugfix.rst diff --git a/changelog/11306.bugfix.rst b/changelog/11306.bugfix.rst new file mode 100644 index 00000000000..02e0957a9c6 --- /dev/null +++ b/changelog/11306.bugfix.rst @@ -0,0 +1 @@ +Fixed bug using ``--importmode=importlib`` which would cause package ``__init__.py`` files to be imported more than once in some cases. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 138a0bdb249..7ecd93fe5e6 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -623,6 +623,10 @@ def module_name_from_path(path: Path, root: Path) -> str: # Use the parts for the relative path to the root path. path_parts = relative_path.parts + # Module name for packages do not contain the __init__ file. + if path_parts[-1] == "__init__": + path_parts = path_parts[:-1] + return ".".join(path_parts) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 3d574e85658..1ca6414375e 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -18,6 +18,7 @@ from _pytest.pathlib import get_extended_length_path_str from _pytest.pathlib import get_lock_path from _pytest.pathlib import import_path +from _pytest.pathlib import ImportMode from _pytest.pathlib import ImportPathMismatchError from _pytest.pathlib import insert_missing_modules from _pytest.pathlib import maybe_delete_a_numbered_dir @@ -585,6 +586,10 @@ def test_module_name_from_path(self, tmp_path: Path) -> None: result = module_name_from_path(Path("/home/foo/test_foo.py"), Path("/bar")) assert result == "home.foo.test_foo" + # Importing __init__.py files should return the package as module name. + result = module_name_from_path(tmp_path / "src/app/__init__.py", tmp_path) + assert result == "src.app" + def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> None: @@ -615,3 +620,43 @@ def test_parent_contains_child_module_attribute( assert sorted(modules) == ["xxx", "xxx.tests", "xxx.tests.foo"] assert modules["xxx"].tests is modules["xxx.tests"] assert modules["xxx.tests"].foo is modules["xxx.tests.foo"] + + def test_importlib_package(self, monkeypatch: MonkeyPatch, tmp_path: Path): + """ + Importing a package using --importmode=importlib should not import the + package's __init__.py file more than once (#11306). + """ + monkeypatch.chdir(tmp_path) + monkeypatch.syspath_prepend(tmp_path) + + package_name = "importlib_import_package" + tmp_path.joinpath(package_name).mkdir() + init = tmp_path.joinpath(f"{package_name}/__init__.py") + init.write_text( + dedent( + """ + from .singleton import Singleton + + instance = Singleton() + """ + ), + encoding="ascii", + ) + singleton = tmp_path.joinpath(f"{package_name}/singleton.py") + singleton.write_text( + dedent( + """ + class Singleton: + INSTANCES = [] + + def __init__(self) -> None: + self.INSTANCES.append(self) + if len(self.INSTANCES) > 1: + raise RuntimeError("Already initialized") + """ + ), + encoding="ascii", + ) + + mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) + assert len(mod.instance.INSTANCES) == 1 From 3ce63bc76874b6b60377c8f001ceb03ed5c2f34f Mon Sep 17 00:00:00 2001 From: Stefaan Lippens Date: Wed, 6 Sep 2023 12:34:38 +0200 Subject: [PATCH 0171/1271] Improve plugin list disclaimer (#11397) Closes #11391 --- AUTHORS | 1 + changelog/11391.doc.rst | 1 + doc/en/reference/plugin_list.rst | 22 +++++++++++++++++----- scripts/update-plugin-list.py | 22 +++++++++++++++++----- 4 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 changelog/11391.doc.rst diff --git a/AUTHORS b/AUTHORS index 52157cc0a36..b6bc0298866 100644 --- a/AUTHORS +++ b/AUTHORS @@ -348,6 +348,7 @@ Simon Holesch Simon Kerr Skylar Downes Srinivas Reddy Thatiparthy +Stefaan Lippens Stefan Farmbauer Stefan Scherfke Stefan Zimmermann diff --git a/changelog/11391.doc.rst b/changelog/11391.doc.rst new file mode 100644 index 00000000000..fff324af18d --- /dev/null +++ b/changelog/11391.doc.rst @@ -0,0 +1 @@ +Improved disclaimer on pytest plugin reference page to better indicate this is an automated, non-curated listing. diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 7dae208a08d..68eaf69ea55 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -3,14 +3,26 @@ .. _plugin-list: -Plugin List -=========== +Pytest Plugin List +================== -PyPI projects that match "pytest-\*" are considered plugins and are listed -automatically together with a manually-maintained list in `the source -code `_. +Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. +It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. Packages classified as inactive are excluded. +For detailed insights into how this list is generated, +please refer to `the update script `_. + +.. warning:: + + Please be aware that this list is not a curated collection of projects + and does not undergo a systematic review process. + It serves purely as an informational resource to aid in the discovery of ``pytest`` plugins. + + Do not presume any endorsement from the ``pytest`` project or its developers, + and always conduct your own quality assessment before incorporating any of these plugins into your own projects. + + .. The following conditional uses a different format for this list when creating a PDF, because otherwise the table gets far too wide for the page. diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index f345e1f7cd6..c5f918724a1 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -20,14 +20,26 @@ .. _plugin-list: -Plugin List -=========== +Pytest Plugin List +================== -PyPI projects that match "pytest-\*" are considered plugins and are listed -automatically together with a manually-maintained list in `the source -code `_. +Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. +It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. Packages classified as inactive are excluded. +For detailed insights into how this list is generated, +please refer to `the update script `_. + +.. warning:: + + Please be aware that this list is not a curated collection of projects + and does not undergo a systematic review process. + It serves purely as an informational resource to aid in the discovery of ``pytest`` plugins. + + Do not presume any endorsement from the ``pytest`` project or its developers, + and always conduct your own quality assessment before incorporating any of these plugins into your own projects. + + .. The following conditional uses a different format for this list when creating a PDF, because otherwise the table gets far too wide for the page. From f6b6478868322a5958a7cf24886257e5990c6ced Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 6 Sep 2023 15:22:27 +0200 Subject: [PATCH 0172/1271] doc: Remove done training (#11399) --- doc/en/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 73bf2e4d8df..b9331eb9adf 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,6 @@ .. sidebar:: Next Open Trainings - - `pytest: Professionelles Testen (nicht nur) für Python `_, at `Workshoptage 2023 `_, **September 5th**, `OST `_ Campus **Rapperswil, Switzerland** - `Professional Testing with Python `_, via `Python Academy `_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote** Also see :doc:`previous talks and blogposts `. From 333e4eba6b09f40f80aaeee6581a37c5af34aad7 Mon Sep 17 00:00:00 2001 From: Fraser Stark Date: Thu, 7 Sep 2023 16:11:59 +0100 Subject: [PATCH 0173/1271] Change PytestReturnNotNoneWarning to return a normal warning (#11211) Fixes #10465 --- AUTHORS | 1 + changelog/10465.deprecation.rst | 1 + changelog/11151.breaking.rst | 3 +-- src/_pytest/warning_types.py | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 changelog/10465.deprecation.rst diff --git a/AUTHORS b/AUTHORS index 5ea751bbc28..466779f6d11 100644 --- a/AUTHORS +++ b/AUTHORS @@ -143,6 +143,7 @@ Feng Ma Florian Bruhin Florian Dahlitz Floris Bruynooghe +Fraser Stark Gabriel Landau Gabriel Reis Garvit Shubham diff --git a/changelog/10465.deprecation.rst b/changelog/10465.deprecation.rst new file mode 100644 index 00000000000..a715af5e624 --- /dev/null +++ b/changelog/10465.deprecation.rst @@ -0,0 +1 @@ +Test functions returning a value other than None will now issue a :class:`pytest.PytestWarning` instead of :class:`pytest.PytestRemovedIn8Warning`, meaning this will stay a warning instead of becoming an error in the future. diff --git a/changelog/11151.breaking.rst b/changelog/11151.breaking.rst index 2e86c5dfba0..114a7d8e20b 100644 --- a/changelog/11151.breaking.rst +++ b/changelog/11151.breaking.rst @@ -1,2 +1 @@ -Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27 -`__. +Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27 `__. diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index 31726e1ce22..4219f1439a2 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -61,7 +61,7 @@ class PytestRemovedIn9Warning(PytestDeprecationWarning): __module__ = "pytest" -class PytestReturnNotNoneWarning(PytestRemovedIn8Warning): +class PytestReturnNotNoneWarning(PytestWarning): """Warning emitted when a test function is returning value other than None.""" __module__ = "pytest" From 28ccf476b91be32ffda303f0d7a8b57e475b465b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Sep 2023 12:49:25 -0300 Subject: [PATCH 0174/1271] Fix crash when passing a very long cmdline argument (#11404) Fixes #11394 --- changelog/11394.bugfix.rst | 1 + src/_pytest/main.py | 3 ++- src/_pytest/pathlib.py | 11 +++++++++++ testing/test_main.py | 31 +++++++++++++++++++++++++++++++ testing/test_pathlib.py | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 changelog/11394.bugfix.rst diff --git a/changelog/11394.bugfix.rst b/changelog/11394.bugfix.rst new file mode 100644 index 00000000000..aa89c81b01f --- /dev/null +++ b/changelog/11394.bugfix.rst @@ -0,0 +1 @@ +Fixed crash when parsing long command line arguments that might be interpreted as files. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index fd3836736ed..d979f3f500f 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -36,6 +36,7 @@ from _pytest.pathlib import absolutepath from _pytest.pathlib import bestrelpath from _pytest.pathlib import fnmatch_ex +from _pytest.pathlib import safe_exists from _pytest.pathlib import visit from _pytest.reports import CollectReport from _pytest.reports import TestReport @@ -888,7 +889,7 @@ def resolve_collection_argument( strpath = search_pypath(strpath) fspath = invocation_path / strpath fspath = absolutepath(fspath) - if not fspath.exists(): + if not safe_exists(fspath): msg = ( "module or package not found: {arg} (missing __init__.py?)" if as_pypath diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 7ecd93fe5e6..f44180f1a17 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,5 +1,6 @@ import atexit import contextlib +import errno import fnmatch import importlib.util import itertools @@ -773,3 +774,13 @@ def bestrelpath(directory: Path, dest: Path) -> str: # Forward from base to dest. *reldest.parts, ) + + +def safe_exists(p: Path) -> bool: + """Like Path.exists(), but account for input arguments that might be too long (#11394).""" + try: + return p.exists() + except OSError as e: + if e.errno == errno.ENAMETOOLONG: + return False + raise diff --git a/testing/test_main.py b/testing/test_main.py index 71597626790..3c8998c1a35 100644 --- a/testing/test_main.py +++ b/testing/test_main.py @@ -262,3 +262,34 @@ def test(fix): "* 1 passed in *", ] ) + + +def test_very_long_cmdline_arg(pytester: Pytester) -> None: + """ + Regression test for #11394. + + Note: we could not manage to actually reproduce the error with this code, we suspect + GitHub runners are configured to support very long paths, however decided to leave + the test in place in case this ever regresses in the future. + """ + pytester.makeconftest( + """ + import pytest + + def pytest_addoption(parser): + parser.addoption("--long-list", dest="long_list", action="store", default="all", help="List of things") + + @pytest.fixture(scope="module") + def specified_feeds(request): + list_string = request.config.getoption("--long-list") + return list_string.split(',') + """ + ) + pytester.makepyfile( + """ + def test_foo(specified_feeds): + assert len(specified_feeds) == 100_000 + """ + ) + result = pytester.runpytest("--long-list", ",".join(["helloworld"] * 100_000)) + result.stdout.fnmatch_lines("* 1 passed *") diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 1ca6414375e..8a9659aabd9 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1,3 +1,4 @@ +import errno import os.path import pickle import sys @@ -24,6 +25,7 @@ from _pytest.pathlib import maybe_delete_a_numbered_dir from _pytest.pathlib import module_name_from_path from _pytest.pathlib import resolve_package_path +from _pytest.pathlib import safe_exists from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit from _pytest.tmpdir import TempPathFactory @@ -660,3 +662,33 @@ def __init__(self) -> None: mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) assert len(mod.instance.INSTANCES) == 1 + + +def test_safe_exists(tmp_path: Path) -> None: + d = tmp_path.joinpath("some_dir") + d.mkdir() + assert safe_exists(d) is True + + f = tmp_path.joinpath("some_file") + f.touch() + assert safe_exists(f) is True + + # Use unittest.mock() as a context manager to have a very narrow + # patch lifetime. + p = tmp_path.joinpath("some long filename" * 100) + with unittest.mock.patch.object( + Path, + "exists", + autospec=True, + side_effect=OSError(errno.ENAMETOOLONG, "name too long"), + ): + assert safe_exists(p) is False + + with unittest.mock.patch.object( + Path, + "exists", + autospec=True, + side_effect=OSError(errno.EIO, "another kind of error"), + ): + with pytest.raises(OSError): + _ = safe_exists(p) From 5936a79fdbf69b7ba274df9bd005c8bad0e9f310 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Sep 2023 15:44:47 -0300 Subject: [PATCH 0175/1271] Use _pytest.pathlib.safe_exists in get_dirs_from_args (#11407) Related to #11394 --- src/_pytest/config/__init__.py | 9 +++------ src/_pytest/config/findpaths.py | 9 +-------- src/_pytest/pathlib.py | 9 ++++----- testing/test_pathlib.py | 5 ++--- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index cde230fdbd9..eb03b633849 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -59,6 +59,7 @@ from _pytest.pathlib import import_path from _pytest.pathlib import ImportMode from _pytest.pathlib import resolve_package_path +from _pytest.pathlib import safe_exists from _pytest.stash import Stash from _pytest.warning_types import PytestConfigWarning from _pytest.warning_types import warn_explicit_for @@ -562,12 +563,8 @@ def _set_initial_conftests( anchor = absolutepath(current / path) # Ensure we do not break if what appears to be an anchor - # is in fact a very long option (#10169). - try: - anchor_exists = anchor.exists() - except OSError: # pragma: no cover - anchor_exists = False - if anchor_exists: + # is in fact a very long option (#10169, #11394). + if safe_exists(anchor): self._try_load_conftest(anchor, importmode, rootpath) foundanchor = True if not foundanchor: diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 9c76947a466..fc30533b6e4 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -15,6 +15,7 @@ from _pytest.outcomes import fail from _pytest.pathlib import absolutepath from _pytest.pathlib import commonpath +from _pytest.pathlib import safe_exists def _parse_ini_config(path: Path) -> iniconfig.IniConfig: @@ -147,14 +148,6 @@ def get_dir_from_path(path: Path) -> Path: return path return path.parent - def safe_exists(path: Path) -> bool: - # This can throw on paths that contain characters unrepresentable at the OS level, - # or with invalid syntax on Windows (https://bugs.python.org/issue35306) - try: - return path.exists() - except OSError: - return False - # These look like paths but may not exist possible_paths = ( absolutepath(get_file_part_from_node_id(arg)) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index f44180f1a17..63b1345b46b 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,6 +1,5 @@ import atexit import contextlib -import errno import fnmatch import importlib.util import itertools @@ -780,7 +779,7 @@ def safe_exists(p: Path) -> bool: """Like Path.exists(), but account for input arguments that might be too long (#11394).""" try: return p.exists() - except OSError as e: - if e.errno == errno.ENAMETOOLONG: - return False - raise + except (ValueError, OSError): + # ValueError: stat: path too long for Windows + # OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect + return False diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 8a9659aabd9..678fd27feac 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -688,7 +688,6 @@ def test_safe_exists(tmp_path: Path) -> None: Path, "exists", autospec=True, - side_effect=OSError(errno.EIO, "another kind of error"), + side_effect=ValueError("name too long"), ): - with pytest.raises(OSError): - _ = safe_exists(p) + assert safe_exists(p) is False From 0a06db0729ef837fdbdfd25f34dbd9cc4fdb59c7 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Sep 2023 16:10:19 -0300 Subject: [PATCH 0176/1271] Merge pull request #11408 from pytest-dev/release-7.4.2 (#11409) Prepare release 7.4.2 (cherry picked from commit b0c4775a28aebcd3d3d6394ebb36838df01f809d) --- changelog/11237.bugfix.rst | 1 - changelog/11306.bugfix.rst | 1 - changelog/11367.bugfix.rst | 1 - changelog/11391.doc.rst | 1 - changelog/11394.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.2.rst | 18 ++++++++++++++++++ doc/en/builtin.rst | 2 +- doc/en/changelog.rst | 25 +++++++++++++++++++++++++ doc/en/example/reportingdemo.rst | 20 ++++++++++---------- doc/en/getting-started.rst | 2 +- 11 files changed, 56 insertions(+), 17 deletions(-) delete mode 100644 changelog/11237.bugfix.rst delete mode 100644 changelog/11306.bugfix.rst delete mode 100644 changelog/11367.bugfix.rst delete mode 100644 changelog/11391.doc.rst delete mode 100644 changelog/11394.bugfix.rst create mode 100644 doc/en/announce/release-7.4.2.rst diff --git a/changelog/11237.bugfix.rst b/changelog/11237.bugfix.rst deleted file mode 100644 index d054fc18d1c..00000000000 --- a/changelog/11237.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix doctest collection of `functools.cached_property` objects. diff --git a/changelog/11306.bugfix.rst b/changelog/11306.bugfix.rst deleted file mode 100644 index 02e0957a9c6..00000000000 --- a/changelog/11306.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed bug using ``--importmode=importlib`` which would cause package ``__init__.py`` files to be imported more than once in some cases. diff --git a/changelog/11367.bugfix.rst b/changelog/11367.bugfix.rst deleted file mode 100644 index dda40db0fc9..00000000000 --- a/changelog/11367.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed bug where `user_properties` where not being saved in the JUnit XML file if a fixture failed during teardown. diff --git a/changelog/11391.doc.rst b/changelog/11391.doc.rst deleted file mode 100644 index fff324af18d..00000000000 --- a/changelog/11391.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Improved disclaimer on pytest plugin reference page to better indicate this is an automated, non-curated listing. diff --git a/changelog/11394.bugfix.rst b/changelog/11394.bugfix.rst deleted file mode 100644 index aa89c81b01f..00000000000 --- a/changelog/11394.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed crash when parsing long command line arguments that might be interpreted as files. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 85dfa0894fe..39fdfc13776 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.2 release-7.4.1 release-7.4.0 release-7.3.2 diff --git a/doc/en/announce/release-7.4.2.rst b/doc/en/announce/release-7.4.2.rst new file mode 100644 index 00000000000..22191e7b4f9 --- /dev/null +++ b/doc/en/announce/release-7.4.2.rst @@ -0,0 +1,18 @@ +pytest-7.4.2 +======================================= + +pytest 7.4.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 0d673d0426e..405289444a8 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -105,7 +105,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:737 + doctest_namespace [session scope] -- .../_pytest/doctest.py:757 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index be7e7fabaef..ecfeeb662b6 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,31 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.2 (2023-09-07) +========================= + +Bug Fixes +--------- + +- `#11237 `_: Fix doctest collection of `functools.cached_property` objects. + + +- `#11306 `_: Fixed bug using ``--importmode=importlib`` which would cause package ``__init__.py`` files to be imported more than once in some cases. + + +- `#11367 `_: Fixed bug where `user_properties` where not being saved in the JUnit XML file if a fixture failed during teardown. + + +- `#11394 `_: Fixed crash when parsing long command line arguments that might be interpreted as files. + + + +Improved Documentation +---------------------- + +- `#11391 `_: Improved disclaimer on pytest plugin reference page to better indicate this is an automated, non-curated listing. + + pytest 7.4.1 (2023-09-02) ========================= diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index d4d3d3ce202..cb59c4b42e1 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -554,13 +554,13 @@ Here is a nice run of several failures and how ``pytest`` presents things: E AssertionError: assert False E + where False = ('456') E + where = '123'.startswith - E + where '123' = .f at 0xdeadbeef0006>() - E + and '456' = .g at 0xdeadbeef0029>() + E + where '123' = .f at 0xdeadbeef0029>() + E + and '456' = .g at 0xdeadbeef002a>() failure_demo.py:235: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -571,18 +571,18 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:238: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - self = + self = def test_instance(self): self.x = 6 * 7 > assert self.x != 42 E assert 42 != 42 - E + where 42 = .x + E + where 42 = .x failure_demo.py:242: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -592,7 +592,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:245: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -603,7 +603,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:250: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -618,7 +618,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:261: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -637,7 +637,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:268: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index c7a1ee54087..f8f9944738f 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 7.4.1 + pytest 7.4.2 .. _`simpletest`: From e5c81fa41aa437261009d2dcbed5f05bb2b86647 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 8 Sep 2023 07:22:16 -0300 Subject: [PATCH 0177/1271] Adjustments to the release process (#11410) As discussed in #11408: * Improve documentation for the release process. * Fix the description for the PRs created by the `prepare release pr` workflow. * Fix pushing tag in the `deploy` workflow. --- .github/workflows/deploy.yml | 2 ++ RELEASING.rst | 3 ++- scripts/prepare-release-pr.py | 12 +++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index dd3d5eeb481..b8a0a67a2d8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -36,8 +36,10 @@ jobs: timeout-minutes: 30 permissions: id-token: write + contents: write steps: - uses: actions/checkout@v3 + - name: Download Package uses: actions/download-artifact@v3 with: diff --git a/RELEASING.rst b/RELEASING.rst index 5d49fb5d6d9..08004a84c00 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -134,7 +134,8 @@ Releasing Both automatic and manual processes described above follow the same steps from this point onward. #. After all tests pass and the PR has been approved, trigger the ``deploy`` job - in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml. + in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml, using the ``release-MAJOR.MINOR.PATCH`` branch + as source. This job will require approval from ``pytest-dev/core``, after which it will publish to PyPI and tag the repository. diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index 7a80de7edaa..a0e5e4d7f37 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -31,10 +31,16 @@ class InvalidFeatureRelease(Exception): SLUG = "pytest-dev/pytest" PR_BODY = """\ -Created automatically from manual trigger. +Created by the [prepare release pr](https://github.com/pytest-dev/pytest/actions/workflows/prepare-release-pr.yml) +workflow. -Once all builds pass and it has been **approved** by one or more maintainers, the build -can be released by pushing a tag `{version}` to this repository. +Once all builds pass and it has been **approved** by one or more maintainers, +start the [deploy](https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml) workflow, using these parameters: + +* `Use workflow from`: `release-{version}`. +* `Release version`: `{version}`. + +After the `deploy` workflow has been approved by a core maintainer, the package will be uploaded to PyPI automatically. """ From 9c112755535400e6008c8a479a72b5f56d0687b0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 4 Sep 2023 23:31:51 +0300 Subject: [PATCH 0178/1271] fixtures: change getfixtureclosure(ignore_args) to a set Only used for containment checks so a Set is more appropriate than a list. --- src/_pytest/fixtures.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index e692c9489d2..205176f5750 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -8,6 +8,7 @@ from collections import deque from contextlib import suppress from pathlib import Path +from typing import AbstractSet from typing import Any from typing import Callable from typing import cast @@ -1382,7 +1383,7 @@ def pytest_addoption(parser: Parser) -> None: ) -def _get_direct_parametrize_args(node: nodes.Node) -> List[str]: +def _get_direct_parametrize_args(node: nodes.Node) -> Set[str]: """Return all direct parametrization arguments of a node, so we don't mistake them for fixtures. @@ -1391,14 +1392,13 @@ def _get_direct_parametrize_args(node: nodes.Node) -> List[str]: These things are done later as well when dealing with parametrization so this could be improved. """ - parametrize_argnames: List[str] = [] + parametrize_argnames: Set[str] = set() for marker in node.iter_markers(name="parametrize"): if not marker.kwargs.get("indirect", False): p_argnames, _ = ParameterSet._parse_parametrize_args( *marker.args, **marker.kwargs ) - parametrize_argnames.extend(p_argnames) - + parametrize_argnames.update(p_argnames) return parametrize_argnames @@ -1519,7 +1519,7 @@ def getfixtureclosure( self, fixturenames: Tuple[str, ...], parentnode: nodes.Node, - ignore_args: Sequence[str] = (), + ignore_args: AbstractSet[str], ) -> Tuple[Tuple[str, ...], List[str], Dict[str, Sequence[FixtureDef[Any]]]]: # Collect the closure of all fixtures, starting with the given # fixturenames as the initial set. As we have to visit all From 48b03956482e2082191bb58d707f3c004f15aa68 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Mon, 4 Sep 2023 23:44:49 +0300 Subject: [PATCH 0179/1271] fixtures: clean up getfixtureclosure() Some code cleanups - no functional changes. --- src/_pytest/fixtures.py | 51 +++++++++++++++++++++----------------- testing/python/fixtures.py | 8 ++++++ 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 205176f5750..80b965b81db 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1402,6 +1402,12 @@ def _get_direct_parametrize_args(node: nodes.Node) -> Set[str]: return parametrize_argnames +def deduplicate_names(*seqs: Iterable[str]) -> Tuple[str, ...]: + """De-duplicate the sequence of names while keeping the original order.""" + # Ideally we would use a set, but it does not preserve insertion order. + return tuple(dict.fromkeys(name for seq in seqs for name in seq)) + + class FixtureManager: """pytest fixture definitions and information is stored and managed from this class. @@ -1476,14 +1482,18 @@ def getfixtureinfo( argnames = getfuncargnames(func, name=node.name, cls=cls) else: argnames = () + usefixturesnames = self._getusefixturesnames(node) + autousenames = self._getautousenames(node.nodeid) + initialnames = deduplicate_names(autousenames, usefixturesnames, argnames) - usefixtures = tuple( - arg for mark in node.iter_markers(name="usefixtures") for arg in mark.args - ) - initialnames = usefixtures + argnames - initialnames, names_closure, arg2fixturedefs = self.getfixtureclosure( - initialnames, node, ignore_args=_get_direct_parametrize_args(node) + direct_parametrize_args = _get_direct_parametrize_args(node) + + names_closure, arg2fixturedefs = self.getfixtureclosure( + parentnode=node, + initialnames=initialnames, + ignore_args=direct_parametrize_args, ) + return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs) def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None: @@ -1515,12 +1525,17 @@ def _getautousenames(self, nodeid: str) -> Iterator[str]: if basenames: yield from basenames + def _getusefixturesnames(self, node: nodes.Item) -> Iterator[str]: + """Return the names of usefixtures fixtures applicable to node.""" + for mark in node.iter_markers(name="usefixtures"): + yield from mark.args + def getfixtureclosure( self, - fixturenames: Tuple[str, ...], parentnode: nodes.Node, + initialnames: Tuple[str, ...], ignore_args: AbstractSet[str], - ) -> Tuple[Tuple[str, ...], List[str], Dict[str, Sequence[FixtureDef[Any]]]]: + ) -> Tuple[List[str], Dict[str, Sequence[FixtureDef[Any]]]]: # Collect the closure of all fixtures, starting with the given # fixturenames as the initial set. As we have to visit all # factory definitions anyway, we also return an arg2fixturedefs @@ -1529,19 +1544,7 @@ def getfixtureclosure( # (discovering matching fixtures for a given name/node is expensive). parentid = parentnode.nodeid - fixturenames_closure = list(self._getautousenames(parentid)) - - def merge(otherlist: Iterable[str]) -> None: - for arg in otherlist: - if arg not in fixturenames_closure: - fixturenames_closure.append(arg) - - merge(fixturenames) - - # At this point, fixturenames_closure contains what we call "initialnames", - # which is a set of fixturenames the function immediately requests. We - # need to return it as well, so save this. - initialnames = tuple(fixturenames_closure) + fixturenames_closure = list(initialnames) arg2fixturedefs: Dict[str, Sequence[FixtureDef[Any]]] = {} lastlen = -1 @@ -1555,7 +1558,9 @@ def merge(otherlist: Iterable[str]) -> None: fixturedefs = self.getfixturedefs(argname, parentid) if fixturedefs: arg2fixturedefs[argname] = fixturedefs - merge(fixturedefs[-1].argnames) + for arg in fixturedefs[-1].argnames: + if arg not in fixturenames_closure: + fixturenames_closure.append(arg) def sort_by_scope(arg_name: str) -> Scope: try: @@ -1566,7 +1571,7 @@ def sort_by_scope(arg_name: str) -> Scope: return fixturedefs[-1]._scope fixturenames_closure.sort(key=sort_by_scope, reverse=True) - return initialnames, fixturenames_closure, arg2fixturedefs + return fixturenames_closure, arg2fixturedefs def pytest_generate_tests(self, metafunc: "Metafunc") -> None: """Generate new tests based on parametrized fixtures used by the given metafunc""" diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index a8f36cb9fae..775056a8e98 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -6,6 +6,7 @@ import pytest from _pytest.compat import getfuncargnames from _pytest.config import ExitCode +from _pytest.fixtures import deduplicate_names from _pytest.fixtures import TopRequest from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import get_public_names @@ -4531,3 +4532,10 @@ def test_fixt(custom): result.assert_outcomes(errors=1) result.stdout.fnmatch_lines([expected]) assert result.ret == ExitCode.TESTS_FAILED + + +def test_deduplicate_names() -> None: + items = deduplicate_names("abacd") + assert items == ("a", "b", "c", "d") + items = deduplicate_names(items + ("g", "f", "g", "e", "b")) + assert items == ("a", "b", "c", "d", "g", "f", "e") From b3a981d3859f563fa6c24d8a30e1bf76030d2968 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 8 Sep 2023 10:23:14 +0300 Subject: [PATCH 0180/1271] fixtures: remove `getfixtureinfo(funcargs)` in favor of None `func` Since we already broke plugins using this (private) interface in this version (pytest-play, pytest-wdl), might as well do a cleanup. --- src/_pytest/doctest.py | 7 +------ src/_pytest/fixtures.py | 9 +++------ src/_pytest/python.py | 5 ++--- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 46a3daa72f3..97aa5d3ddbd 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -592,14 +592,9 @@ def _from_module(self, module, object): def _setup_fixtures(doctest_item: DoctestItem) -> TopRequest: """Used by DoctestTextfile and DoctestItem to setup fixture information.""" - def func() -> None: - pass - doctest_item.funcargs = {} # type: ignore[attr-defined] fm = doctest_item.session._fixturemanager - fixtureinfo = fm.getfixtureinfo( - node=doctest_item, func=func, cls=None, funcargs=False - ) + fixtureinfo = fm.getfixtureinfo(node=doctest_item, func=None, cls=None) doctest_item._fixtureinfo = fixtureinfo # type: ignore[attr-defined] doctest_item.fixturenames = fixtureinfo.names_closure # type: ignore[attr-defined] fixture_request = TopRequest(doctest_item, _ispytest=True) # type: ignore[arg-type] diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 80b965b81db..d56274629a8 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1460,13 +1460,12 @@ def __init__(self, session: "Session") -> None: def getfixtureinfo( self, node: nodes.Item, - func: Callable[..., object], + func: Optional[Callable[..., object]], cls: Optional[type], - funcargs: bool = True, ) -> FuncFixtureInfo: """Calculate the :class:`FuncFixtureInfo` for an item. - If ``funcargs`` is false, or if the item sets an attribute + If ``func`` is None, or if the item sets an attribute ``nofuncargs = True``, then ``func`` is not examined at all. :param node: @@ -1475,10 +1474,8 @@ def getfixtureinfo( The item's function. :param cls: If the function is a method, the method's class. - :param funcargs: - Whether to look into func's parameters as fixture requests. """ - if funcargs and not getattr(node, "nofuncargs", False): + if func is not None and not getattr(node, "nofuncargs", False): argnames = getfuncargnames(func, name=node.name, cls=cls) else: argnames = () diff --git a/src/_pytest/python.py b/src/_pytest/python.py index e8d55c92915..cbb82e39090 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1800,9 +1800,8 @@ def __init__( self.keywords.update(keywords) if fixtureinfo is None: - fixtureinfo = self.session._fixturemanager.getfixtureinfo( - self, self.obj, self.cls, funcargs=True - ) + fm = self.session._fixturemanager + fixtureinfo = fm.getfixtureinfo(self, self.obj, self.cls) self._fixtureinfo: FuncFixtureInfo = fixtureinfo self.fixturenames = fixtureinfo.names_closure self._initrequest() From ab63ebb3dc07b89670b96ae97044f48406c44fa0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 8 Sep 2023 10:52:08 +0300 Subject: [PATCH 0181/1271] doctest: inline `_setup_fixtures`, make more similar to `Function` There used to be two callers to `_setup_fixtures()`, now there's only one, so inline it and make `DoctestItem` more similar to `Function`. (Eventually we may want to generalize `TopRequest` from taking `Function` directly to some "fixture-supporting item", removing the remaining `type: ignore` here and allowing plugins to do it in a stable manner). --- src/_pytest/doctest.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 97aa5d3ddbd..bc930724b30 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -261,8 +261,14 @@ def __init__( super().__init__(name, parent) self.runner = runner self.dtest = dtest + + # Stuff needed for fixture support. self.obj = None - self.fixture_request: Optional[TopRequest] = None + fm = self.session._fixturemanager + fixtureinfo = fm.getfixtureinfo(node=self, func=None, cls=None) + self._fixtureinfo = fixtureinfo + self.fixturenames = fixtureinfo.names_closure + self._initrequest() @classmethod def from_parent( # type: ignore @@ -277,11 +283,16 @@ def from_parent( # type: ignore """The public named constructor.""" return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest) + def _initrequest(self) -> None: + self.funcargs: Dict[str, object] = {} + self._request = TopRequest(self, _ispytest=True) # type: ignore[arg-type] + def setup(self) -> None: if self.dtest is not None: - self.fixture_request = _setup_fixtures(self) - globs = dict(getfixture=self.fixture_request.getfixturevalue) - for name, value in self.fixture_request.getfixturevalue( + self._request._fillfixtures() + + globs = dict(getfixture=self._request.getfixturevalue) + for name, value in self._request.getfixturevalue( "doctest_namespace" ).items(): globs[name] = value @@ -589,19 +600,6 @@ def _from_module(self, module, object): ) -def _setup_fixtures(doctest_item: DoctestItem) -> TopRequest: - """Used by DoctestTextfile and DoctestItem to setup fixture information.""" - - doctest_item.funcargs = {} # type: ignore[attr-defined] - fm = doctest_item.session._fixturemanager - fixtureinfo = fm.getfixtureinfo(node=doctest_item, func=None, cls=None) - doctest_item._fixtureinfo = fixtureinfo # type: ignore[attr-defined] - doctest_item.fixturenames = fixtureinfo.names_closure # type: ignore[attr-defined] - fixture_request = TopRequest(doctest_item, _ispytest=True) # type: ignore[arg-type] - fixture_request._fillfixtures() - return fixture_request - - def _init_checker_class() -> Type["doctest.OutputChecker"]: import doctest import re From 2ed2e9208dfc39597c122a2c1ad884aab0559783 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 8 Sep 2023 11:00:09 +0300 Subject: [PATCH 0182/1271] doctest: remove unnecessary Optionals --- src/_pytest/doctest.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index bc930724b30..f4a2d4bca07 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -255,8 +255,8 @@ def __init__( self, name: str, parent: "Union[DoctestTextfile, DoctestModule]", - runner: Optional["doctest.DocTestRunner"] = None, - dtest: Optional["doctest.DocTest"] = None, + runner: "doctest.DocTestRunner", + dtest: "doctest.DocTest", ) -> None: super().__init__(name, parent) self.runner = runner @@ -288,19 +288,13 @@ def _initrequest(self) -> None: self._request = TopRequest(self, _ispytest=True) # type: ignore[arg-type] def setup(self) -> None: - if self.dtest is not None: - self._request._fillfixtures() - - globs = dict(getfixture=self._request.getfixturevalue) - for name, value in self._request.getfixturevalue( - "doctest_namespace" - ).items(): - globs[name] = value - self.dtest.globs.update(globs) + self._request._fillfixtures() + globs = dict(getfixture=self._request.getfixturevalue) + for name, value in self._request.getfixturevalue("doctest_namespace").items(): + globs[name] = value + self.dtest.globs.update(globs) def runtest(self) -> None: - assert self.dtest is not None - assert self.runner is not None _check_all_skipped(self.dtest) self._disable_output_capturing_for_darwin() failures: List["doctest.DocTestFailure"] = [] @@ -387,7 +381,6 @@ def repr_failure( # type: ignore[override] return ReprFailDoctest(reprlocation_lines) def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: - assert self.dtest is not None return self.path, self.dtest.lineno, "[doctest] %s" % self.name From 6ad9499c9cb02846d22f6217dc54e70b2e459f2b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 8 Sep 2023 15:15:19 +0300 Subject: [PATCH 0183/1271] doctest: some missing type annotations --- src/_pytest/doctest.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index f4a2d4bca07..a0125e93c2d 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -400,8 +400,8 @@ def _get_flag_lookup() -> Dict[str, int]: ) -def get_optionflags(parent): - optionflags_str = parent.config.getini("doctest_optionflags") +def get_optionflags(config: Config) -> int: + optionflags_str = config.getini("doctest_optionflags") flag_lookup_table = _get_flag_lookup() flag_acc = 0 for flag in optionflags_str: @@ -409,8 +409,8 @@ def get_optionflags(parent): return flag_acc -def _get_continue_on_failure(config): - continue_on_failure = config.getvalue("doctest_continue_on_failure") +def _get_continue_on_failure(config: Config) -> bool: + continue_on_failure: bool = config.getvalue("doctest_continue_on_failure") if continue_on_failure: # We need to turn off this if we use pdb since we should stop at # the first failure. @@ -433,7 +433,7 @@ def collect(self) -> Iterable[DoctestItem]: name = self.path.name globs = {"__name__": "__main__"} - optionflags = get_optionflags(self) + optionflags = get_optionflags(self.config) runner = _get_runner( verbose=False, @@ -578,7 +578,7 @@ def _from_module(self, module, object): raise # Uses internal doctest module parsing mechanism. finder = MockAwareDocTestFinder() - optionflags = get_optionflags(self) + optionflags = get_optionflags(self.config) runner = _get_runner( verbose=False, optionflags=optionflags, From 7259e8db9844f6f973c1d0c0ce46cc68c8248abb Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 9 Sep 2023 14:09:31 +0200 Subject: [PATCH 0184/1271] Fix assert rewriting with assignment expressions (#11414) Fixes #11239 --- AUTHORS | 1 + changelog/11239.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 54 +++++++++++++++++++++++--------- testing/test_assertrewrite.py | 21 +++++++++++++ 4 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 changelog/11239.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 466779f6d11..e9e033c73f0 100644 --- a/AUTHORS +++ b/AUTHORS @@ -235,6 +235,7 @@ Maho Maik Figura Mandeep Bhutani Manuel Krebber +Marc Mueller Marc Schlaich Marcelo Duarte Trevisani Marcin Bachry diff --git a/changelog/11239.bugfix.rst b/changelog/11239.bugfix.rst new file mode 100644 index 00000000000..a486224cdda --- /dev/null +++ b/changelog/11239.bugfix.rst @@ -0,0 +1 @@ +Fixed ``:=`` in asserts impacting unrelated test cases. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 9bf79f1e107..258ed9f9ab0 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -13,6 +13,7 @@ import sys import tokenize import types +from collections import defaultdict from pathlib import Path from pathlib import PurePath from typing import Callable @@ -45,6 +46,10 @@ from _pytest.assertion import AssertionState +class Sentinel: + pass + + assertstate_key = StashKey["AssertionState"]() # pytest caches rewritten pycs in pycache dirs @@ -52,6 +57,9 @@ PYC_EXT = ".py" + (__debug__ and "c" or "o") PYC_TAIL = "." + PYTEST_TAG + PYC_EXT +# Special marker that denotes we have just left a scope definition +_SCOPE_END_MARKER = Sentinel() + class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader): """PEP302/PEP451 import hook which rewrites asserts.""" @@ -634,6 +642,8 @@ class AssertionRewriter(ast.NodeVisitor): .push_format_context() and .pop_format_context() which allows to build another %-formatted string while already building one. + :scope: A tuple containing the current scope used for variables_overwrite. + :variables_overwrite: A dict filled with references to variables that change value within an assert. This happens when a variable is reassigned with the walrus operator @@ -655,7 +665,10 @@ def __init__( else: self.enable_assertion_pass_hook = False self.source = source - self.variables_overwrite: Dict[str, str] = {} + self.scope: tuple[ast.AST, ...] = () + self.variables_overwrite: defaultdict[ + tuple[ast.AST, ...], Dict[str, str] + ] = defaultdict(dict) def run(self, mod: ast.Module) -> None: """Find all assert statements in *mod* and rewrite them.""" @@ -719,9 +732,17 @@ def run(self, mod: ast.Module) -> None: mod.body[pos:pos] = imports # Collect asserts. - nodes: List[ast.AST] = [mod] + self.scope = (mod,) + nodes: List[Union[ast.AST, Sentinel]] = [mod] while nodes: node = nodes.pop() + if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)): + self.scope = tuple((*self.scope, node)) + nodes.append(_SCOPE_END_MARKER) + if node == _SCOPE_END_MARKER: + self.scope = self.scope[:-1] + continue + assert isinstance(node, ast.AST) for name, field in ast.iter_fields(node): if isinstance(field, list): new: List[ast.AST] = [] @@ -992,7 +1013,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: ] ): pytest_temp = self.variable() - self.variables_overwrite[ + self.variables_overwrite[self.scope][ v.left.target.id ] = v.left # type:ignore[assignment] v.left.target.id = pytest_temp @@ -1035,17 +1056,20 @@ def visit_Call(self, call: ast.Call) -> Tuple[ast.Name, str]: new_args = [] new_kwargs = [] for arg in call.args: - if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite: - arg = self.variables_overwrite[arg.id] # type:ignore[assignment] + if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite.get( + self.scope, {} + ): + arg = self.variables_overwrite[self.scope][ + arg.id + ] # type:ignore[assignment] res, expl = self.visit(arg) arg_expls.append(expl) new_args.append(res) for keyword in call.keywords: - if ( - isinstance(keyword.value, ast.Name) - and keyword.value.id in self.variables_overwrite - ): - keyword.value = self.variables_overwrite[ + if isinstance( + keyword.value, ast.Name + ) and keyword.value.id in self.variables_overwrite.get(self.scope, {}): + keyword.value = self.variables_overwrite[self.scope][ keyword.value.id ] # type:ignore[assignment] res, expl = self.visit(keyword.value) @@ -1081,12 +1105,14 @@ def visit_Attribute(self, attr: ast.Attribute) -> Tuple[ast.Name, str]: def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: self.push_format_context() # We first check if we have overwritten a variable in the previous assert - if isinstance(comp.left, ast.Name) and comp.left.id in self.variables_overwrite: - comp.left = self.variables_overwrite[ + if isinstance( + comp.left, ast.Name + ) and comp.left.id in self.variables_overwrite.get(self.scope, {}): + comp.left = self.variables_overwrite[self.scope][ comp.left.id ] # type:ignore[assignment] if isinstance(comp.left, ast.NamedExpr): - self.variables_overwrite[ + self.variables_overwrite[self.scope][ comp.left.target.id ] = comp.left # type:ignore[assignment] left_res, left_expl = self.visit(comp.left) @@ -1106,7 +1132,7 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: and next_operand.target.id == left_res.id ): next_operand.target.id = self.variable() - self.variables_overwrite[ + self.variables_overwrite[self.scope][ left_res.id ] = next_operand # type:ignore[assignment] next_res, next_expl = self.visit(next_operand) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 08813c4dcf0..b3fd0c2f2e7 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1543,6 +1543,27 @@ def test_gt(): result.stdout.fnmatch_lines(["*assert 4 > 5", "*where 5 = add_one(4)"]) +class TestIssue11239: + def test_assertion_walrus_different_test_cases(self, pytester: Pytester) -> None: + """Regression for (#11239) + + Walrus operator rewriting would leak to separate test cases if they used the same variables. + """ + pytester.makepyfile( + """ + def test_1(): + state = {"x": 2}.get("x") + assert state is not None + + def test_2(): + db = {"x": 2} + assert (state := db.get("x")) is not None + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + + @pytest.mark.skipif( sys.maxsize <= (2**31 - 1), reason="Causes OverflowError on 32bit systems" ) From 71f265f1f32c7d9884b07f08819fb148b5b13521 Mon Sep 17 00:00:00 2001 From: Warren Markham Date: Sat, 9 Sep 2023 22:16:22 +1000 Subject: [PATCH 0185/1271] Refactor: use division operator to join paths (#11413) Starting with `resolve_package_path` and its associated tests, this refactoring seeks to make path concatenation more readable and consistent within tests/functions. As discussed in #11413: - code is free to use either `/` and `joinpath` - consistency within a function is more important than consistency across the codebase - it is nice to use `/` when it is more readable - it is nice to use `joinpath` when there is little context - be mindful that `joinpath` may be clearer when joining multiple segments --- src/_pytest/pathlib.py | 2 +- testing/test_pathlib.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 63b1345b46b..68372f67c49 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -680,7 +680,7 @@ def resolve_package_path(path: Path) -> Optional[Path]: result = None for parent in itertools.chain((path,), path.parents): if parent.is_dir(): - if not parent.joinpath("__init__.py").is_file(): + if not (parent / "__init__.py").is_file(): break if not parent.name.isidentifier(): break diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 678fd27feac..50c1d5967d2 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -345,18 +345,18 @@ def test_resolve_package_path(tmp_path: Path) -> None: (pkg / "subdir").mkdir() (pkg / "subdir/__init__.py").touch() assert resolve_package_path(pkg) == pkg - assert resolve_package_path(pkg.joinpath("subdir", "__init__.py")) == pkg + assert resolve_package_path(pkg / "subdir/__init__.py") == pkg def test_package_unimportable(tmp_path: Path) -> None: pkg = tmp_path / "pkg1-1" pkg.mkdir() pkg.joinpath("__init__.py").touch() - subdir = pkg.joinpath("subdir") + subdir = pkg / "subdir" subdir.mkdir() - pkg.joinpath("subdir/__init__.py").touch() + (pkg / "subdir/__init__.py").touch() assert resolve_package_path(subdir) == subdir - xyz = subdir.joinpath("xyz.py") + xyz = subdir / "xyz.py" xyz.touch() assert resolve_package_path(xyz) == subdir assert not resolve_package_path(pkg) From e2acc1a99b4e7d0942d7a9de57a7490ac9a3978d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 10 Sep 2023 09:57:40 -0300 Subject: [PATCH 0186/1271] Fix --import-mode=importlib when root contains `__init__.py` file (#11420) We cannot have an empty module name when importing a `__init__.py` file that is at the rootdir. Fixes #11417 --- src/_pytest/pathlib.py | 5 +++-- testing/test_pathlib.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 68372f67c49..e39b3dc8eec 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -623,8 +623,9 @@ def module_name_from_path(path: Path, root: Path) -> str: # Use the parts for the relative path to the root path. path_parts = relative_path.parts - # Module name for packages do not contain the __init__ file. - if path_parts[-1] == "__init__": + # Module name for packages do not contain the __init__ file, unless + # the `__init__.py` file is at the root. + if len(path_parts) >= 2 and path_parts[-1] == "__init__": path_parts = path_parts[:-1] return ".".join(path_parts) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 50c1d5967d2..2c5432cef0a 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -28,6 +28,7 @@ from _pytest.pathlib import safe_exists from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit +from _pytest.pytester import Pytester from _pytest.tmpdir import TempPathFactory @@ -592,6 +593,10 @@ def test_module_name_from_path(self, tmp_path: Path) -> None: result = module_name_from_path(tmp_path / "src/app/__init__.py", tmp_path) assert result == "src.app" + # Unless __init__.py file is at the root, in which case we cannot have an empty module name. + result = module_name_from_path(tmp_path / "__init__.py", tmp_path) + assert result == "__init__" + def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> None: @@ -663,6 +668,22 @@ def __init__(self) -> None: mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) assert len(mod.instance.INSTANCES) == 1 + def test_importlib_root_is_package(self, pytester: Pytester) -> None: + """ + Regression for importing a `__init__`.py file that is at the root + (#11417). + """ + pytester.makepyfile(__init__="") + pytester.makepyfile( + """ + def test_my_test(): + assert True + """ + ) + + result = pytester.runpytest("--import-mode=importlib") + result.stdout.fnmatch_lines("* 1 passed *") + def test_safe_exists(tmp_path: Path) -> None: d = tmp_path.joinpath("some_dir") From 24a6ee1ffdc85d7e6a9972cc39583e514919abc6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 10 Sep 2023 13:09:41 +0000 Subject: [PATCH 0187/1271] [automated] Update plugin list (#11422) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 82 ++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 68eaf69ea55..fdc80809450 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.1.0) + :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Sep 06, 2023 4 - Beta pytest >=6.1.0 :pypi:`pytest-aiohttp-client` Pytest \`client\` fixture for the Aiohttp Jan 10, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-aiomoto` pytest-aiomoto Jun 24, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-aioresponses` py.test integration for aioresponses Jul 29, 2021 4 - Beta pytest (>=3.5.0) @@ -66,7 +66,7 @@ This list contains 1315 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Aug 24, 2023 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Sep 05, 2023 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -85,7 +85,7 @@ This list contains 1315 plugins. :pypi:`pytest-appengine` AppEngine integration that works well with pytest-django Feb 27, 2017 N/A N/A :pypi:`pytest-appium` Pytest plugin for appium Dec 05, 2019 N/A N/A :pypi:`pytest-approvaltests` A plugin to use approvaltests with pytest May 08, 2022 4 - Beta pytest (>=7.0.1) - :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Mar 04, 2023 5 - Production/Stable pytest + :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Sep 06, 2023 5 - Production/Stable pytest :pypi:`pytest-archon` Rule your architecture like a real developer Jul 11, 2023 5 - Production/Stable pytest (>=7.2) :pypi:`pytest-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 Jan 13, 2022 4 - Beta pytest (>=4.6) @@ -244,6 +244,7 @@ This list contains 1315 plugins. :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) + :pypi:`pytest-copie` The pytest plugin for your Copier templates. Sep 07, 2023 3 - Alpha pytest :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Jun 23, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A @@ -253,7 +254,7 @@ This list contains 1315 plugins. :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' - :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Jan 30, 2023 5 - Production/Stable pytest (>=7.0) + :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Sep 08, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 26, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A @@ -477,7 +478,7 @@ This list contains 1315 plugins. :pypi:`pytest-find-dependencies` A pytest plugin to find dependencies between tests Apr 09, 2022 4 - Beta pytest (>=4.3.0) :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) - :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Jan 20, 2023 4 - Beta pytest + :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest :pypi:`pytest-fixture-config` Fixture configuration utils for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-fixture-maker` Pytest plugin to load fixtures from YAML files Sep 21, 2021 N/A N/A :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A @@ -558,7 +559,7 @@ This list contains 1315 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 25, 2023 3 - Alpha pytest ==7.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Sep 09, 2023 3 - Alpha pytest ==7.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -582,14 +583,14 @@ This list contains 1315 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Aug 02, 2023 5 - Production/Stable pytest (<8.0,>=6.0) + :pypi:`pytest-httpx` Send responses to httpx. Sep 04, 2023 5 - Production/Stable pytest <8.0,>=6.0 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Aug 31, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 - :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Aug 09, 2022 4 - Beta N/A + :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Sep 04, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A @@ -632,7 +633,7 @@ This list contains 1315 plugins. :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Jun 12, 2023 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Jul 11, 2023 4 - Beta pytest + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Sep 08, 2023 4 - Beta pytest >=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -783,7 +784,7 @@ This list contains 1315 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Aug 02, 2023 N/A pytest (==6.2.5) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Sep 08, 2023 N/A pytest (==6.2.5) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A @@ -954,7 +955,7 @@ This list contains 1315 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. Aug 04, 2023 3 - Alpha N/A + :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 05, 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-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 @@ -1021,7 +1022,7 @@ This list contains 1315 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 30, 2023 N/A pytest (>=7,<8) + :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 09, 2023 N/A pytest (>=7,<8) :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1054,7 +1055,7 @@ This list contains 1315 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 29, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-selenium-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Sep 06, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 02, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A @@ -1126,7 +1127,7 @@ This list contains 1315 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 Jul 25, 2023 N/A pytest (>5.4.0,<8) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Sep 06, 2023 N/A pytest (>5.4.0,<8) :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 07, 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 @@ -1140,7 +1141,7 @@ This list contains 1315 plugins. :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A - :pypi:`pytest-static` pytest-static May 07, 2023 1 - Planning N/A + :pypi:`pytest-static` pytest-static Sep 03, 2023 1 - Planning N/A :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A @@ -1467,9 +1468,9 @@ This list contains 1315 plugins. :pypi:`pytest-aiohttp` - *last release*: Feb 12, 2022, + *last release*: Sep 06, 2023, *status*: 4 - Beta, - *requires*: pytest (>=6.1.0) + *requires*: pytest >=6.1.0 Pytest plugin for aiohttp support @@ -1579,7 +1580,7 @@ This list contains 1315 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Aug 24, 2023, + *last release*: Sep 05, 2023, *status*: N/A, *requires*: pytest >=7.3.1 @@ -1712,7 +1713,7 @@ This list contains 1315 plugins. A plugin to use approvaltests with pytest :pypi:`pytest-approvaltests-geo` - *last release*: Mar 04, 2023, + *last release*: Sep 06, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -2824,6 +2825,13 @@ This list contains 1315 plugins. The pytest plugin for your Cookiecutter templates. 🍪 + :pypi:`pytest-copie` + *last release*: Sep 07, 2023, + *status*: 3 - Alpha, + *requires*: pytest + + The pytest plugin for your Copier templates. + :pypi:`pytest-copier` *last release*: Jun 23, 2023, *status*: 4 - Beta, @@ -2888,9 +2896,9 @@ This list contains 1315 plugins. Pytest plugin for excluding tests based on coverage data :pypi:`pytest-cpp` - *last release*: Jan 30, 2023, + *last release*: Sep 08, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.0) + *requires*: pytest >=7.0 Use pytest's runner to discover and execute C++ tests @@ -4456,8 +4464,8 @@ This list contains 1315 plugins. pytest plugin to manipulate firefox :pypi:`pytest-fixture-classes` - *last release*: Jan 20, 2023, - *status*: 4 - Beta, + *last release*: Sep 02, 2023, + *status*: 5 - Production/Stable, *requires*: pytest Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers @@ -5023,7 +5031,7 @@ This list contains 1315 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Aug 25, 2023, + *last release*: Sep 09, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.3.1 @@ -5191,9 +5199,9 @@ This list contains 1315 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Aug 02, 2023, + *last release*: Sep 04, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (<8.0,>=6.0) + *requires*: pytest <8.0,>=6.0 Send responses to httpx. @@ -5240,9 +5248,9 @@ This list contains 1315 plugins. A plugin to sent pytest results to an Ibutsu server :pypi:`pytest-icdiff` - *last release*: Aug 09, 2022, + *last release*: Sep 04, 2023, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest use icdiff for better error messages in pytest assertions @@ -5541,9 +5549,9 @@ This list contains 1315 plugins. Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: Jul 11, 2023, + *last release*: Sep 08, 2023, *status*: 4 - Beta, - *requires*: pytest + *requires*: pytest >=6.2.4 pytest plugin to integrate tests with JIRA XRAY @@ -6598,7 +6606,7 @@ This list contains 1315 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Aug 02, 2023, + *last release*: Sep 08, 2023, *status*: N/A, *requires*: pytest (==6.2.5) @@ -7795,7 +7803,7 @@ This list contains 1315 plugins. Test your README.md file :pypi:`pytest-reana` - *last release*: Aug 04, 2023, + *last release*: Sep 05, 2023, *status*: 3 - Alpha, *requires*: N/A @@ -8264,7 +8272,7 @@ This list contains 1315 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest-robotframework` - *last release*: Aug 30, 2023, + *last release*: Sep 09, 2023, *status*: N/A, *requires*: pytest (>=7,<8) @@ -8495,7 +8503,7 @@ This list contains 1315 plugins. pytest plugin for Selenium :pypi:`pytest-selenium-auto` - *last release*: Aug 29, 2023, + *last release*: Sep 06, 2023, *status*: N/A, *requires*: pytest >= 7.0.0 @@ -8999,7 +9007,7 @@ This list contains 1315 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jul 25, 2023, + *last release*: Sep 06, 2023, *status*: N/A, *requires*: pytest (>5.4.0,<8) @@ -9097,7 +9105,7 @@ This list contains 1315 plugins. A package to prevent Dependency Confusion attacks against Yandex. :pypi:`pytest-static` - *last release*: May 07, 2023, + *last release*: Sep 03, 2023, *status*: 1 - Planning, *requires*: N/A From a60c23c3d8e9109246f4fe62ade3b63cfb345d33 Mon Sep 17 00:00:00 2001 From: Aleksandr Brodin Date: Tue, 5 Sep 2023 17:54:20 +0700 Subject: [PATCH 0188/1271] fix invalid signature --- testing/python/collect.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testing/python/collect.py b/testing/python/collect.py index 0415c3fbe3f..309d7e6801a 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -776,13 +776,13 @@ def test_ordered_by_definition_order(self, pytester: Pytester) -> None: pytester.makepyfile( """\ class Test1: - def test_foo(): pass - def test_bar(): pass + def test_foo(self): pass + def test_bar(self): pass class Test2: - def test_foo(): pass + def test_foo(self): pass test_bar = Test1.test_bar class Test3(Test2): - def test_baz(): pass + def test_baz(self): pass """ ) result = pytester.runpytest("--collect-only") From 1949b09fd3416d710607eb062de442460d08d522 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 06:50:08 -0300 Subject: [PATCH 0189/1271] build(deps): Bump actions/checkout from 3 to 4 (#11429) Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/backport.yml | 2 +- .github/workflows/deploy.yml | 6 +++--- .github/workflows/prepare-release-pr.yml | 2 +- .github/workflows/test.yml | 4 ++-- .github/workflows/update-plugin-list.yml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index aa90b51e273..38ce7260278 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -22,7 +22,7 @@ jobs: pull-requests: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 persist-credentials: true diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b8a0a67a2d8..08e99e954a7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -20,7 +20,7 @@ jobs: timeout-minutes: 10 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 persist-credentials: false @@ -38,7 +38,7 @@ jobs: id-token: write contents: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Download Package uses: actions/download-artifact@v3 @@ -67,7 +67,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 persist-credentials: false diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index 76bf14d7e56..ce8130c86a2 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -27,7 +27,7 @@ jobs: pull-requests: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 726dbf0f8cd..450d8e99ad4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,7 +30,7 @@ jobs: package: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 persist-credentials: false @@ -167,7 +167,7 @@ jobs: use_coverage: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 persist-credentials: false diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index bbce63f7b78..ff148e10891 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -20,7 +20,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 From e0d04bdfabf9869c43add446116f0c5c78d9f746 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 06:50:32 -0300 Subject: [PATCH 0190/1271] build(deps): Bump django in /testing/plugins_integration (#11430) Bumps [django](https://github.com/django/django) from 4.2.4 to 4.2.5. - [Commits](https://github.com/django/django/compare/4.2.4...4.2.5) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 4850adf9b12..56029613baf 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.0.0 -django==4.2.4 +django==4.2.5 pytest-asyncio==0.21.1 pytest-bdd==6.1.1 pytest-cov==4.1.0 From 39f930635786fc34abea812dc2473c95631610e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 06:50:46 -0300 Subject: [PATCH 0191/1271] build(deps): Bump pytest-html in /testing/plugins_integration (#11431) Bumps [pytest-html](https://github.com/pytest-dev/pytest-html) from 4.0.0 to 4.0.1. - [Release notes](https://github.com/pytest-dev/pytest-html/releases) - [Changelog](https://github.com/pytest-dev/pytest-html/blob/master/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-html/compare/4.0.0...4.0.1) --- updated-dependencies: - dependency-name: pytest-html dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 56029613baf..6a13925ac4e 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -5,7 +5,7 @@ pytest-bdd==6.1.1 pytest-cov==4.1.0 pytest-django==4.5.2 pytest-flakes==4.0.5 -pytest-html==4.0.0 +pytest-html==4.0.1 pytest-mock==3.11.1 pytest-rerunfailures==12.0 pytest-sugar==0.9.7 From 241f2a890e3fb3f83eac807de0b4ad00510c7f65 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 11 Sep 2023 09:22:56 -0300 Subject: [PATCH 0192/1271] Force terminal width when running tests (#11425) Related to #11423 --- testing/conftest.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/testing/conftest.py b/testing/conftest.py index 926a1d5d364..06116fee49d 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -22,6 +22,15 @@ def restore_tracing(): sys.settrace(orig_trace) +@pytest.fixture(autouse=True) +def set_column_width(monkeypatch: pytest.MonkeyPatch) -> None: + """ + Force terminal width to 80: some tests check the formatting of --help, which is sensible + to terminal width. + """ + monkeypatch.setenv("COLUMNS", "80") + + @pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_collection_modifyitems(items) -> Generator[None, None, None]: """Prefer faster tests. From fcb8e73288ba0f3ed88524a1c95413b4cd0efd0c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 08:37:19 -0300 Subject: [PATCH 0193/1271] [pre-commit.ci] pre-commit autoupdate (#11434) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 509ac5212f3..5a31c4a201a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 23.7.0 + rev: 23.9.1 hooks: - id: black args: [--safe, --quiet] From 6c2feb75d2c4bb01aa145f8b85f7fb09fe4133cf Mon Sep 17 00:00:00 2001 From: pomponchik <34486915+pomponchik@users.noreply.github.com> Date: Wed, 13 Sep 2023 01:17:20 +0300 Subject: [PATCH 0194/1271] Add flask_fixture to the manual plugin list Fixes #11435 --- scripts/update-plugin-list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index c5f918724a1..46f22ad1e08 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -57,6 +57,7 @@ ADDITIONAL_PROJECTS = { # set of additional projects to consider as plugins "logassert", "nuts", + "flask_fixture", } From f43a8db618a7f0ef9c44a403993cab758eb16ef0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 15 Sep 2023 10:38:58 +0300 Subject: [PATCH 0195/1271] Improve pluggy-related typing --- src/_pytest/config/__init__.py | 6 +++--- src/_pytest/config/compat.py | 39 ++++++++++++++++++++++------------ src/_pytest/main.py | 21 ++++++++++++------ src/_pytest/nodes.py | 13 ++++-------- 4 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index eb03b633849..447ebc42abb 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -37,6 +37,7 @@ from typing import TYPE_CHECKING from typing import Union +import pluggy from pluggy import HookimplMarker from pluggy import HookimplOpts from pluggy import HookspecMarker @@ -46,6 +47,7 @@ import _pytest._code import _pytest.deprecated import _pytest.hookspec +from .compat import PathAwareHookProxy from .exceptions import PrintHelp as PrintHelp from .exceptions import UsageError as UsageError from .findpaths import determine_setup @@ -1005,10 +1007,8 @@ def __init__( # Deprecated alias. Was never public. Can be removed in a few releases. self._store = self.stash - from .compat import PathAwareHookProxy - self.trace = self.pluginmanager.trace.root.get("config") - self.hook = PathAwareHookProxy(self.pluginmanager.hook) + self.hook: pluggy.HookRelay = PathAwareHookProxy(self.pluginmanager.hook) # type: ignore[assignment] self._inicache: Dict[str, Any] = {} self._override_ini: Sequence[str] = () self._opt2dest: Dict[str, str] = {} diff --git a/src/_pytest/config/compat.py b/src/_pytest/config/compat.py index 5bd922a4a87..afb38bbcc62 100644 --- a/src/_pytest/config/compat.py +++ b/src/_pytest/config/compat.py @@ -1,15 +1,18 @@ +from __future__ import annotations + import functools import warnings from pathlib import Path -from typing import Optional +from typing import Mapping + +import pluggy from ..compat import LEGACY_PATH from ..compat import legacy_path from ..deprecated import HOOK_LEGACY_PATH_ARG -from _pytest.nodes import _check_path # hookname: (Path, LEGACY_PATH) -imply_paths_hooks = { +imply_paths_hooks: Mapping[str, tuple[str, str]] = { "pytest_ignore_collect": ("collection_path", "path"), "pytest_collect_file": ("file_path", "path"), "pytest_pycollect_makemodule": ("module_path", "path"), @@ -18,6 +21,14 @@ } +def _check_path(path: Path, fspath: LEGACY_PATH) -> None: + if Path(fspath) != path: + raise ValueError( + f"Path({fspath!r}) != {path!r}\n" + "if both path and fspath are given they need to be equal" + ) + + class PathAwareHookProxy: """ this helper wraps around hook callers @@ -27,24 +38,24 @@ class PathAwareHookProxy: this may have to be changed later depending on bugs """ - def __init__(self, hook_caller): - self.__hook_caller = hook_caller + def __init__(self, hook_relay: pluggy.HookRelay) -> None: + self._hook_relay = hook_relay - def __dir__(self): - return dir(self.__hook_caller) + def __dir__(self) -> list[str]: + return dir(self._hook_relay) - def __getattr__(self, key, _wraps=functools.wraps): - hook = getattr(self.__hook_caller, key) + def __getattr__(self, key: str) -> pluggy.HookCaller: + hook: pluggy.HookCaller = getattr(self._hook_relay, key) if key not in imply_paths_hooks: self.__dict__[key] = hook return hook else: path_var, fspath_var = imply_paths_hooks[key] - @_wraps(hook) + @functools.wraps(hook) def fixed_hook(**kw): - path_value: Optional[Path] = kw.pop(path_var, None) - fspath_value: Optional[LEGACY_PATH] = kw.pop(fspath_var, None) + path_value: Path | None = kw.pop(path_var, None) + fspath_value: LEGACY_PATH | None = kw.pop(fspath_var, None) if fspath_value is not None: warnings.warn( HOOK_LEGACY_PATH_ARG.format( @@ -65,6 +76,8 @@ def fixed_hook(**kw): kw[fspath_var] = fspath_value return hook(**kw) + fixed_hook.name = hook.name # type: ignore[attr-defined] + fixed_hook.spec = hook.spec # type: ignore[attr-defined] fixed_hook.__name__ = key self.__dict__[key] = fixed_hook - return fixed_hook + return fixed_hook # type: ignore[return-value] diff --git a/src/_pytest/main.py b/src/_pytest/main.py index d979f3f500f..5cee8e89b26 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -7,6 +7,7 @@ import os import sys from pathlib import Path +from typing import AbstractSet from typing import Callable from typing import Dict from typing import final @@ -22,6 +23,8 @@ from typing import TYPE_CHECKING from typing import Union +import pluggy + import _pytest._code from _pytest import nodes from _pytest.config import Config @@ -31,6 +34,7 @@ from _pytest.config import PytestPluginManager from _pytest.config import UsageError from _pytest.config.argparsing import Parser +from _pytest.config.compat import PathAwareHookProxy from _pytest.fixtures import FixtureManager from _pytest.outcomes import exit from _pytest.pathlib import absolutepath @@ -429,11 +433,15 @@ def pytest_collection_modifyitems(items: List[nodes.Item], config: Config) -> No class FSHookProxy: - def __init__(self, pm: PytestPluginManager, remove_mods) -> None: + def __init__( + self, + pm: PytestPluginManager, + remove_mods: AbstractSet[object], + ) -> None: self.pm = pm self.remove_mods = remove_mods - def __getattr__(self, name: str): + def __getattr__(self, name: str) -> pluggy.HookCaller: x = self.pm.subset_hook_caller(name, remove_plugins=self.remove_mods) self.__dict__[name] = x return x @@ -546,7 +554,7 @@ def isinitpath(self, path: Union[str, "os.PathLike[str]"]) -> bool: path_ = path if isinstance(path, Path) else Path(path) return path_ in self._initialpaths - def gethookproxy(self, fspath: "os.PathLike[str]"): + def gethookproxy(self, fspath: "os.PathLike[str]") -> pluggy.HookRelay: # Optimization: Path(Path(...)) is much slower than isinstance. path = fspath if isinstance(fspath, Path) else Path(fspath) pm = self.config.pluginmanager @@ -563,11 +571,10 @@ def gethookproxy(self, fspath: "os.PathLike[str]"): ) my_conftestmodules = pm._getconftestmodules(path) remove_mods = pm._conftest_plugins.difference(my_conftestmodules) + proxy: pluggy.HookRelay if remove_mods: - # One or more conftests are not in use at this fspath. - from .config.compat import PathAwareHookProxy - - proxy = PathAwareHookProxy(FSHookProxy(pm, remove_mods)) + # One or more conftests are not in use at this path. + proxy = PathAwareHookProxy(FSHookProxy(pm, remove_mods)) # type: ignore[arg-type,assignment] else: # All plugins are active for this fspath. proxy = self.config.hook diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index cb8907fe8bb..c06fa8ecd6d 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -19,6 +19,8 @@ from typing import TypeVar from typing import Union +import pluggy + import _pytest._code from _pytest._code import getfslineno from _pytest._code.code import ExceptionInfo @@ -27,6 +29,7 @@ from _pytest.compat import LEGACY_PATH from _pytest.config import Config from _pytest.config import ConftestImportFailure +from _pytest.config.compat import _check_path from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH from _pytest.deprecated import NODE_CTOR_FSPATH_ARG from _pytest.mark.structures import Mark @@ -94,14 +97,6 @@ def iterparentnodeids(nodeid: str) -> Iterator[str]: yield nodeid -def _check_path(path: Path, fspath: LEGACY_PATH) -> None: - if Path(fspath) != path: - raise ValueError( - f"Path({fspath!r}) != {path!r}\n" - "if both path and fspath are given they need to be equal" - ) - - def _imply_path( node_type: Type["Node"], path: Optional[Path], @@ -264,7 +259,7 @@ def from_parent(cls, parent: "Node", **kw): return cls._create(parent=parent, **kw) @property - def ihook(self): + def ihook(self) -> pluggy.HookRelay: """fspath-sensitive hook proxy used to call pytest hooks.""" return self.session.gethookproxy(self.path) From ab8f5ce7f46593b0d7217ea75c1c919fa51b1ea7 Mon Sep 17 00:00:00 2001 From: Mihail Milushev Date: Sun, 10 Sep 2023 12:24:18 +0100 Subject: [PATCH 0196/1271] Add new `ExceptionInfo.group_contains` assertion helper method Tests if a captured exception group contains an expected exception. Will raise `AssertionError` if the wrapped exception is not an exception group. Supports recursive search into nested exception groups. --- AUTHORS | 1 + changelog/10441.feature.rst | 2 ++ src/_pytest/_code/code.py | 65 ++++++++++++++++++++++++++++++++---- testing/code/test_excinfo.py | 59 ++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 changelog/10441.feature.rst diff --git a/AUTHORS b/AUTHORS index e9e033c73f0..16918b40c06 100644 --- a/AUTHORS +++ b/AUTHORS @@ -266,6 +266,7 @@ Michal Wajszczuk Michał Zięba Mickey Pashov Mihai Capotă +Mihail Milushev Mike Hoyle (hoylemd) Mike Lundy Milan Lesnek diff --git a/changelog/10441.feature.rst b/changelog/10441.feature.rst new file mode 100644 index 00000000000..0019926ac4d --- /dev/null +++ b/changelog/10441.feature.rst @@ -0,0 +1,2 @@ +Added :func:`ExceptionInfo.group_contains() `, an assertion +helper that tests if an `ExceptionGroup` contains a matching exception. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index b73c8bbb3da..48a8685bd97 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -697,6 +697,14 @@ def getrepr( ) return fmt.repr_excinfo(self) + def _stringify_exception(self, exc: BaseException) -> str: + return "\n".join( + [ + str(exc), + *getattr(exc, "__notes__", []), + ] + ) + def match(self, regexp: Union[str, Pattern[str]]) -> "Literal[True]": """Check whether the regular expression `regexp` matches the string representation of the exception using :func:`python:re.search`. @@ -704,12 +712,7 @@ def match(self, regexp: Union[str, Pattern[str]]) -> "Literal[True]": If it matches `True` is returned, otherwise an `AssertionError` is raised. """ __tracebackhide__ = True - value = "\n".join( - [ - str(self.value), - *getattr(self.value, "__notes__", []), - ] - ) + value = self._stringify_exception(self.value) msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" if regexp == value: msg += "\n Did you mean to `re.escape()` the regex?" @@ -717,6 +720,56 @@ def match(self, regexp: Union[str, Pattern[str]]) -> "Literal[True]": # Return True to allow for "assert excinfo.match()". return True + def _group_contains( + self, + exc_group: BaseExceptionGroup[BaseException], + expected_exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], + match: Union[str, Pattern[str], None], + recursive: bool = False, + ) -> bool: + """Return `True` if a `BaseExceptionGroup` contains a matching exception.""" + for exc in exc_group.exceptions: + if recursive and isinstance(exc, BaseExceptionGroup): + if self._group_contains(exc, expected_exception, match, recursive): + return True + if not isinstance(exc, expected_exception): + continue + if match is not None: + value = self._stringify_exception(exc) + if not re.search(match, value): + continue + return True + return False + + def group_contains( + self, + expected_exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], + match: Union[str, Pattern[str], None] = None, + recursive: bool = False, + ) -> bool: + """Check whether a captured exception group contains a matching exception. + + :param Type[BaseException] | Tuple[Type[BaseException]] expected_exception: + The expected exception type, or a tuple if one of multiple possible + exception types are expected. + + :param str | Pattern[str] | None match: + If specified, a string containing a regular expression, + or a regular expression object, that is tested against the string + representation of the exception and its `PEP-678 ` `__notes__` + using :func:`re.search`. + + To match a literal string that may contain :ref:`special characters + `, the pattern can first be escaped with :func:`re.escape`. + + :param bool recursive: + If `True`, search will descend recursively into any nested exception groups. + If `False`, only the top exception group will be searched. + """ + msg = "Captured exception is not an instance of `BaseExceptionGroup`" + assert isinstance(self.value, BaseExceptionGroup), msg + return self._group_contains(self.value, expected_exception, match, recursive) + @dataclasses.dataclass class FormattedExcinfo: diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 90f81123e01..4e6e89a209e 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -27,6 +27,9 @@ if TYPE_CHECKING: from _pytest._code.code import _TracebackStyle +if sys.version_info[:2] < (3, 11): + from exceptiongroup import ExceptionGroup + @pytest.fixture def limited_recursion_depth(): @@ -444,6 +447,62 @@ def test_division_zero(): result.stdout.re_match_lines([r".*__tracebackhide__ = True.*", *match]) +class TestGroupContains: + def test_contains_exception_type(self) -> None: + exc_group = ExceptionGroup("", [RuntimeError()]) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert exc_info.group_contains(RuntimeError) + + def test_doesnt_contain_exception_type(self) -> None: + exc_group = ExceptionGroup("", [ValueError()]) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert not exc_info.group_contains(RuntimeError) + + def test_contains_exception_match(self) -> None: + exc_group = ExceptionGroup("", [RuntimeError("exception message")]) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert exc_info.group_contains(RuntimeError, match=r"^exception message$") + + def test_doesnt_contain_exception_match(self) -> None: + exc_group = ExceptionGroup("", [RuntimeError("message that will not match")]) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert not exc_info.group_contains(RuntimeError, match=r"^exception message$") + + def test_contains_exception_type_recursive(self) -> None: + exc_group = ExceptionGroup("", [ExceptionGroup("", [RuntimeError()])]) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert exc_info.group_contains(RuntimeError, recursive=True) + + def test_doesnt_contain_exception_type_nonrecursive(self) -> None: + exc_group = ExceptionGroup("", [ExceptionGroup("", [RuntimeError()])]) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert not exc_info.group_contains(RuntimeError) + + def test_contains_exception_match_recursive(self) -> None: + exc_group = ExceptionGroup( + "", [ExceptionGroup("", [RuntimeError("exception message")])] + ) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert exc_info.group_contains( + RuntimeError, match=r"^exception message$", recursive=True + ) + + def test_doesnt_contain_exception_match_nonrecursive(self) -> None: + exc_group = ExceptionGroup( + "", [ExceptionGroup("", [RuntimeError("message that will not match")])] + ) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert not exc_info.group_contains(RuntimeError, match=r"^exception message$") + + class TestFormattedExcinfo: @pytest.fixture def importasmod(self, tmp_path: Path, _sys_snapshot): From a47fcb48733e586b4e674ca6d21a392678c0f85c Mon Sep 17 00:00:00 2001 From: Mihail Milushev Date: Fri, 15 Sep 2023 13:36:04 +0100 Subject: [PATCH 0197/1271] code review: kwarg-only `match`, replace `recursive` with `depth` --- src/_pytest/_code/code.py | 29 ++++++++++++++++------ testing/code/test_excinfo.py | 48 +++++++++++++++++++++++++++++------- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 48a8685bd97..0288d7a54f5 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -725,13 +725,22 @@ def _group_contains( exc_group: BaseExceptionGroup[BaseException], expected_exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], match: Union[str, Pattern[str], None], - recursive: bool = False, + target_depth: Optional[int] = None, + current_depth: int = 1, ) -> bool: """Return `True` if a `BaseExceptionGroup` contains a matching exception.""" + if (target_depth is not None) and (current_depth > target_depth): + # already descended past the target depth + return False for exc in exc_group.exceptions: - if recursive and isinstance(exc, BaseExceptionGroup): - if self._group_contains(exc, expected_exception, match, recursive): + if isinstance(exc, BaseExceptionGroup): + if self._group_contains( + exc, expected_exception, match, target_depth, current_depth + 1 + ): return True + if (target_depth is not None) and (current_depth != target_depth): + # not at the target depth, no match + continue if not isinstance(exc, expected_exception): continue if match is not None: @@ -744,8 +753,9 @@ def _group_contains( def group_contains( self, expected_exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], + *, match: Union[str, Pattern[str], None] = None, - recursive: bool = False, + depth: Optional[int] = None, ) -> bool: """Check whether a captured exception group contains a matching exception. @@ -762,13 +772,16 @@ def group_contains( To match a literal string that may contain :ref:`special characters `, the pattern can first be escaped with :func:`re.escape`. - :param bool recursive: - If `True`, search will descend recursively into any nested exception groups. - If `False`, only the top exception group will be searched. + :param Optional[int] depth: + If `None`, will search for a matching exception at any nesting depth. + If >= 1, will only match an exception if it's at the specified depth (depth = 1 being + the exceptions contained within the topmost exception group). """ msg = "Captured exception is not an instance of `BaseExceptionGroup`" assert isinstance(self.value, BaseExceptionGroup), msg - return self._group_contains(self.value, expected_exception, match, recursive) + msg = "`depth` must be >= 1 if specified" + assert (depth is None) or (depth >= 1), msg + return self._group_contains(self.value, expected_exception, match, depth) @dataclasses.dataclass diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 4e6e89a209e..89beefce547 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -472,35 +472,65 @@ def test_doesnt_contain_exception_match(self) -> None: raise exc_group assert not exc_info.group_contains(RuntimeError, match=r"^exception message$") - def test_contains_exception_type_recursive(self) -> None: + def test_contains_exception_type_unlimited_depth(self) -> None: exc_group = ExceptionGroup("", [ExceptionGroup("", [RuntimeError()])]) with pytest.raises(ExceptionGroup) as exc_info: raise exc_group - assert exc_info.group_contains(RuntimeError, recursive=True) + assert exc_info.group_contains(RuntimeError) - def test_doesnt_contain_exception_type_nonrecursive(self) -> None: + def test_contains_exception_type_at_depth_1(self) -> None: + exc_group = ExceptionGroup("", [RuntimeError()]) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert exc_info.group_contains(RuntimeError, depth=1) + + def test_doesnt_contain_exception_type_past_depth(self) -> None: exc_group = ExceptionGroup("", [ExceptionGroup("", [RuntimeError()])]) with pytest.raises(ExceptionGroup) as exc_info: raise exc_group - assert not exc_info.group_contains(RuntimeError) + assert not exc_info.group_contains(RuntimeError, depth=1) - def test_contains_exception_match_recursive(self) -> None: + def test_contains_exception_type_specific_depth(self) -> None: + exc_group = ExceptionGroup("", [ExceptionGroup("", [RuntimeError()])]) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert exc_info.group_contains(RuntimeError, depth=2) + + def test_contains_exception_match_unlimited_depth(self) -> None: exc_group = ExceptionGroup( "", [ExceptionGroup("", [RuntimeError("exception message")])] ) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert exc_info.group_contains(RuntimeError, match=r"^exception message$") + + def test_contains_exception_match_at_depth_1(self) -> None: + exc_group = ExceptionGroup("", [RuntimeError("exception message")]) with pytest.raises(ExceptionGroup) as exc_info: raise exc_group assert exc_info.group_contains( - RuntimeError, match=r"^exception message$", recursive=True + RuntimeError, match=r"^exception message$", depth=1 ) - def test_doesnt_contain_exception_match_nonrecursive(self) -> None: + def test_doesnt_contain_exception_match_past_depth(self) -> None: exc_group = ExceptionGroup( - "", [ExceptionGroup("", [RuntimeError("message that will not match")])] + "", [ExceptionGroup("", [RuntimeError("exception message")])] ) with pytest.raises(ExceptionGroup) as exc_info: raise exc_group - assert not exc_info.group_contains(RuntimeError, match=r"^exception message$") + assert not exc_info.group_contains( + RuntimeError, match=r"^exception message$", depth=1 + ) + + def test_contains_exception_match_specific_depth(self) -> None: + exc_group = ExceptionGroup( + "", [ExceptionGroup("", [RuntimeError("exception message")])] + ) + with pytest.raises(ExceptionGroup) as exc_info: + raise exc_group + assert exc_info.group_contains( + RuntimeError, match=r"^exception message$", depth=2 + ) class TestFormattedExcinfo: From e7caaa0b3ee60ebb4aa446156f080053dd6a2d03 Mon Sep 17 00:00:00 2001 From: Mihail Milushev Date: Sun, 17 Sep 2023 22:26:58 +0100 Subject: [PATCH 0198/1271] Document the new `ExceptionInfo.group_contains()` method --- doc/en/getting-started.rst | 24 ++++++++++++++++++++ doc/en/how-to/assert.rst | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index f8f9944738f..8d37612df7b 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -97,6 +97,30 @@ Use the :ref:`raises ` helper to assert that some code raises an e with pytest.raises(SystemExit): f() +You can also use the context provided by :ref:`raises ` to +assert that an expected exception is part of a raised ``ExceptionGroup``: + +.. code-block:: python + + # content of test_exceptiongroup.py + import pytest + + + def f(): + raise ExceptionGroup( + "Group message", + [ + RuntimeError(), + ], + ) + + + def test_exception_in_group(): + with pytest.raises(ExceptionGroup) as excinfo: + f() + assert excinfo.group_contains(RuntimeError) + assert not excinfo.group_contains(TypeError) + Execute the test function with “quiet” reporting mode: .. code-block:: pytest diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index d99a1ce5c97..f52ddc27820 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -119,6 +119,52 @@ The regexp parameter of the ``match`` method is matched with the ``re.search`` function, so in the above example ``match='123'`` would have worked as well. +You can also use the :func:`excinfo.group_contains() ` +method to test for exceptions returned as part of an ``ExceptionGroup``: + +.. code-block:: python + + def test_exception_in_group(): + with pytest.raises(RuntimeError) as excinfo: + raise ExceptionGroup( + "Group message", + [ + RuntimeError("Exception 123 raised"), + ], + ) + assert excinfo.group_contains(RuntimeError, match=r".* 123 .*") + assert not excinfo.group_contains(TypeError) + +The optional ``match`` keyword parameter works the same way as for +:func:`pytest.raises`. + +By default ``group_contains()`` will recursively search for a matching +exception at any level of nested ``ExceptionGroup`` instances. You can +specify a ``depth`` keyword parameter if you only want to match an +exception at a specific level; exceptions contained directly in the top +``ExceptionGroup`` would match ``depth=1``. + +.. code-block:: python + + def test_exception_in_group_at_given_depth(): + with pytest.raises(RuntimeError) as excinfo: + raise ExceptionGroup( + "Group message", + [ + RuntimeError(), + ExceptionGroup( + "Nested group", + [ + TypeError(), + ], + ), + ], + ) + assert excinfo.group_contains(RuntimeError, depth=1) + assert excinfo.group_contains(TypeError, depth=2) + assert not excinfo.group_contains(RuntimeError, depth=2) + assert not excinfo.group_contains(TypeError, depth=1) + There's an alternate form of the :func:`pytest.raises` function where you pass a function that will be executed with the given ``*args`` and ``**kwargs`` and assert that the given exception is raised: From 5ace48ca5bc701d01cb50d30ca945234c26d5f17 Mon Sep 17 00:00:00 2001 From: Mihail Milushev Date: Sun, 17 Sep 2023 22:27:36 +0100 Subject: [PATCH 0199/1271] Fix a minor mistake in docs ("``match`` method" is actually talking about the `match` keyword parameter) --- doc/en/how-to/assert.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index f52ddc27820..cc53d001f70 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -115,7 +115,7 @@ that a regular expression matches on the string representation of an exception with pytest.raises(ValueError, match=r".* 123 .*"): myfunc() -The regexp parameter of the ``match`` method is matched with the ``re.search`` +The regexp parameter of the ``match`` parameter is matched with the ``re.search`` function, so in the above example ``match='123'`` would have worked as well. From 8062743f6b03f43d2c06d4c6a4b4b0a9bf91b5ea Mon Sep 17 00:00:00 2001 From: Chris Mahoney <44449504+chrimaho@users.noreply.github.com> Date: Mon, 18 Sep 2023 22:34:05 +1000 Subject: [PATCH 0200/1271] Change deprecated_call to handle FutureWarning (#11448) Fixes #11447 --- changelog/11447.improvement.rst | 1 + src/_pytest/recwarn.py | 6 ++++-- testing/test_recwarn.py | 3 +-- 3 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 changelog/11447.improvement.rst diff --git a/changelog/11447.improvement.rst b/changelog/11447.improvement.rst new file mode 100644 index 00000000000..96be8dffe60 --- /dev/null +++ b/changelog/11447.improvement.rst @@ -0,0 +1 @@ +:func:`pytest.deprecated_call` now also considers warnings of type :class:`FutureWarning`. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 5484d6f3b33..d1d83ea2a13 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -56,7 +56,7 @@ def deprecated_call( # noqa: F811 def deprecated_call( # noqa: F811 func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any ) -> Union["WarningsRecorder", Any]: - """Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning``. + """Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning`` or ``FutureWarning``. This function can be used as a context manager:: @@ -82,7 +82,9 @@ def deprecated_call( # noqa: F811 __tracebackhide__ = True if func is not None: args = (func,) + args - return warns((DeprecationWarning, PendingDeprecationWarning), *args, **kwargs) + return warns( + (DeprecationWarning, PendingDeprecationWarning, FutureWarning), *args, **kwargs + ) @overload diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 8b70c8afffa..19a1cd534f1 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -192,7 +192,7 @@ def f(): f() @pytest.mark.parametrize( - "warning_type", [PendingDeprecationWarning, DeprecationWarning] + "warning_type", [PendingDeprecationWarning, DeprecationWarning, FutureWarning] ) @pytest.mark.parametrize("mode", ["context_manager", "call"]) @pytest.mark.parametrize("call_f_first", [True, False]) @@ -221,7 +221,6 @@ def test_deprecated_call_specificity(self) -> None: UserWarning, SyntaxWarning, RuntimeWarning, - FutureWarning, ImportWarning, UnicodeWarning, ] From 5e081162df925200adee1cfb2fbe4b6832081d16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 11:10:48 -0300 Subject: [PATCH 0201/1271] build(deps): Bump pytest-html in /testing/plugins_integration (#11449) Bumps [pytest-html](https://github.com/pytest-dev/pytest-html) from 4.0.1 to 4.0.2. - [Release notes](https://github.com/pytest-dev/pytest-html/releases) - [Changelog](https://github.com/pytest-dev/pytest-html/blob/master/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-html/compare/4.0.1...4.0.2) --- updated-dependencies: - dependency-name: pytest-html dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 6a13925ac4e..fe17b8816d1 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -5,7 +5,7 @@ pytest-bdd==6.1.1 pytest-cov==4.1.0 pytest-django==4.5.2 pytest-flakes==4.0.5 -pytest-html==4.0.1 +pytest-html==4.0.2 pytest-mock==3.11.1 pytest-rerunfailures==12.0 pytest-sugar==0.9.7 From 8bac8d7807a5fb9f716d1b59e2af860ec59480da Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:20:47 -0300 Subject: [PATCH 0202/1271] [automated] Update plugin list (#11443) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 170 +++++++++++++++++++------------ 1 file changed, 105 insertions(+), 65 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index fdc80809450..793ece8e035 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Aug 09, 2023 5 - Production/Stable pytest <8.0.0,>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Sep 13, 2023 5 - Production/Stable pytest <8.0.0,>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -108,6 +108,7 @@ This list contains 1316 plugins. :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进行自定义 Sep 14, 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 @@ -244,7 +245,7 @@ This list contains 1316 plugins. :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) - :pypi:`pytest-copie` The pytest plugin for your Copier templates. Sep 07, 2023 3 - Alpha pytest + :pypi:`pytest-copie` The pytest plugin for your Copier templates. Sep 10, 2023 3 - Alpha pytest :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Jun 23, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A @@ -396,18 +397,18 @@ This list contains 1316 plugins. :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Jan 08, 2020 5 - Production/Stable N/A :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest - :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Aug 03, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Sep 13, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest - :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jul 09, 2023 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jul 09, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jul 09, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jul 09, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jul 09, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jul 09, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jul 09, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Sep 13, 2023 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Sep 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Sep 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Sep 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Sep 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Sep 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Sep 13, 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) @@ -430,7 +431,7 @@ This list contains 1316 plugins. :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 - :pypi:`pytest-excel` pytest plugin for generating excel reports Jul 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest :pypi:`pytest-executable` pytest plugin for testing executables Mar 25, 2023 N/A pytest (<8,>=4.3) @@ -524,7 +525,7 @@ This list contains 1316 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Aug 30, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Sep 13, 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 Jun 22, 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 @@ -534,6 +535,7 @@ This list contains 1316 plugins. :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A + :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Sep 15, 2023 4 - Beta pytest >=2.6.0 :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest :pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest @@ -550,7 +552,7 @@ This list contains 1316 plugins. :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Jun 10, 2022 5 - Production/Stable N/A :pypi:`pytest-helm-chart` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Jun 15, 2020 4 - Beta pytest (>=5.4.2,<6.0.0) - :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Mar 08, 2023 4 - Beta pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Sep 13, 2023 4 - Beta pytest (>=7.1.2,<8.0.0) :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) @@ -559,7 +561,7 @@ This list contains 1316 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Sep 09, 2023 3 - Alpha pytest ==7.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Sep 13, 2023 3 - Alpha pytest ==7.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -567,7 +569,7 @@ This list contains 1316 plugins. :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Sep 01, 2023 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-html` pytest plugin for generating HTML reports Sep 14, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Apr 03, 2022 N/A N/A @@ -583,7 +585,7 @@ This list contains 1316 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Sep 04, 2023 5 - Production/Stable pytest <8.0,>=6.0 + :pypi:`pytest-httpx` Send responses to httpx. Sep 11, 2023 5 - Production/Stable pytest ==7.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest @@ -600,6 +602,7 @@ This list contains 1316 plugins. :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 + :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A @@ -616,7 +619,7 @@ This list contains 1316 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. Jul 14, 2023 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Sep 14, 2023 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 02, 2023 5 - Production/Stable pytest (<7.2.0,>=6) :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A @@ -649,13 +652,14 @@ This list contains 1316 plugins. :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-keep-together` Pytest plugin to customize test ordering by running all 'related' tests together Dec 07, 2022 5 - Production/Stable pytest :pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Sep 14, 2023 N/A pytest (>=7.1) :pypi:`pytest-kind` Kubernetes test support with KIND for pytest Nov 30, 2022 5 - Production/Stable N/A :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A :pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A - :pypi:`pytest-kubernetes` May 17, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-kwparametrize` Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks Jan 22, 2021 N/A pytest (>=6) :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. Aug 20, 2022 3 - Alpha pytest (>=3.6,<8) :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A @@ -716,7 +720,7 @@ This list contains 1316 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Jul 16, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) + :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Sep 10, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 @@ -931,7 +935,7 @@ This list contains 1316 plugins. :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvista` Pytest-pyvista package Mar 19, 2023 4 - Beta pytest>=3.5.0 - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 11, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) :pypi:`pytest-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) @@ -1022,7 +1026,7 @@ This list contains 1316 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 09, 2023 N/A pytest (>=7,<8) + :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 13, 2023 N/A pytest (>=7,<8) :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1047,7 +1051,7 @@ This list contains 1316 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 02, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 15, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) @@ -1056,7 +1060,7 @@ This list contains 1316 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Sep 06, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 02, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 15, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 @@ -1110,14 +1114,14 @@ This list contains 1316 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Aug 12, 2023 N/A pytest >=7.0.0 + :pypi:`pytest-sort` Tools for sorting test cases Sep 11, 2023 N/A pytest >=7.0.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest :pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A :pypi:`pytest-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. Jun 26, 2022 N/A pytest (>7.0) + :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-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 @@ -1128,7 +1132,7 @@ This list contains 1316 plugins. :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 Sep 06, 2023 N/A pytest (>5.4.0,<8) - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 07, 2023 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Sep 15, 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 @@ -1226,7 +1230,7 @@ This list contains 1316 plugins. :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A :pypi:`pytest-timer` A timer plugin for pytest Jun 02, 2021 N/A N/A :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A - :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Apr 01, 2023 N/A pytest (>=5.2) + :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) :pypi:`pytest-tipsi-django` Nov 17, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Nov 04, 2020 4 - Beta pytest (>=3.3.0) @@ -1248,7 +1252,7 @@ This list contains 1316 plugins. :pypi:`pytest-tornasync` py.test plugin for testing Python 3.5+ Tornado code Jul 15, 2019 3 - Alpha pytest (>=3.0) :pypi:`pytest-trace` Save OpenTelemetry spans generated during testing Jun 19, 2022 N/A pytest (>=4.6) :pypi:`pytest-track` Feb 26, 2021 3 - Alpha pytest (>=3.0) - :pypi:`pytest-translations` Test your translation files. Nov 05, 2021 5 - Production/Stable N/A + :pypi:`pytest-translations` Test your translation files. Sep 11, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-travis-fold` Folds captured output sections in Travis CI build log Nov 29, 2017 4 - Beta pytest (>=2.6.0) :pypi:`pytest-trello` Plugin for py.test that integrates trello using markers Nov 20, 2015 5 - Production/Stable N/A :pypi:`pytest-trepan` Pytest plugin for trepan debugger. Jul 28, 2018 5 - Production/Stable N/A @@ -1270,8 +1274,9 @@ This list contains 1316 plugins. :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest :pypi:`pytest-ui-failed-screenshot` UI自动测试失败时自动截图,并将截图加入到测试报告中 Dec 06, 2022 N/A N/A :pypi:`pytest-ui-failed-screenshot-allure` UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 Dec 06, 2022 N/A N/A - :pypi:`pytest-unflakable` Unflakable plugin for PyTest Mar 24, 2023 4 - Beta pytest (>=6.2.0) + :pypi:`pytest-unflakable` Unflakable plugin for PyTest Sep 10, 2023 4 - Beta pytest >=6.2.0 :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) + :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) @@ -1608,7 +1613,7 @@ This list contains 1316 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Aug 09, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, *requires*: pytest <8.0.0,>=6 @@ -1873,6 +1878,13 @@ This list contains 1316 plugins. Database testing fixtures using the SQLAlchemy asyncio API + :pypi:`pytest-atf-allure` + *last release*: Sep 14, 2023, + *status*: N/A, + *requires*: pytest (>=7.4.2,<8.0.0) + + 基于allure-pytest进行自定义 + :pypi:`pytest-atomic` *last release*: Nov 24, 2018, *status*: 4 - Beta, @@ -2826,7 +2838,7 @@ This list contains 1316 plugins. The pytest plugin for your Cookiecutter templates. 🍪 :pypi:`pytest-copie` - *last release*: Sep 07, 2023, + *last release*: Sep 10, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -3890,9 +3902,9 @@ This list contains 1316 plugins. Pytest plugin to select test using Ekstazi algorithm :pypi:`pytest-elasticsearch` - *last release*: Aug 03, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2) + *requires*: pytest >=7.0 Elasticsearch fixtures and fixture factories for Pytest. @@ -3925,49 +3937,49 @@ This list contains 1316 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jul 09, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jul 09, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jul 09, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jul 09, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jul 09, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jul 09, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jul 09, 2023, + *last release*: Sep 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4128,7 +4140,7 @@ This list contains 1316 plugins. Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-excel` - *last release*: Jul 20, 2023, + *last release*: Sep 14, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4786,7 +4798,7 @@ This list contains 1316 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Aug 30, 2023, + *last release*: Sep 13, 2023, *status*: N/A, *requires*: N/A @@ -4855,6 +4867,13 @@ This list contains 1316 plugins. Parallelize pytest across GitLab CI workers. + :pypi:`pytest-gitlab-fold` + *last release*: Sep 15, 2023, + *status*: 4 - Beta, + *requires*: pytest >=2.6.0 + + Folds output sections in GitLab CI build log + :pypi:`pytest-git-selector` *last release*: Nov 17, 2022, *status*: N/A, @@ -4968,7 +4987,7 @@ This list contains 1316 plugins. A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. :pypi:`pytest-helm-charts` - *last release*: Mar 08, 2023, + *last release*: Sep 13, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.1.2,<8.0.0) @@ -5031,7 +5050,7 @@ This list contains 1316 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Sep 09, 2023, + *last release*: Sep 13, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.3.1 @@ -5087,7 +5106,7 @@ This list contains 1316 plugins. Helpers for testing hpfeeds in your python project :pypi:`pytest-html` - *last release*: Sep 01, 2023, + *last release*: Sep 14, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -5199,9 +5218,9 @@ This list contains 1316 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Sep 04, 2023, + *last release*: Sep 11, 2023, *status*: 5 - Production/Stable, - *requires*: pytest <8.0,>=6.0 + *requires*: pytest ==7.* Send responses to httpx. @@ -5317,6 +5336,13 @@ This list contains 1316 plugins. pytest plugin to collect information from tests + :pypi:`pytest-info-plugin` + *last release*: Sep 14, 2023, + *status*: N/A, + *requires*: N/A + + Get executed interface information in pytest interface automation framework + :pypi:`pytest-informative-node` *last release*: Apr 25, 2019, *status*: 4 - Beta, @@ -5430,7 +5456,7 @@ This list contains 1316 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Jul 14, 2023, + *last release*: Sep 14, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5660,6 +5686,13 @@ This list contains 1316 plugins. + :pypi:`pytest-keyring` + *last release*: Sep 14, 2023, + *status*: N/A, + *requires*: pytest (>=7.1) + + A Pytest plugin to access the system's keyring to provide credentials for tests + :pypi:`pytest-kind` *last release*: Nov 30, 2022, *status*: 5 - Production/Stable, @@ -5703,7 +5736,7 @@ This list contains 1316 plugins. pytest krtech common library :pypi:`pytest-kubernetes` - *last release*: May 17, 2023, + *last release*: Sep 14, 2023, *status*: N/A, *requires*: pytest (>=7.2.1,<8.0.0) @@ -6130,9 +6163,9 @@ This list contains 1316 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: Jul 16, 2023, + *last release*: Sep 10, 2023, *status*: 4 - Beta, - *requires*: pytest (!=6.0.0,<8,>=3.3.2) + *requires*: pytest !=6.0.0,<8,>=3.3.2 A pytest plugin to make a test results report with Markdown table format. @@ -7635,7 +7668,7 @@ This list contains 1316 plugins. Pytest-pyvista package :pypi:`pytest-qaseio` - *last release*: May 11, 2023, + *last release*: Sep 12, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.2.2,<8.0.0) @@ -8272,7 +8305,7 @@ This list contains 1316 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest-robotframework` - *last release*: Sep 09, 2023, + *last release*: Sep 13, 2023, *status*: N/A, *requires*: pytest (>=7,<8) @@ -8447,7 +8480,7 @@ This list contains 1316 plugins. :pypi:`pytest-sbase` - *last release*: Sep 02, 2023, + *last release*: Sep 15, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8510,7 +8543,7 @@ This list contains 1316 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Sep 02, 2023, + *last release*: Sep 15, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8888,7 +8921,7 @@ This list contains 1316 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Aug 12, 2023, + *last release*: Sep 11, 2023, *status*: N/A, *requires*: pytest >=7.0.0 @@ -8937,7 +8970,7 @@ This list contains 1316 plugins. Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. :pypi:`pytest-spec2md` - *last release*: Jun 26, 2022, + *last release*: Sep 15, 2023, *status*: N/A, *requires*: pytest (>7.0) @@ -9014,7 +9047,7 @@ This list contains 1316 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Mar 07, 2023, + *last release*: Sep 15, 2023, *status*: N/A, *requires*: N/A @@ -9700,9 +9733,9 @@ This list contains 1316 plugins. Pytest plugin to add a timestamp prefix to the pytest output :pypi:`pytest-timestamps` - *last release*: Apr 01, 2023, + *last release*: Sep 11, 2023, *status*: N/A, - *requires*: pytest (>=5.2) + *requires*: pytest (>=7.3,<8.0) A simple plugin to view timestamps for each test @@ -9854,9 +9887,9 @@ This list contains 1316 plugins. :pypi:`pytest-translations` - *last release*: Nov 05, 2021, + *last release*: Sep 11, 2023, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest (>=7) Test your translation files. @@ -10008,9 +10041,9 @@ This list contains 1316 plugins. UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 :pypi:`pytest-unflakable` - *last release*: Mar 24, 2023, + *last release*: Sep 10, 2023, *status*: 4 - Beta, - *requires*: pytest (>=6.2.0) + *requires*: pytest >=6.2.0 Unflakable plugin for PyTest @@ -10021,6 +10054,13 @@ This list contains 1316 plugins. Plugin for py.test set a different exit code on uncaught exceptions + :pypi:`pytest-unique` + *last release*: Sep 15, 2023, + *status*: N/A, + *requires*: pytest (>=7.4.2,<8.0.0) + + Pytest fixture to generate unique values. + :pypi:`pytest-unittest-filter` *last release*: Jan 12, 2019, *status*: 4 - Beta, From 9a58e6283dc499eca722ac7929fde0f32c43031f Mon Sep 17 00:00:00 2001 From: Sharad Nair <134932980+SharadNair7@users.noreply.github.com> Date: Mon, 18 Sep 2023 22:20:04 +0530 Subject: [PATCH 0203/1271] Fixes issue #11314 - log_file_format does not default to log_format (#11444) * Fixes issue #11314 - * Incorporated review comments for issue #11314 * Update changelog/11314.improvement.rst Co-authored-by: Bruno Oliveira --------- Co-authored-by: Zac Hatfield-Dodds Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/11314.improvement.rst | 2 + src/_pytest/logging.py | 8 ++-- testing/logging/test_reporting.py | 67 +++++++++++++++++++++++++++++-- 4 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 changelog/11314.improvement.rst diff --git a/AUTHORS b/AUTHORS index 16918b40c06..00157e8abff 100644 --- a/AUTHORS +++ b/AUTHORS @@ -345,6 +345,7 @@ Segev Finer Serhii Mozghovyi Seth Junot Shantanu Jain +Sharad Nair Shubham Adep Simon Gomizelj Simon Holesch diff --git a/changelog/11314.improvement.rst b/changelog/11314.improvement.rst new file mode 100644 index 00000000000..272af21f528 --- /dev/null +++ b/changelog/11314.improvement.rst @@ -0,0 +1,2 @@ +Logging to a file using the ``--log-file`` option will use ``--log-level``, ``--log-format`` and ``--log-date-format`` as fallback +if ``--log-file-level``, ``--log-file-format`` and ``--log-file-date-format`` are not provided respectively. diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 245b7aed06c..bacca4b2aa9 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -303,13 +303,13 @@ def add_option_ini(option, dest, default=None, type=None, **kwargs): add_option_ini( "--log-file-format", dest="log_file_format", - default=DEFAULT_LOG_FORMAT, + default=None, help="Log format used by the logging module", ) add_option_ini( "--log-file-date-format", dest="log_file_date_format", - default=DEFAULT_LOG_DATE_FORMAT, + default=None, help="Log date format used by the logging module", ) add_option_ini( @@ -635,7 +635,9 @@ def __init__(self, config: Config) -> None: self.report_handler.setFormatter(self.formatter) # File logging. - self.log_file_level = get_log_level_for_setting(config, "log_file_level") + self.log_file_level = get_log_level_for_setting( + config, "log_file_level", "log_level" + ) log_file = get_option_ini(config, "log_file") or os.devnull if log_file != os.devnull: directory = os.path.dirname(os.path.abspath(log_file)) diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 8c1e4f8cc19..5d10688a00e 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -77,14 +77,14 @@ def test_foo(): assert "warning text going to logger" not in stdout assert "info text going to logger" not in stdout - # The log file should contain the warning and the error log messages and - # not the info one, because the default level of the root logger is - # WARNING. + # The log file should only contain the error log messages and + # not the warning or info ones, because the root logger is set to + # ERROR using --log-level=ERROR. assert os.path.isfile(log_file) with open(log_file, encoding="utf-8") as rfh: contents = rfh.read() assert "info text going to logger" not in contents - assert "warning text going to logger" in contents + assert "warning text going to logger" not in contents assert "error text going to logger" in contents @@ -1331,3 +1331,62 @@ def test_foo(): result.stdout.re_match_lines( [r"^[0-9-]{10} [0-9:]{8}.[0-9]{6}[+-][0-9\.]+; WARNING; text"] ) + + +def test_log_file_cli_fallback_options(pytester: Pytester) -> None: + """Make sure that fallback values for log-file formats and level works.""" + pytester.makepyfile( + """ + import logging + logger = logging.getLogger() + + def test_foo(): + logger.info('info text going to logger') + logger.warning('warning text going to logger') + logger.error('error text going to logger') + + assert 0 + """ + ) + log_file = str(pytester.path.joinpath("pytest.log")) + result = pytester.runpytest( + "--log-level=ERROR", + "--log-format=%(asctime)s %(message)s", + "--log-date-format=%H:%M", + "--log-file=pytest.log", + ) + assert result.ret == 1 + + # The log file should only contain the error log messages + # not the warning or info ones and the format and date format + # should match the formats provided using --log-format and --log-date-format + assert os.path.isfile(log_file) + with open(log_file, encoding="utf-8") as rfh: + contents = rfh.read() + assert re.match(r"[0-9]{2}:[0-9]{2} error text going to logger\s*", contents) + assert "info text going to logger" not in contents + assert "warning text going to logger" not in contents + assert "error text going to logger" in contents + + # Try with a different format and date format to make sure that the formats + # are being used + result = pytester.runpytest( + "--log-level=ERROR", + "--log-format=%(asctime)s : %(message)s", + "--log-date-format=%H:%M:%S", + "--log-file=pytest.log", + ) + assert result.ret == 1 + + # The log file should only contain the error log messages + # not the warning or info ones and the format and date format + # should match the formats provided using --log-format and --log-date-format + assert os.path.isfile(log_file) + with open(log_file, encoding="utf-8") as rfh: + contents = rfh.read() + assert re.match( + r"[0-9]{2}:[0-9]{2}:[0-9]{2} : error text going to logger\s*", contents + ) + assert "info text going to logger" not in contents + assert "warning text going to logger" not in contents + assert "error text going to logger" in contents From 9f22d3281c707b42526ed5a781670b33c7cba1b1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:51:41 +0200 Subject: [PATCH 0204/1271] [pre-commit.ci] pre-commit autoupdate (#11451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/reorder-python-imports: v3.10.0 → v3.11.0](https://github.com/asottile/reorder-python-imports/compare/v3.10.0...v3.11.0) - [github.com/asottile/pyupgrade: v3.10.1 → v3.11.0](https://github.com/asottile/pyupgrade/compare/v3.10.1...v3.11.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5a31c4a201a..afc67b32640 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,12 +37,12 @@ repos: - flake8-typing-imports==1.12.0 - flake8-docstrings==1.5.0 - repo: https://github.com/asottile/reorder-python-imports - rev: v3.10.0 + rev: v3.11.0 hooks: - id: reorder-python-imports args: ['--application-directories=.:src', --py38-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.10.1 + rev: v3.11.0 hooks: - id: pyupgrade args: [--py38-plus] From a38ad254ef955fbb2f784b42d93eb30350b26957 Mon Sep 17 00:00:00 2001 From: Simon Blanchard Date: Wed, 20 Sep 2023 20:06:43 +0800 Subject: [PATCH 0205/1271] Handle ValueError raised during faulthandler teardown code (#11453) Fixes #11439 --- AUTHORS | 1 + changelog/11439.bugfix.rst | 1 + src/_pytest/faulthandler.py | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 changelog/11439.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 00157e8abff..f8c66cae945 100644 --- a/AUTHORS +++ b/AUTHORS @@ -347,6 +347,7 @@ Seth Junot Shantanu Jain Sharad Nair Shubham Adep +Simon Blanchard Simon Gomizelj Simon Holesch Simon Kerr diff --git a/changelog/11439.bugfix.rst b/changelog/11439.bugfix.rst new file mode 100644 index 00000000000..b5104b1bcab --- /dev/null +++ b/changelog/11439.bugfix.rst @@ -0,0 +1 @@ +Handle an edge case where :data:`sys.stderr` might already be closed when :ref:`faulthandler` is tearing down. diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index 2dc672c8d7f..a9418f34e11 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -1,4 +1,3 @@ -import io import os import sys from typing import Generator @@ -51,7 +50,7 @@ def get_stderr_fileno() -> int: if fileno == -1: raise AttributeError() return fileno - except (AttributeError, io.UnsupportedOperation): + except (AttributeError, ValueError): # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file. # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors # This is potentially dangerous, but the best we can do. From d2b214220f63e1fc90120495d600893cfba6219f Mon Sep 17 00:00:00 2001 From: Warren Markham Date: Wed, 20 Sep 2023 22:08:07 +1000 Subject: [PATCH 0206/1271] Add class docstring to NodeMeta (#11427) --- src/_pytest/nodes.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index cb8907fe8bb..2b2dff2466e 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -127,6 +127,20 @@ def _imply_path( class NodeMeta(type): + """Metaclass used by :class:`Node` to enforce that direct construction raises + :class:`Failed`. + + This behaviour supports the indirection introduced with :meth:`Node.from_parent`, + the named constructor to be used instead of direct construction. The design + decision to enforce indirection with :class:`NodeMeta` was made as a + temporary aid for refactoring the collection tree, which was diagnosed to + have :class:`Node` objects whose creational patterns were overly entangled. + Once the refactoring is complete, this metaclass can be removed. + + See https://github.com/pytest-dev/pytest/projects/3 for an overview of the + progress on detangling the :class:`Node` classes. + """ + def __call__(self, *k, **kw): msg = ( "Direct construction of {name} has been deprecated, please use {name}.from_parent.\n" From c614590ec995d14119694ee7c53101cb43cbc6d1 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 24 Sep 2023 00:18:30 +0000 Subject: [PATCH 0207/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 136 +++++++++++++++++-------------- 1 file changed, 76 insertions(+), 60 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 793ece8e035..82ce198d795 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6,<8) :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) - :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Aug 15, 2023 N/A N/A + :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Sep 21, 2023 N/A N/A :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-adf` Pytest plugin for writing Azure Data Factory integration tests May 10, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) @@ -77,7 +77,7 @@ This list contains 1321 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 Dec 08, 2022 N/A pytest ; extra == 'test' + :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-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 @@ -167,7 +167,7 @@ This list contains 1321 plugins. :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A :pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest - :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Jun 23, 2023 5 - Production/Stable pytest (>=7.1.0) + :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Sep 23, 2023 5 - Production/Stable pytest >=7.1.0 :pypi:`pytest-bugtong-tag` pytest-bugtong-tag is a plugin for pytest Jan 16, 2022 N/A N/A :pypi:`pytest-bugzilla` py.test bugzilla integration plugin May 05, 2010 4 - Beta N/A :pypi:`pytest-bugzilla-notifier` A plugin that allows you to execute create, update, and read information from BugZilla bugs Jun 15, 2018 4 - Beta pytest (>=2.9.2) @@ -196,7 +196,7 @@ This list contains 1321 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Aug 11, 2023 N/A pytest + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Sep 22, 2023 N/A pytest :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Jul 22, 2020 5 - Production/Stable pytest (>=2.9.2) :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -525,7 +525,7 @@ This list contains 1321 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Sep 13, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Sep 19, 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 Jun 22, 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 @@ -566,13 +566,14 @@ This list contains 1321 plugins. :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-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. Sep 19, 2023 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) :pypi:`pytest-html` pytest plugin for generating HTML reports Sep 14, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-html-merger` Pytest HTML reports merging utility Apr 03, 2022 N/A N/A + :pypi:`pytest-html-merger` Pytest HTML reports merging utility Sep 23, 2023 N/A N/A :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Mar 04, 2022 5 - Production/Stable N/A :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A @@ -585,14 +586,14 @@ This list contains 1321 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Sep 11, 2023 5 - Production/Stable pytest ==7.* + :pypi:`pytest-httpx` Send responses to httpx. Sep 18, 2023 5 - Production/Stable pytest ==7.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Aug 31, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 - :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Sep 04, 2023 4 - Beta pytest + :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Sep 20, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A @@ -664,7 +665,6 @@ This list contains 1321 plugins. :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. Aug 20, 2022 3 - Alpha pytest (>=3.6,<8) :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A :pypi:`pytest-langchain` Pytest-style test runner for langchain agents Feb 26, 2023 N/A pytest - :pypi:`pytest-lark` A package for enhancing pytest Nov 20, 2022 N/A N/A :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) @@ -780,7 +780,7 @@ This list contains 1321 plugins. :pypi:`pytest-ndb` Open Source Software Health Report Jul 19, 2023 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jul 06, 2023 N/A pytest (>=3.5.0) + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Sep 21, 2023 N/A pytest <7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -788,7 +788,7 @@ This list contains 1321 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Sep 08, 2023 N/A pytest (==6.2.5) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Sep 18, 2023 N/A pytest (==6.2.5) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A @@ -815,7 +815,7 @@ This list contains 1321 plugins. :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) - :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Mar 15, 2023 N/A pytest + :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Sep 23, 2023 N/A pytest :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Jun 02, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest :pypi:`pytest-optional` include/exclude values of fixtures in pytest Oct 07, 2015 N/A N/A @@ -1026,7 +1026,7 @@ This list contains 1321 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 13, 2023 N/A pytest (>=7,<8) + :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 21, 2023 N/A pytest (>=7,<8) :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1045,13 +1045,13 @@ This list contains 1321 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 Jul 31, 2023 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-salt-factories` Pytest Salt Plugin Sep 20, 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. Sep 15, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 20, 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) @@ -1060,7 +1060,7 @@ This list contains 1321 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Sep 06, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 15, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 20, 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-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 @@ -1069,7 +1069,7 @@ This list contains 1321 plugins. :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Jul 26, 2023 3 - Alpha pytest (>=6.2) + :pypi:`pytest-servers` pytest servers Sep 22, 2023 3 - Alpha pytest >=6.2 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1114,7 +1114,7 @@ This list contains 1321 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Sep 11, 2023 N/A pytest >=7.0.0 + :pypi:`pytest-sort` Tools for sorting test cases Sep 23, 2023 N/A pytest >=7.0.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest @@ -1128,6 +1128,7 @@ This list contains 1321 plugins. :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Jun 11, 2022 6 - Mature pytest (<8.0,>=7.1.2) :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Apr 12, 2023 4 - Beta pytest (>=5,<8) + :pypi:`pytest-split-ext` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Sep 23, 2023 4 - Beta pytest (>=5,<8) :pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-split-tests-tresorit` Feb 22, 2021 1 - Planning N/A @@ -1161,7 +1162,7 @@ This list contains 1321 plugins. :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) - :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Aug 29, 2017 N/A N/A + :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Apr 10, 2023 4 - Beta pytest (>=6.2.0) :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A @@ -1194,6 +1195,8 @@ This list contains 1321 plugins. :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A :pypi:`pytest-testinfra` Test infrastructures Aug 24, 2023 5 - Production/Stable pytest !=3.0.2 + :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 Jul 13, 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) @@ -1313,7 +1316,6 @@ This list contains 1321 plugins. :pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable Jun 05, 2023 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -1332,7 +1334,7 @@ This list contains 1321 plugins. :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jul 03, 2023 N/A pytest<8,>=7.4.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest - :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Jan 05, 2023 4 - Beta pytest (>=2.8) + :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Sep 23, 2023 4 - Beta pytest (>=2.8) :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) @@ -1403,7 +1405,7 @@ This list contains 1321 plugins. pytest plugin for generating test execution results within Jira Test Management (tm4j) :pypi:`pytest-adaptavist-fixed` - *last release*: Aug 15, 2023, + *last release*: Sep 21, 2023, *status*: N/A, *requires*: N/A @@ -1662,8 +1664,8 @@ This list contains 1321 plugins. Pytest fixtures to assert anything and something :pypi:`pytest-aoc` - *last release*: Dec 08, 2022, - *status*: N/A, + *last release*: Sep 19, 2023, + *status*: 5 - Production/Stable, *requires*: pytest ; extra == 'test' Downloads puzzle inputs for Advent of Code and synthesizes PyTest fixtures @@ -2292,9 +2294,9 @@ This list contains 1321 plugins. Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. :pypi:`pytest-bug` - *last release*: Jun 23, 2023, + *last release*: Sep 23, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.1.0) + *requires*: pytest >=7.1.0 Pytest plugin for marking tests as a bug @@ -2495,7 +2497,7 @@ This list contains 1321 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Aug 11, 2023, + *last release*: Sep 22, 2023, *status*: N/A, *requires*: pytest @@ -4798,7 +4800,7 @@ This list contains 1321 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Sep 13, 2023, + *last release*: Sep 19, 2023, *status*: N/A, *requires*: N/A @@ -5084,6 +5086,13 @@ This list contains 1321 plugins. A plugin that tracks test changes + :pypi:`pytest-houdini` + *last release*: Sep 19, 2023, + *status*: N/A, + *requires*: pytest + + pytest plugin for testing code in Houdini. + :pypi:`pytest-hoverfly` *last release*: Jan 30, 2023, *status*: N/A, @@ -5127,7 +5136,7 @@ This list contains 1321 plugins. optimized pytest plugin for generating HTML reports :pypi:`pytest-html-merger` - *last release*: Apr 03, 2022, + *last release*: Sep 23, 2023, *status*: N/A, *requires*: N/A @@ -5218,7 +5227,7 @@ This list contains 1321 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Sep 11, 2023, + *last release*: Sep 18, 2023, *status*: 5 - Production/Stable, *requires*: pytest ==7.* @@ -5267,7 +5276,7 @@ This list contains 1321 plugins. A plugin to sent pytest results to an Ibutsu server :pypi:`pytest-icdiff` - *last release*: Sep 04, 2023, + *last release*: Sep 20, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5770,13 +5779,6 @@ This list contains 1321 plugins. Pytest-style test runner for langchain agents - :pypi:`pytest-lark` - *last release*: Nov 20, 2022, - *status*: N/A, - *requires*: N/A - - A package for enhancing pytest - :pypi:`pytest-launchable` *last release*: Apr 05, 2023, *status*: N/A, @@ -6583,9 +6585,9 @@ This list contains 1321 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-netdut` - *last release*: Jul 06, 2023, + *last release*: Sep 21, 2023, *status*: N/A, - *requires*: pytest (>=3.5.0) + *requires*: pytest <7.3,>=3.5.0 "Automated software testing for switches using pytest" @@ -6639,7 +6641,7 @@ This list contains 1321 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Sep 08, 2023, + *last release*: Sep 18, 2023, *status*: N/A, *requires*: pytest (==6.2.5) @@ -6828,7 +6830,7 @@ This list contains 1321 plugins. Pytest plugin for detecting inadvertent open file handles :pypi:`pytest-opentelemetry` - *last release*: Mar 15, 2023, + *last release*: Sep 23, 2023, *status*: N/A, *requires*: pytest @@ -8305,7 +8307,7 @@ This list contains 1321 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest-robotframework` - *last release*: Sep 13, 2023, + *last release*: Sep 21, 2023, *status*: N/A, *requires*: pytest (>=7,<8) @@ -8438,7 +8440,7 @@ This list contains 1321 plugins. A Pytest plugin that builds and creates docker containers :pypi:`pytest-salt-factories` - *last release*: Jul 31, 2023, + *last release*: Sep 20, 2023, *status*: 4 - Beta, *requires*: pytest (>=6.0.0) @@ -8480,7 +8482,7 @@ This list contains 1321 plugins. :pypi:`pytest-sbase` - *last release*: Sep 15, 2023, + *last release*: Sep 20, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8543,7 +8545,7 @@ This list contains 1321 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Sep 15, 2023, + *last release*: Sep 20, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8606,9 +8608,9 @@ This list contains 1321 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Jul 26, 2023, + *last release*: Sep 22, 2023, *status*: 3 - Alpha, - *requires*: pytest (>=6.2) + *requires*: pytest >=6.2 pytest servers @@ -8921,7 +8923,7 @@ This list contains 1321 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Sep 11, 2023, + *last release*: Sep 23, 2023, *status*: N/A, *requires*: pytest >=7.0.0 @@ -9018,6 +9020,13 @@ This list contains 1321 plugins. Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. + :pypi:`pytest-split-ext` + *last release*: Sep 23, 2023, + *status*: 4 - Beta, + *requires*: pytest (>=5,<8) + + Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. + :pypi:`pytest-splitio` *last release*: Sep 22, 2020, *status*: N/A, @@ -9250,9 +9259,9 @@ This list contains 1321 plugins. unittest subTest() support and subtests fixture :pypi:`pytest-subunit` - *last release*: Aug 29, 2017, + *last release*: Sep 17, 2023, *status*: N/A, - *requires*: N/A + *requires*: pytest (>=2.3) pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. @@ -9480,6 +9489,20 @@ This list contains 1321 plugins. Test infrastructures + :pypi:`pytest-testinfra-jpic` + *last release*: Sep 21, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + Test infrastructures + + :pypi:`pytest-testinfra-winrm-transport` + *last release*: Sep 21, 2023, + *status*: 5 - Production/Stable, + *requires*: N/A + + Test infrastructures + :pypi:`pytest-testlink-adaptor` *last release*: Dec 20, 2018, *status*: 4 - Beta, @@ -10313,13 +10336,6 @@ This list contains 1321 plugins. Welian API Automation test framework pytest plugin - :pypi:`pytest-when` - *last release*: Jun 05, 2023, - *status*: N/A, - *requires*: pytest>=7.3.1 - - Utility which makes mocking more readable and controllable - :pypi:`pytest-whirlwind` *last release*: Jun 12, 2020, *status*: N/A, @@ -10447,7 +10463,7 @@ This list contains 1321 plugins. An extended parametrizing plugin of pytest. :pypi:`pytest-xprocess` - *last release*: Jan 05, 2023, + *last release*: Sep 23, 2023, *status*: 4 - Beta, *requires*: pytest (>=2.8) From 81192ca85f8e64ddf71a7c467c228be08440ebce Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 15 Aug 2023 22:09:00 +0300 Subject: [PATCH 0208/1271] pytester: use monkeypatch.chdir() for dir changing The current method as the following problem, described by Sadra Barikbin: The tests that request both `pytester` and `monkeypatch` and use `monkeypatch.chdir` without context, relying on `monkeypatch`'s teardown to restore cwd. This doesn't work because the following sequence of actions take place: - `monkeypatch` is set up. - `pytester` is set up. It saves the original cwd and changes it to a new one dedicated to the test function. - Test function calls `monkeypatch.chdir()` without context. `monkeypatch` saves cwd, which is not the original one, before changing it. - `pytester` is torn down. It restores the cwd to the original one. - `monkeypatch` is torn down. It restores cwd to what it has saved. The solution here is to have pytester use `monkeypatch.chdir()` itself, then everything is handled correctly. --- changelog/11315.trivial.rst | 3 +++ src/_pytest/pytester.py | 14 ++------------ testing/_py/test_local.py | 16 ++++++++-------- testing/code/test_excinfo.py | 22 +++++++++++++--------- testing/test_assertrewrite.py | 20 ++++++++++++-------- testing/test_pathlib.py | 18 +++++++++--------- testing/test_pytester.py | 13 ------------- 7 files changed, 47 insertions(+), 59 deletions(-) create mode 100644 changelog/11315.trivial.rst diff --git a/changelog/11315.trivial.rst b/changelog/11315.trivial.rst new file mode 100644 index 00000000000..309dccd8b40 --- /dev/null +++ b/changelog/11315.trivial.rst @@ -0,0 +1,3 @@ +The :fixture:`pytester` fixture now uses the :fixture:`monkeypatch` fixture to manage the current working directory. +If you use ``pytester`` in combination with :func:`monkeypatch.undo() `, the CWD might get restored. +Use :func:`monkeypatch.context() ` instead. diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 854ee6834aa..ea1c302140e 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -625,14 +625,6 @@ def assert_outcomes( ) -class CwdSnapshot: - def __init__(self) -> None: - self.__saved = os.getcwd() - - def restore(self) -> None: - os.chdir(self.__saved) - - class SysModulesSnapshot: def __init__(self, preserve: Optional[Callable[[str], bool]] = None) -> None: self.__preserve = preserve @@ -696,15 +688,14 @@ def __init__( #: be added to the list. The type of items to add to the list depends on #: the method using them so refer to them for details. self.plugins: List[Union[str, _PluggyPlugin]] = [] - self._cwd_snapshot = CwdSnapshot() self._sys_path_snapshot = SysPathsSnapshot() self._sys_modules_snapshot = self.__take_sys_modules_snapshot() - self.chdir() self._request.addfinalizer(self._finalize) self._method = self._request.config.getoption("--runpytest") self._test_tmproot = tmp_path_factory.mktemp(f"tmp-{name}", numbered=True) self._monkeypatch = mp = monkeypatch + self.chdir() mp.setenv("PYTEST_DEBUG_TEMPROOT", str(self._test_tmproot)) # Ensure no unexpected caching via tox. mp.delenv("TOX_ENV_DIR", raising=False) @@ -735,7 +726,6 @@ def _finalize(self) -> None: """ self._sys_modules_snapshot.restore() self._sys_path_snapshot.restore() - self._cwd_snapshot.restore() def __take_sys_modules_snapshot(self) -> SysModulesSnapshot: # Some zope modules used by twisted-related tests keep internal state @@ -760,7 +750,7 @@ def chdir(self) -> None: This is done automatically upon instantiation. """ - os.chdir(self.path) + self._monkeypatch.chdir(self.path) def _makefile( self, diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 57e2d91f900..aebee380cb9 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -1080,14 +1080,14 @@ def test_pyimport_check_filepath_consistency(self, monkeypatch, tmpdir): name = "pointsback123" ModuleType = type(os) p = tmpdir.ensure(name + ".py") - for ending in (".pyc", "$py.class", ".pyo"): - mod = ModuleType(name) - pseudopath = tmpdir.ensure(name + ending) - mod.__file__ = str(pseudopath) - monkeypatch.setitem(sys.modules, name, mod) - newmod = p.pyimport() - assert mod == newmod - monkeypatch.undo() + with monkeypatch.context() as mp: + for ending in (".pyc", "$py.class", ".pyo"): + mod = ModuleType(name) + pseudopath = tmpdir.ensure(name + ending) + mod.__file__ = str(pseudopath) + mp.setitem(sys.modules, name, mod) + newmod = p.pyimport() + assert mod == newmod mod = ModuleType(name) pseudopath = tmpdir.ensure(name + "123.py") mod.__file__ = str(pseudopath) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 89beefce547..22be51d407e 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -854,7 +854,11 @@ def entry(): reprtb = p.repr_traceback(excinfo) assert len(reprtb.reprentries) == 3 - def test_traceback_short_no_source(self, importasmod, monkeypatch) -> None: + def test_traceback_short_no_source( + self, + importasmod, + monkeypatch: pytest.MonkeyPatch, + ) -> None: mod = importasmod( """ def func1(): @@ -866,14 +870,14 @@ def entry(): excinfo = pytest.raises(ValueError, mod.entry) from _pytest._code.code import Code - monkeypatch.setattr(Code, "path", "bogus") - p = FormattedExcinfo(style="short") - reprtb = p.repr_traceback_entry(excinfo.traceback[-2]) - lines = reprtb.lines - last_p = FormattedExcinfo(style="short") - last_reprtb = last_p.repr_traceback_entry(excinfo.traceback[-1], excinfo) - last_lines = last_reprtb.lines - monkeypatch.undo() + with monkeypatch.context() as mp: + mp.setattr(Code, "path", "bogus") + p = FormattedExcinfo(style="short") + reprtb = p.repr_traceback_entry(excinfo.traceback[-2]) + lines = reprtb.lines + last_p = FormattedExcinfo(style="short") + last_reprtb = last_p.repr_traceback_entry(excinfo.traceback[-1], excinfo) + last_lines = last_reprtb.lines assert lines[0] == " func1()" assert last_lines[0] == ' raise ValueError("hello")' diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index b3fd0c2f2e7..d3cd6144404 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -895,7 +895,11 @@ def test_foo(): ) @pytest.mark.skipif('"__pypy__" in sys.modules') - def test_pyc_vs_pyo(self, pytester: Pytester, monkeypatch) -> None: + def test_pyc_vs_pyo( + self, + pytester: Pytester, + monkeypatch: pytest.MonkeyPatch, + ) -> None: pytester.makepyfile( """ import pytest @@ -905,13 +909,13 @@ def test_optimized(): ) p = make_numbered_dir(root=Path(pytester.path), prefix="runpytest-") tmp = "--basetemp=%s" % p - monkeypatch.setenv("PYTHONOPTIMIZE", "2") - monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False) - monkeypatch.delenv("PYTHONPYCACHEPREFIX", raising=False) - assert pytester.runpytest_subprocess(tmp).ret == 0 - tagged = "test_pyc_vs_pyo." + PYTEST_TAG - assert tagged + ".pyo" in os.listdir("__pycache__") - monkeypatch.undo() + with monkeypatch.context() as mp: + mp.setenv("PYTHONOPTIMIZE", "2") + mp.delenv("PYTHONDONTWRITEBYTECODE", raising=False) + mp.delenv("PYTHONPYCACHEPREFIX", raising=False) + assert pytester.runpytest_subprocess(tmp).ret == 0 + tagged = "test_pyc_vs_pyo." + PYTEST_TAG + assert tagged + ".pyo" in os.listdir("__pycache__") monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False) monkeypatch.delenv("PYTHONPYCACHEPREFIX", raising=False) assert pytester.runpytest_subprocess(tmp).ret == 1 diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 2c5432cef0a..3e1d2265bb7 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -236,15 +236,15 @@ def test_check_filepath_consistency( name = "pointsback123" p = tmp_path.joinpath(name + ".py") p.touch() - for ending in (".pyc", ".pyo"): - mod = ModuleType(name) - pseudopath = tmp_path.joinpath(name + ending) - pseudopath.touch() - mod.__file__ = str(pseudopath) - monkeypatch.setitem(sys.modules, name, mod) - newmod = import_path(p, root=tmp_path) - assert mod == newmod - monkeypatch.undo() + with monkeypatch.context() as mp: + for ending in (".pyc", ".pyo"): + mod = ModuleType(name) + pseudopath = tmp_path.joinpath(name + ending) + pseudopath.touch() + mod.__file__ = str(pseudopath) + mp.setitem(sys.modules, name, mod) + newmod = import_path(p, root=tmp_path) + assert mod == newmod mod = ModuleType(name) pseudopath = tmp_path.joinpath(name + "123.py") pseudopath.touch() diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 8f8b4d2914f..6fc6bd24519 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -2,7 +2,6 @@ import subprocess import sys import time -from pathlib import Path from types import ModuleType from typing import List @@ -11,7 +10,6 @@ from _pytest.config import ExitCode from _pytest.config import PytestPluginManager from _pytest.monkeypatch import MonkeyPatch -from _pytest.pytester import CwdSnapshot from _pytest.pytester import HookRecorder from _pytest.pytester import LineMatcher from _pytest.pytester import Pytester @@ -301,17 +299,6 @@ def test_assert_outcomes_after_pytest_error(pytester: Pytester) -> None: result.assert_outcomes(passed=0) -def test_cwd_snapshot(pytester: Pytester) -> None: - foo = pytester.mkdir("foo") - bar = pytester.mkdir("bar") - os.chdir(foo) - snapshot = CwdSnapshot() - os.chdir(bar) - assert Path().absolute() == bar - snapshot.restore() - assert Path().absolute() == foo - - class TestSysModulesSnapshot: key = "my-test-module" From b73b4c464c6fa54f55a1c6ed8eaceb5529a161bb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:31:39 +0000 Subject: [PATCH 0209/1271] [pre-commit.ci] pre-commit autoupdate (#11468) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v3.11.0 → v3.13.0](https://github.com/asottile/pyupgrade/compare/v3.11.0...v3.13.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index afc67b32640..6c11d1c6c02 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,7 +42,7 @@ repos: - id: reorder-python-imports args: ['--application-directories=.:src', --py38-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.11.0 + rev: v3.13.0 hooks: - id: pyupgrade args: [--py38-plus] From d015bc1b8fae14e224dc2e05caf6f38e261c328f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 08:39:53 -0300 Subject: [PATCH 0210/1271] [automated] Update plugin list (#11472) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 138 +++++++++++++++++++------------ 1 file changed, 85 insertions(+), 53 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 82ce198d795..1aa8349a9db 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.5,<8.0.0) - :pypi:`pytest-astropy` Meta-package containing dependencies for testing Apr 12, 2022 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-astropy` Meta-package containing dependencies for testing Sep 26, 2023 5 - Production/Stable pytest >=4.6 :pypi:`pytest-astropy-header` pytest plugin to add diagnostic information to the header of the test output Sep 06, 2022 3 - Alpha pytest (>=4.6) :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A @@ -212,6 +212,7 @@ This list contains 1323 plugins. :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) + :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 25, 2023 4 - Beta N/A :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) @@ -231,7 +232,9 @@ This list contains 1323 plugins. :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A + :pypi:`pytest-collect-interface-info-plugin` Get executed interface information in pytest interface automation framework Sep 25, 2023 4 - Beta N/A :pypi:`pytest-collector` Python package for collecting pytest. Aug 02, 2022 N/A pytest (>=7.0,<8.0) + :pypi:`pytest-collect-pytest-interinfo` A simple plugin to use with pytest Sep 26, 2023 4 - Beta N/A :pypi:`pytest-colordots` Colorizes the progress indicators Oct 06, 2017 5 - Production/Stable N/A :pypi:`pytest-commander` An interactive GUI test runner for PyTest Aug 17, 2021 N/A pytest (<7.0.0,>=6.2.4) :pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method May 15, 2022 N/A pytest (>=3.6,<8) @@ -241,7 +244,7 @@ This list contains 1323 plugins. :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest - :pypi:`pytest-container` Pytest fixtures for writing container based tests Jun 19, 2023 4 - Beta pytest (>=3.10) + :pypi:`pytest-container` Pytest fixtures for writing container based tests Sep 26, 2023 4 - Beta pytest (>=3.10) :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) @@ -375,6 +378,7 @@ This list contains 1323 plugins. :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-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. Sep 28, 2023 4 - Beta pytest >=7.3.1 :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest @@ -525,7 +529,7 @@ This list contains 1323 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Sep 19, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Sep 28, 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 Jun 22, 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 @@ -561,7 +565,7 @@ This list contains 1323 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-homeassistant` A pytest plugin for use with homeassistant custom components. Aug 12, 2020 4 - Beta N/A - :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Sep 13, 2023 3 - Alpha pytest ==7.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Sep 29, 2023 3 - Alpha pytest ==7.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -716,6 +720,7 @@ This list contains 1323 plugins. :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) + :pypi:`pytest-maxcov` Compute the maximum coverage available through pytest with the minimum execution time cost Sep 24, 2023 N/A pytest (>=7.4.0,<8.0.0) :pypi:`pytest-maybe-context` Simplify tests with warning and exception cases. Apr 16, 2023 N/A pytest (>=7,<8) :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) @@ -731,7 +736,7 @@ This list contains 1323 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 01, 2023 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Sep 27, 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) @@ -744,7 +749,7 @@ This list contains 1323 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jul 24, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Sep 25, 2023 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -865,6 +870,7 @@ This list contains 1323 plugins. :pypi:`pytest-pinned` A simple pytest plugin for pinning tests Sep 17, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-pinpoint` A pytest plugin which runs SBFL algorithms to detect faults. Sep 25, 2020 N/A pytest (>=4.4.0) :pypi:`pytest-pipeline` Pytest plugin for functional testing of data analysispipelines Jan 24, 2017 3 - Alpha N/A + :pypi:`pytest-pitch` runs tests in an order such that coverage increases as fast as possible Sep 29, 2023 4 - Beta pytest >=7.3.1 :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) @@ -934,7 +940,7 @@ This list contains 1323 plugins. :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest - :pypi:`pytest-pyvista` Pytest-pyvista package Mar 19, 2023 4 - Beta pytest>=3.5.0 + :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) :pypi:`pytest-qatouch` Pytest plugin for uploading test results to your QA Touch Testrun. Feb 14, 2023 4 - Beta pytest (>=6.2.0) @@ -959,7 +965,7 @@ This list contains 1323 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 05, 2023 3 - Alpha 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-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 @@ -975,7 +981,7 @@ This list contains 1323 plugins. :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A - :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Dec 12, 2022 3 - Alpha pytest (>=4.6) + :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Sep 26, 2023 5 - Production/Stable pytest >=4.6 :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest @@ -991,7 +997,7 @@ This list contains 1323 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Jul 18, 2023 N/A pytest (>=3.8.0) + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Sep 25, 2023 N/A pytest >=3.8.0 :pypi:`pytest-reports` An interesting python package Jun 07, 2023 N/A N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) @@ -1026,7 +1032,6 @@ This list contains 1323 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest-robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 21, 2023 N/A pytest (>=7,<8) :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1041,17 +1046,16 @@ This list contains 1323 plugins. :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-runtime-yoyo` run case mark timeout Jun 12, 2023 N/A pytest (>=7.2.0) - :pypi:`pytest-ry-demo1` 测试 Mar 26, 2023 N/A N/A :pypi:`pytest-saccharin` pytest-saccharin is a updated fork of pytest-sugar, a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Oct 31, 2022 3 - Alpha N/A :pypi:`pytest-salt` Pytest Salt Plugin Jan 27, 2020 4 - Beta N/A :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 20, 2023 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-salt-factories` Pytest Salt Plugin Sep 27, 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. Sep 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 27, 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) @@ -1060,7 +1064,7 @@ This list contains 1323 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Sep 06, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 27, 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-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 @@ -1114,7 +1118,7 @@ This list contains 1323 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Sep 23, 2023 N/A pytest >=7.0.0 + :pypi:`pytest-sort` Tools for sorting test cases Sep 30, 2023 N/A pytest >=7.4.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest @@ -1327,7 +1331,7 @@ This list contains 1323 plugins. :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) - :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Sep 29, 2023 4 - Beta pytest (>=7.3,<8.0) :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A @@ -1818,9 +1822,9 @@ This list contains 1323 plugins. PyTest plugin for docker-based testing on database images :pypi:`pytest-astropy` - *last release*: Apr 12, 2022, + *last release*: Sep 26, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.6) + *requires*: pytest >=4.6 Meta-package containing dependencies for testing @@ -2608,6 +2612,13 @@ This list contains 1323 plugins. Easy quality control for CLDF datasets using pytest + :pypi:`pytest-cleanuptotal` + *last release*: Sep 25, 2023, + *status*: 4 - Beta, + *requires*: N/A + + A cleanup plugin for pytest + :pypi:`pytest-click` *last release*: Feb 11, 2022, *status*: 5 - Production/Stable, @@ -2741,6 +2752,13 @@ This list contains 1323 plugins. Formatter for pytest collect output + :pypi:`pytest-collect-interface-info-plugin` + *last release*: Sep 25, 2023, + *status*: 4 - Beta, + *requires*: N/A + + Get executed interface information in pytest interface automation framework + :pypi:`pytest-collector` *last release*: Aug 02, 2022, *status*: N/A, @@ -2748,6 +2766,13 @@ This list contains 1323 plugins. Python package for collecting pytest. + :pypi:`pytest-collect-pytest-interinfo` + *last release*: Sep 26, 2023, + *status*: 4 - Beta, + *requires*: N/A + + A simple plugin to use with pytest + :pypi:`pytest-colordots` *last release*: Oct 06, 2017, *status*: 5 - Production/Stable, @@ -2812,7 +2837,7 @@ This list contains 1323 plugins. pytest plugin with fixtures for testing consul aware apps :pypi:`pytest-container` - *last release*: Jun 19, 2023, + *last release*: Sep 26, 2023, *status*: 4 - Beta, *requires*: pytest (>=3.10) @@ -3749,6 +3774,13 @@ This list contains 1323 plugins. Some extra stuff that we use ininternally + :pypi:`pytest-donde` + *last release*: Sep 28, 2023, + *status*: 4 - Beta, + *requires*: pytest >=7.3.1 + + record pytest session characteristics per test item (coverage and duration) into a persistent file and use them in your own plugin or script. + :pypi:`pytest-doorstop` *last release*: Jun 09, 2020, *status*: 4 - Beta, @@ -4800,7 +4832,7 @@ This list contains 1323 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Sep 19, 2023, + *last release*: Sep 28, 2023, *status*: N/A, *requires*: N/A @@ -5052,7 +5084,7 @@ This list contains 1323 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Sep 13, 2023, + *last release*: Sep 29, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.3.1 @@ -6136,6 +6168,13 @@ This list contains 1323 plugins. Provide tools for generating tests from combinations of fixtures. + :pypi:`pytest-maxcov` + *last release*: Sep 24, 2023, + *status*: N/A, + *requires*: pytest (>=7.4.0,<8.0.0) + + Compute the maximum coverage available through pytest with the minimum execution time cost + :pypi:`pytest-maybe-context` *last release*: Apr 16, 2023, *status*: N/A, @@ -6242,7 +6281,7 @@ This list contains 1323 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Sep 01, 2023, + *last release*: Sep 27, 2023, *status*: N/A, *requires*: pytest @@ -6333,7 +6372,7 @@ This list contains 1323 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Jul 24, 2023, + *last release*: Sep 25, 2023, *status*: N/A, *requires*: pytest (>=1.0) @@ -7179,6 +7218,13 @@ This list contains 1323 plugins. Pytest plugin for functional testing of data analysispipelines + :pypi:`pytest-pitch` + *last release*: Sep 29, 2023, + *status*: 4 - Beta, + *requires*: pytest >=7.3.1 + + runs tests in an order such that coverage increases as fast as possible + :pypi:`pytest-platform-markers` *last release*: Sep 09, 2019, *status*: 4 - Beta, @@ -7663,7 +7709,7 @@ This list contains 1323 plugins. pytest plugin for a better developer experience when working with the PyTorch test suite :pypi:`pytest-pyvista` - *last release*: Mar 19, 2023, + *last release*: Sep 29, 2023, *status*: 4 - Beta, *requires*: pytest>=3.5.0 @@ -7838,7 +7884,7 @@ This list contains 1323 plugins. Test your README.md file :pypi:`pytest-reana` - *last release*: Sep 05, 2023, + *last release*: Sep 26, 2023, *status*: 3 - Alpha, *requires*: N/A @@ -7950,9 +7996,9 @@ This list contains 1323 plugins. Pytest plugin to create a temporary directory with remote files :pypi:`pytest-remotedata` - *last release*: Dec 12, 2022, - *status*: 3 - Alpha, - *requires*: pytest (>=4.6) + *last release*: Sep 26, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest >=4.6 Pytest plugin for controlling remote data access. @@ -8062,9 +8108,9 @@ This list contains 1323 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Jul 18, 2023, + *last release*: Sep 25, 2023, *status*: N/A, - *requires*: pytest (>=3.8.0) + *requires*: pytest >=3.8.0 Agent for Reporting results of tests to the Report Portal @@ -8306,13 +8352,6 @@ This list contains 1323 plugins. pytest plugin for ROAST configuration override and fixtures - :pypi:`pytest-robotframework` - *last release*: Sep 21, 2023, - *status*: N/A, - *requires*: pytest (>=7,<8) - - a pytest plugin that can run both python and robotframework tests while generating robot reports for them - :pypi:`pytest-rocketchat` *last release*: Apr 18, 2021, *status*: 5 - Production/Stable, @@ -8411,13 +8450,6 @@ This list contains 1323 plugins. run case mark timeout - :pypi:`pytest-ry-demo1` - *last release*: Mar 26, 2023, - *status*: N/A, - *requires*: N/A - - 测试 - :pypi:`pytest-saccharin` *last release*: Oct 31, 2022, *status*: 3 - Alpha, @@ -8440,7 +8472,7 @@ This list contains 1323 plugins. A Pytest plugin that builds and creates docker containers :pypi:`pytest-salt-factories` - *last release*: Sep 20, 2023, + *last release*: Sep 27, 2023, *status*: 4 - Beta, *requires*: pytest (>=6.0.0) @@ -8482,7 +8514,7 @@ This list contains 1323 plugins. :pypi:`pytest-sbase` - *last release*: Sep 20, 2023, + *last release*: Sep 27, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8545,7 +8577,7 @@ This list contains 1323 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Sep 20, 2023, + *last release*: Sep 27, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8923,9 +8955,9 @@ This list contains 1323 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Sep 23, 2023, + *last release*: Sep 30, 2023, *status*: N/A, - *requires*: pytest >=7.0.0 + *requires*: pytest >=7.4.0 Tools for sorting test cases @@ -10414,9 +10446,9 @@ This list contains 1323 plugins. pytest plugin helps to reproduce failures for particular xdist node :pypi:`pytest-xdist-worker-stats` - *last release*: Aug 08, 2023, + *last release*: Sep 29, 2023, *status*: 4 - Beta, - *requires*: pytest (>=7.3.2,<8.0.0) + *requires*: pytest (>=7.3,<8.0) A pytest plugin to list worker statistics after a xdist run. From 9bbfe995eed5c0f32a726d3c3fb98a474c87dc44 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:37:52 -0700 Subject: [PATCH 0211/1271] Add more comprehensive set assertion rewrites (#11469) Fixes #10617 --- changelog/10617.feature.rst | 2 + src/_pytest/assertion/util.py | 68 ++++++++++++++++++--- testing/test_assertion.py | 108 ++++++++++++++++++++++------------ 3 files changed, 131 insertions(+), 47 deletions(-) create mode 100644 changelog/10617.feature.rst diff --git a/changelog/10617.feature.rst b/changelog/10617.feature.rst new file mode 100644 index 00000000000..c99ec488912 --- /dev/null +++ b/changelog/10617.feature.rst @@ -0,0 +1,2 @@ +Added more comprehensive set assertion rewrites for comparisons other than equality ``==``, with +the following operations now providing better failure messages: ``!=``, ``<=``, ``>=``, ``<``, and ``>``. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 01534797d73..057352cd387 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -193,6 +193,22 @@ def assertrepr_compare( elif op == "not in": if istext(left) and istext(right): explanation = _notin_text(left, right, verbose) + elif op == "!=": + if isset(left) and isset(right): + explanation = ["Both sets are equal"] + elif op == ">=": + if isset(left) and isset(right): + explanation = _compare_gte_set(left, right, verbose) + elif op == "<=": + if isset(left) and isset(right): + explanation = _compare_lte_set(left, right, verbose) + elif op == ">": + if isset(left) and isset(right): + explanation = _compare_gt_set(left, right, verbose) + elif op == "<": + if isset(left) and isset(right): + explanation = _compare_lt_set(left, right, verbose) + except outcomes.Exit: raise except Exception: @@ -392,15 +408,49 @@ def _compare_eq_set( left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 ) -> List[str]: explanation = [] - diff_left = left - right - diff_right = right - left - if diff_left: - explanation.append("Extra items in the left set:") - for item in diff_left: - explanation.append(saferepr(item)) - if diff_right: - explanation.append("Extra items in the right set:") - for item in diff_right: + explanation.extend(_set_one_sided_diff("left", left, right)) + explanation.extend(_set_one_sided_diff("right", right, left)) + return explanation + + +def _compare_gt_set( + left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 +) -> List[str]: + explanation = _compare_gte_set(left, right, verbose) + if not explanation: + return ["Both sets are equal"] + return explanation + + +def _compare_lt_set( + left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 +) -> List[str]: + explanation = _compare_lte_set(left, right, verbose) + if not explanation: + return ["Both sets are equal"] + return explanation + + +def _compare_gte_set( + left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 +) -> List[str]: + return _set_one_sided_diff("right", right, left) + + +def _compare_lte_set( + left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 +) -> List[str]: + return _set_one_sided_diff("left", left, right) + + +def _set_one_sided_diff( + posn: str, set1: AbstractSet[Any], set2: AbstractSet[Any] +) -> List[str]: + explanation = [] + diff = set1 - set2 + if diff: + explanation.append(f"Extra items in the {posn} set:") + for item in diff: explanation.append(saferepr(item)) return explanation diff --git a/testing/test_assertion.py b/testing/test_assertion.py index c04c31f31b6..d3caa5e4848 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1345,48 +1345,80 @@ def test_reprcompare_whitespaces() -> None: ] -def test_pytest_assertrepr_compare_integration(pytester: Pytester) -> None: - pytester.makepyfile( +class TestSetAssertions: + @pytest.mark.parametrize("op", [">=", ">", "<=", "<", "=="]) + def test_set_extra_item(self, op, pytester: Pytester) -> None: + pytester.makepyfile( + f""" + def test_hello(): + x = set("hello x") + y = set("hello y") + assert x {op} y """ - def test_hello(): - x = set(range(100)) - y = x.copy() - y.remove(50) - assert x == y - """ - ) - result = pytester.runpytest() - result.stdout.fnmatch_lines( - [ - "*def test_hello():*", - "*assert x == y*", - "*E*Extra items*left*", - "*E*50*", - "*= 1 failed in*", - ] - ) + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*def test_hello():*", + f"*assert x {op} y*", + ] + ) + if op in [">=", ">", "=="]: + result.stdout.fnmatch_lines( + [ + "*E*Extra items in the right set:*", + "*E*'y'", + ] + ) + if op in ["<=", "<", "=="]: + result.stdout.fnmatch_lines( + [ + "*E*Extra items in the left set:*", + "*E*'x'", + ] + ) + + @pytest.mark.parametrize("op", [">", "<", "!="]) + def test_set_proper_superset_equal(self, pytester: Pytester, op) -> None: + pytester.makepyfile( + f""" + def test_hello(): + x = set([1, 2, 3]) + y = x.copy() + assert x {op} y + """ + ) -def test_sequence_comparison_uses_repr(pytester: Pytester) -> None: - pytester.makepyfile( + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*def test_hello():*", + f"*assert x {op} y*", + "*E*Both sets are equal*", + ] + ) + + def test_pytest_assertrepr_compare_integration(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + def test_hello(): + x = set(range(100)) + y = x.copy() + y.remove(50) + assert x == y """ - def test_hello(): - x = set("hello x") - y = set("hello y") - assert x == y - """ - ) - result = pytester.runpytest() - result.stdout.fnmatch_lines( - [ - "*def test_hello():*", - "*assert x == y*", - "*E*Extra items*left*", - "*E*'x'*", - "*E*Extra items*right*", - "*E*'y'*", - ] - ) + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*def test_hello():*", + "*assert x == y*", + "*E*Extra items*left*", + "*E*50*", + "*= 1 failed in*", + ] + ) def test_assertrepr_loaded_per_dir(pytester: Pytester) -> None: From 54623f0f33c367e19c4041d30f11f71787e30719 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:47:19 +0000 Subject: [PATCH 0212/1271] [pre-commit.ci] pre-commit autoupdate (#11478) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/reorder-python-imports: v3.11.0 → v3.12.0](https://github.com/asottile/reorder-python-imports/compare/v3.11.0...v3.12.0) - [github.com/asottile/pyupgrade: v3.13.0 → v3.14.0](https://github.com/asottile/pyupgrade/compare/v3.13.0...v3.14.0) - [github.com/asottile/setup-cfg-fmt: v2.4.0 → v2.5.0](https://github.com/asottile/setup-cfg-fmt/compare/v2.4.0...v2.5.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c11d1c6c02..bd584e99509 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,17 +37,17 @@ repos: - flake8-typing-imports==1.12.0 - flake8-docstrings==1.5.0 - repo: https://github.com/asottile/reorder-python-imports - rev: v3.11.0 + rev: v3.12.0 hooks: - id: reorder-python-imports args: ['--application-directories=.:src', --py38-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.13.0 + rev: v3.14.0 hooks: - id: pyupgrade args: [--py38-plus] - repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.4.0 + rev: v2.5.0 hooks: - id: setup-cfg-fmt args: ["--max-py-version=3.12", "--include-version-classifiers"] From e966dcd93c0fa3eb80f420088c6de7d9251627e2 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Sat, 7 Oct 2023 15:54:45 +0200 Subject: [PATCH 0213/1271] Update CONTRIBUTING.rst to mention tag fetches closes #11485 --- CONTRIBUTING.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index bcfd205b107..59b1a533d54 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -197,6 +197,7 @@ Short version ~~~~~~~~~~~~~ #. Fork the repository. +#. fetch tags from upstream if necessary (if you cloned only main `git fetch --tags https://github.com/pytest-dev/pytest` #. Enable and install `pre-commit `_ to ensure style-guides and code checks are followed. #. Follow **PEP-8** for naming and `black `_ for formatting. #. Tests are run using ``tox``:: @@ -236,6 +237,7 @@ Here is a simple overview, with pytest-specific bits: $ git clone git@github.com:YOUR_GITHUB_USERNAME/pytest.git $ cd pytest + $ git fetch --tags https://github.com/pytest-dev/pytest # now, create your own branch off "main": $ git checkout -b your-bugfix-branch-name main From 696859fc434ddbbfa582002dc2cf5d82eb3a1765 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Sat, 7 Oct 2023 16:16:18 +0200 Subject: [PATCH 0214/1271] Update CONTRIBUTING.rst Co-authored-by: Bruno Oliveira --- CONTRIBUTING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 59b1a533d54..e2230cbbdfd 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -197,7 +197,7 @@ Short version ~~~~~~~~~~~~~ #. Fork the repository. -#. fetch tags from upstream if necessary (if you cloned only main `git fetch --tags https://github.com/pytest-dev/pytest` +#. Fetch tags from upstream if necessary (if you cloned only main `git fetch --tags https://github.com/pytest-dev/pytest`). #. Enable and install `pre-commit `_ to ensure style-guides and code checks are followed. #. Follow **PEP-8** for naming and `black `_ for formatting. #. Tests are run using ``tox``:: From af9b1dcc24ab1c71ae4109323ceb5270738bb5e1 Mon Sep 17 00:00:00 2001 From: Tanya Agarwal Date: Sun, 8 Oct 2023 22:56:31 +0530 Subject: [PATCH 0215/1271] Duplicated parameters in parametrize marker (#11489) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Zac Hatfield-Dodds --- AUTHORS | 1 + changelog/11456.bugfix.rst | 4 ++++ src/_pytest/python.py | 12 +++++++++++- testing/acceptance_test.py | 39 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 changelog/11456.bugfix.rst diff --git a/AUTHORS b/AUTHORS index f8c66cae945..3c23d227730 100644 --- a/AUTHORS +++ b/AUTHORS @@ -367,6 +367,7 @@ Tadek Teleżyński Takafumi Arakaki Taneli Hukkinen Tanvi Mehta +Tanya Agarwal Tarcisio Fischer Tareq Alayan Tatiana Ovary diff --git a/changelog/11456.bugfix.rst b/changelog/11456.bugfix.rst new file mode 100644 index 00000000000..77a2ccfb002 --- /dev/null +++ b/changelog/11456.bugfix.rst @@ -0,0 +1,4 @@ +Parametrized tests now *really do* ensure that the ids given to each input are unique - for +example, ``a, a, a0`` now results in ``a1, a2, a0`` instead of the previous (buggy) ``a0, a1, a0``. +This necessarily means changing nodeids where these were previously colliding, and for +readability adds an underscore when non-unique ids end in a number. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index cbb82e39090..f54bbb3793e 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1002,8 +1002,18 @@ def make_unique_parameterset_ids(self) -> List[str]: # Suffix non-unique IDs to make them unique. for index, id in enumerate(resolved_ids): if id_counts[id] > 1: - resolved_ids[index] = f"{id}{id_suffixes[id]}" + suffix = "" + if id[-1].isdigit(): + suffix = "_" + new_id = f"{id}{suffix}{id_suffixes[id]}" + while new_id in set(resolved_ids): + id_suffixes[id] += 1 + new_id = f"{id}{suffix}{id_suffixes[id]}" + resolved_ids[index] = new_id id_suffixes[id] += 1 + assert len(resolved_ids) == len( + set(resolved_ids) + ), f"Internal error: {resolved_ids=}" return resolved_ids def _resolve_ids(self) -> Iterable[str]: diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 429fb4e4372..d597311ae38 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -341,6 +341,45 @@ def test_func(i): assert res.ret == 0 res.stdout.fnmatch_lines(["*1 passed*"]) + def test_direct_addressing_selects_duplicates(self, pytester: Pytester) -> None: + p = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("a", [1, 2, 10, 11, 2, 1, 12, 11]) + def test_func(a): + pass + """ + ) + result = pytester.runpytest(p) + result.assert_outcomes(failed=0, passed=8) + + def test_direct_addressing_selects_duplicates_1(self, pytester: Pytester) -> None: + p = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("a", [1, 2, 10, 11, 2, 1, 12, 1_1,2_1]) + def test_func(a): + pass + """ + ) + result = pytester.runpytest(p) + result.assert_outcomes(failed=0, passed=9) + + def test_direct_addressing_selects_duplicates_2(self, pytester: Pytester) -> None: + p = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("a", ["a","b","c","a","a1"]) + def test_func(a): + pass + """ + ) + result = pytester.runpytest(p) + result.assert_outcomes(failed=0, passed=5) + def test_direct_addressing_notfound(self, pytester: Pytester) -> None: p = pytester.makepyfile( """ From 2401d76655bdf2ba8fbeba9dff1d0c487c4fd335 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Oct 2023 08:32:49 -0300 Subject: [PATCH 0216/1271] [automated] Update plugin list (#11487) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 122 +++++++++++++++++-------------- 1 file changed, 69 insertions(+), 53 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 1aa8349a9db..c980868d833 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ads-testplan` Azure DevOps Test Case reporting for pytest tests Sep 15, 2022 N/A N/A + :pypi:`pytest-affected` Oct 05, 2023 N/A N/A :pypi:`pytest-agent` Service that exposes a REST API that can be used to interract remotely with Pytest. It is shipped with a dashboard that enables running tests in a more convenient way. Nov 25, 2021 N/A N/A :pypi:`pytest-aggreport` pytest plugin for pytest-repeat that generate aggregate report of the same test cases with additional statistics details. Mar 07, 2021 4 - Beta pytest (>=6.2.2) :pypi:`pytest-aio` Pytest plugin for testing async python code Feb 03, 2023 4 - Beta pytest @@ -126,7 +127,7 @@ This list contains 1327 plugins. :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest :pypi:`pytest-azure-devops` Simplifies using azure devops parallel strategy (https://docs.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner) with pytest. Jun 20, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-azurepipelines` Formatting PyTest output for Azure Pipelines UI Oct 20, 2022 5 - Production/Stable pytest (>=5.0.0) + :pypi:`pytest-azurepipelines` Formatting PyTest output for Azure Pipelines UI Oct 06, 2023 5 - Production/Stable pytest (>=5.0.0) :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) @@ -282,7 +283,7 @@ This list contains 1327 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest - :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 25, 2022 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) :pypi:`pytest-datadir-ng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Dec 25, 2019 5 - Production/Stable pytest :pypi:`pytest-datadir-nng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Nov 09, 2022 5 - Production/Stable pytest (>=7.0.0,<8.0.0) @@ -378,7 +379,7 @@ This list contains 1327 plugins. :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-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. Sep 28, 2023 4 - Beta pytest >=7.3.1 + :pypi:`pytest-donde` record pytest session characteristics per test item (coverage and duration) into a persistent file and use them in your own plugin or script. Oct 01, 2023 4 - Beta pytest >=7.3.1 :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest @@ -469,7 +470,7 @@ This list contains 1327 plugins. :pypi:`pytest-fantasy` Pytest plugin for Flask Fantasy Framework Mar 14, 2019 N/A N/A :pypi:`pytest-fastapi` Dec 27, 2020 N/A N/A :pypi:`pytest-fastapi-deps` A fixture which allows easy replacement of fastapi dependencies for testing Jul 20, 2022 5 - Production/Stable pytest - :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Jun 15, 2023 4 - Beta pytest (>=4.4) + :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) @@ -529,7 +530,7 @@ This list contains 1327 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Sep 28, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Oct 04, 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 Jun 22, 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 @@ -564,8 +565,9 @@ This list contains 1327 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-home` Home directory fixtures Oct 05, 2023 5 - Production/Stable pytest >=6 ; extra == 'testing' :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 Sep 29, 2023 3 - Alpha pytest ==7.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Oct 07, 2023 3 - Alpha pytest ==7.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -625,7 +627,7 @@ This list contains 1327 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Sep 14, 2023 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 02, 2023 5 - Production/Stable pytest (<7.2.0,>=6) + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Oct 02, 2023 5 - Production/Stable pytest <7.2.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A @@ -657,7 +659,7 @@ This list contains 1327 plugins. :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-keep-together` Pytest plugin to customize test ordering by running all 'related' tests together Dec 07, 2022 5 - Production/Stable pytest :pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Sep 14, 2023 N/A pytest (>=7.1) + :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Oct 01, 2023 N/A pytest (>=7.1) :pypi:`pytest-kind` Kubernetes test support with KIND for pytest Nov 30, 2022 5 - Production/Stable N/A :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A @@ -704,9 +706,9 @@ This list contains 1327 plugins. :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logikal` Common testing environment Jul 17, 2023 5 - Production/Stable pytest (==7.4.0) :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A - :pypi:`pytest-loguru` Pytest Loguru Apr 12, 2022 5 - Production/Stable N/A + :pypi:`pytest-loguru` Pytest Loguru Oct 04, 2023 5 - Production/Stable pytest :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) - :pypi:`pytest-lsp` pytest plugin for end-to-end testing of language servers May 19, 2023 3 - Alpha pytest + :pypi:`pytest-lsp` pytest plugin for end-to-end testing of language servers Oct 06, 2023 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) @@ -820,7 +822,7 @@ This list contains 1327 plugins. :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) - :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Sep 23, 2023 N/A pytest + :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Oct 01, 2023 N/A pytest :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Jun 02, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest :pypi:`pytest-optional` include/exclude values of fixtures in pytest Oct 07, 2015 N/A N/A @@ -894,7 +896,7 @@ This list contains 1327 plugins. :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-porringer` Aug 26, 2023 N/A pytest>=7.4.0 + :pypi:`pytest-porringer` Oct 03, 2023 N/A pytest>=7.4.0 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) @@ -924,7 +926,7 @@ This list contains 1327 plugins. :pypi:`pytest-pycodestyle` pytest plugin to run pycodestyle Oct 28, 2022 3 - Alpha N/A :pypi:`pytest-pydev` py.test plugin to connect to a remote debug server with PyDev or PyCharm. Nov 15, 2017 3 - Alpha N/A :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A - :pypi:`pytest-pylint` pytest plugin to check source code with pylint Sep 10, 2022 5 - Production/Stable pytest (>=5.4) + :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 Aug 29, 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 @@ -985,7 +987,7 @@ This list contains 1327 plugins. :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest - :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 31, 2020 5 - Production/Stable pytest (>=3.6) + :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 02, 2023 5 - Production/Stable pytest >=3.6 :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jun 09, 2021 4 - Beta pytest (>=3.0.0) :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A @@ -1009,7 +1011,7 @@ This list contains 1327 plugins. :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-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 Aug 31, 2023 N/A pytest ~=4.6 ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Oct 05, 2023 N/A pytest ~=4.6 ; python_version == "2.7" :pypi:`pytest-resource` Load resource fixture plugin to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-resource-path` Provides path for uniform access to test resources in isolated directory May 01, 2021 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-resource-usage` Pytest plugin for reporting running time and peak memory usage Nov 06, 2022 5 - Production/Stable pytest>=7.0.0 @@ -1021,7 +1023,7 @@ This list contains 1327 plugins. :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Aug 23, 2023 N/A pytest >=7.0.0 + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Oct 04, 2023 N/A pytest >=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest @@ -1055,7 +1057,7 @@ This list contains 1327 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 27, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 06, 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) @@ -1063,8 +1065,8 @@ This list contains 1327 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Sep 06, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 27, 2023 5 - Production/Stable N/A + :pypi:`pytest-selenium-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Oct 03, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 06, 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-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 @@ -1118,7 +1120,7 @@ This list contains 1327 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Sep 30, 2023 N/A pytest >=7.4.0 + :pypi:`pytest-sort` Tools for sorting test cases Oct 06, 2023 N/A pytest >=7.4.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest @@ -1137,7 +1139,7 @@ This list contains 1327 plugins. :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 Sep 06, 2023 N/A pytest (>5.4.0,<8) - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Sep 15, 2023 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Oct 02, 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 @@ -1317,7 +1319,7 @@ This list contains 1327 plugins. :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 24, 2023 4 - Beta N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A - :pypi:`pytest-web3-data` Sep 15, 2022 4 - Beta pytest + :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A @@ -1344,7 +1346,7 @@ This list contains 1327 plugins. :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (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. Aug 27, 2023 4 - Beta pytest >=7.1.0 + :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Oct 01, 2023 4 - Beta pytest >=7.1.0 :pypi:`pytest-yaml` This plugin is used to load yaml output to your test using pytest framework. Oct 05, 2018 N/A pytest :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Jul 03, 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) @@ -1443,6 +1445,13 @@ This list contains 1327 plugins. Azure DevOps Test Case reporting for pytest tests + :pypi:`pytest-affected` + *last release*: Oct 05, 2023, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-agent` *last release*: Nov 25, 2021, *status*: N/A, @@ -2011,7 +2020,7 @@ This list contains 1327 plugins. Simplifies using azure devops parallel strategy (https://docs.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner) with pytest. :pypi:`pytest-azurepipelines` - *last release*: Oct 20, 2022, + *last release*: Oct 06, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=5.0.0) @@ -3103,9 +3112,9 @@ This list contains 1327 plugins. Pytest plugin for remote Databricks notebooks testing :pypi:`pytest-datadir` - *last release*: Oct 25, 2022, + *last release*: Oct 03, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.0) + *requires*: pytest >=5.0 pytest plugin for test data directories and files @@ -3775,7 +3784,7 @@ This list contains 1327 plugins. Some extra stuff that we use ininternally :pypi:`pytest-donde` - *last release*: Sep 28, 2023, + *last release*: Oct 01, 2023, *status*: 4 - Beta, *requires*: pytest >=7.3.1 @@ -4412,7 +4421,7 @@ This list contains 1327 plugins. A fixture which allows easy replacement of fastapi dependencies for testing :pypi:`pytest-fastest` - *last release*: Jun 15, 2023, + *last release*: Oct 04, 2023, *status*: 4 - Beta, *requires*: pytest (>=4.4) @@ -4832,7 +4841,7 @@ This list contains 1327 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Sep 28, 2023, + *last release*: Oct 04, 2023, *status*: N/A, *requires*: N/A @@ -5076,6 +5085,13 @@ This list contains 1327 plugins. Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report + :pypi:`pytest-home` + *last release*: Oct 05, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest >=6 ; extra == 'testing' + + Home directory fixtures + :pypi:`pytest-homeassistant` *last release*: Aug 12, 2020, *status*: 4 - Beta, @@ -5084,7 +5100,7 @@ This list contains 1327 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Sep 29, 2023, + *last release*: Oct 07, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.3.1 @@ -5504,9 +5520,9 @@ This list contains 1327 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Jun 02, 2023, + *last release*: Oct 02, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (<7.2.0,>=6) + *requires*: pytest <7.2.0,>=6 Pytest fixtures for Invenio. @@ -5728,7 +5744,7 @@ This list contains 1327 plugins. :pypi:`pytest-keyring` - *last release*: Sep 14, 2023, + *last release*: Oct 01, 2023, *status*: N/A, *requires*: pytest (>=7.1) @@ -6057,9 +6073,9 @@ This list contains 1327 plugins. Package for creating a pytest test run reprot :pypi:`pytest-loguru` - *last release*: Apr 12, 2022, + *last release*: Oct 04, 2023, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest Pytest Loguru @@ -6071,7 +6087,7 @@ This list contains 1327 plugins. pytest plugin for looping tests :pypi:`pytest-lsp` - *last release*: May 19, 2023, + *last release*: Oct 06, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -6869,7 +6885,7 @@ This list contains 1327 plugins. Pytest plugin for detecting inadvertent open file handles :pypi:`pytest-opentelemetry` - *last release*: Sep 23, 2023, + *last release*: Oct 01, 2023, *status*: N/A, *requires*: pytest @@ -7387,7 +7403,7 @@ This list contains 1327 plugins. A pytest plugin to help with testing pop projects :pypi:`pytest-porringer` - *last release*: Aug 26, 2023, + *last release*: Oct 03, 2023, *status*: N/A, *requires*: pytest>=7.4.0 @@ -7597,9 +7613,9 @@ This list contains 1327 plugins. pytest plugin to run pydocstyle :pypi:`pytest-pylint` - *last release*: Sep 10, 2022, + *last release*: Oct 06, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.4) + *requires*: pytest >=7.0 pytest plugin to check source code with pylint @@ -8024,9 +8040,9 @@ This list contains 1327 plugins. Reorder tests depending on their paths and names. :pypi:`pytest-repeat` - *last release*: Oct 31, 2020, + *last release*: Oct 02, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.6) + *requires*: pytest >=3.6 pytest plugin for repeating tests @@ -8192,7 +8208,7 @@ This list contains 1327 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Aug 31, 2023, + *last release*: Oct 05, 2023, *status*: N/A, *requires*: pytest ~=4.6 ; python_version == "2.7" @@ -8276,7 +8292,7 @@ This list contains 1327 plugins. A RethinkDB plugin for pytest. :pypi:`pytest-retry` - *last release*: Aug 23, 2023, + *last release*: Oct 04, 2023, *status*: N/A, *requires*: pytest >=7.0.0 @@ -8514,7 +8530,7 @@ This list contains 1327 plugins. :pypi:`pytest-sbase` - *last release*: Sep 27, 2023, + *last release*: Oct 06, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8570,14 +8586,14 @@ This list contains 1327 plugins. pytest plugin for Selenium :pypi:`pytest-selenium-auto` - *last release*: Sep 06, 2023, + *last release*: Oct 03, 2023, *status*: N/A, *requires*: pytest >= 7.0.0 pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Sep 27, 2023, + *last release*: Oct 06, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8955,7 +8971,7 @@ This list contains 1327 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Sep 30, 2023, + *last release*: Oct 06, 2023, *status*: N/A, *requires*: pytest >=7.4.0 @@ -9088,7 +9104,7 @@ This list contains 1327 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Sep 15, 2023, + *last release*: Oct 02, 2023, *status*: N/A, *requires*: N/A @@ -10348,11 +10364,11 @@ This list contains 1327 plugins. Pytest plugin for testing WDL workflows. :pypi:`pytest-web3-data` - *last release*: Sep 15, 2022, + *last release*: Oct 04, 2023, *status*: 4 - Beta, *requires*: pytest - + A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. :pypi:`pytest-webdriver` *last release*: May 28, 2019, @@ -10537,7 +10553,7 @@ This list contains 1327 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-xvirt` - *last release*: Aug 27, 2023, + *last release*: Oct 01, 2023, *status*: 4 - Beta, *requires*: pytest >=7.1.0 From fb3a46dd8a943554c0659c156fa7026d2ddca84d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 06:33:25 +0200 Subject: [PATCH 0217/1271] [pre-commit.ci] pre-commit autoupdate (#11492) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.5.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.5.0) - [github.com/asottile/pyupgrade: v3.14.0 → v3.15.0](https://github.com/asottile/pyupgrade/compare/v3.14.0...v3.15.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bd584e99509..1b7b0278e65 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,7 +10,7 @@ repos: - id: blacken-docs additional_dependencies: [black==23.7.0] - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -42,7 +42,7 @@ repos: - id: reorder-python-imports args: ['--application-directories=.:src', --py38-plus] - repo: https://github.com/asottile/pyupgrade - rev: v3.14.0 + rev: v3.15.0 hooks: - id: pyupgrade args: [--py38-plus] From 23825f2983db1015a3f861de782b06ae9940bcec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:50:54 -0300 Subject: [PATCH 0218/1271] build(deps): Bump django in /testing/plugins_integration (#11491) Bumps [django](https://github.com/django/django) from 4.2.5 to 4.2.6. - [Commits](https://github.com/django/django/compare/4.2.5...4.2.6) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index fe17b8816d1..599706b2b4f 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.0.0 -django==4.2.5 +django==4.2.6 pytest-asyncio==0.21.1 pytest-bdd==6.1.1 pytest-cov==4.1.0 From 3ab70cd561cb0b7e5188b22ecf54a0e2d7a67bcb Mon Sep 17 00:00:00 2001 From: ryanpudd Date: Tue, 10 Oct 2023 22:16:24 +0100 Subject: [PATCH 0219/1271] Use hyphenated cmdline options in docs (#11490) Fix #11091 --- AUTHORS | 1 + changelog/11091.doc.rst | 1 + changelog/README.rst | 2 +- doc/en/deprecations.rst | 2 +- doc/en/example/markers.rst | 2 +- doc/en/example/simple.rst | 2 +- doc/en/how-to/output.rst | 2 +- src/_pytest/junitxml.py | 2 +- src/_pytest/pytester.py | 2 +- testing/python/metafunc.py | 2 +- 10 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 changelog/11091.doc.rst diff --git a/AUTHORS b/AUTHORS index 3c23d227730..f3461addfb7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -330,6 +330,7 @@ Ronny Pfannschmidt Ross Lawley Ruaridh Williamson Russel Winder +Ryan Puddephatt Ryan Wooden Sadra Barikbin Saiprasad Kale diff --git a/changelog/11091.doc.rst b/changelog/11091.doc.rst new file mode 100644 index 00000000000..429f2ac283b --- /dev/null +++ b/changelog/11091.doc.rst @@ -0,0 +1 @@ +Updated documentation and tests to refer to hyphonated options: replaced ``--junitxml`` with ``--junit-xml`` and ``--collectonly`` with ``--collect-only``. diff --git a/changelog/README.rst b/changelog/README.rst index 6d026f57ef3..88956ef28d8 100644 --- a/changelog/README.rst +++ b/changelog/README.rst @@ -14,7 +14,7 @@ Each file should be named like ``..rst``, where ```` is an issue number, and ```` is one of: * ``feature``: new user facing features, like new command-line options and new behavior. -* ``improvement``: improvement of existing functionality, usually without requiring user intervention (for example, new fields being written in ``--junitxml``, improved colors in terminal, etc). +* ``improvement``: improvement of existing functionality, usually without requiring user intervention (for example, new fields being written in ``--junit-xml``, improved colors in terminal, etc). * ``bugfix``: fixes a bug. * ``doc``: documentation improvement, like rewording an entire session or adding missing docs. * ``deprecation``: feature deprecation. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 7b4e9996526..0e47bdb0958 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -645,7 +645,7 @@ By using ``legacy`` you will keep using the legacy/xunit1 format when upgrading pytest 6.0, where the default format will be ``xunit2``. In order to let users know about the transition, pytest will issue a warning in case -the ``--junitxml`` option is given in the command line but ``junit_family`` is not explicitly +the ``--junit-xml`` option is given in the command line but ``junit_family`` is not explicitly configured in ``pytest.ini``. Services known to support the ``xunit2`` format: diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 55fd1f576cf..6cdf4eb42d8 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -136,7 +136,7 @@ Or select multiple nodes: Node IDs for failing tests are displayed in the test summary info when running pytest with the ``-rf`` option. You can also - construct Node IDs from the output of ``pytest --collectonly``. + construct Node IDs from the output of ``pytest --collect-only``. Using ``-k expr`` to select tests based on their name ------------------------------------------------------- diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 5648aa3834d..b798e711a11 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -1090,4 +1090,4 @@ application with standard ``pytest`` command-line options: .. code-block:: bash - ./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/ + ./app_main --pytest --verbose --tb=long --junit=xml=results.xml test-suite/ diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index e8e9af0c70b..cf72a2d291c 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -478,7 +478,7 @@ integration servers, use this invocation: .. code-block:: bash - pytest --junitxml=path + pytest --junit-xml=path to create an XML file at ``path``. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index ed259e4c41d..9ee35b84e84 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -369,7 +369,7 @@ def test_foo(record_testsuite_property): __tracebackhide__ = True def record_func(name: str, value: object) -> None: - """No-op function in case --junitxml was not passed in the command-line.""" + """No-op function in case --junit-xml was not passed in the command-line.""" __tracebackhide__ = True _check_record_param_type("name", name) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index ea1c302140e..99d33954da7 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1063,7 +1063,7 @@ def inline_runsource(self, source: str, *cmdlineargs) -> HookRecorder: return self.inline_run(*values) def inline_genitems(self, *args) -> Tuple[List[Item], HookRecorder]: - """Run ``pytest.main(['--collectonly'])`` in-process. + """Run ``pytest.main(['--collect-only'])`` in-process. Runs the :py:func:`pytest.main` function to run all of pytest inside the test process itself like :py:meth:`inline_run`, but returns a diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 4ee9e32d6e9..16ec37f9a7e 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1518,7 +1518,7 @@ def test_foo(x): pass """ ) - result = pytester.runpytest("--collectonly") + result = pytester.runpytest("--collect-only") result.stdout.fnmatch_lines( [ "collected 0 items / 1 error", From dd68f9c95aed1dbad6d07766b0a1906a1a1e1f55 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 15 Oct 2023 10:03:38 -0300 Subject: [PATCH 0220/1271] [automated] Update plugin list (#11504) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 124 +++++++++++++++---------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index c980868d833..0761c00a5a4 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -40,7 +40,7 @@ This list contains 1329 plugins. :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) - :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Sep 21, 2023 N/A N/A + :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 12, 2023 N/A pytest >=5.4.0 :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-adf` Pytest plugin for writing Azure Data Factory integration tests May 10, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) @@ -71,7 +71,7 @@ This list contains 1329 plugins. :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Sep 13, 2023 5 - Production/Stable pytest <8.0.0,>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Oct 11, 2023 5 - Production/Stable pytest <8.0.0,>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -131,7 +131,7 @@ This list contains 1329 plugins. :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) - :pypi:`pytest-bdd` BDD for pytest Nov 08, 2022 6 - Mature pytest (>=6.2.0) + :pypi:`pytest-bdd` BDD for pytest Oct 10, 2023 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0) :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 20, 2023 N/A N/A @@ -185,7 +185,7 @@ This list contains 1329 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-cases` Separate test code from test cases in pytest. Feb 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-cases` Separate test code from test cases in pytest. Oct 11, 2023 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A @@ -264,7 +264,7 @@ This list contains 1329 plugins. :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) - :pypi:`pytest-crayons` A pytest plugin for colorful print statements Mar 19, 2023 N/A pytest + :pypi:`pytest-crayons` A pytest plugin for colorful print statements Oct 08, 2023 N/A pytest :pypi:`pytest-create` pytest-create Feb 15, 2023 1 - Planning N/A :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest :pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A @@ -439,7 +439,7 @@ This list contains 1329 plugins. :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest - :pypi:`pytest-executable` pytest plugin for testing executables Mar 25, 2023 N/A pytest (<8,>=4.3) + :pypi:`pytest-executable` pytest plugin for testing executables Oct 07, 2023 N/A pytest <8,>=5 :pypi:`pytest-execution-timer` A timer for the phases of Pytest's execution. Dec 24, 2021 4 - Beta N/A :pypi:`pytest-expect` py.test plugin to store test expectations and mark tests based on them Apr 21, 2016 4 - Beta N/A :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) @@ -457,7 +457,7 @@ This list contains 1329 plugins. :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) - :pypi:`pytest-factoryboy` Factory Boy support for pytest. Dec 01, 2022 6 - Mature pytest (>=5.0.0) + :pypi:`pytest-factoryboy` Factory Boy support for pytest. Oct 10, 2023 6 - Mature pytest (>=6.2) :pypi:`pytest-factoryboy-fixtures` Generates pytest fixtures that allow the use of type hinting Jun 25, 2020 N/A N/A :pypi:`pytest-factoryboy-state` Simple factoryboy random state management Mar 22, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-failed-screen-record` Create a video of the screen when pytest fails Jan 05, 2023 4 - Beta pytest (>=7.1.2d,<8.0.0) @@ -530,9 +530,9 @@ This list contains 1329 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Oct 04, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Oct 09, 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 Jun 22, 2023 4 - Beta pytest>=7.1.2 + :pypi:`pytest-gitconfig` Provide a gitconfig sandbox for testing Oct 14, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A @@ -565,9 +565,9 @@ This list contains 1329 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-home` Home directory fixtures Oct 05, 2023 5 - Production/Stable pytest >=6 ; extra == 'testing' + :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 Oct 07, 2023 3 - Alpha pytest ==7.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Oct 14, 2023 3 - Alpha pytest ==7.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jun 23, 2023 N/A N/A @@ -603,7 +603,7 @@ This list contains 1329 plugins. :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A - :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 23, 2021 5 - Production/Stable N/A + :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-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A @@ -613,9 +613,9 @@ This list contains 1329 plugins. :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A - :pypi:`pytest-inline` A pytest plugin for writing inline tests. Feb 08, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 10, 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-extensions` Inmanta tests package Jul 04, 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-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 @@ -693,7 +693,7 @@ This list contains 1329 plugins. :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 04, 2022 5 - Production/Stable pytest - :pypi:`pytest-localserver` pytest plugin to test server connections locally. Jul 16, 2023 4 - Beta N/A + :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lockable` lockable resource plugin for pytest Aug 09, 2023 5 - Production/Stable pytest :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) @@ -727,7 +727,7 @@ This list contains 1329 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Sep 10, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 + :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Oct 08, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 @@ -808,7 +808,7 @@ This list contains 1329 plugins. :pypi:`pytest-notifier` A pytest plugin to notify test result Jun 12, 2020 3 - Alpha pytest :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A - :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Oct 20, 2022 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Oct 11, 2023 5 - Production/Stable N/A :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A @@ -876,7 +876,7 @@ This list contains 1329 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Aug 07, 2023 N/A pytest (<8.0.0,>=6.2.4) + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Oct 09, 2023 N/A pytest (<8.0.0,>=6.2.4) :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A @@ -928,12 +928,12 @@ This list contains 1329 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 Aug 29, 2023 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Oct 10, 2023 N/A pytest :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A - :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Dec 13, 2022 5 - Production/Stable pytest + :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Aug 27, 2023 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Aug 20, 2023 4 - Beta pytest >=7.0.0 @@ -987,7 +987,7 @@ This list contains 1329 plugins. :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest - :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 02, 2023 5 - Production/Stable pytest >=3.6 + :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jun 09, 2021 4 - Beta pytest (>=3.0.0) :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A @@ -1057,7 +1057,7 @@ This list contains 1329 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 06, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 13, 2023 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Mar 14, 2022 5 - Production/Stable pytest (>=3.5.0) @@ -1066,7 +1066,7 @@ This list contains 1329 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Oct 03, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 06, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 13, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 @@ -1157,7 +1157,7 @@ This list contains 1329 plugins. :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A - :pypi:`pytest-stf` pytest plugin for openSTF Aug 16, 2023 N/A pytest >=5.0 + :pypi:`pytest-stf` pytest plugin for openSTF Oct 10, 2023 N/A pytest >=5.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-structlog` Structured logging assertions Dec 18, 2022 N/A pytest @@ -1221,7 +1221,7 @@ This list contains 1329 plugins. :pypi:`pytest-testrail-plugin` PyTest plugin for TestRail Apr 21, 2020 3 - Alpha pytest :pypi:`pytest-testrail-reporter` Sep 10, 2018 N/A N/A :pypi:`pytest-testreport` Dec 01, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-testreport-new` Aug 15, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-testreport-new` Oct 07, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) @@ -1235,7 +1235,7 @@ This list contains 1329 plugins. :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A - :pypi:`pytest-timeout` pytest plugin to abort hanging tests Jan 18, 2022 5 - Production/Stable pytest (>=5.0.0) + :pypi:`pytest-timeout` pytest plugin to abort hanging tests Oct 08, 2023 5 - Production/Stable pytest >=5.0.0 :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A :pypi:`pytest-timer` A timer plugin for pytest Jun 02, 2021 N/A N/A :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A @@ -1411,9 +1411,9 @@ This list contains 1329 plugins. pytest plugin for generating test execution results within Jira Test Management (tm4j) :pypi:`pytest-adaptavist-fixed` - *last release*: Sep 21, 2023, + *last release*: Oct 12, 2023, *status*: N/A, - *requires*: N/A + *requires*: pytest >=5.4.0 pytest plugin for generating test execution results within Jira Test Management (tm4j) @@ -1628,7 +1628,7 @@ This list contains 1329 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Sep 13, 2023, + *last release*: Oct 11, 2023, *status*: 5 - Production/Stable, *requires*: pytest <8.0.0,>=6 @@ -2048,7 +2048,7 @@ This list contains 1329 plugins. pytest plugin for URL based testing :pypi:`pytest-bdd` - *last release*: Nov 08, 2022, + *last release*: Oct 10, 2023, *status*: 6 - Mature, *requires*: pytest (>=6.2.0) @@ -2426,7 +2426,7 @@ This list contains 1329 plugins. pytest plugin to capture all warnings and put them in one file of your choice :pypi:`pytest-cases` - *last release*: Feb 23, 2023, + *last release*: Oct 11, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -2979,7 +2979,7 @@ This list contains 1329 plugins. Manages CrateDB instances during your integration tests :pypi:`pytest-crayons` - *last release*: Mar 19, 2023, + *last release*: Oct 08, 2023, *status*: N/A, *requires*: pytest @@ -4204,9 +4204,9 @@ This list contains 1329 plugins. Walk your code through exception script to check it's resiliency to failures. :pypi:`pytest-executable` - *last release*: Mar 25, 2023, + *last release*: Oct 07, 2023, *status*: N/A, - *requires*: pytest (<8,>=4.3) + *requires*: pytest <8,>=5 pytest plugin for testing executables @@ -4330,9 +4330,9 @@ This list contains 1329 plugins. Use factories for test setup with py.test :pypi:`pytest-factoryboy` - *last release*: Dec 01, 2022, + *last release*: Oct 10, 2023, *status*: 6 - Mature, - *requires*: pytest (>=5.0.0) + *requires*: pytest (>=6.2) Factory Boy support for pytest. @@ -4841,7 +4841,7 @@ This list contains 1329 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Oct 04, 2023, + *last release*: Oct 09, 2023, *status*: N/A, *requires*: N/A @@ -4855,7 +4855,7 @@ This list contains 1329 plugins. Git repository fixture for py.test :pypi:`pytest-gitconfig` - *last release*: Jun 22, 2023, + *last release*: Oct 14, 2023, *status*: 4 - Beta, *requires*: pytest>=7.1.2 @@ -5086,9 +5086,9 @@ This list contains 1329 plugins. Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report :pypi:`pytest-home` - *last release*: Oct 05, 2023, + *last release*: Oct 09, 2023, *status*: 5 - Production/Stable, - *requires*: pytest >=6 ; extra == 'testing' + *requires*: pytest Home directory fixtures @@ -5100,7 +5100,7 @@ This list contains 1329 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Oct 07, 2023, + *last release*: Oct 14, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.3.1 @@ -5352,9 +5352,9 @@ This list contains 1329 plugins. Pytest plugin for testing function idempotence. :pypi:`pytest-ignore-flaky` - *last release*: Apr 23, 2021, + *last release*: Oct 11, 2023, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest >=6.0 ignore failures from flaky tests (pytest plugin) @@ -5422,9 +5422,9 @@ This list contains 1329 plugins. Reuse pytest.ini to store env variables :pypi:`pytest-inline` - *last release*: Feb 08, 2023, + *last release*: Oct 10, 2023, *status*: 4 - Beta, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 A pytest plugin for writing inline tests. @@ -5436,7 +5436,7 @@ This list contains 1329 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Jul 04, 2023, + *last release*: Oct 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5982,7 +5982,7 @@ This list contains 1329 plugins. A PyTest plugin which provides an FTP fixture for your tests :pypi:`pytest-localserver` - *last release*: Jul 16, 2023, + *last release*: Oct 12, 2023, *status*: 4 - Beta, *requires*: N/A @@ -6220,7 +6220,7 @@ This list contains 1329 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: Sep 10, 2023, + *last release*: Oct 08, 2023, *status*: 4 - Beta, *requires*: pytest !=6.0.0,<8,>=3.3.2 @@ -6787,9 +6787,9 @@ This list contains 1329 plugins. A PyTest Reporter to send test runs to Notion.so :pypi:`pytest-nunit` - *last release*: Oct 20, 2022, + *last release*: Oct 11, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.6.0) + *requires*: N/A A pytest plugin for generating NUnit3 test result XML output @@ -7263,7 +7263,7 @@ This list contains 1329 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Aug 07, 2023, + *last release*: Oct 09, 2023, *status*: N/A, *requires*: pytest (<8.0.0,>=6.2.4) @@ -7627,7 +7627,7 @@ This list contains 1329 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Aug 29, 2023, + *last release*: Oct 10, 2023, *status*: N/A, *requires*: pytest @@ -7662,7 +7662,7 @@ This list contains 1329 plugins. Pytest fixture "q" for pyq :pypi:`pytest-pyramid` - *last release*: Dec 13, 2022, + *last release*: Oct 11, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -8040,9 +8040,9 @@ This list contains 1329 plugins. Reorder tests depending on their paths and names. :pypi:`pytest-repeat` - *last release*: Oct 02, 2023, + *last release*: Oct 09, 2023, *status*: 5 - Production/Stable, - *requires*: pytest >=3.6 + *requires*: pytest pytest plugin for repeating tests @@ -8530,7 +8530,7 @@ This list contains 1329 plugins. :pypi:`pytest-sbase` - *last release*: Oct 06, 2023, + *last release*: Oct 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8593,7 +8593,7 @@ This list contains 1329 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Oct 06, 2023, + *last release*: Oct 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9230,7 +9230,7 @@ This list contains 1329 plugins. Run a test suite one failing test at a time. :pypi:`pytest-stf` - *last release*: Aug 16, 2023, + *last release*: Oct 10, 2023, *status*: N/A, *requires*: pytest >=5.0 @@ -9678,9 +9678,9 @@ This list contains 1329 plugins. :pypi:`pytest-testreport-new` - *last release*: Aug 15, 2022, + *last release*: Oct 07, 2023, *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *requires*: pytest >=3.5.0 @@ -9776,9 +9776,9 @@ This list contains 1329 plugins. A pytest plugin to time test function runs :pypi:`pytest-timeout` - *last release*: Jan 18, 2022, + *last release*: Oct 08, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.0.0) + *requires*: pytest >=5.0.0 pytest plugin to abort hanging tests From cdddd6d69533c07092c64445a0d42d1fc75c8299 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Oct 2023 08:08:50 -0300 Subject: [PATCH 0221/1271] build(deps): Bump pytest-bdd in /testing/plugins_integration (#11506) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 6.1.1 to 7.0.0. - [Release notes](https://github.com/pytest-dev/pytest-bdd/releases) - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/6.1.1...7.0.0) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 599706b2b4f..82d1a55a757 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,7 +1,7 @@ anyio[curio,trio]==4.0.0 django==4.2.6 pytest-asyncio==0.21.1 -pytest-bdd==6.1.1 +pytest-bdd==7.0.0 pytest-cov==4.1.0 pytest-django==4.5.2 pytest-flakes==4.0.5 From cac1eed0ea2901c6acc249cdd0050fe61caf1e85 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 21 Oct 2023 23:43:14 -0300 Subject: [PATCH 0222/1271] [automated] Update plugin list (#11534) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 108 ++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 38 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 0761c00a5a4..6ee6098cf33 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =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 @@ -329,7 +330,7 @@ This list contains 1329 plugins. :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Jun 23, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Jul 16, 2023 4 - Beta pytest (!=6.0.0,<8,>=3.3.2) + :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 :pypi:`pytest-django` A Django plugin for pytest. Dec 07, 2021 5 - Production/Stable pytest (>=5.4.0) :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest @@ -532,7 +533,7 @@ This list contains 1329 plugins. :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. Oct 09, 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 14, 2023 4 - Beta pytest>=7.1.2 + :pypi:`pytest-gitconfig` Provide a gitconfig sandbox for testing Oct 15, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A @@ -613,7 +614,7 @@ This list contains 1329 plugins. :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A - :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 10, 2023 4 - Beta pytest >=7.0.0 + :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 19, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Aug 03, 2023 5 - Production/Stable N/A :pypi:`pytest-inmanta-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 @@ -692,7 +693,7 @@ This list contains 1329 plugins. :pypi:`pytest-litter` Pytest plugin which verifies that tests do not modify file trees. Aug 08, 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 04, 2022 5 - Production/Stable pytest + :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests Oct 14, 2023 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lockable` lockable resource plugin for pytest Aug 09, 2023 5 - Production/Stable pytest @@ -745,7 +746,7 @@ This list contains 1329 plugins. :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) - :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Jun 15, 2023 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Oct 19, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-mock-api` A mock API server with configurable routes and responses available as a fixture. Feb 13, 2019 1 - Planning pytest (>=4.0.0) :pypi:`pytest-mock-generator` A pytest fixture wrapper for https://pypi.org/project/mock-generator May 16, 2022 5 - Production/Stable N/A :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest @@ -784,7 +785,7 @@ This list contains 1329 plugins. :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) - :pypi:`pytest-ndb` Open Source Software Health Report Jul 19, 2023 N/A pytest + :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Sep 21, 2023 N/A pytest <7.3,>=3.5.0 @@ -846,6 +847,7 @@ This list contains 1329 plugins. :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Sep 13, 2022 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest + :pypi:`pytest-param-scope` pytest parametrize scope fixture workaround Oct 18, 2023 N/A pytest :pypi:`pytest-parawtf` Finally spell paramete?ri[sz]e correctly Dec 03, 2018 4 - Beta pytest (>=3.6.0) :pypi:`pytest-pass` Check out https://github.com/elilutsky/pytest-pass Dec 04, 2019 N/A N/A :pypi:`pytest-passrunner` Pytest plugin providing the 'run_on_pass' marker Feb 10, 2021 5 - Production/Stable pytest (>=4.6.0) @@ -885,10 +887,10 @@ This list contains 1329 plugins. :pypi:`pytest-plone` Pytest plugin to test Plone addons Jan 05, 2023 3 - Alpha pytest :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Aug 17, 2020 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Dec 24, 2022 5 - Production/Stable pytest (>=6.0.1) + :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Oct 18, 2023 5 - Production/Stable pytest >=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A - :pypi:`pytest-pokie` Pokie plugin for pytest May 22, 2023 5 - Production/Stable N/A + :pypi:`pytest-pokie` Pokie plugin for pytest Oct 19, 2023 5 - Production/Stable N/A :pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A :pypi:`pytest-polarion-collect` pytest plugin for collecting polarion test cases data Jun 18, 2020 3 - Alpha pytest :pypi:`pytest-polecat` Provides Polecat pytest fixtures Aug 12, 2019 4 - Beta N/A @@ -999,7 +1001,7 @@ This list contains 1329 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Sep 25, 2023 N/A pytest >=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Oct 17, 2023 N/A pytest >=3.8.0 :pypi:`pytest-reports` An interesting python package Jun 07, 2023 N/A N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) @@ -1019,7 +1021,7 @@ This list contains 1329 plugins. :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jul 10, 2023 5 - Production/Stable pytest - :pypi:`pytest-result-log` Write the execution result of the case to the log Apr 17, 2023 N/A pytest>=7.2.0 + :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Oct 15, 2023 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A @@ -1057,7 +1059,7 @@ This list contains 1329 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 20, 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) @@ -1065,8 +1067,8 @@ This list contains 1329 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Oct 03, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-selenium-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Oct 18, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 20, 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-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 @@ -1095,7 +1097,7 @@ This list contains 1329 plugins. :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest :pypi:`pytest-single-file-logging` Allow for multiple processes to log to a single file May 05, 2016 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-skip-markers` Pytest Salt Plugin Jul 31, 2023 5 - Production/Stable pytest (>=7.1.0) + :pypi:`pytest-skip-markers` Pytest Salt Plugin Oct 20, 2023 5 - Production/Stable pytest >=7.1.0 :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 @@ -1204,7 +1206,7 @@ This list contains 1329 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 Jul 13, 2023 4 - Beta pytest (<8,>=5) + :pypi:`pytest-testmon` selects tests affected by changed files and methods Oct 17, 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) @@ -1287,6 +1289,7 @@ This list contains 1329 plugins. :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) + :pypi:`pytest-unitvis` Oct 20, 2023 3 - Alpha pytest >=7.0.0 :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A @@ -1322,6 +1325,7 @@ This list contains 1329 plugins. :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A + :pypi:`pytest-when` Utility which makes mocking more readable and controllable Oct 18, 2023 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -2572,6 +2576,13 @@ This list contains 1329 plugins. A pytest plugin to send a report and printing summary of tests. + :pypi:`pytest-choose` + *last release*: Oct 17, 2023, + *status*: N/A, + *requires*: pytest >=7.0.0 + + Provide the pytest with the ability to collect use cases based on rules in text files + :pypi:`pytest-chunks` *last release*: Jul 05, 2022, *status*: N/A, @@ -3434,9 +3445,9 @@ This list contains 1329 plugins. Disable plugins per test :pypi:`pytest-discord` - *last release*: Jul 16, 2023, + *last release*: Oct 18, 2023, *status*: 4 - Beta, - *requires*: pytest (!=6.0.0,<8,>=3.3.2) + *requires*: pytest !=6.0.0,<8,>=3.3.2 A pytest plugin to notify test results to a Discord channel. @@ -4855,7 +4866,7 @@ This list contains 1329 plugins. Git repository fixture for py.test :pypi:`pytest-gitconfig` - *last release*: Oct 14, 2023, + *last release*: Oct 15, 2023, *status*: 4 - Beta, *requires*: pytest>=7.1.2 @@ -5422,7 +5433,7 @@ This list contains 1329 plugins. Reuse pytest.ini to store env variables :pypi:`pytest-inline` - *last release*: Oct 10, 2023, + *last release*: Oct 19, 2023, *status*: 4 - Beta, *requires*: pytest >=7.0.0 @@ -5975,7 +5986,7 @@ This list contains 1329 plugins. Generate local badges (shields) reporting your test suite status. :pypi:`pytest-localftpserver` - *last release*: Oct 04, 2022, + *last release*: Oct 14, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -6346,9 +6357,9 @@ This list contains 1329 plugins. pytest plugin to display test execution output like a mochajs :pypi:`pytest-mock` - *last release*: Jun 15, 2023, + *last release*: Oct 19, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.0) + *requires*: pytest >=5.0 Thin-wrapper around the mock package for easier use with pytest @@ -6619,11 +6630,11 @@ This list contains 1329 plugins. MySQL process and client fixtures for pytest :pypi:`pytest-ndb` - *last release*: Jul 19, 2023, + *last release*: Oct 15, 2023, *status*: N/A, *requires*: pytest - Open Source Software Health Report + pytest notebook debugger :pypi:`pytest-needle` *last release*: Dec 10, 2018, @@ -7052,6 +7063,13 @@ This list contains 1329 plugins. A simple pytest extension for creating a named test suite. + :pypi:`pytest-param-scope` + *last release*: Oct 18, 2023, + *status*: N/A, + *requires*: pytest + + pytest parametrize scope fixture workaround + :pypi:`pytest-parawtf` *last release*: Dec 03, 2018, *status*: 4 - Beta, @@ -7326,9 +7344,9 @@ This list contains 1329 plugins. A plugin to help developing and testing other plugins :pypi:`pytest-plus` - *last release*: Dec 24, 2022, + *last release*: Oct 18, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.0.1) + *requires*: pytest >=7.4.2 PyTest Plus Plugin :: extends pytest functionality @@ -7347,7 +7365,7 @@ This list contains 1329 plugins. Pytest plugin to define functions you test with special marks for better navigation and reports :pypi:`pytest-pokie` - *last release*: May 22, 2023, + *last release*: Oct 19, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8124,7 +8142,7 @@ This list contains 1329 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Sep 25, 2023, + *last release*: Oct 17, 2023, *status*: N/A, *requires*: pytest >=3.8.0 @@ -8264,11 +8282,11 @@ This list contains 1329 plugins. Pytest plugin to restrict the test types allowed :pypi:`pytest-result-log` - *last release*: Apr 17, 2023, + *last release*: Oct 15, 2023, *status*: N/A, *requires*: pytest>=7.2.0 - Write the execution result of the case to the log + A pytest plugin that records the start, end, and result information of each use case in a log file :pypi:`pytest-result-sender` *last release*: Apr 20, 2023, @@ -8530,7 +8548,7 @@ This list contains 1329 plugins. :pypi:`pytest-sbase` - *last release*: Oct 13, 2023, + *last release*: Oct 20, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8586,14 +8604,14 @@ This list contains 1329 plugins. pytest plugin for Selenium :pypi:`pytest-selenium-auto` - *last release*: Oct 03, 2023, + *last release*: Oct 18, 2023, *status*: N/A, *requires*: pytest >= 7.0.0 pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Oct 13, 2023, + *last release*: Oct 20, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8796,9 +8814,9 @@ This list contains 1329 plugins. Allow for multiple processes to log to a single file :pypi:`pytest-skip-markers` - *last release*: Jul 31, 2023, + *last release*: Oct 20, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.1.0) + *requires*: pytest >=7.1.0 Pytest Salt Plugin @@ -9559,9 +9577,9 @@ This list contains 1329 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: Jul 13, 2023, + *last release*: Oct 17, 2023, *status*: 4 - Beta, - *requires*: pytest (<8,>=5) + *requires*: pytest <8,>=5 selects tests affected by changed files and methods @@ -10139,6 +10157,13 @@ This list contains 1329 plugins. A pytest plugin for filtering unittest-based test classes + :pypi:`pytest-unitvis` + *last release*: Oct 20, 2023, + *status*: 3 - Alpha, + *requires*: pytest >=7.0.0 + + + :pypi:`pytest-unmarked` *last release*: Aug 27, 2019, *status*: 5 - Production/Stable, @@ -10384,6 +10409,13 @@ This list contains 1329 plugins. Welian API Automation test framework pytest plugin + :pypi:`pytest-when` + *last release*: Oct 18, 2023, + *status*: N/A, + *requires*: pytest>=7.3.1 + + Utility which makes mocking more readable and controllable + :pypi:`pytest-whirlwind` *last release*: Jun 12, 2020, *status*: N/A, From 40e9abd66b3b8cafa11a08442f16849d92478fc7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 08:05:40 -0300 Subject: [PATCH 0223/1271] [pre-commit.ci] pre-commit autoupdate (#11510) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/pre-commit/mirrors-mypy: v1.5.1 → v1.6.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.5.1...v1.6.0) * Ignore two typing errors after updating to mypy 1.6.0 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bruno Oliveira --- .pre-commit-config.yaml | 2 +- src/_pytest/_py/path.py | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1b7b0278e65..bb2a464ba70 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.5.1 + rev: v1.6.0 hooks: - id: mypy files: ^(src/|testing/) diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 41a7926c5ed..24348525a3e 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -755,7 +755,13 @@ def open(self, mode="r", ensure=False, encoding=None): if ensure: self.dirpath().ensure(dir=1) if encoding: - return error.checked_call(io.open, self.strpath, mode, encoding=encoding) + # Using type ignore here because of this error: + # error: Argument 1 has incompatible type overloaded function; + # expected "Callable[[str, Any, Any], TextIOWrapper]" [arg-type] + # Which seems incorrect, given io.open supports the given argument types. + return error.checked_call( + io.open, self.strpath, mode, encoding=encoding # type:ignore[arg-type] + ) return error.checked_call(open, self.strpath, mode) def _fastjoin(self, name): @@ -1261,13 +1267,19 @@ def get_temproot(cls): @classmethod def mkdtemp(cls, rootdir=None): """Return a Path object pointing to a fresh new temporary directory - (which we created ourself). + (which we created ourselves). """ import tempfile if rootdir is None: rootdir = cls.get_temproot() - return cls(error.checked_call(tempfile.mkdtemp, dir=str(rootdir))) + # Using type ignore here because of this error: + # error: Argument 1 has incompatible type overloaded function; expected "Callable[[str], str]" [arg-type] + # Which seems incorrect, given tempfile.mkdtemp supports the given argument types. + path = error.checked_call( + tempfile.mkdtemp, dir=str(rootdir) # type:ignore[arg-type] + ) + return cls(path) @classmethod def make_numbered_dir( From 304ab8495e11a0182fa2d65f4d7603ee3420db1c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 09:01:08 -0300 Subject: [PATCH 0224/1271] build(deps): Bump pytest-mock in /testing/plugins_integration (#11539) Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.11.1 to 3.12.0. - [Release notes](https://github.com/pytest-dev/pytest-mock/releases) - [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.11.1...v3.12.0) --- updated-dependencies: - dependency-name: pytest-mock dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 82d1a55a757..6fc3e8dc415 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -6,7 +6,7 @@ pytest-cov==4.1.0 pytest-django==4.5.2 pytest-flakes==4.0.5 pytest-html==4.0.2 -pytest-mock==3.11.1 +pytest-mock==3.12.0 pytest-rerunfailures==12.0 pytest-sugar==0.9.7 pytest-trio==0.7.0 From ee53433542463c91c12dace0ea7046087417cbbd Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 23 Oct 2023 09:56:33 -0300 Subject: [PATCH 0225/1271] Configure ReadTheDocs to fail on warnings (#11535) * Configure ReadTheDocs to fail on warnings Important to catch broken links and references. * Remove dead link to distutils configuration docs --- .readthedocs.yml | 4 ++++ doc/en/reference/customize.rst | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index b506c5f4039..266d4e07aea 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,6 +9,10 @@ python: path: . - requirements: doc/en/requirements.txt +sphinx: + configuration: doc/en/conf.py + fail_on_warning: true + build: os: ubuntu-20.04 tools: diff --git a/doc/en/reference/customize.rst b/doc/en/reference/customize.rst index b794d646b8e..24c0ed21752 100644 --- a/doc/en/reference/customize.rst +++ b/doc/en/reference/customize.rst @@ -90,7 +90,7 @@ and can also be used to hold pytest configuration if they have a ``[pytest]`` se setup.cfg ~~~~~~~~~ -``setup.cfg`` files are general purpose configuration files, used originally by :doc:`distutils `, and can also be used to hold pytest configuration +``setup.cfg`` files are general purpose configuration files, used originally by ``distutils`` (now deprecated) and `setuptools `__, and can also be used to hold pytest configuration if they have a ``[tool:pytest]`` section. .. code-block:: ini From 395bbae8a28e2d5302d54ef94fc583b065d9a1c1 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 21 Oct 2023 15:35:07 -0300 Subject: [PATCH 0226/1271] Ensure logging tests always cleanup after themselves Logging has many global states, and we did foresee this by creating a ``cleanup_disabled_logging`` fixture, however one might still forget to use it and failures leak later -- sometimes not even in the same PR, because the order of the tests might change in the future, specially when running under xdist. This problem surfaced during pytest-dev/pytest#11530, where tests unrelated to the change started to fail. --- testing/logging/test_fixture.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index 8eaa2de96a8..193535bace5 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -1,5 +1,6 @@ # mypy: disable-error-code="attr-defined" import logging +from typing import Iterator import pytest from _pytest.logging import caplog_records_key @@ -9,8 +10,8 @@ sublogger = logging.getLogger(__name__ + ".baz") -@pytest.fixture -def cleanup_disabled_logging(): +@pytest.fixture(autouse=True) +def cleanup_disabled_logging() -> Iterator[None]: """Simple fixture that ensures that a test doesn't disable logging. This is necessary because ``logging.disable()`` is global, so a test disabling logging @@ -42,7 +43,7 @@ def test_change_level(caplog): assert "CRITICAL" in caplog.text -def test_change_level_logging_disabled(caplog, cleanup_disabled_logging): +def test_change_level_logging_disabled(caplog): logging.disable(logging.CRITICAL) assert logging.root.manager.disable == logging.CRITICAL caplog.set_level(logging.WARNING) @@ -85,9 +86,7 @@ def test2(caplog): result.stdout.no_fnmatch_line("*log from test2*") -def test_change_disabled_level_undo( - pytester: Pytester, cleanup_disabled_logging -) -> None: +def test_change_disabled_level_undo(pytester: Pytester) -> None: """Ensure that '_force_enable_logging' in 'set_level' is undone after the end of the test. Tests the logging output themselves (affected by disabled logging level). @@ -159,7 +158,7 @@ def test_with_statement(caplog): assert "CRITICAL" in caplog.text -def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging): +def test_with_statement_logging_disabled(caplog): logging.disable(logging.CRITICAL) assert logging.root.manager.disable == logging.CRITICAL with caplog.at_level(logging.WARNING): @@ -197,9 +196,7 @@ def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging): ("NOTVALIDLEVEL", logging.NOTSET), ], ) -def test_force_enable_logging_level_string( - caplog, cleanup_disabled_logging, level_str, expected_disable_level -): +def test_force_enable_logging_level_string(caplog, level_str, expected_disable_level): """Test _force_enable_logging using a level string. ``expected_disable_level`` is one level below ``level_str`` because the disabled log level From 7e69ce744909372c9686ab5efe5180de1799df73 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 21 Oct 2023 16:02:54 -0300 Subject: [PATCH 0227/1271] Add full type annotations to logging/test_fixture.py --- testing/logging/test_fixture.py | 47 +++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index 193535bace5..753cf5fcd03 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -1,4 +1,5 @@ # mypy: disable-error-code="attr-defined" +# mypy: disallow-untyped-defs import logging from typing import Iterator @@ -28,7 +29,7 @@ def test_fixture_help(pytester: Pytester) -> None: result.stdout.fnmatch_lines(["*caplog*"]) -def test_change_level(caplog): +def test_change_level(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.debug("handler DEBUG level") logger.info("handler INFO level") @@ -43,7 +44,7 @@ def test_change_level(caplog): assert "CRITICAL" in caplog.text -def test_change_level_logging_disabled(caplog): +def test_change_level_logging_disabled(caplog: pytest.LogCaptureFixture) -> None: logging.disable(logging.CRITICAL) assert logging.root.manager.disable == logging.CRITICAL caplog.set_level(logging.WARNING) @@ -143,7 +144,7 @@ def test3(caplog): result.assert_outcomes(passed=3) -def test_with_statement(caplog): +def test_with_statement(caplog: pytest.LogCaptureFixture) -> None: with caplog.at_level(logging.INFO): logger.debug("handler DEBUG level") logger.info("handler INFO level") @@ -158,7 +159,7 @@ def test_with_statement(caplog): assert "CRITICAL" in caplog.text -def test_with_statement_logging_disabled(caplog): +def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> None: logging.disable(logging.CRITICAL) assert logging.root.manager.disable == logging.CRITICAL with caplog.at_level(logging.WARNING): @@ -196,7 +197,9 @@ def test_with_statement_logging_disabled(caplog): ("NOTVALIDLEVEL", logging.NOTSET), ], ) -def test_force_enable_logging_level_string(caplog, level_str, expected_disable_level): +def test_force_enable_logging_level_string( + caplog: pytest.LogCaptureFixture, level_str: str, expected_disable_level: int +) -> None: """Test _force_enable_logging using a level string. ``expected_disable_level`` is one level below ``level_str`` because the disabled log level @@ -215,7 +218,7 @@ def test_force_enable_logging_level_string(caplog, level_str, expected_disable_l assert test_logger.manager.disable == expected_disable_level -def test_log_access(caplog): +def test_log_access(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("boo %s", "arg") assert caplog.records[0].levelname == "INFO" @@ -223,7 +226,7 @@ def test_log_access(caplog): assert "boo arg" in caplog.text -def test_messages(caplog): +def test_messages(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("boo %s", "arg") logger.info("bar %s\nbaz %s", "arg1", "arg2") @@ -244,14 +247,14 @@ def test_messages(caplog): assert "Exception" not in caplog.messages[-1] -def test_record_tuples(caplog): +def test_record_tuples(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("boo %s", "arg") assert caplog.record_tuples == [(__name__, logging.INFO, "boo arg")] -def test_unicode(caplog): +def test_unicode(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("bū") assert caplog.records[0].levelname == "INFO" @@ -259,7 +262,7 @@ def test_unicode(caplog): assert "bū" in caplog.text -def test_clear(caplog): +def test_clear(caplog: pytest.LogCaptureFixture) -> None: caplog.set_level(logging.INFO) logger.info("bū") assert len(caplog.records) @@ -270,7 +273,9 @@ def test_clear(caplog): @pytest.fixture -def logging_during_setup_and_teardown(caplog): +def logging_during_setup_and_teardown( + caplog: pytest.LogCaptureFixture, +) -> Iterator[None]: caplog.set_level("INFO") logger.info("a_setup_log") yield @@ -278,7 +283,9 @@ def logging_during_setup_and_teardown(caplog): assert [x.message for x in caplog.get_records("teardown")] == ["a_teardown_log"] -def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardown): +def test_caplog_captures_for_all_stages( + caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None +) -> None: assert not caplog.records assert not caplog.get_records("call") logger.info("a_call_log") @@ -287,25 +294,31 @@ def test_caplog_captures_for_all_stages(caplog, logging_during_setup_and_teardow assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] # This reaches into private API, don't use this type of thing in real tests! - assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"} + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} -def test_clear_for_call_stage(caplog, logging_during_setup_and_teardown): +def test_clear_for_call_stage( + caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None +) -> None: logger.info("a_call_log") assert [x.message for x in caplog.get_records("call")] == ["a_call_log"] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"} + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} caplog.clear() assert caplog.get_records("call") == [] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"} + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} logging.info("a_call_log_after_clear") assert [x.message for x in caplog.get_records("call")] == ["a_call_log_after_clear"] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"} + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} def test_ini_controls_global_log_level(pytester: Pytester) -> None: From 38f7c1e3469369bfdad2a6b1019578c3e0522501 Mon Sep 17 00:00:00 2001 From: Carsten Grohmann Date: Mon, 23 Oct 2023 20:45:16 +0200 Subject: [PATCH 0228/1271] Use pytestconfig instead of request.config in cache example (#11542) to be consistent with the API documentation. --- changelog/11065.doc.rst | 3 +++ doc/en/how-to/cache.rst | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 changelog/11065.doc.rst diff --git a/changelog/11065.doc.rst b/changelog/11065.doc.rst new file mode 100644 index 00000000000..70a3db92c09 --- /dev/null +++ b/changelog/11065.doc.rst @@ -0,0 +1,3 @@ +Use pytestconfig instead of request.config in cache example + +to be consistent with the API documentation. diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index 03ab0c77780..1b2a454cc2e 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -213,12 +213,12 @@ across pytest invocations: @pytest.fixture - def mydata(request): - val = request.config.cache.get("example/value", None) + def mydata(pytestconfig): + val = pytestconfig.cache.get("example/value", None) if val is None: expensive_computation() val = 42 - request.config.cache.set("example/value", val) + pytestconfig.cache.set("example/value", val) return val From 667b9fd7fd4a1965c8a15849397498a7c905e0bd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 03:42:43 +0200 Subject: [PATCH 0229/1271] [pre-commit.ci] pre-commit autoupdate (#11543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.9.1 → 23.10.1](https://github.com/psf/black/compare/23.9.1...23.10.1) - [github.com/pre-commit/mirrors-mypy: v1.6.0 → v1.6.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.6.0...v1.6.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bb2a464ba70..0f7e4b2a726 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 23.10.1 hooks: - id: black args: [--safe, --quiet] @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.6.0 + rev: v1.6.1 hooks: - id: mypy files: ^(src/|testing/) From fbe3e29a55ea8f299659e2be1392ade8b3b9a642 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Tue, 24 Oct 2023 12:42:21 +0100 Subject: [PATCH 0230/1271] Color the full diff that pytest shows as a diff (#11530) Related to #11520 --- AUTHORS | 1 + changelog/11520.improvement.rst | 1 + src/_pytest/_io/terminalwriter.py | 15 ++++++--- src/_pytest/assertion/util.py | 39 ++++++++++++++++++----- testing/conftest.py | 9 ++++++ testing/test_assertion.py | 52 +++++++++++++++++++++++++++++++ 6 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 changelog/11520.improvement.rst diff --git a/AUTHORS b/AUTHORS index f3461addfb7..5ccff644c1c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -56,6 +56,7 @@ Barney Gale Ben Gartner Ben Webb Benjamin Peterson +Benjamin Schubert Bernard Pratz Bo Wu Bob Ippolito diff --git a/changelog/11520.improvement.rst b/changelog/11520.improvement.rst new file mode 100644 index 00000000000..46e4992dd39 --- /dev/null +++ b/changelog/11520.improvement.rst @@ -0,0 +1 @@ +Improved very verbose diff output to color it as a diff instead of only red. diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index eb1b469395e..934278b93ed 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -3,6 +3,7 @@ import shutil import sys from typing import final +from typing import Literal from typing import Optional from typing import Sequence from typing import TextIO @@ -193,15 +194,21 @@ def _write_source(self, lines: Sequence[str], indents: Sequence[str] = ()) -> No for indent, new_line in zip(indents, new_lines): self.line(indent + new_line) - def _highlight(self, source: str) -> str: - """Highlight the given source code if we have markup support.""" + def _highlight( + self, source: str, lexer: Literal["diff", "python"] = "python" + ) -> str: + """Highlight the given source if we have markup support.""" from _pytest.config.exceptions import UsageError if not self.hasmarkup or not self.code_highlight: return source try: from pygments.formatters.terminal import TerminalFormatter - from pygments.lexers.python import PythonLexer + + if lexer == "python": + from pygments.lexers.python import PythonLexer as Lexer + elif lexer == "diff": + from pygments.lexers.diff import DiffLexer as Lexer from pygments import highlight import pygments.util except ImportError: @@ -210,7 +217,7 @@ def _highlight(self, source: str) -> str: try: highlighted: str = highlight( source, - PythonLexer(), + Lexer(), TerminalFormatter( bg=os.getenv("PYTEST_THEME_MODE", "dark"), style=os.getenv("PYTEST_THEME"), diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 057352cd387..b9123c97dbe 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -7,8 +7,10 @@ from typing import Callable from typing import Iterable from typing import List +from typing import Literal from typing import Mapping from typing import Optional +from typing import Protocol from typing import Sequence from unicodedata import normalize @@ -33,6 +35,11 @@ _config: Optional[Config] = None +class _HighlightFunc(Protocol): + def __call__(self, source: str, lexer: Literal["diff", "python"] = "python") -> str: + """Apply highlighting to the given source.""" + + def format_explanation(explanation: str) -> str: r"""Format an explanation. @@ -189,7 +196,8 @@ def assertrepr_compare( explanation = None try: if op == "==": - explanation = _compare_eq_any(left, right, verbose) + writer = config.get_terminal_writer() + explanation = _compare_eq_any(left, right, writer._highlight, verbose) elif op == "not in": if istext(left) and istext(right): explanation = _notin_text(left, right, verbose) @@ -225,7 +233,9 @@ def assertrepr_compare( return [summary] + explanation -def _compare_eq_any(left: Any, right: Any, verbose: int = 0) -> List[str]: +def _compare_eq_any( + left: Any, right: Any, highlighter: _HighlightFunc, verbose: int = 0 +) -> List[str]: explanation = [] if istext(left) and istext(right): explanation = _diff_text(left, right, verbose) @@ -245,7 +255,7 @@ def _compare_eq_any(left: Any, right: Any, verbose: int = 0) -> List[str]: # field values, not the type or field names. But this branch # intentionally only handles the same-type case, which was often # used in older code bases before dataclasses/attrs were available. - explanation = _compare_eq_cls(left, right, verbose) + explanation = _compare_eq_cls(left, right, highlighter, verbose) elif issequence(left) and issequence(right): explanation = _compare_eq_sequence(left, right, verbose) elif isset(left) and isset(right): @@ -254,7 +264,7 @@ def _compare_eq_any(left: Any, right: Any, verbose: int = 0) -> List[str]: explanation = _compare_eq_dict(left, right, verbose) if isiterable(left) and isiterable(right): - expl = _compare_eq_iterable(left, right, verbose) + expl = _compare_eq_iterable(left, right, highlighter, verbose) explanation.extend(expl) return explanation @@ -321,7 +331,10 @@ def _surrounding_parens_on_own_lines(lines: List[str]) -> None: def _compare_eq_iterable( - left: Iterable[Any], right: Iterable[Any], verbose: int = 0 + left: Iterable[Any], + right: Iterable[Any], + highligher: _HighlightFunc, + verbose: int = 0, ) -> List[str]: if verbose <= 0 and not running_on_ci(): return ["Use -v to get more diff"] @@ -346,7 +359,13 @@ def _compare_eq_iterable( # "right" is the expected base against which we compare "left", # see https://github.com/pytest-dev/pytest/issues/3333 explanation.extend( - line.rstrip() for line in difflib.ndiff(right_formatting, left_formatting) + highligher( + "\n".join( + line.rstrip() + for line in difflib.ndiff(right_formatting, left_formatting) + ), + lexer="diff", + ).splitlines() ) return explanation @@ -496,7 +515,9 @@ def _compare_eq_dict( return explanation -def _compare_eq_cls(left: Any, right: Any, verbose: int) -> List[str]: +def _compare_eq_cls( + left: Any, right: Any, highlighter: _HighlightFunc, verbose: int +) -> List[str]: if not has_default_eq(left): return [] if isdatacls(left): @@ -542,7 +563,9 @@ def _compare_eq_cls(left: Any, right: Any, verbose: int) -> List[str]: ] explanation += [ indent + line - for line in _compare_eq_any(field_left, field_right, verbose) + for line in _compare_eq_any( + field_left, field_right, highlighter, verbose + ) ] return explanation diff --git a/testing/conftest.py b/testing/conftest.py index 06116fee49d..6a50e810fbd 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -160,6 +160,9 @@ class ColorMapping: "red": "\x1b[31m", "green": "\x1b[32m", "yellow": "\x1b[33m", + "light-gray": "\x1b[90m", + "light-red": "\x1b[91m", + "light-green": "\x1b[92m", "bold": "\x1b[1m", "reset": "\x1b[0m", "kw": "\x1b[94m", @@ -171,6 +174,7 @@ class ColorMapping: "endline": "\x1b[90m\x1b[39;49;00m", } RE_COLORS = {k: re.escape(v) for k, v in COLORS.items()} + NO_COLORS = {k: "" for k in COLORS.keys()} @classmethod def format(cls, lines: List[str]) -> List[str]: @@ -187,6 +191,11 @@ def format_for_rematch(cls, lines: List[str]) -> List[str]: """Replace color names for use with LineMatcher.re_match_lines""" return [line.format(**cls.RE_COLORS) for line in lines] + @classmethod + def strip_colors(cls, lines: List[str]) -> List[str]: + """Entirely remove every color code""" + return [line.format(**cls.NO_COLORS) for line in lines] + return ColorMapping diff --git a/testing/test_assertion.py b/testing/test_assertion.py index d3caa5e4848..62c465d8a34 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -18,12 +18,19 @@ def mock_config(verbose=0): + class TerminalWriter: + def _highlight(self, source, lexer): + return source + class Config: def getoption(self, name): if name == "verbose": return verbose raise KeyError("Not mocked out: %s" % name) + def get_terminal_writer(self): + return TerminalWriter() + return Config() @@ -1784,3 +1791,48 @@ def test_reprcompare_verbose_long() -> None: "{'v0': 0, 'v1': 1, 'v2': 12, 'v3': 3, 'v4': 4, 'v5': 5, " "'v6': 6, 'v7': 7, 'v8': 8, 'v9': 9, 'v10': 10}" ) + + +@pytest.mark.parametrize("enable_colors", [True, False]) +@pytest.mark.parametrize( + ("test_code", "expected_lines"), + ( + ( + """ + def test(): + 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}", + ], + ), + ( + """ + def test(): + assert {f"number-is-{i}": i for i in range(1, 6)} == { + f"number-is-{i}": i for i in range(5) + } + """, + [ + "{bold}{red}E {light-gray} {hl-reset} {{{endline}{reset}", + "{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}", + "{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}", + ], + ), + ), +) +def test_comparisons_handle_colors( + pytester: Pytester, color_mapping, enable_colors, test_code, expected_lines +) -> None: + p = pytester.makepyfile(test_code) + result = pytester.runpytest( + f"--color={'yes' if enable_colors else 'no'}", "-vv", str(p) + ) + formatter = ( + color_mapping.format_for_fnmatch + if enable_colors + else color_mapping.strip_colors + ) + + result.stdout.fnmatch_lines(formatter(expected_lines), consecutive=False) From c7e9b22f37821aa059a63a026ed4f25756fce8e0 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 24 Oct 2023 16:50:13 -0300 Subject: [PATCH 0231/1271] Merge pull request #11546 from pytest-dev/release-7.4.3 (#11549) Prepare release 7.4.3 (cherry picked from commit 53df6164b44269f85334eace9c473c3f3a04aae7) --- changelog/10447.bugfix.rst | 2 -- changelog/11239.bugfix.rst | 1 - changelog/11439.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.3.rst | 19 +++++++++++++++++++ doc/en/changelog.rst | 15 +++++++++++++++ doc/en/getting-started.rst | 2 +- 7 files changed, 36 insertions(+), 5 deletions(-) delete mode 100644 changelog/10447.bugfix.rst delete mode 100644 changelog/11239.bugfix.rst delete mode 100644 changelog/11439.bugfix.rst create mode 100644 doc/en/announce/release-7.4.3.rst diff --git a/changelog/10447.bugfix.rst b/changelog/10447.bugfix.rst deleted file mode 100644 index fff94b28fb5..00000000000 --- a/changelog/10447.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -markers are now considered in the reverse mro order to ensure base class markers are considered first -this resolves a regression. diff --git a/changelog/11239.bugfix.rst b/changelog/11239.bugfix.rst deleted file mode 100644 index a486224cdda..00000000000 --- a/changelog/11239.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed ``:=`` in asserts impacting unrelated test cases. diff --git a/changelog/11439.bugfix.rst b/changelog/11439.bugfix.rst deleted file mode 100644 index b5104b1bcab..00000000000 --- a/changelog/11439.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Handle an edge case where :data:`sys.stderr` might already be closed when :ref:`faulthandler` is tearing down. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 39fdfc13776..854666f6725 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.3 release-7.4.2 release-7.4.1 release-7.4.0 diff --git a/doc/en/announce/release-7.4.3.rst b/doc/en/announce/release-7.4.3.rst new file mode 100644 index 00000000000..0f319c1e7f0 --- /dev/null +++ b/doc/en/announce/release-7.4.3.rst @@ -0,0 +1,19 @@ +pytest-7.4.3 +======================================= + +pytest 7.4.3 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Marc Mueller + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index ecfeeb662b6..121d1708da7 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,21 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.3 (2023-10-24) +========================= + +Bug Fixes +--------- + +- `#10447 `_: Markers are now considered in the reverse mro order to ensure base class markers are considered first -- this resolves a regression. + + +- `#11239 `_: Fixed ``:=`` in asserts impacting unrelated test cases. + + +- `#11439 `_: Handled an edge case where :data:`sys.stderr` might already be closed when :ref:`faulthandler` is tearing down. + + pytest 7.4.2 (2023-09-07) ========================= diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 8d37612df7b..3b9d773b00c 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 7.4.2 + pytest 7.4.3 .. _`simpletest`: From dcd8b145d9049d2a885b5832d1974763fc42045c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 25 Oct 2023 10:04:06 -0300 Subject: [PATCH 0232/1271] Add deploy instructions using the command-line (#11547) Tested this to trigger the deploy of #11546. --- scripts/prepare-release-pr.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index a0e5e4d7f37..8ffa6696466 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -31,16 +31,22 @@ class InvalidFeatureRelease(Exception): SLUG = "pytest-dev/pytest" PR_BODY = """\ -Created by the [prepare release pr](https://github.com/pytest-dev/pytest/actions/workflows/prepare-release-pr.yml) -workflow. +Created by the [prepare release pr]\ +(https://github.com/pytest-dev/pytest/actions/workflows/prepare-release-pr.yml) workflow. -Once all builds pass and it has been **approved** by one or more maintainers, -start the [deploy](https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml) workflow, using these parameters: +Once all builds pass and it has been **approved** by one or more maintainers, start the \ +[deploy](https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml) workflow, using these parameters: * `Use workflow from`: `release-{version}`. * `Release version`: `{version}`. -After the `deploy` workflow has been approved by a core maintainer, the package will be uploaded to PyPI automatically. +Or execute on the command line: + +```console +gh workflow run deploy.yml -r release-{version} -f version={version} +``` + +After the workflow has been approved by a core maintainer, the package will be uploaded to PyPI automatically. """ From c1728948ac7bcd807a40f9aaae63f2f09f5df5b7 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 25 Oct 2023 13:19:47 -0300 Subject: [PATCH 0233/1271] Fix tag name generated by deploy workflow (#11550) Traditionally pytest publishes tags in the form `X.Y.Z`, however the deploy workflow (copied from somewhere else) published tags in the form `vX.Y.Z`. This is the root cause of #11548, because it tried to publish the release notes for tag `X.Y.Z` (which did not exist). Fix #11548 --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 08e99e954a7..b00bbe006d9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -53,8 +53,8 @@ jobs: run: | git config user.name "pytest bot" git config user.email "pytestbot@gmail.com" - git tag --annotate --message=v${{ github.event.inputs.version }} v${{ github.event.inputs.version }} ${{ github.sha }} - git push origin v${{ github.event.inputs.version }} + git tag --annotate --message=v${{ github.event.inputs.version }} ${{ github.event.inputs.version }} ${{ github.sha }} + git push origin ${{ github.event.inputs.version }} release-notes: From 247436819a49a4c21c0926ed0a12bfe7e8166237 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 27 Oct 2023 08:32:02 -0300 Subject: [PATCH 0234/1271] Update build-and-inspect-python-package action (#11561) This should fix the action for Python 3.12. Ref: hynek/build-and-inspect-python-package#72 --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index b00bbe006d9..efc30f7f6bc 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v1.5 + uses: hynek/build-and-inspect-python-package@v1.5.3 deploy: if: github.repository == 'pytest-dev/pytest' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 450d8e99ad4..4a50761df2d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v1.5 + uses: hynek/build-and-inspect-python-package@v1.5.3 build: needs: [package] From ed8701a57fa40296e8dd302015cd5f805f2aede0 Mon Sep 17 00:00:00 2001 From: Ziad Kermadi Date: Fri, 27 Oct 2023 19:35:45 +0200 Subject: [PATCH 0235/1271] Mention -q and -s in the docs (#11558) Fixes #11507. --- doc/en/how-to/output.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index cf72a2d291c..04f201610b5 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -16,6 +16,12 @@ Examples for modifying traceback printing: pytest -l # show local variables (shortcut) pytest --no-showlocals # hide local variables (if addopts enables them) + pytest --capture=fd # default, capture at the file descriptor level + pytest --capture=sys # capture at the sys level + pytest --capture=no # don't capture + pytest -s # don't capture (shortcut) + pytest --capture=tee-sys # capture to logs but also output to sys level streams + pytest --tb=auto # (default) 'long' tracebacks for the first and last # entry, but 'short' style for the other entries pytest --tb=long # exhaustive, informative traceback formatting @@ -36,6 +42,16 @@ option you make sure a trace is shown. Verbosity -------------------------------------------------- +Examples for modifying printing verbosity: + +.. code-block:: bash + + pytest --quiet # quiet - less verbose - mode + pytest -q # quiet - less verbose - mode (shortcut) + pytest -v # increase verbosity, display individual test names + pytest -vv # more verbose, display more details from the test output + pytest -vvv # not a standard , but may be used for even more detail in certain setups + The ``-v`` flag controls the verbosity of pytest output in various aspects: test session progress, assertion details when tests fail, fixtures details with ``--fixtures``, etc. From 7156a97f9a1471f35c48988f2153047db4fd5e95 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 27 Oct 2023 17:23:57 -0300 Subject: [PATCH 0236/1271] Fix crash using empty string for parametrized value more than once Fixes #11563. --- changelog/11563.bugfix.rst | 1 + src/_pytest/python.py | 2 +- testing/python/metafunc.py | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 changelog/11563.bugfix.rst diff --git a/changelog/11563.bugfix.rst b/changelog/11563.bugfix.rst new file mode 100644 index 00000000000..35b5e4f15a1 --- /dev/null +++ b/changelog/11563.bugfix.rst @@ -0,0 +1 @@ +Fixed crash when using an empty string for the same parametrized value more than once. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index f54bbb3793e..0985c871d3b 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1003,7 +1003,7 @@ def make_unique_parameterset_ids(self) -> List[str]: for index, id in enumerate(resolved_ids): if id_counts[id] > 1: suffix = "" - if id[-1].isdigit(): + if id and id[-1].isdigit(): suffix = "_" new_id = f"{id}{suffix}{id_suffixes[id]}" while new_id in set(resolved_ids): diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 16ec37f9a7e..e93363a787e 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -626,6 +626,13 @@ def getini(self, name): ).make_unique_parameterset_ids() assert result == [expected] + def test_idmaker_duplicated_empty_str(self) -> None: + """Regression test for empty strings parametrized more than once (#11563).""" + result = IdMaker( + ("a",), [pytest.param(""), pytest.param("")], None, None, None, None, None + ).make_unique_parameterset_ids() + assert result == ["0", "1"] + def test_parametrize_ids_exception(self, pytester: Pytester) -> None: """ :param pytester: the instance of Pytester class, a temporary From d0a09d8627ae9076dafce5e6cd5eca681be3164e Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 29 Oct 2023 00:19:06 +0000 Subject: [PATCH 0237/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 122 +++++++++++++++++++------------ 1 file changed, 77 insertions(+), 45 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6ee6098cf33..0e919ade9e9 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Sep 05, 2023 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Oct 21, 2023 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -91,6 +91,7 @@ This list contains 1333 plugins. :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 Jan 13, 2022 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 :pypi:`pytest-assertcount` Plugin to count actual number of asserts in pytest Oct 23, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-assertions` Pytest Assertions Apr 27, 2022 N/A N/A @@ -109,7 +110,7 @@ This list contains 1333 plugins. :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进行自定义 Sep 14, 2023 N/A pytest (>=7.4.2,<8.0.0) + :pypi:`pytest-atf-allure` 基于allure-pytest进行自定义 Oct 22, 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 @@ -383,6 +384,7 @@ This list contains 1333 plugins. :pypi:`pytest-donde` record pytest session characteristics per test item (coverage and duration) into a persistent file and use them in your own plugin or script. Oct 01, 2023 4 - Beta pytest >=7.3.1 :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) + :pypi:`pytest-dot-only-pkcopley` A Pytest marker for only running a single test Oct 27, 2023 N/A N/A :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A @@ -424,7 +426,7 @@ This list contains 1333 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` py.test plugin that allows you to add environment variables. Aug 24, 2023 5 - Production/Stable pytest>=7.3.1 + :pypi:`pytest-env` pytest plugin that allows you to add environment variables. Oct 24, 2023 5 - Production/Stable pytest>=7.4.2 :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) @@ -464,7 +466,7 @@ This list contains 1333 plugins. :pypi:`pytest-failed-screen-record` Create a video of the screen when pytest fails Jan 05, 2023 4 - Beta pytest (>=7.1.2d,<8.0.0) :pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A :pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0) - :pypi:`pytest-fail-slow` Fail tests that take too long to run Aug 13, 2022 4 - Beta pytest (>=6.0) + :pypi:`pytest-fail-slow` Fail tests that take too long to run Oct 21, 2023 N/A pytest >=6.0 :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A :pypi:`pytest-falcon-client` Pytest \`client\` fixture for the Falcon Framework Mar 19, 2019 N/A N/A @@ -501,7 +503,7 @@ This list contains 1333 plugins. :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) :pypi:`pytest-flaptastic` Flaptastic py.test plugin Mar 17, 2019 N/A N/A - :pypi:`pytest-flask` A set of py.test fixtures to test Flask applications. Feb 27, 2021 5 - Production/Stable pytest (>=5.2) + :pypi:`pytest-flask` A set of py.test fixtures to test Flask applications. Oct 23, 2023 5 - Production/Stable pytest >=5.2 :pypi:`pytest-flask-ligand` Pytest fixtures and helper functions to use for testing flask-ligand microservices. Apr 25, 2023 4 - Beta pytest (~=7.3) :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) @@ -531,7 +533,7 @@ This list contains 1333 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Oct 09, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Oct 26, 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 @@ -568,7 +570,7 @@ This list contains 1333 plugins. :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-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 Oct 14, 2023 3 - Alpha pytest ==7.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Oct 28, 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 @@ -584,7 +586,7 @@ This list contains 1333 plugins. :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Mar 04, 2022 5 - Production/Stable N/A :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A - :pypi:`pytest-html-report-merger` Aug 31, 2022 N/A N/A + :pypi:`pytest-html-report-merger` Oct 23, 2023 N/A N/A :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' @@ -788,7 +790,7 @@ This list contains 1333 plugins. :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Sep 21, 2023 N/A pytest <7.3,>=3.5.0 + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Oct 26, 2023 N/A pytest <7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -937,7 +939,7 @@ This list contains 1333 plugins. :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Aug 27, 2023 N/A pytest + :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Oct 21, 2023 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Aug 20, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Mar 12, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. May 07, 2023 N/A pytest (>=3.5.0) @@ -1003,6 +1005,7 @@ This list contains 1333 plugins. :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Oct 17, 2023 N/A pytest >=3.8.0 :pypi:`pytest-reports` An interesting python package Jun 07, 2023 N/A N/A + :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A @@ -1030,6 +1033,7 @@ This list contains 1333 plugins. :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) + :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) :pypi:`pytest-richtrace` A pytest plugin that displays the names and information of the pytest hook functions as they are executed. Jun 20, 2023 N/A N/A :pypi:`pytest-ringo` pytest plugin to test webapplications using the Ringo webframework Sep 27, 2017 3 - Alpha N/A @@ -1059,7 +1063,7 @@ This list contains 1333 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 27, 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) @@ -1068,7 +1072,7 @@ This list contains 1333 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Oct 18, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 20, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 27, 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-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 @@ -1140,8 +1144,8 @@ This list contains 1333 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 Sep 06, 2023 N/A pytest (>5.4.0,<8) - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Oct 02, 2023 N/A 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 Oct 27, 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 @@ -1289,7 +1293,6 @@ This list contains 1333 plugins. :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) - :pypi:`pytest-unitvis` Oct 20, 2023 3 - Alpha pytest >=7.0.0 :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A @@ -1309,6 +1312,7 @@ This list contains 1333 plugins. :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 + :pypi:`pytest-visual` Oct 24, 2023 3 - Alpha pytest >=7.0.0 :pypi:`pytest-vnc` VNC client for Pytest Feb 25, 2023 N/A pytest :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A @@ -1363,7 +1367,7 @@ This list contains 1333 plugins. :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A - :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Dec 12, 2022 5 - Production/Stable pytest (>=4.5.0) + :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Oct 27, 2023 5 - Production/Stable pytest (>=4.5.0) :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest @@ -1604,7 +1608,7 @@ This list contains 1333 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Sep 05, 2023, + *last release*: Oct 21, 2023, *status*: N/A, *requires*: pytest >=7.3.1 @@ -1771,6 +1775,13 @@ This list contains 1333 plugins. Convenient ASGI client/server fixtures for Pytest + :pypi:`pytest-aspec` + *last release*: Oct 23, 2023, + *status*: 4 - Beta, + *requires*: N/A + + A rspec format reporter for pytest + :pypi:`pytest-asptest` *last release*: Apr 28, 2018, *status*: 4 - Beta, @@ -1898,7 +1909,7 @@ This list contains 1333 plugins. Database testing fixtures using the SQLAlchemy asyncio API :pypi:`pytest-atf-allure` - *last release*: Sep 14, 2023, + *last release*: Oct 22, 2023, *status*: N/A, *requires*: pytest (>=7.4.2,<8.0.0) @@ -3815,6 +3826,13 @@ This list contains 1333 plugins. A py.test plugin that parses environment files before running tests + :pypi:`pytest-dot-only-pkcopley` + *last release*: Oct 27, 2023, + *status*: N/A, + *requires*: N/A + + A Pytest marker for only running a single test + :pypi:`pytest-draw` *last release*: Mar 21, 2023, *status*: 3 - Alpha, @@ -4103,11 +4121,11 @@ This list contains 1333 plugins. Improvements for pytest (rejected upstream) :pypi:`pytest-env` - *last release*: Aug 24, 2023, + *last release*: Oct 24, 2023, *status*: 5 - Production/Stable, - *requires*: pytest>=7.3.1 + *requires*: pytest>=7.4.2 - py.test plugin that allows you to add environment variables. + pytest plugin that allows you to add environment variables. :pypi:`pytest-envfiles` *last release*: Oct 08, 2015, @@ -4383,9 +4401,9 @@ This list contains 1333 plugins. A pytest plugin that helps better distinguishing real test failures from setup flakiness. :pypi:`pytest-fail-slow` - *last release*: Aug 13, 2022, - *status*: 4 - Beta, - *requires*: pytest (>=6.0) + *last release*: Oct 21, 2023, + *status*: N/A, + *requires*: pytest >=6.0 Fail tests that take too long to run @@ -4642,9 +4660,9 @@ This list contains 1333 plugins. Flaptastic py.test plugin :pypi:`pytest-flask` - *last release*: Feb 27, 2021, + *last release*: Oct 23, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.2) + *requires*: pytest >=5.2 A set of py.test fixtures to test Flask applications. @@ -4852,7 +4870,7 @@ This list contains 1333 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Oct 09, 2023, + *last release*: Oct 26, 2023, *status*: N/A, *requires*: N/A @@ -5111,9 +5129,9 @@ This list contains 1333 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Oct 14, 2023, + *last release*: Oct 28, 2023, *status*: 3 - Alpha, - *requires*: pytest ==7.3.1 + *requires*: pytest ==7.4.3 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -5223,7 +5241,7 @@ This list contains 1333 plugins. Generates a static html report based on pytest framework :pypi:`pytest-html-report-merger` - *last release*: Aug 31, 2022, + *last release*: Oct 23, 2023, *status*: N/A, *requires*: N/A @@ -6651,7 +6669,7 @@ This list contains 1333 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-netdut` - *last release*: Sep 21, 2023, + *last release*: Oct 26, 2023, *status*: N/A, *requires*: pytest <7.3,>=3.5.0 @@ -7694,7 +7712,7 @@ This list contains 1333 plugins. Pyramid server fixture for py.test :pypi:`pytest-pyreport` - *last release*: Aug 27, 2023, + *last release*: Oct 21, 2023, *status*: N/A, *requires*: pytest @@ -8155,6 +8173,13 @@ This list contains 1333 plugins. An interesting python package + :pypi:`pytest-report-stream` + *last release*: Oct 22, 2023, + *status*: 4 - Beta, + *requires*: N/A + + A pytest plugin which allows to stream test reports at runtime + :pypi:`pytest-reqs` *last release*: May 12, 2019, *status*: N/A, @@ -8344,6 +8369,13 @@ This list contains 1333 plugins. Leverage rich for richer test session output + :pypi:`pytest-richer` + *last release*: Oct 27, 2023, + *status*: 3 - Alpha, + *requires*: pytest + + Pytest plugin providing a Rich based reporter. + :pypi:`pytest-rich-reporter` *last release*: Feb 17, 2022, *status*: 1 - Planning, @@ -8548,7 +8580,7 @@ This list contains 1333 plugins. :pypi:`pytest-sbase` - *last release*: Oct 20, 2023, + *last release*: Oct 27, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8611,7 +8643,7 @@ This list contains 1333 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Oct 20, 2023, + *last release*: Oct 27, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9115,14 +9147,14 @@ This list contains 1333 plugins. :pypi:`pytest-splunk-addon` - *last release*: Sep 06, 2023, + *last release*: Oct 23, 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*: Oct 02, 2023, + *last release*: Oct 27, 2023, *status*: N/A, *requires*: N/A @@ -10157,13 +10189,6 @@ This list contains 1333 plugins. A pytest plugin for filtering unittest-based test classes - :pypi:`pytest-unitvis` - *last release*: Oct 20, 2023, - *status*: 3 - Alpha, - *requires*: pytest >=7.0.0 - - - :pypi:`pytest-unmarked` *last release*: Aug 27, 2019, *status*: 5 - Production/Stable, @@ -10297,6 +10322,13 @@ This list contains 1333 plugins. Virtualenv fixture for py.test + :pypi:`pytest-visual` + *last release*: Oct 24, 2023, + *status*: 3 - Alpha, + *requires*: pytest >=7.0.0 + + + :pypi:`pytest-vnc` *last release*: Feb 25, 2023, *status*: N/A, @@ -10676,7 +10708,7 @@ This list contains 1333 plugins. OWASP ZAP plugin for py.test. :pypi:`pytest-zebrunner` - *last release*: Dec 12, 2022, + *last release*: Oct 27, 2023, *status*: 5 - Production/Stable, *requires*: pytest (>=4.5.0) From 4ecf313604af484731af17f1225921f99e4e8959 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 29 Oct 2023 21:55:17 +0200 Subject: [PATCH 0238/1271] doc/reference: fix sidebar TOC depth Previously, the sidebar TOC had unlimited depth, making it useless and interfering with the content. This seems to have regressed in pytest 7.2.x going by the RTD version selector. --- doc/en/reference/reference.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index d8efbbbaadc..7764b03eb43 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1,3 +1,5 @@ +:tocdepth: 3 + .. _`api-reference`: API Reference From 0d74a1c8a00c25d78404cb7db0bc9e0c31939ce0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 30 Oct 2023 00:00:27 +0200 Subject: [PATCH 0239/1271] doc: allow Sphinx 6.x and 7.x (#11568) They seem to work fine, let's allow them. --- doc/en/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 0ee999e0faf..36801746aae 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -2,7 +2,7 @@ pallets-sphinx-themes pluggy>=1.2.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 -sphinx>=5,<6 +sphinx>=5,<8 sphinxcontrib-trio sphinxcontrib-svg2pdfconverter # Pin packaging because it no longer handles 'latest' version, which From 1ea10c20dfeafd05e608943f7fa671be09e2854f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Nov 2023 08:27:47 -0300 Subject: [PATCH 0240/1271] build(deps): Bump django in /testing/plugins_integration (#11579) Bumps [django](https://github.com/django/django) from 4.2.6 to 4.2.7. - [Commits](https://github.com/django/django/compare/4.2.6...4.2.7) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 6fc3e8dc415..69b48fe2a40 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.0.0 -django==4.2.6 +django==4.2.7 pytest-asyncio==0.21.1 pytest-bdd==7.0.0 pytest-cov==4.1.0 From 13e5ef010250ae98b8b2aa76952d447274d20e25 Mon Sep 17 00:00:00 2001 From: neilmartin2000 <143754352+neilmartin2000@users.noreply.github.com> Date: Fri, 3 Nov 2023 12:05:05 -0600 Subject: [PATCH 0241/1271] Created link to PEP-8 in documentation (#11582) --- AUTHORS | 1 + CONTRIBUTING.rst | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 5ccff644c1c..212d4a8832a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -275,6 +275,7 @@ Miro Hrončok Nathaniel Compton Nathaniel Waisbrot Ned Batchelder +Neil Martin Neven Mundar Nicholas Devenish Nicholas Murphy diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index e2230cbbdfd..6f55c230c92 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -199,7 +199,7 @@ Short version #. Fork the repository. #. Fetch tags from upstream if necessary (if you cloned only main `git fetch --tags https://github.com/pytest-dev/pytest`). #. Enable and install `pre-commit `_ to ensure style-guides and code checks are followed. -#. Follow **PEP-8** for naming and `black `_ for formatting. +#. Follow `PEP-8 `_ for naming. #. Tests are run using ``tox``:: tox -e linting,py39 @@ -282,7 +282,7 @@ Here is a simple overview, with pytest-specific bits: This command will run tests via the "tox" tool against Python 3.9 and also perform "lint" coding-style checks. -#. You can now edit your local working copy and run the tests again as necessary. Please follow PEP-8 for naming. +#. You can now edit your local working copy and run the tests again as necessary. Please follow `PEP-8 `_ for naming. You can pass different options to ``tox``. For example, to run tests on Python 3.9 and pass options to pytest (e.g. enter pdb on failure) to pytest you can do:: From 1e02797d153522b5495e16d1d28b01aedf8d48f3 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 4 Nov 2023 07:24:57 -0300 Subject: [PATCH 0242/1271] Improve pytest.raises docs (#11578) --- doc/en/how-to/assert.rst | 78 ++++++++++++++++++++++++++++------ doc/en/reference/reference.rst | 4 +- src/_pytest/python_api.py | 32 +++++++++++--- 3 files changed, 93 insertions(+), 21 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index cc53d001f70..1401064d772 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -98,6 +98,27 @@ and if you need to have access to the actual exception info you may use: the actual exception raised. The main attributes of interest are ``.type``, ``.value`` and ``.traceback``. +Note that ``pytest.raises`` will match the exception type or any subclasses (like the standard ``except`` statement). +If you want to check if a block of code is raising an exact exception type, you need to check that explicitly: + + +.. code-block:: python + + def test_recursion_depth(): + def foo(): + raise NotImplementedError + + with pytest.raises(RuntimeError) as excinfo: + foo() + assert type(excinfo.value) is RuntimeError + +The :func:`pytest.raises` call will succeed, even though the function raises :class:`NotImplementedError`, because +:class:`NotImplementedError` is a subclass of :class:`RuntimeError`; however the following `assert` statement will +catch the problem. + +Matching exception messages +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + You can pass a ``match`` keyword parameter to the context-manager to test that a regular expression matches on the string representation of an exception (similar to the ``TestCase.assertRaisesRegex`` method from ``unittest``): @@ -115,9 +136,15 @@ that a regular expression matches on the string representation of an exception with pytest.raises(ValueError, match=r".* 123 .*"): myfunc() -The regexp parameter of the ``match`` parameter is matched with the ``re.search`` -function, so in the above example ``match='123'`` would have worked as -well. +Notes: + +* The ``match`` parameter is matched with the :func:`re.search` + function, so in the above example ``match='123'`` would have worked as well. +* The ``match`` parameter also matches against `PEP-678 `__ ``__notes__``. + + +Matching exception groups +~~~~~~~~~~~~~~~~~~~~~~~~~ You can also use the :func:`excinfo.group_contains() ` method to test for exceptions returned as part of an ``ExceptionGroup``: @@ -165,32 +192,55 @@ exception at a specific level; exceptions contained directly in the top assert not excinfo.group_contains(RuntimeError, depth=2) assert not excinfo.group_contains(TypeError, depth=1) -There's an alternate form of the :func:`pytest.raises` function where you pass -a function that will be executed with the given ``*args`` and ``**kwargs`` and -assert that the given exception is raised: +Alternate form (legacy) +~~~~~~~~~~~~~~~~~~~~~~~ + +There is an alternate form where you pass +a function that will be executed, along ``*args`` and ``**kwargs``, and :func:`pytest.raises` +will execute the function with the arguments and assert that the given exception is raised: .. code-block:: python - pytest.raises(ExpectedException, func, *args, **kwargs) + def func(x): + if x <= 0: + raise ValueError("x needs to be larger than zero") + + + pytest.raises(ValueError, func, x=-1) The reporter will provide you with helpful output in case of failures such as *no exception* or *wrong exception*. -Note that it is also possible to specify a "raises" argument to -``pytest.mark.xfail``, which checks that the test is failing in a more +This form was the original :func:`pytest.raises` API, developed before the ``with`` statement was +added to the Python language. Nowadays, this form is rarely used, with the context-manager form (using ``with``) +being considered more readable. +Nonetheless, this form is fully supported and not deprecated in any way. + +xfail mark and pytest.raises +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is also possible to specify a ``raises`` argument to +:ref:`pytest.mark.xfail `, which checks that the test is failing in a more specific way than just having any exception raised: .. code-block:: python + def f(): + raise IndexError() + + @pytest.mark.xfail(raises=IndexError) def test_f(): f() -Using :func:`pytest.raises` is likely to be better for cases where you are -testing exceptions your own code is deliberately raising, whereas using -``@pytest.mark.xfail`` with a check function is probably better for something -like documenting unfixed bugs (where the test describes what "should" happen) -or bugs in dependencies. + +This will only "xfail" if the test fails by raising ``IndexError`` or subclasses. + +* Using :ref:`pytest.mark.xfail ` with the ``raises`` parameter is probably better for something + like documenting unfixed bugs (where the test describes what "should" happen) or bugs in dependencies. + +* Using :func:`pytest.raises` is likely to be better for cases where you are + testing exceptions your own code is deliberately raising, which is the majority of cases. .. _`assertwarns`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 7764b03eb43..0240e1f4aad 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -249,7 +249,9 @@ Marks a test function as *expected to fail*. :keyword str reason: Reason why the test function is marked as xfail. :keyword Type[Exception] raises: - Exception subclass (or tuple of subclasses) expected to be raised by the test function; other exceptions will fail the test. + Exception class (or tuple of classes) expected to be raised by the test function; other exceptions will fail the test. + Note that subclasses of the classes passed will also result in a match (similar to how the ``except`` statement works). + :keyword bool run: Whether the test function should actually be executed. If ``False``, the function will always xfail and will not be executed (useful if a function is segfaulting). diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 27826863ead..07db0f234d4 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -804,11 +804,13 @@ def raises( # noqa: F811 def raises( # noqa: F811 expected_exception: Union[Type[E], Tuple[Type[E], ...]], *args: Any, **kwargs: Any ) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]: - r"""Assert that a code block/function call raises an exception. + r"""Assert that a code block/function call raises an exception type, or one of its subclasses. :param typing.Type[E] | typing.Tuple[typing.Type[E], ...] expected_exception: The expected exception type, or a tuple if one of multiple possible - exception types are expected. + exception types are expected. Note that subclasses of the passed exceptions + will also match. + :kwparam str | typing.Pattern[str] | None match: If specified, a string containing a regular expression, or a regular expression object, that is tested against the string @@ -826,13 +828,13 @@ def raises( # noqa: F811 .. currentmodule:: _pytest._code Use ``pytest.raises`` as a context manager, which will capture the exception of the given - type:: + type, or any of its subclasses:: >>> import pytest >>> with pytest.raises(ZeroDivisionError): ... 1/0 - If the code block does not raise the expected exception (``ZeroDivisionError`` in the example + If the code block does not raise the expected exception (:class:`ZeroDivisionError` in the example above), or no exception at all, the check will fail instead. You can also use the keyword argument ``match`` to assert that the @@ -845,7 +847,7 @@ def raises( # noqa: F811 ... raise ValueError("value must be 42") The ``match`` argument searches the formatted exception string, which includes any - `PEP-678 ` ``__notes__``: + `PEP-678 `__ ``__notes__``: >>> with pytest.raises(ValueError, match=r'had a note added'): # doctest: +SKIP ... e = ValueError("value must be 42") @@ -860,6 +862,20 @@ def raises( # noqa: F811 >>> assert exc_info.type is ValueError >>> assert exc_info.value.args[0] == "value must be 42" + .. warning:: + + Given that ``pytest.raises`` matches subclasses, be wary of using it to match :class:`Exception` like this:: + + with pytest.raises(Exception): # Careful, this will catch ANY exception raised. + some_function() + + Because :class:`Exception` is the base class of almost all exceptions, it is easy for this to hide + real bugs, where the user wrote this expecting a specific exception, but some other exception is being + raised due to a bug introduced during a refactoring. + + Avoid using ``pytest.raises`` to catch :class:`Exception` unless certain that you really want to catch + **any** exception raised. + .. note:: When using ``pytest.raises`` as a context manager, it's worthwhile to @@ -872,7 +888,7 @@ def raises( # noqa: F811 >>> with pytest.raises(ValueError) as exc_info: ... if value > 10: ... raise ValueError("value must be <= 10") - ... assert exc_info.type is ValueError # this will not execute + ... assert exc_info.type is ValueError # This will not execute. Instead, the following approach must be taken (note the difference in scope):: @@ -891,6 +907,10 @@ def raises( # noqa: F811 See :ref:`parametrizing_conditional_raising` for an example. + .. seealso:: + + :ref:`assertraises` for more examples and detailed discussion. + **Legacy form** It is possible to specify a callable by passing a to-be-called lambda:: From 70f03dbc3e6f5f7bd81a26d040a39f02f97d460f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 4 Nov 2023 12:37:47 -0300 Subject: [PATCH 0243/1271] Adjustments to assert raises docs (#11586) Followup from #11578. --- doc/en/how-to/assert.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 1401064d772..7d5076a50a0 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -104,13 +104,13 @@ If you want to check if a block of code is raising an exact exception type, you .. code-block:: python - def test_recursion_depth(): + def test_foo_not_implemented(): def foo(): raise NotImplementedError with pytest.raises(RuntimeError) as excinfo: foo() - assert type(excinfo.value) is RuntimeError + assert excinfo.type is RuntimeError The :func:`pytest.raises` call will succeed, even though the function raises :class:`NotImplementedError`, because :class:`NotImplementedError` is a subclass of :class:`RuntimeError`; however the following `assert` statement will From 1a7641cf88198e6f4c7cf85c3a48fc8bbff9916d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 03:58:57 +0000 Subject: [PATCH 0244/1271] build(deps): Bump twisted in /testing/plugins_integration Bumps [twisted](https://github.com/twisted/twisted) from 23.8.0 to 23.10.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-23.8.0...twisted-23.10.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 69b48fe2a40..2027258d806 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -11,5 +11,5 @@ pytest-rerunfailures==12.0 pytest-sugar==0.9.7 pytest-trio==0.7.0 pytest-twisted==1.14.0 -twisted==23.8.0 +twisted==23.10.0 pytest-xvfb==3.0.0 From 01a248d2a98736d9dfb146b55bf17c7a11e00637 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 07:49:53 +0100 Subject: [PATCH 0245/1271] build(deps): Bump pytest-html in /testing/plugins_integration (#11590) Bumps [pytest-html](https://github.com/pytest-dev/pytest-html) from 4.0.2 to 4.1.0. - [Release notes](https://github.com/pytest-dev/pytest-html/releases) - [Changelog](https://github.com/pytest-dev/pytest-html/blob/master/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-html/compare/4.0.2...4.1.0) --- updated-dependencies: - dependency-name: pytest-html dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 69b48fe2a40..1589a6d587b 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -5,7 +5,7 @@ pytest-bdd==7.0.0 pytest-cov==4.1.0 pytest-django==4.5.2 pytest-flakes==4.0.5 -pytest-html==4.0.2 +pytest-html==4.1.0 pytest-mock==3.12.0 pytest-rerunfailures==12.0 pytest-sugar==0.9.7 From ef2216c21b8fd84724e9c371cac732a295490ff1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 07:50:49 +0100 Subject: [PATCH 0246/1271] build(deps): Bump hynek/build-and-inspect-python-package (#11589) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 1.5.3 to 1.5.4. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v1.5.3...v1.5.4) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index efc30f7f6bc..95ec0d1749c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v1.5.3 + uses: hynek/build-and-inspect-python-package@v1.5.4 deploy: if: github.repository == 'pytest-dev/pytest' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4a50761df2d..5f5832475d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v1.5.3 + uses: hynek/build-and-inspect-python-package@v1.5.4 build: needs: [package] From 92cd7950e685c9d7f21584d30838d4febfc5f739 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 09:26:10 +0100 Subject: [PATCH 0247/1271] build(deps): Bump pytest-django in /testing/plugins_integration (#11592) Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.5.2 to 4.6.0. - [Release notes](https://github.com/pytest-dev/pytest-django/releases) - [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.5.2...v4.6.0) --- updated-dependencies: - dependency-name: pytest-django dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 1589a6d587b..7dc04055a84 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -3,7 +3,7 @@ django==4.2.7 pytest-asyncio==0.21.1 pytest-bdd==7.0.0 pytest-cov==4.1.0 -pytest-django==4.5.2 +pytest-django==4.6.0 pytest-flakes==4.0.5 pytest-html==4.1.0 pytest-mock==3.12.0 From e701df5eb6645c0aaaab385e28f6ecf98b692a31 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:40:44 -0300 Subject: [PATCH 0248/1271] [automated] Update plugin list (#11587) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 142 ++++++++++++++++--------------- 1 file changed, 75 insertions(+), 67 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 0e919ade9e9..7fdc39b9c01 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =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 Jul 12, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-asyncio` Pytest support for asyncio Oct 31, 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-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) @@ -207,7 +207,7 @@ This list contains 1337 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 Oct 17, 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 02, 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 @@ -261,7 +261,7 @@ This list contains 1337 plugins. :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' - :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Sep 08, 2023 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 26, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A @@ -332,7 +332,7 @@ This list contains 1337 plugins. :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 - :pypi:`pytest-django` A Django plugin for pytest. Dec 07, 2021 5 - Production/Stable pytest (>=5.4.0) + :pypi:`pytest-django` A Django plugin for pytest. Oct 30, 2023 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A @@ -426,7 +426,7 @@ This list contains 1337 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 24, 2023 5 - Production/Stable pytest>=7.4.2 + :pypi:`pytest-env` pytest plugin that allows you to add environment variables. Oct 30, 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) @@ -516,7 +516,7 @@ This list contains 1337 plugins. :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A - :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Aug 07, 2023 4 - Beta pytest>=7.0.0 + :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Oct 29, 2023 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -570,7 +570,7 @@ This list contains 1337 plugins. :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-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 Oct 28, 2023 3 - Alpha pytest ==7.4.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Nov 02, 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 @@ -579,7 +579,7 @@ This list contains 1337 plugins. :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Sep 14, 2023 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-html` pytest plugin for generating HTML reports Nov 04, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Sep 23, 2023 N/A N/A @@ -590,7 +590,7 @@ This list contains 1337 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace May 09, 2023 3 - Alpha pytest (>=7.0.0) + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Nov 03, 2023 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A @@ -630,7 +630,7 @@ This list contains 1337 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Sep 14, 2023 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Oct 02, 2023 5 - Production/Stable pytest <7.2.0,>=6 + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Oct 31, 2023 5 - Production/Stable pytest <7.2.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A @@ -654,6 +654,7 @@ This list contains 1337 plugins. :pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Mar 14, 2023 4 - Beta N/A :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) + :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Mar 30, 2023 4 - Beta pytest :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest @@ -731,6 +732,7 @@ This list contains 1337 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Oct 08, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Nov 04, 2023 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 @@ -781,12 +783,13 @@ This list contains 1337 plugins. :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A :pypi:`pytest-multithreading-allure` pytest_multithreading_allure Nov 25, 2022 N/A N/A :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) + :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jul 25, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 - :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Mar 27, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) @@ -847,7 +850,7 @@ This list contains 1337 plugins. :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) - :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Sep 13, 2022 5 - Production/Stable pytest + :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest :pypi:`pytest-param-scope` pytest parametrize scope fixture workaround Oct 18, 2023 N/A pytest :pypi:`pytest-parawtf` Finally spell paramete?ri[sz]e correctly Dec 03, 2018 4 - Beta pytest (>=3.6.0) @@ -876,7 +879,7 @@ This list contains 1337 plugins. :pypi:`pytest-pinned` A simple pytest plugin for pinning tests Sep 17, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-pinpoint` A pytest plugin which runs SBFL algorithms to detect faults. Sep 25, 2020 N/A pytest (>=4.4.0) :pypi:`pytest-pipeline` Pytest plugin for functional testing of data analysispipelines Jan 24, 2017 3 - Alpha N/A - :pypi:`pytest-pitch` runs tests in an order such that coverage increases as fast as possible Sep 29, 2023 4 - Beta pytest >=7.3.1 + :pypi:`pytest-pitch` runs tests in an order such that coverage increases as fast as possible Nov 02, 2023 4 - Beta pytest >=7.3.1 :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) @@ -932,14 +935,14 @@ This list contains 1337 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 Oct 10, 2023 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Nov 04, 2023 N/A pytest :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Oct 21, 2023 N/A pytest + :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Nov 03, 2023 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Aug 20, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Mar 12, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. May 07, 2023 N/A pytest (>=3.5.0) @@ -1004,7 +1007,6 @@ This list contains 1337 plugins. :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Oct 17, 2023 N/A pytest >=3.8.0 - :pypi:`pytest-reports` An interesting python package Jun 07, 2023 N/A N/A :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) @@ -1046,7 +1048,7 @@ This list contains 1337 plugins. :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 31, 2023 4 - Beta N/A + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Oct 31, 2023 4 - Beta N/A :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-runner` Invoke py.test as distutils command with dependency resolution Feb 25, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' @@ -1063,7 +1065,7 @@ This list contains 1337 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 27, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 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) @@ -1072,16 +1074,15 @@ This list contains 1337 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Oct 18, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 27, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 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-selenium-screenshot` pytest plugin to automatically capture screenshots upon selenium webdriver events Aug 22, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Sep 22, 2023 3 - Alpha pytest >=6.2 + :pypi:`pytest-servers` pytest servers Oct 31, 2023 3 - Alpha pytest >=6.2 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1210,7 +1211,7 @@ This list contains 1337 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 Oct 17, 2023 4 - Beta pytest <8,>=5 + :pypi:`pytest-testmon` selects tests affected by changed files and methods Nov 03, 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) @@ -1308,11 +1309,11 @@ This list contains 1337 plugins. :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 Mar 22, 2023 4 - Beta N/A + :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Nov 01, 2023 4 - Beta N/A :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 - :pypi:`pytest-visual` Oct 24, 2023 3 - Alpha pytest >=7.0.0 + :pypi:`pytest-visual` Nov 01, 2023 3 - Alpha pytest >=7.0.0 :pypi:`pytest-vnc` VNC client for Pytest Feb 25, 2023 N/A pytest :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A @@ -1363,7 +1364,7 @@ This list contains 1337 plugins. :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A - :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Jun 21, 2023 N/A pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Nov 03, 2023 N/A pytest (>=7.2.2,<8.0.0) :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A @@ -1874,7 +1875,7 @@ This list contains 1337 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jul 12, 2023, + *last release*: Oct 31, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0.0) @@ -2588,7 +2589,7 @@ This list contains 1337 plugins. A pytest plugin to send a report and printing summary of tests. :pypi:`pytest-choose` - *last release*: Oct 17, 2023, + *last release*: Nov 02, 2023, *status*: N/A, *requires*: pytest >=7.0.0 @@ -2966,7 +2967,7 @@ This list contains 1337 plugins. Pytest plugin for excluding tests based on coverage data :pypi:`pytest-cpp` - *last release*: Sep 08, 2023, + *last release*: Nov 01, 2023, *status*: 5 - Production/Stable, *requires*: pytest >=7.0 @@ -3463,9 +3464,9 @@ This list contains 1337 plugins. A pytest plugin to notify test results to a Discord channel. :pypi:`pytest-django` - *last release*: Dec 07, 2021, + *last release*: Oct 30, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.4.0) + *requires*: pytest >=7.0.0 A Django plugin for pytest. @@ -4121,9 +4122,9 @@ This list contains 1337 plugins. Improvements for pytest (rejected upstream) :pypi:`pytest-env` - *last release*: Oct 24, 2023, + *last release*: Oct 30, 2023, *status*: 5 - Production/Stable, - *requires*: pytest>=7.4.2 + *requires*: pytest>=7.4.3 pytest plugin that allows you to add environment variables. @@ -4751,7 +4752,7 @@ This list contains 1337 plugins. A pytest plugin to shim pytest commandline options for fowards compatibility :pypi:`pytest-frappe` - *last release*: Aug 07, 2023, + *last release*: Oct 29, 2023, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -5129,7 +5130,7 @@ This list contains 1337 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Oct 28, 2023, + *last release*: Nov 02, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5192,7 +5193,7 @@ This list contains 1337 plugins. Helpers for testing hpfeeds in your python project :pypi:`pytest-html` - *last release*: Sep 14, 2023, + *last release*: Nov 04, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -5269,9 +5270,9 @@ This list contains 1337 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: May 09, 2023, + *last release*: Nov 03, 2023, *status*: 3 - Alpha, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 A pytest plugin to record HTTP(S) requests with stack trace @@ -5549,7 +5550,7 @@ This list contains 1337 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Oct 02, 2023, + *last release*: Oct 31, 2023, *status*: 5 - Production/Stable, *requires*: pytest <7.2.0,>=6 @@ -5716,6 +5717,13 @@ This list contains 1337 plugins. A pytest plugin to report test results as JSON files + :pypi:`pytest-json-report-wip` + *last release*: Oct 28, 2023, + *status*: 4 - Beta, + *requires*: pytest >=3.8.0 + + A pytest plugin to report test results as JSON files + :pypi:`pytest-jtr` *last release*: Nov 29, 2022, *status*: N/A, @@ -6255,6 +6263,13 @@ This list contains 1337 plugins. A pytest plugin to make a test results report with Markdown table format. + :pypi:`pytest-meilisearch` + *last release*: Nov 04, 2023, + *status*: N/A, + *requires*: pytest (>=7.4.3) + + Pytest helpers for testing projects using Meilisearch + :pypi:`pytest-memlog` *last release*: May 03, 2023, *status*: N/A, @@ -6605,6 +6620,13 @@ This list contains 1337 plugins. Add the mutation testing feature to pytest + :pypi:`pytest-my-cool-lib` + *last release*: Nov 02, 2023, + *status*: N/A, + *requires*: pytest (>=7.1.3,<8.0.0) + + + :pypi:`pytest-mypy` *last release*: Dec 18, 2022, *status*: 4 - Beta, @@ -6641,9 +6663,9 @@ This list contains 1337 plugins. Pytest plugin to check mypy output. :pypi:`pytest-mysql` - *last release*: Mar 27, 2023, + *last release*: Oct 30, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2) + *requires*: pytest >=6.2 MySQL process and client fixtures for pytest @@ -7068,7 +7090,7 @@ This list contains 1337 plugins. A more user-friendly way to write parametrized tests. :pypi:`pytest-parametrized` - *last release*: Sep 13, 2022, + *last release*: Nov 03, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -7271,7 +7293,7 @@ This list contains 1337 plugins. Pytest plugin for functional testing of data analysispipelines :pypi:`pytest-pitch` - *last release*: Sep 29, 2023, + *last release*: Nov 02, 2023, *status*: 4 - Beta, *requires*: pytest >=7.3.1 @@ -7663,7 +7685,7 @@ This list contains 1337 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Oct 10, 2023, + *last release*: Nov 04, 2023, *status*: N/A, *requires*: pytest @@ -7712,7 +7734,7 @@ This list contains 1337 plugins. Pyramid server fixture for py.test :pypi:`pytest-pyreport` - *last release*: Oct 21, 2023, + *last release*: Nov 03, 2023, *status*: N/A, *requires*: pytest @@ -8166,13 +8188,6 @@ This list contains 1337 plugins. Agent for Reporting results of tests to the Report Portal - :pypi:`pytest-reports` - *last release*: Jun 07, 2023, - *status*: N/A, - *requires*: N/A - - An interesting python package - :pypi:`pytest-report-stream` *last release*: Oct 22, 2023, *status*: 4 - Beta, @@ -8461,7 +8476,7 @@ This list contains 1337 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Jul 31, 2023, + *last release*: Oct 31, 2023, *status*: 4 - Beta, *requires*: N/A @@ -8580,7 +8595,7 @@ This list contains 1337 plugins. :pypi:`pytest-sbase` - *last release*: Oct 27, 2023, + *last release*: Nov 01, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8643,7 +8658,7 @@ This list contains 1337 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Oct 27, 2023, + *last release*: Nov 01, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8663,13 +8678,6 @@ This list contains 1337 plugins. A pytest package implementing perceptualdiff for Selenium tests. - :pypi:`pytest-selenium-screenshot` - *last release*: Aug 22, 2023, - *status*: N/A, - *requires*: pytest >= 7.0.0 - - pytest plugin to automatically capture screenshots upon selenium webdriver events - :pypi:`pytest-send-email` *last release*: Dec 04, 2019, *status*: N/A, @@ -8706,7 +8714,7 @@ This list contains 1337 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Sep 22, 2023, + *last release*: Oct 31, 2023, *status*: 3 - Alpha, *requires*: pytest >=6.2 @@ -9609,7 +9617,7 @@ This list contains 1337 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: Oct 17, 2023, + *last release*: Nov 03, 2023, *status*: 4 - Beta, *requires*: pytest <8,>=5 @@ -10295,7 +10303,7 @@ This list contains 1337 plugins. py.test fixture for creating a virtual environment :pypi:`pytest-ver` - *last release*: Mar 22, 2023, + *last release*: Nov 01, 2023, *status*: 4 - Beta, *requires*: N/A @@ -10323,7 +10331,7 @@ This list contains 1337 plugins. Virtualenv fixture for py.test :pypi:`pytest-visual` - *last release*: Oct 24, 2023, + *last release*: Nov 01, 2023, *status*: 3 - Alpha, *requires*: pytest >=7.0.0 @@ -10680,7 +10688,7 @@ This list contains 1337 plugins. PyTest plugin to run tests concurrently, each \`yield\` switch context to other one :pypi:`pytest-yls` - *last release*: Jun 21, 2023, + *last release*: Nov 03, 2023, *status*: N/A, *requires*: pytest (>=7.2.2,<8.0.0) From 7c7bdf457417cdc238d1e0911d7b4af8133cb208 Mon Sep 17 00:00:00 2001 From: Sharad Nair <134932980+SharadNair7@users.noreply.github.com> Date: Sat, 11 Nov 2023 21:38:18 +0530 Subject: [PATCH 0249/1271] Sanitize ini-options default handling #11282 (#11594) Fixes #11282 --- changelog/11282.breaking.rst | 11 ++++++ src/_pytest/config/__init__.py | 27 +++++++++++--- src/_pytest/config/argparsing.py | 30 ++++++++++++++- testing/test_config.py | 64 ++++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 changelog/11282.breaking.rst diff --git a/changelog/11282.breaking.rst b/changelog/11282.breaking.rst new file mode 100644 index 00000000000..cee9788ef1c --- /dev/null +++ b/changelog/11282.breaking.rst @@ -0,0 +1,11 @@ +Sanitized the handling of the ``default`` parameter when defining configuration options. + +Previously if ``default`` was not supplied for :meth:`parser.addini ` and the configuration option value was not defined in a test session, then calls to :func:`config.getini ` returned an *empty list* or an *empty string* depending on whether ``type`` was supplied or not respectively, which is clearly incorrect. Also, ``None`` was not honored even if ``default=None`` was used explicitly while defining the option. + +Now the behavior of :meth:`parser.addini ` is as follows: + +* If ``default`` is NOT passed but ``type`` is provided, then a type-specific default will be returned. For example ``type=bool`` will return ``False``, ``type=str`` will return ``""``, etc. +* If ``default=None`` is passed and the option is not defined in a test session, then ``None`` will be returned, regardless of the ``type``. +* If neither ``default`` nor ``type`` are provided, assume ``type=str`` and return ``""`` as default (this is as per previous behavior). + +The team decided to not introduce a deprecation period for this change, as doing so would be complicated both in terms of communicating this to the community as well as implementing it, and also because the team believes this change should not break existing plugins except in rare cases. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 447ebc42abb..03f69ed31e3 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1495,6 +1495,27 @@ def addinivalue_line(self, name: str, line: str) -> None: def getini(self, name: str): """Return configuration value from an :ref:`ini file `. + If a configuration value is not defined in an + :ref:`ini file `, then the ``default`` value provided while + registering the configuration through + :func:`parser.addini ` will be returned. + Please note that you can even provide ``None`` as a valid + default value. + + If ``default`` is not provided while registering using + :func:`parser.addini `, then a default value + based on the ``type`` parameter passed to + :func:`parser.addini ` will be returned. + The default values based on ``type`` are: + ``paths``, ``pathlist``, ``args`` and ``linelist`` : empty list ``[]`` + ``bool`` : ``False`` + ``string`` : empty string ``""`` + + If neither the ``default`` nor the ``type`` parameter is passed + while registering the configuration through + :func:`parser.addini `, then the configuration + is treated as a string and a default empty string '' is returned. + If the specified name hasn't been registered through a prior :func:`parser.addini ` call (usually from a plugin), a ValueError is raised. @@ -1521,11 +1542,7 @@ def _getini(self, name: str): try: value = self.inicfg[name] except KeyError: - if default is not None: - return default - if type is None: - return "" - return [] + return default else: value = override_value # Coerce the values based on types. diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index e345de01639..461b8afdff9 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -27,6 +27,14 @@ FILE_OR_DIR = "file_or_dir" +class NotSet: + def __repr__(self) -> str: + return "" + + +NOT_SET = NotSet() + + @final class Parser: """Parser for command line arguments and ini-file values. @@ -176,7 +184,7 @@ def addini( type: Optional[ Literal["string", "paths", "pathlist", "args", "linelist", "bool"] ] = None, - default: Any = None, + default: Any = NOT_SET, ) -> None: """Register an ini-file option. @@ -203,10 +211,30 @@ def addini( :py:func:`config.getini(name) `. """ assert type in (None, "string", "paths", "pathlist", "args", "linelist", "bool") + if default is NOT_SET: + default = get_ini_default_for_type(type) + self._inidict[name] = (help, type, default) self._ininames.append(name) +def get_ini_default_for_type( + type: Optional[Literal["string", "paths", "pathlist", "args", "linelist", "bool"]] +) -> Any: + """ + Used by addini to get the default value for a given ini-option type, when + default is not supplied. + """ + if type is None: + return "" + elif type in ("paths", "pathlist", "args", "linelist"): + return [] + elif type == "bool": + return False + else: + return "" + + class ArgumentError(Exception): """Raised if an Argument instance is created with invalid or inconsistent arguments.""" diff --git a/testing/test_config.py b/testing/test_config.py index ded30790188..b7c61feea98 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -5,6 +5,7 @@ import sys import textwrap from pathlib import Path +from typing import Any from typing import Dict from typing import List from typing import Sequence @@ -21,6 +22,7 @@ from _pytest.config import ConftestImportFailure from _pytest.config import ExitCode from _pytest.config import parse_warning_filter +from _pytest.config.argparsing import get_ini_default_for_type from _pytest.config.exceptions import UsageError from _pytest.config.findpaths import determine_setup from _pytest.config.findpaths import get_common_ancestor @@ -857,6 +859,68 @@ def pytest_addoption(parser): assert len(values) == 2 assert values == ["456", "123"] + def test_addini_default_values(self, pytester: Pytester) -> None: + """Tests the default values for configuration based on + config type + """ + + pytester.makeconftest( + """ + def pytest_addoption(parser): + parser.addini("linelist1", "", type="linelist") + parser.addini("paths1", "", type="paths") + parser.addini("pathlist1", "", type="pathlist") + parser.addini("args1", "", type="args") + parser.addini("bool1", "", type="bool") + parser.addini("string1", "", type="string") + parser.addini("none_1", "", type="linelist", default=None) + parser.addini("none_2", "", default=None) + parser.addini("no_type", "") + """ + ) + + config = pytester.parseconfig() + # default for linelist, paths, pathlist and args is [] + value = config.getini("linelist1") + assert value == [] + value = config.getini("paths1") + assert value == [] + value = config.getini("pathlist1") + assert value == [] + value = config.getini("args1") + assert value == [] + # default for bool is False + value = config.getini("bool1") + assert value is False + # default for string is "" + value = config.getini("string1") + assert value == "" + # should return None if None is explicity set as default value + # irrespective of the type argument + value = config.getini("none_1") + assert value is None + value = config.getini("none_2") + assert value is None + # in case no type is provided and no default set + # treat it as string and default value will be "" + value = config.getini("no_type") + assert value == "" + + @pytest.mark.parametrize( + "type, expected", + [ + pytest.param(None, "", id="None"), + pytest.param("string", "", id="string"), + pytest.param("paths", [], id="paths"), + pytest.param("pathlist", [], id="pathlist"), + pytest.param("args", [], id="args"), + pytest.param("linelist", [], id="linelist"), + pytest.param("bool", False, id="bool"), + ], + ) + def test_get_ini_default_for_type(self, type: Any, expected: Any) -> None: + assert get_ini_default_for_type(type) == expected + def test_confcutdir_check_isdir(self, pytester: Pytester) -> None: """Give an error if --confcutdir is not a valid directory (#2078)""" exp_match = r"^--confcutdir must be a directory, given: " From 99f77388107fcee4cbc665659fac61c8468b693d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 12 Nov 2023 10:41:08 -0300 Subject: [PATCH 0250/1271] [automated] Update plugin list (#11607) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 152 +++++++++++++++++++------------ 1 file changed, 96 insertions(+), 56 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 7fdc39b9c01..70e2b9b0ce9 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6,<8) :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) - :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 12, 2023 N/A pytest >=5.4.0 + :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Nov 08, 2023 N/A pytest >=5.4.0 :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-adf` Pytest plugin for writing Azure Data Factory integration tests May 10, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ads-testplan` Azure DevOps Test Case reporting for pytest tests Sep 15, 2022 N/A N/A - :pypi:`pytest-affected` Oct 05, 2023 N/A N/A + :pypi:`pytest-affected` Nov 06, 2023 N/A N/A :pypi:`pytest-agent` Service that exposes a REST API that can be used to interract remotely with Pytest. It is shipped with a dashboard that enables running tests in a more convenient way. Nov 25, 2021 N/A N/A :pypi:`pytest-aggreport` pytest plugin for pytest-repeat that generate aggregate report of the same test cases with additional statistics details. Mar 07, 2021 4 - Beta pytest (>=6.2.2) :pypi:`pytest-aio` Pytest plugin for testing async python code Feb 03, 2023 4 - Beta pytest @@ -67,7 +67,7 @@ This list contains 1338 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Oct 21, 2023 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Nov 08, 2023 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -135,7 +135,7 @@ This list contains 1338 plugins. :pypi:`pytest-bdd` BDD for pytest Oct 10, 2023 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0) - :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 20, 2023 N/A N/A + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 06, 2023 N/A N/A :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A @@ -186,7 +186,7 @@ This list contains 1338 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-cases` Separate test code from test cases in pytest. Oct 11, 2023 5 - Production/Stable N/A + :pypi:`pytest-cases` Separate test code from test cases in pytest. Nov 10, 2023 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A @@ -332,7 +332,7 @@ This list contains 1338 plugins. :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 - :pypi:`pytest-django` A Django plugin for pytest. Oct 30, 2023 5 - Production/Stable pytest >=7.0.0 + :pypi:`pytest-django` A Django plugin for pytest. Nov 08, 2023 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A @@ -410,13 +410,14 @@ This list contains 1338 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. Sep 13, 2023 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Sep 13, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Sep 13, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Sep 13, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Sep 13, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Sep 13, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Sep 13, 2023 5 - Production/Stable N/A + :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-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) @@ -488,6 +489,7 @@ This list contains 1338 plugins. :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest + :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Nov 09, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-fixture-config` Fixture configuration utils for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-fixture-maker` Pytest plugin to load fixtures from YAML files Sep 21, 2021 N/A N/A :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A @@ -525,7 +527,7 @@ This list contains 1338 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 Aug 17, 2022 1 - Planning pytest (>=7.1.2) + :pypi:`pytest-fzf` fzf-based test selector for pytest Nov 09, 2023 1 - Planning pytest >=7.1.2 :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 @@ -533,7 +535,7 @@ This list contains 1338 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Oct 26, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Nov 08, 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,16 +572,16 @@ This list contains 1338 plugins. :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-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 02, 2023 3 - Alpha pytest ==7.4.3 + :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-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-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. Sep 19, 2023 N/A pytest + :pypi:`pytest-houdini` pytest plugin for testing code in Houdini. Nov 10, 2023 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Nov 04, 2023 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-html` pytest plugin for generating HTML reports Nov 07, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Sep 23, 2023 N/A N/A @@ -675,6 +677,7 @@ This list contains 1338 plugins. :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. Aug 20, 2022 3 - Alpha pytest (>=3.6,<8) :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A :pypi:`pytest-langchain` Pytest-style test runner for langchain agents Feb 26, 2023 N/A pytest + :pypi:`pytest-lark` Create fancy and clear HTML test reports. Nov 05, 2023 N/A N/A :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) @@ -699,7 +702,7 @@ This list contains 1338 plugins. :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests Oct 14, 2023 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-lockable` lockable resource plugin for pytest Aug 09, 2023 5 - Production/Stable pytest + :pypi:`pytest-lockable` lockable resource plugin for pytest Nov 06, 2023 5 - Production/Stable pytest :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) :pypi:`pytest-log` print log Aug 15, 2021 N/A pytest (>=3.8) :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) @@ -732,7 +735,7 @@ This list contains 1338 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Oct 08, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 - :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Nov 04, 2023 N/A pytest (>=7.4.3) + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Nov 06, 2023 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 @@ -1065,7 +1068,7 @@ This list contains 1338 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 01, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 10, 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) @@ -1073,8 +1076,8 @@ This list contains 1338 plugins. :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-auto` pytest plugin to automatically capture screenshots upon selenium webdriver events Oct 18, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 01, 2023 5 - Production/Stable N/A + :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 10, 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 @@ -1146,7 +1149,7 @@ This list contains 1338 plugins. :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 Oct 27, 2023 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Nov 10, 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 @@ -1211,7 +1214,7 @@ This list contains 1338 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 03, 2023 4 - Beta pytest <8,>=5 + :pypi:`pytest-testmon` selects tests affected by changed files and methods Nov 07, 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) @@ -1284,6 +1287,7 @@ This list contains 1338 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 06, 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 @@ -1314,7 +1318,7 @@ This list contains 1338 plugins. :pypi:`pytest-vimqf` A simple pytest plugin that will shrink pytest output when specified, to fit vim quickfix window. Feb 08, 2021 4 - Beta pytest (>=6.2.2,<7.0.0) :pypi:`pytest-virtualenv` Virtualenv fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-visual` Nov 01, 2023 3 - Alpha pytest >=7.0.0 - :pypi:`pytest-vnc` VNC client for Pytest Feb 25, 2023 N/A pytest + :pypi:`pytest-vnc` VNC client for Pytest Nov 06, 2023 N/A pytest :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest @@ -1323,12 +1327,13 @@ This list contains 1338 plugins. :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-wake` Aug 30, 2023 N/A pytest + :pypi:`pytest-wake` Nov 07, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 24, 2023 4 - Beta N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 09, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A :pypi:`pytest-when` Utility which makes mocking more readable and controllable Oct 18, 2023 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A @@ -1420,7 +1425,7 @@ This list contains 1338 plugins. pytest plugin for generating test execution results within Jira Test Management (tm4j) :pypi:`pytest-adaptavist-fixed` - *last release*: Oct 12, 2023, + *last release*: Nov 08, 2023, *status*: N/A, *requires*: pytest >=5.4.0 @@ -1455,7 +1460,7 @@ This list contains 1338 plugins. Azure DevOps Test Case reporting for pytest tests :pypi:`pytest-affected` - *last release*: Oct 05, 2023, + *last release*: Nov 06, 2023, *status*: N/A, *requires*: N/A @@ -1609,7 +1614,7 @@ This list contains 1338 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Oct 21, 2023, + *last release*: Nov 08, 2023, *status*: N/A, *requires*: pytest >=7.3.1 @@ -2085,7 +2090,7 @@ This list contains 1338 plugins. BDD for pytest :pypi:`pytest-bdd-report` - *last release*: Aug 20, 2023, + *last release*: Nov 06, 2023, *status*: N/A, *requires*: N/A @@ -2442,7 +2447,7 @@ This list contains 1338 plugins. pytest plugin to capture all warnings and put them in one file of your choice :pypi:`pytest-cases` - *last release*: Oct 11, 2023, + *last release*: Nov 10, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -3464,7 +3469,7 @@ This list contains 1338 plugins. A pytest plugin to notify test results to a Discord channel. :pypi:`pytest-django` - *last release*: Oct 30, 2023, + *last release*: Nov 08, 2023, *status*: 5 - Production/Stable, *requires*: pytest >=7.0.0 @@ -4010,54 +4015,61 @@ This list contains 1338 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Sep 13, 2023, + *last release*: Nov 07, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Sep 13, 2023, + *last release*: Nov 07, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Sep 13, 2023, + *last release*: Nov 07, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Sep 13, 2023, + *last release*: Nov 07, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Sep 13, 2023, + *last release*: Nov 07, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Sep 13, 2023, + *last release*: Nov 07, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Sep 13, 2023, + *last release*: Nov 07, 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, + *status*: 5 - Production/Stable, + *requires*: N/A + + Make pytest-embedded plugin work with the Wokwi CLI. + :pypi:`pytest-embrace` *last release*: Mar 25, 2023, *status*: N/A, @@ -4555,6 +4567,13 @@ This list contains 1338 plugins. Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers + :pypi:`pytest-fixturecollection` + *last release*: Nov 09, 2023, + *status*: 4 - Beta, + *requires*: pytest >=3.5.0 + + A pytest plugin to collect tests based on fixtures being used by tests + :pypi:`pytest-fixture-config` *last release*: May 28, 2019, *status*: 5 - Production/Stable, @@ -4815,9 +4834,9 @@ This list contains 1338 plugins. :pypi:`pytest-fzf` - *last release*: Aug 17, 2022, + *last release*: Nov 09, 2023, *status*: 1 - Planning, - *requires*: pytest (>=7.1.2) + *requires*: pytest >=7.1.2 fzf-based test selector for pytest @@ -4871,7 +4890,7 @@ This list contains 1338 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Oct 26, 2023, + *last release*: Nov 08, 2023, *status*: N/A, *requires*: N/A @@ -5130,7 +5149,7 @@ This list contains 1338 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Nov 02, 2023, + *last release*: Nov 11, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5165,7 +5184,7 @@ This list contains 1338 plugins. A plugin that tracks test changes :pypi:`pytest-houdini` - *last release*: Sep 19, 2023, + *last release*: Nov 10, 2023, *status*: N/A, *requires*: pytest @@ -5193,7 +5212,7 @@ This list contains 1338 plugins. Helpers for testing hpfeeds in your python project :pypi:`pytest-html` - *last release*: Nov 04, 2023, + *last release*: Nov 07, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -5864,6 +5883,13 @@ This list contains 1338 plugins. Pytest-style test runner for langchain agents + :pypi:`pytest-lark` + *last release*: Nov 05, 2023, + *status*: N/A, + *requires*: N/A + + Create fancy and clear HTML test reports. + :pypi:`pytest-launchable` *last release*: Apr 05, 2023, *status*: N/A, @@ -6033,7 +6059,7 @@ This list contains 1338 plugins. Pytest plugin for AWS integration tests :pypi:`pytest-lockable` - *last release*: Aug 09, 2023, + *last release*: Nov 06, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -6264,7 +6290,7 @@ This list contains 1338 plugins. A pytest plugin to make a test results report with Markdown table format. :pypi:`pytest-meilisearch` - *last release*: Nov 04, 2023, + *last release*: Nov 06, 2023, *status*: N/A, *requires*: pytest (>=7.4.3) @@ -8595,7 +8621,7 @@ This list contains 1338 plugins. :pypi:`pytest-sbase` - *last release*: Nov 01, 2023, + *last release*: Nov 10, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8651,14 +8677,14 @@ This list contains 1338 plugins. pytest plugin for Selenium :pypi:`pytest-selenium-auto` - *last release*: Oct 18, 2023, + *last release*: Nov 07, 2023, *status*: N/A, *requires*: pytest >= 7.0.0 pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Nov 01, 2023, + *last release*: Nov 10, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9162,7 +9188,7 @@ This list contains 1338 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Oct 27, 2023, + *last release*: Nov 10, 2023, *status*: N/A, *requires*: N/A @@ -9617,7 +9643,7 @@ This list contains 1338 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: Nov 03, 2023, + *last release*: Nov 07, 2023, *status*: 4 - Beta, *requires*: pytest <8,>=5 @@ -10127,6 +10153,13 @@ This list contains 1338 plugins. A Typhoon HIL plugin that facilitates test parameter configuration at runtime + :pypi:`pytest-typhoon-polarion` + *last release*: Nov 06, 2023, + *status*: 4 - Beta, + *requires*: N/A + + Typhoontest plugin for Siemens Polarion + :pypi:`pytest-typhoon-xray` *last release*: Aug 15, 2023, *status*: 4 - Beta, @@ -10338,7 +10371,7 @@ This list contains 1338 plugins. :pypi:`pytest-vnc` - *last release*: Feb 25, 2023, + *last release*: Nov 06, 2023, *status*: N/A, *requires*: pytest @@ -10401,7 +10434,7 @@ This list contains 1338 plugins. Pytest plugin for testing whatsapp bots with end to end tests :pypi:`pytest-wake` - *last release*: Aug 30, 2023, + *last release*: Nov 07, 2023, *status*: N/A, *requires*: pytest @@ -10442,6 +10475,13 @@ This list contains 1338 plugins. Selenium webdriver fixture for py.test + :pypi:`pytest-webtest-extras` + *last release*: Nov 09, 2023, + *status*: N/A, + *requires*: pytest >= 7.0.0 + + Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. + :pypi:`pytest-wetest` *last release*: Nov 10, 2018, *status*: 4 - Beta, From 9417aeb2d800377656ecc0a49dd079bccfe32bdb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 09:28:54 +0100 Subject: [PATCH 0251/1271] build(deps): Bump pytest-html in /testing/plugins_integration (#11608) Bumps [pytest-html](https://github.com/pytest-dev/pytest-html) from 4.1.0 to 4.1.1. - [Release notes](https://github.com/pytest-dev/pytest-html/releases) - [Changelog](https://github.com/pytest-dev/pytest-html/blob/master/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-html/compare/4.1.0...4.1.1) --- updated-dependencies: - dependency-name: pytest-html dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 23eac432778..84c40db95eb 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -5,7 +5,7 @@ pytest-bdd==7.0.0 pytest-cov==4.1.0 pytest-django==4.6.0 pytest-flakes==4.0.5 -pytest-html==4.1.0 +pytest-html==4.1.1 pytest-mock==3.12.0 pytest-rerunfailures==12.0 pytest-sugar==0.9.7 From 442b09ed9f645c42a44a6230cec6501b2d034ffd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 09:29:21 +0100 Subject: [PATCH 0252/1271] build(deps): Bump pytest-django in /testing/plugins_integration (#11609) Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.6.0 to 4.7.0. - [Release notes](https://github.com/pytest-dev/pytest-django/releases) - [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.6.0...v4.7.0) --- updated-dependencies: - dependency-name: pytest-django dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 84c40db95eb..fcbe3f16883 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -3,7 +3,7 @@ django==4.2.7 pytest-asyncio==0.21.1 pytest-bdd==7.0.0 pytest-cov==4.1.0 -pytest-django==4.6.0 +pytest-django==4.7.0 pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.12.0 From d4c56c72d8a623414da9ec9bd76a00bb844c71e4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 21:00:52 +0000 Subject: [PATCH 0253/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.10.1 → 23.11.0](https://github.com/psf/black/compare/23.10.1...23.11.0) - [github.com/pre-commit/mirrors-mypy: v1.6.1 → v1.7.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.6.1...v1.7.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0f7e4b2a726..1fb0266024d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 23.10.1 + rev: 23.11.0 hooks: - id: black args: [--safe, --quiet] @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.6.1 + rev: v1.7.0 hooks: - id: mypy files: ^(src/|testing/) From 970d11cf348b45e830a0b9b3a3d70c511b4d517e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 14 Nov 2023 07:29:40 -0300 Subject: [PATCH 0254/1271] Explicitly export error and path from py Required by mypy 1.7.0 --- src/py.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/py.py b/src/py.py index 7813c9b93cd..c997903363a 100644 --- a/src/py.py +++ b/src/py.py @@ -8,3 +8,5 @@ sys.modules["py.error"] = error sys.modules["py.path"] = path + +__all__ = ["error", "path"] From 223e030604d1f5de54fe07cdb12689aa46556e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 14 Nov 2023 15:41:35 +0100 Subject: [PATCH 0255/1271] XFAIL TestLocalPath.test_make_numbered_dir_multiprocess_safe (#11611) The tested py.path.local.make_numbered_dir function is *not* multiprocess safe, because is uses os.listdir which itself is not. The os.listdir documentation explicitly states that: > If a file is removed from or added to the directory during the call > of this function, whether a name for that file be included is unspecified. This can lead to a race when: 1. process A attempts to create directory N 2. the creation fails, as another process already created it in the meantime 3. process A calls listdir to determine a more recent maxnum 4. processes B+ repeatedly create newer directories and they delete directory N 5. process A doesn't have directory N or any newer directory in listdir result 6. process A attempts to create directory N again and raises For details, see https://github.com/pytest-dev/pytest/issues/11603#issuecomment-1805708144 and bellow. Additionally, the test itself has a race in batch_make_numbered_dirs. When this functions attempts to write to repro-N/foo, repro-N may have already been removed by another process. For details, see https://github.com/pytest-dev/pytest/issues/11603#issuecomment-1804714313 and bellow. --- The tested py.path.local.make_numbered_dir function is not used in pytest. There is a different implementation in _pytest.pathlib. Closes #11603 --- testing/_py/test_local.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index aebee380cb9..77a9838cf11 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -868,6 +868,9 @@ def test_fspath_protocol_other_class(self, fake_fspath_obj): py_path.strpath, str_path ) + @pytest.mark.xfail( + reason="#11603", raises=(error.EEXIST, error.ENOENT), strict=False + ) def test_make_numbered_dir_multiprocess_safe(self, tmpdir): # https://github.com/pytest-dev/py/issues/30 with multiprocessing.Pool() as pool: From 80442ae2f2177039e5395d8a26fc6e3ca3a54f3e Mon Sep 17 00:00:00 2001 From: Avasam Date: Fri, 17 Nov 2023 03:42:05 -0500 Subject: [PATCH 0256/1271] Use `False`, instead of `None` as default for `_XfailMarkDecorator`'s `condition` param and update doc (#11600) --- AUTHORS | 1 + changelog/11600.improvement.rst | 1 + doc/en/reference/reference.rst | 7 +++---- src/_pytest/mark/structures.py | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 changelog/11600.improvement.rst diff --git a/AUTHORS b/AUTHORS index 212d4a8832a..d8e90171504 100644 --- a/AUTHORS +++ b/AUTHORS @@ -339,6 +339,7 @@ Saiprasad Kale Samuel Colvin Samuel Dion-Girardeau Samuel Searles-Bryant +Samuel Therrien (Avasam) Samuele Pedroni Sanket Duthade Sankt Petersbug diff --git a/changelog/11600.improvement.rst b/changelog/11600.improvement.rst new file mode 100644 index 00000000000..7082e2c1e10 --- /dev/null +++ b/changelog/11600.improvement.rst @@ -0,0 +1 @@ +Improved the documentation and type signature for :func:`pytest.mark.xfail `'s ``condition`` param to use ``False`` as the default value. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 0240e1f4aad..f6dabb24510 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -239,12 +239,11 @@ pytest.mark.xfail Marks a test function as *expected to fail*. -.. py:function:: pytest.mark.xfail(condition=None, *, reason=None, raises=None, run=True, strict=xfail_strict) +.. py:function:: pytest.mark.xfail(condition=False, *, reason=None, raises=None, run=True, strict=xfail_strict) - :type condition: bool or str - :param condition: + :keyword Union[bool, str] condition: Condition for marking the test function as xfail (``True/False`` or a - :ref:`condition string `). If a bool, you also have + :ref:`condition string `). If a ``bool``, you also have to specify ``reason`` (see :ref:`condition string `). :keyword str reason: Reason why the test function is marked as xfail. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index bbde6864486..55ec67700b6 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -457,7 +457,7 @@ def __call__(self, arg: Markable) -> Markable: @overload def __call__( self, - condition: Union[str, bool] = ..., + condition: Union[str, bool] = False, *conditions: Union[str, bool], reason: str = ..., run: bool = ..., From 9dc1fc4523e60f0c8795e9693e47f35769a66471 Mon Sep 17 00:00:00 2001 From: Patrick Lannigan Date: Sun, 19 Nov 2023 09:56:29 -0500 Subject: [PATCH 0257/1271] Add verbosity_assertions and config.get_verbosity Fixes #11387 --- AUTHORS | 1 + changelog/11387.feature.rst | 5 ++ doc/en/how-to/output.rst | 14 ++++ doc/en/reference/reference.rst | 13 ++++ src/_pytest/assertion/__init__.py | 8 +++ src/_pytest/assertion/rewrite.py | 5 +- src/_pytest/assertion/truncate.py | 5 +- src/_pytest/assertion/util.py | 2 +- src/_pytest/config/__init__.py | 75 ++++++++++++++++++++- testing/test_assertion.py | 104 ++++++++++++++++++++++++++++-- testing/test_assertrewrite.py | 6 +- testing/test_config.py | 74 +++++++++++++++++++++ 12 files changed, 299 insertions(+), 13 deletions(-) create mode 100644 changelog/11387.feature.rst diff --git a/AUTHORS b/AUTHORS index d8e90171504..e30131d1a7e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -293,6 +293,7 @@ Ondřej Súkup Oscar Benjamin Parth Patel Patrick Hayes +Patrick Lannigan Paul Müller Paul Reece Pauli Virtanen diff --git a/changelog/11387.feature.rst b/changelog/11387.feature.rst new file mode 100644 index 00000000000..90f20885b0a --- /dev/null +++ b/changelog/11387.feature.rst @@ -0,0 +1,5 @@ +Added the new :confval:`verbosity_assertions` configuration option for fine-grained control of failed assertions verbosity. + +See :ref:`Fine-grained verbosity ` for more details. + +For plugin authors, :attr:`config.get_verbosity ` can be used to retrieve the verbosity level for a specific verbosity type. diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index 04f201610b5..8af9a38b768 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -286,6 +286,20 @@ situations, for example you are shown even fixtures that start with ``_`` if you Using higher verbosity levels (``-vvv``, ``-vvvv``, ...) is supported, but has no effect in pytest itself at the moment, however some plugins might make use of higher verbosity. +.. _`pytest.fine_grained_verbosity`: + +Fine-grained verbosity +~~~~~~~~~~~~~~~~~~~~~~ + +In addition to specifying the application wide verbosity level, it is possible to control specific aspects independently. +This is done by setting a verbosity level in the configuration file for the specific aspect of the output. + +:confval:`verbosity_assertions`: Controls how verbose the assertion output should be when pytest is executed. Running +``pytest --no-header`` with a value of ``2`` would have the same output as the previous example, but each test inside +the file is shown by a single character in the output. + +(Note: currently this is the only option available, but more might be added in the future). + .. _`pytest.detailed_failed_tests_usage`: Producing a detailed summary report diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index f6dabb24510..254973709af 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1822,6 +1822,19 @@ passed multiple times. The expected format is ``name=value``. For example:: clean_db +.. confval:: verbosity_assertions + + Set a verbosity level specifically for assertion related output, overriding the application wide level. + + .. code-block:: ini + + [pytest] + verbosity_assertions = 2 + + Defaults to application wide verbosity level (via the ``-v`` command-line option). A special value of + "auto" can be used to explicitly use the global verbosity level. + + .. confval:: xfail_strict If set to ``True``, tests marked with ``@pytest.mark.xfail`` that actually succeed will by default fail the diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index 64ad4b0e662..e1e7a5e6663 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -42,6 +42,14 @@ def pytest_addoption(parser: Parser) -> None: help="Enables the pytest_assertion_pass hook. " "Make sure to delete any previously generated pyc cache files.", ) + Config._add_verbosity_ini( + parser, + Config.VERBOSITY_ASSERTIONS, + help=( + "Specify a verbosity level for assertions, overriding the main level. " + "Higher levels will provide more detailed explanation when an assertion fails." + ), + ) def register_assert_rewrite(*names: str) -> None: diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 258ed9f9ab0..149101e716f 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -426,7 +426,10 @@ def _saferepr(obj: object) -> str: def _get_maxsize_for_saferepr(config: Optional[Config]) -> Optional[int]: """Get `maxsize` configuration for saferepr based on the given config object.""" - verbosity = config.getoption("verbose") if config is not None else 0 + if config is None: + verbosity = 0 + else: + verbosity = config.get_verbosity(Config.VERBOSITY_ASSERTIONS) if verbosity >= 2: return None if verbosity >= 1: diff --git a/src/_pytest/assertion/truncate.py b/src/_pytest/assertion/truncate.py index dfd6f65d281..16de27f256e 100644 --- a/src/_pytest/assertion/truncate.py +++ b/src/_pytest/assertion/truncate.py @@ -1,12 +1,13 @@ """Utilities for truncating assertion output. Current default behaviour is to truncate assertion explanations at -~8 terminal lines, unless running in "-vv" mode or running on CI. +terminal lines, unless running with an assertions verbosity level of at least 2 or running on CI. """ from typing import List from typing import Optional from _pytest.assertion import util +from _pytest.config import Config from _pytest.nodes import Item @@ -26,7 +27,7 @@ def truncate_if_required( def _should_truncate_item(item: Item) -> bool: """Whether or not this test item is eligible for truncation.""" - verbose = item.config.option.verbose + verbose = item.config.get_verbosity(Config.VERBOSITY_ASSERTIONS) return verbose < 2 and not util.running_on_ci() diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index b9123c97dbe..65abe8d238e 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -168,7 +168,7 @@ def assertrepr_compare( config, op: str, left: Any, right: Any, use_ascii: bool = False ) -> Optional[List[str]]: """Return specialised explanations for some operators/operands.""" - verbose = config.getoption("verbose") + verbose = config.get_verbosity(Config.VERBOSITY_ASSERTIONS) # Strings which normalize equal are often hard to distinguish when printed; use ascii() to make this easier. # See issue #3246. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 03f69ed31e3..ea23c77421a 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -22,6 +22,7 @@ from typing import Callable from typing import cast from typing import Dict +from typing import Final from typing import final from typing import Generator from typing import IO @@ -69,7 +70,7 @@ if TYPE_CHECKING: from _pytest._code.code import _TracebackStyle from _pytest.terminal import TerminalReporter - from .argparsing import Argument + from .argparsing import Argument, Parser _PluggyPlugin = object @@ -1650,6 +1651,78 @@ def getvalueorskip(self, name: str, path=None): """Deprecated, use getoption(skip=True) instead.""" return self.getoption(name, skip=True) + #: Verbosity type for failed assertions (see :confval:`verbosity_assertions`). + VERBOSITY_ASSERTIONS: Final = "assertions" + _VERBOSITY_INI_DEFAULT: Final = "auto" + + def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: + r"""Retrieve the verbosity level for a fine-grained verbosity type. + + :param verbosity_type: Verbosity type to get level for. If a level is + configured for the given type, that value will be returned. If the + given type is not a known verbosity type, the global verbosity + level will be returned. If the given type is None (default), the + global verbosity level will be returned. + + To configure a level for a fine-grained verbosity type, the + configuration file should have a setting for the configuration name + and a numeric value for the verbosity level. A special value of "auto" + can be used to explicitly use the global verbosity level. + + Example: + + .. code-block:: ini + + # content of pytest.ini + [pytest] + verbosity_assertions = 2 + + .. code-block:: console + + pytest -v + + .. code-block:: python + + print(config.get_verbosity()) # 1 + print(config.get_verbosity(Config.VERBOSITY_ASSERTIONS)) # 2 + """ + global_level = self.option.verbose + assert isinstance(global_level, int) + if verbosity_type is None: + return global_level + + ini_name = Config._verbosity_ini_name(verbosity_type) + if ini_name not in self._parser._inidict: + return global_level + + level = self.getini(ini_name) + if level == Config._VERBOSITY_INI_DEFAULT: + return global_level + + return int(level) + + @staticmethod + def _verbosity_ini_name(verbosity_type: str) -> str: + return f"verbosity_{verbosity_type}" + + @staticmethod + def _add_verbosity_ini(parser: "Parser", verbosity_type: str, help: str) -> None: + """Add a output verbosity configuration option for the given output type. + + :param parser: Parser for command line arguments and ini-file values. + :param verbosity_type: Fine-grained verbosity category. + :param help: Description of the output this type controls. + + The value should be retrieved via a call to + :py:func:`config.get_verbosity(type) `. + """ + parser.addini( + Config._verbosity_ini_name(verbosity_type), + help=help, + type="string", + default=Config._VERBOSITY_INI_DEFAULT, + ) + def _warn_about_missing_assertion(self, mode: str) -> None: if not _assertion_supported(): if mode == "plain": diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 62c465d8a34..7c8c0155681 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -13,27 +13,68 @@ from _pytest import outcomes from _pytest.assertion import truncate from _pytest.assertion import util +from _pytest.config import Config as _Config from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester -def mock_config(verbose=0): +def mock_config(verbose: int = 0, assertion_override: Optional[int] = None): class TerminalWriter: def _highlight(self, source, lexer): return source class Config: - def getoption(self, name): - if name == "verbose": - return verbose - raise KeyError("Not mocked out: %s" % name) - def get_terminal_writer(self): return TerminalWriter() + def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: + if verbosity_type is None: + return verbose + if verbosity_type == _Config.VERBOSITY_ASSERTIONS: + if assertion_override is not None: + return assertion_override + return verbose + + raise KeyError(f"Not mocked out: {verbosity_type}") + return Config() +class TestMockConfig: + SOME_VERBOSITY_LEVEL = 3 + SOME_OTHER_VERBOSITY_LEVEL = 10 + + def test_verbose_exposes_value(self): + config = mock_config(verbose=TestMockConfig.SOME_VERBOSITY_LEVEL) + + assert config.get_verbosity() == TestMockConfig.SOME_VERBOSITY_LEVEL + + def test_get_assertion_override_not_set_verbose_value(self): + config = mock_config(verbose=TestMockConfig.SOME_VERBOSITY_LEVEL) + + assert ( + config.get_verbosity(_Config.VERBOSITY_ASSERTIONS) + == TestMockConfig.SOME_VERBOSITY_LEVEL + ) + + def test_get_assertion_override_set_custom_value(self): + config = mock_config( + verbose=TestMockConfig.SOME_VERBOSITY_LEVEL, + assertion_override=TestMockConfig.SOME_OTHER_VERBOSITY_LEVEL, + ) + + assert ( + config.get_verbosity(_Config.VERBOSITY_ASSERTIONS) + == TestMockConfig.SOME_OTHER_VERBOSITY_LEVEL + ) + + def test_get_unsupported_type_error(self): + config = mock_config(verbose=TestMockConfig.SOME_VERBOSITY_LEVEL) + + with pytest.raises(KeyError): + config.get_verbosity("--- NOT A VERBOSITY LEVEL ---") + + class TestImportHookInstallation: @pytest.mark.parametrize("initial_conftest", [True, False]) @pytest.mark.parametrize("mode", ["plain", "rewrite"]) @@ -1836,3 +1877,54 @@ def test_comparisons_handle_colors( ) result.stdout.fnmatch_lines(formatter(expected_lines), consecutive=False) + + +def test_fine_grained_assertion_verbosity(pytester: Pytester): + long_text = "Lorem ipsum dolor sit amet " * 10 + p = pytester.makepyfile( + f""" + def test_ok(): + pass + + + def test_words_fail(): + fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"] + fruits2 = ["banana", "apple", "orange", "melon", "kiwi"] + assert fruits1 == fruits2 + + + def test_numbers_fail(): + number_to_text1 = {{str(x): x for x in range(5)}} + number_to_text2 = {{str(x * 10): x * 10 for x in range(5)}} + assert number_to_text1 == number_to_text2 + + + def test_long_text_fail(): + long_text = "{long_text}" + assert "hello world" in long_text + """ + ) + pytester.makeini( + """ + [pytest] + verbosity_assertions = 2 + """ + ) + result = pytester.runpytest(p) + + result.stdout.fnmatch_lines( + [ + f"{p.name} .FFF [100%]", + "E At index 2 diff: 'grapes' != 'orange'", + "E Full diff:", + "E - ['banana', 'apple', 'orange', 'melon', 'kiwi']", + "E ? ^ ^^", + "E + ['banana', 'apple', 'grapes', 'melon', '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}", + f"E AssertionError: assert 'hello world' in '{long_text}'", + ] + ) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index d3cd6144404..a4d48b6feeb 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -2056,13 +2056,15 @@ class TestReprSizeVerbosity: ) def test_get_maxsize_for_saferepr(self, verbose: int, expected_size) -> None: class FakeConfig: - def getoption(self, name: str) -> int: - assert name == "verbose" + def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: return verbose config = FakeConfig() assert _get_maxsize_for_saferepr(cast(Config, config)) == expected_size + def test_get_maxsize_for_saferepr_no_config(self) -> None: + assert _get_maxsize_for_saferepr(None) == DEFAULT_REPR_MAX_SIZE + def create_test_file(self, pytester: Pytester, size: int) -> None: pytester.makepyfile( f""" diff --git a/testing/test_config.py b/testing/test_config.py index b7c61feea98..58671e6ed3c 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -23,6 +23,7 @@ from _pytest.config import ExitCode from _pytest.config import parse_warning_filter from _pytest.config.argparsing import get_ini_default_for_type +from _pytest.config.argparsing import Parser from _pytest.config.exceptions import UsageError from _pytest.config.findpaths import determine_setup from _pytest.config.findpaths import get_common_ancestor @@ -2245,3 +2246,76 @@ def test_debug_help(self, pytester: Pytester) -> None: "*Default: pytestdebug.log.", ] ) + + +class TestVerbosity: + SOME_OUTPUT_TYPE = Config.VERBOSITY_ASSERTIONS + SOME_OUTPUT_VERBOSITY_LEVEL = 5 + + class VerbosityIni: + def pytest_addoption(self, parser: Parser) -> None: + Config._add_verbosity_ini( + parser, TestVerbosity.SOME_OUTPUT_TYPE, help="some help text" + ) + + def test_level_matches_verbose_when_not_specified( + self, pytester: Pytester, tmp_path: Path + ) -> None: + tmp_path.joinpath("pytest.ini").write_text( + textwrap.dedent( + """\ + [pytest] + addopts = --verbose + """ + ), + encoding="utf-8", + ) + pytester.plugins = [TestVerbosity.VerbosityIni()] + + config = pytester.parseconfig(tmp_path) + + assert ( + config.get_verbosity(TestVerbosity.SOME_OUTPUT_TYPE) + == config.option.verbose + ) + + def test_level_matches_verbose_when_not_known_type( + self, pytester: Pytester, tmp_path: Path + ) -> None: + tmp_path.joinpath("pytest.ini").write_text( + textwrap.dedent( + """\ + [pytest] + addopts = --verbose + """ + ), + encoding="utf-8", + ) + pytester.plugins = [TestVerbosity.VerbosityIni()] + + config = pytester.parseconfig(tmp_path) + + assert config.get_verbosity("some fake verbosity type") == config.option.verbose + + def test_level_matches_specified_override( + self, pytester: Pytester, tmp_path: Path + ) -> None: + setting_name = f"verbosity_{TestVerbosity.SOME_OUTPUT_TYPE}" + tmp_path.joinpath("pytest.ini").write_text( + textwrap.dedent( + f"""\ + [pytest] + addopts = --verbose + {setting_name} = {TestVerbosity.SOME_OUTPUT_VERBOSITY_LEVEL} + """ + ), + encoding="utf-8", + ) + pytester.plugins = [TestVerbosity.VerbosityIni()] + + config = pytester.parseconfig(tmp_path) + + assert ( + config.get_verbosity(TestVerbosity.SOME_OUTPUT_TYPE) + == TestVerbosity.SOME_OUTPUT_VERBOSITY_LEVEL + ) From 476bab84f782064de364a4acd42255ae141556b1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 19 Nov 2023 11:57:25 -0300 Subject: [PATCH 0258/1271] [automated] Update plugin list (#11627) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 112 +++++++++++++++++++------------ 1 file changed, 68 insertions(+), 44 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 70e2b9b0ce9..2e39b41530b 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =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 Jan 13, 2022 4 - Beta pytest (>=4.6) + :pypi:`pytest-arraydiff` pytest plugin to help with comparing array output from tests Nov 15, 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,7 +105,7 @@ This list contains 1343 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 Oct 31, 2023 4 - Beta pytest (>=7.0.0) + :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-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) @@ -135,7 +135,7 @@ This list contains 1343 plugins. :pypi:`pytest-bdd` BDD for pytest Oct 10, 2023 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0) - :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 06, 2023 N/A N/A + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 15, 2023 N/A pytest >=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A @@ -251,7 +251,7 @@ This list contains 1343 plugins. :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) - :pypi:`pytest-copie` The pytest plugin for your Copier templates. Sep 10, 2023 3 - Alpha pytest + :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Nov 14, 2023 3 - Alpha pytest :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Jun 23, 2023 4 - Beta pytest>=7.1.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A @@ -362,7 +362,7 @@ This list contains 1343 plugins. :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) - :pypi:`pytest-docker-fixtures` pytest docker fixtures May 02, 2023 3 - Alpha pytest + :pypi:`pytest-docker-fixtures` pytest docker fixtures Nov 17, 2023 3 - Alpha N/A :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Feb 09, 2022 4 - Beta pytest :pypi:`pytest-docker-haproxy-fixtures` Pytest fixtures for testing with haproxy. Feb 09, 2022 4 - Beta pytest :pypi:`pytest-docker-pexpect` pytest plugin for writing functional tests with pexpect and docker Jan 14, 2019 N/A pytest @@ -527,7 +527,7 @@ This list contains 1343 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 09, 2023 1 - Planning pytest >=7.1.2 + :pypi:`pytest-fzf` fzf-based test selector for pytest Nov 15, 2023 1 - Planning pytest >=7.1.2 :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 @@ -584,7 +584,7 @@ This list contains 1343 plugins. :pypi:`pytest-html` pytest plugin for generating HTML reports Nov 07, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-html-merger` Pytest HTML reports merging utility Sep 23, 2023 N/A N/A + :pypi:`pytest-html-merger` Pytest HTML reports merging utility Nov 11, 2023 N/A N/A :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Mar 04, 2022 5 - Production/Stable N/A :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A @@ -597,7 +597,7 @@ This list contains 1343 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Sep 18, 2023 5 - Production/Stable pytest ==7.* + :pypi:`pytest-httpx` Send responses to httpx. Nov 13, 2023 5 - Production/Stable pytest ==7.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest @@ -611,6 +611,7 @@ This list contains 1343 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-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 @@ -715,7 +716,7 @@ This list contains 1343 plugins. :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Oct 04, 2023 5 - Production/Stable pytest :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) - :pypi:`pytest-lsp` pytest plugin for end-to-end testing of language servers Oct 06, 2023 3 - Alpha pytest + :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 13, 2023 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) @@ -1018,6 +1019,7 @@ This list contains 1343 plugins. :pypi:`pytest-requires` A pytest plugin to elegantly skip tests with optional requirements Dec 21, 2021 4 - Beta pytest (>=3.5.0) :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-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 @@ -1068,7 +1070,7 @@ This list contains 1343 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 10, 2023 5 - Production/Stable 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-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) @@ -1077,7 +1079,7 @@ This list contains 1343 plugins. :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-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 10, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 17, 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 @@ -1149,7 +1151,7 @@ This list contains 1343 plugins. :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 10, 2023 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Nov 15, 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 @@ -1169,6 +1171,7 @@ This list contains 1343 plugins. :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A :pypi:`pytest-stf` pytest plugin for openSTF Oct 10, 2023 N/A pytest >=5.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A + :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-structlog` Structured logging assertions Dec 18, 2022 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A @@ -1210,7 +1213,7 @@ This list contains 1343 plugins. :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A - :pypi:`pytest-testinfra` Test infrastructures Aug 24, 2023 5 - Production/Stable pytest !=3.0.2 + :pypi:`pytest-testinfra` Test infrastructures Nov 13, 2023 5 - Production/Stable pytest !=3.0.2 :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) @@ -1287,14 +1290,14 @@ This list contains 1343 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 06, 2023 4 - Beta N/A + :pypi:`pytest-typhoon-polarion` Typhoontest plugin for Siemens Polarion Nov 17, 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 :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest :pypi:`pytest-ui-failed-screenshot` UI自动测试失败时自动截图,并将截图加入到测试报告中 Dec 06, 2022 N/A N/A :pypi:`pytest-ui-failed-screenshot-allure` UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 Dec 06, 2022 N/A N/A - :pypi:`pytest-unflakable` Unflakable plugin for PyTest Sep 10, 2023 4 - Beta pytest >=6.2.0 + :pypi:`pytest-unflakable` Unflakable plugin for PyTest Nov 12, 2023 4 - Beta pytest >=6.2.0 :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) @@ -1313,7 +1316,7 @@ This list contains 1343 plugins. :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 01, 2023 4 - Beta N/A + :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Nov 18, 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 @@ -1333,7 +1336,7 @@ This list contains 1343 plugins. :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 09, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 13, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A :pypi:`pytest-when` Utility which makes mocking more readable and controllable Oct 18, 2023 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A @@ -1343,7 +1346,7 @@ This list contains 1343 plugins. :pypi:`pytest-wiremock` A pytest plugin for programmatically using wiremock in integration tests Mar 27, 2022 N/A pytest (>=7.1.1,<8.0.0) :pypi:`pytest-with-docker` pytest with docker helpers. Nov 09, 2021 N/A pytest :pypi:`pytest-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Jan 13, 2023 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs May 19, 2023 5 - Production/Stable pytest (>=6.2.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-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) @@ -1768,9 +1771,9 @@ This list contains 1343 plugins. pyest results colection plugin :pypi:`pytest-arraydiff` - *last release*: Jan 13, 2022, + *last release*: Nov 15, 2023, *status*: 4 - Beta, - *requires*: pytest (>=4.6) + *requires*: pytest >=4.6 pytest plugin to help with comparing array output from tests @@ -1880,7 +1883,7 @@ This list contains 1343 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Oct 31, 2023, + *last release*: Nov 16, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.0.0) @@ -2090,9 +2093,9 @@ This list contains 1343 plugins. BDD for pytest :pypi:`pytest-bdd-report` - *last release*: Nov 06, 2023, + *last release*: Nov 15, 2023, *status*: N/A, - *requires*: N/A + *requires*: pytest >=7.1.3 A pytest-bdd plugin for generating useful and informative BDD test reports @@ -2902,11 +2905,11 @@ This list contains 1343 plugins. The pytest plugin for your Cookiecutter templates. 🍪 :pypi:`pytest-copie` - *last release*: Sep 10, 2023, + *last release*: Nov 14, 2023, *status*: 3 - Alpha, *requires*: pytest - The pytest plugin for your Copier templates. + The pytest plugin for your copier templates 📒 :pypi:`pytest-copier` *last release*: Jun 23, 2023, @@ -3679,9 +3682,9 @@ This list contains 1343 plugins. A plugin to use docker databases for pytests :pypi:`pytest-docker-fixtures` - *last release*: May 02, 2023, + *last release*: Nov 17, 2023, *status*: 3 - Alpha, - *requires*: pytest + *requires*: N/A pytest docker fixtures @@ -4834,7 +4837,7 @@ This list contains 1343 plugins. :pypi:`pytest-fzf` - *last release*: Nov 09, 2023, + *last release*: Nov 15, 2023, *status*: 1 - Planning, *requires*: pytest >=7.1.2 @@ -5233,7 +5236,7 @@ This list contains 1343 plugins. optimized pytest plugin for generating HTML reports :pypi:`pytest-html-merger` - *last release*: Sep 23, 2023, + *last release*: Nov 11, 2023, *status*: N/A, *requires*: N/A @@ -5324,7 +5327,7 @@ This list contains 1343 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Sep 18, 2023, + *last release*: Nov 13, 2023, *status*: 5 - Production/Stable, *requires*: pytest ==7.* @@ -5421,6 +5424,13 @@ This list contains 1343 plugins. + :pypi:`pytest-image-snapshot` + *last release*: Nov 16, 2023, + *status*: 4 - Beta, + *requires*: pytest >=3.5.0 + + A pytest plugin for image snapshot management and comparison. + :pypi:`pytest-incremental` *last release*: Apr 24, 2021, *status*: 5 - Production/Stable, @@ -6150,11 +6160,11 @@ This list contains 1343 plugins. pytest plugin for looping tests :pypi:`pytest-lsp` - *last release*: Oct 06, 2023, + *last release*: Nov 13, 2023, *status*: 3 - Alpha, *requires*: pytest - pytest plugin for end-to-end testing of language servers + A pytest plugin for end-to-end testing of language servers :pypi:`pytest-manual-marker` *last release*: Aug 04, 2022, @@ -8270,6 +8280,13 @@ This list contains 1343 plugins. Re-run only changed files in specified branch + :pypi:`pytest-rerun-all` + *last release*: Nov 16, 2023, + *status*: 3 - Alpha, + *requires*: pytest (>=7.0.0) + + Rerun testsuite for a certain time or iterations + :pypi:`pytest-rerunfailures` *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, @@ -8621,7 +8638,7 @@ This list contains 1343 plugins. :pypi:`pytest-sbase` - *last release*: Nov 10, 2023, + *last release*: Nov 17, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8684,7 +8701,7 @@ This list contains 1343 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Nov 10, 2023, + *last release*: Nov 17, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9188,7 +9205,7 @@ This list contains 1343 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Nov 10, 2023, + *last release*: Nov 15, 2023, *status*: N/A, *requires*: N/A @@ -9327,6 +9344,13 @@ This list contains 1343 plugins. A plugin to pytest stoq + :pypi:`pytest-store` + *last release*: Nov 16, 2023, + *status*: 3 - Alpha, + *requires*: pytest (>=7.0.0) + + Pytest plugin to store values from test runs + :pypi:`pytest-stress` *last release*: Dec 07, 2019, *status*: 4 - Beta, @@ -9615,7 +9639,7 @@ This list contains 1343 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-testinfra` - *last release*: Aug 24, 2023, + *last release*: Nov 13, 2023, *status*: 5 - Production/Stable, *requires*: pytest !=3.0.2 @@ -10154,7 +10178,7 @@ This list contains 1343 plugins. A Typhoon HIL plugin that facilitates test parameter configuration at runtime :pypi:`pytest-typhoon-polarion` - *last release*: Nov 06, 2023, + *last release*: Nov 17, 2023, *status*: 4 - Beta, *requires*: N/A @@ -10203,7 +10227,7 @@ This list contains 1343 plugins. UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 :pypi:`pytest-unflakable` - *last release*: Sep 10, 2023, + *last release*: Nov 12, 2023, *status*: 4 - Beta, *requires*: pytest >=6.2.0 @@ -10336,9 +10360,9 @@ This list contains 1343 plugins. py.test fixture for creating a virtual environment :pypi:`pytest-ver` - *last release*: Nov 01, 2023, + *last release*: Nov 18, 2023, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest Pytest module with Verification Protocol, Verification Report and Trace Matrix @@ -10476,7 +10500,7 @@ This list contains 1343 plugins. Selenium webdriver fixture for py.test :pypi:`pytest-webtest-extras` - *last release*: Nov 09, 2023, + *last release*: Nov 13, 2023, *status*: N/A, *requires*: pytest >= 7.0.0 @@ -10546,9 +10570,9 @@ This list contains 1343 plugins. A pytest plugin for configuring workflow/pipeline tests using YAML files :pypi:`pytest-xdist` - *last release*: May 19, 2023, + *last release*: Nov 11, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.0) + *requires*: pytest >=6.2.0 pytest xdist plugin for distributed testing, most importantly across multiple CPUs From 09161918275897a9393b835d5330f0436f9a56e7 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 19 Nov 2023 11:19:30 -0500 Subject: [PATCH 0259/1271] use name-independent github actions badge (#11628) if we were ever to change the `name:` field in `test.yml` this would suddenly break -- this references the workflow file directly (and is what github generates now for badges) --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index e6bb6d4cf7f..bbf41a18399 100644 --- a/README.rst +++ b/README.rst @@ -20,7 +20,7 @@ :target: https://codecov.io/gh/pytest-dev/pytest :alt: Code coverage Status -.. image:: https://github.com/pytest-dev/pytest/workflows/test/badge.svg +.. image:: https://github.com/pytest-dev/pytest/actions/workflows/test.yml/badge.svg :target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Atest .. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg From eb6ad08e5de1b63c1a46e2fce36be3ded899bead Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Fri, 17 Nov 2023 18:40:29 +0000 Subject: [PATCH 0260/1271] Vendor in the pprint module to allow further modifications We already have the AlwaysDispatchingPrettyPrinter override of the default pretty printer. In order to make more in depth changes, we need to copy the upstream version in, as it doesn't lend itself well to being extended. This does a verbatime copy, adding provenance information at the top. --- src/_pytest/_io/pprint.py | 664 ++++++++++++++++++++++++++++++++++++ src/_pytest/_io/saferepr.py | 6 +- 2 files changed, 668 insertions(+), 2 deletions(-) create mode 100644 src/_pytest/_io/pprint.py diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py new file mode 100644 index 00000000000..3875f713145 --- /dev/null +++ b/src/_pytest/_io/pprint.py @@ -0,0 +1,664 @@ +# This module was imported from the cpython standard library +# (https://github.com/python/cpython/) at commit +# c5140945c723ae6c4b7ee81ff720ac8ea4b52cfd (python3.12). +# +# fmt: off +# flake8: noqa +# type: ignore + +# +# Author: Fred L. Drake, Jr. +# fdrake@acm.org +# +# This is a simple little module I wrote to make life easier. I didn't +# see anything quite like it in the library, though I may have overlooked +# something. I wrote this when I was trying to read some heavily nested +# tuples with fairly non-descriptive content. This is modeled very much +# after Lisp/Scheme - style pretty-printing of lists. If you find it +# useful, thank small children who sleep at night. + +"""Support to pretty-print lists, tuples, & dictionaries recursively. + +Very simple, but useful, especially in debugging data structures. + +Classes +------- + +PrettyPrinter() + Handle pretty-printing operations onto a stream using a configured + set of formatting parameters.htop + +Functions +--------- + +pformat() + Format a Python object into a pretty-printed representation. + +pprint() + Pretty-print a Python object to a stream [default is sys.stdout]. + +saferepr() + Generate a 'standard' repr()-like value, but protect against recursive + data structures. + +""" + +import collections as _collections +import dataclasses as _dataclasses +import re +import sys as _sys +import types as _types +from io import StringIO as _StringIO + +__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", + "PrettyPrinter", "pp"] + + +def pprint(object, stream=None, indent=1, width=80, depth=None, *, + compact=False, sort_dicts=True, underscore_numbers=False): + """Pretty-print a Python object to a stream [default is sys.stdout].""" + printer = PrettyPrinter( + stream=stream, indent=indent, width=width, depth=depth, + compact=compact, sort_dicts=sort_dicts, + underscore_numbers=underscore_numbers) + printer.pprint(object) + +def pformat(object, indent=1, width=80, depth=None, *, + compact=False, sort_dicts=True, underscore_numbers=False): + """Format a Python object into a pretty-printed representation.""" + return PrettyPrinter(indent=indent, width=width, depth=depth, + compact=compact, sort_dicts=sort_dicts, + underscore_numbers=underscore_numbers).pformat(object) + +def pp(object, *args, sort_dicts=False, **kwargs): + """Pretty-print a Python object""" + pprint(object, *args, sort_dicts=sort_dicts, **kwargs) + +def saferepr(object): + """Version of repr() which can handle recursive data structures.""" + return PrettyPrinter()._safe_repr(object, {}, None, 0)[0] + +def isreadable(object): + """Determine if saferepr(object) is readable by eval().""" + return PrettyPrinter()._safe_repr(object, {}, None, 0)[1] + +def isrecursive(object): + """Determine if object requires a recursive representation.""" + return PrettyPrinter()._safe_repr(object, {}, None, 0)[2] + +class _safe_key: + """Helper function for key functions when sorting unorderable objects. + + The wrapped-object will fallback to a Py2.x style comparison for + unorderable types (sorting first comparing the type name and then by + the obj ids). Does not work recursively, so dict.items() must have + _safe_key applied to both the key and the value. + + """ + + __slots__ = ['obj'] + + def __init__(self, obj): + self.obj = obj + + def __lt__(self, other): + try: + return self.obj < other.obj + except TypeError: + return ((str(type(self.obj)), id(self.obj)) < \ + (str(type(other.obj)), id(other.obj))) + +def _safe_tuple(t): + "Helper function for comparing 2-tuples" + return _safe_key(t[0]), _safe_key(t[1]) + +class PrettyPrinter: + def __init__(self, indent=1, width=80, depth=None, stream=None, *, + compact=False, sort_dicts=True, underscore_numbers=False): + """Handle pretty printing operations onto a stream using a set of + configured parameters. + + indent + Number of spaces to indent for each level of nesting. + + width + Attempted maximum number of columns in the output. + + 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. + + """ + indent = int(indent) + width = int(width) + if indent < 0: + raise ValueError('indent must be >= 0') + if depth is not None and depth <= 0: + raise ValueError('depth must be > 0') + if not width: + raise ValueError('width must be != 0') + 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 pprint(self, object): + if self._stream is not None: + self._format(object, self._stream, 0, 0, {}, 0) + self._stream.write("\n") + + def pformat(self, object): + sio = _StringIO() + self._format(object, sio, 0, 0, {}, 0) + return sio.getvalue() + + def isrecursive(self, object): + return self.format(object, {}, 0, 0)[2] + + def isreadable(self, object): + s, readable, recursive = self.format(object, {}, 0, 0) + return readable and not recursive + + def _format(self, object, stream, indent, allowance, context, level): + objid = id(object) + if objid in context: + stream.write(_recursion(object)) + self._recursive = True + self._readable = False + return + rep = self._repr(object, context, level) + max_width = self._width - indent - allowance + if len(rep) > max_width: + p = self._dispatch.get(type(object).__repr__, None) + if p is not None: + context[objid] = 1 + p(self, object, stream, indent, allowance, context, level + 1) + del context[objid] + return + elif (_dataclasses.is_dataclass(object) and + not isinstance(object, type) and + object.__dataclass_params__.repr and + # Check dataclass has generated repr method. + hasattr(object.__repr__, "__wrapped__") and + "__create_fn__" in object.__repr__.__wrapped__.__qualname__): + context[objid] = 1 + self._pprint_dataclass(object, stream, indent, allowance, context, level + 1) + del context[objid] + return + stream.write(rep) + + def _pprint_dataclass(self, object, stream, indent, allowance, context, level): + cls_name = object.__class__.__name__ + indent += len(cls_name) + 1 + items = [(f.name, getattr(object, f.name)) for f in _dataclasses.fields(object) if f.repr] + stream.write(cls_name + '(') + self._format_namespace_items(items, stream, indent, allowance, context, level) + stream.write(')') + + _dispatch = {} + + def _pprint_dict(self, object, stream, indent, allowance, context, level): + 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) + write('}') + + _dispatch[dict.__repr__] = _pprint_dict + + def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level): + 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) + stream.write(')') + + _dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict + + def _pprint_list(self, object, stream, indent, allowance, context, level): + stream.write('[') + self._format_items(object, stream, indent, allowance + 1, + context, level) + stream.write(']') + + _dispatch[list.__repr__] = _pprint_list + + def _pprint_tuple(self, object, stream, indent, allowance, context, level): + stream.write('(') + endchar = ',)' if len(object) == 1 else ')' + self._format_items(object, stream, indent, allowance + len(endchar), + context, level) + stream.write(endchar) + + _dispatch[tuple.__repr__] = _pprint_tuple + + def _pprint_set(self, object, stream, indent, allowance, context, level): + if not len(object): + stream.write(repr(object)) + return + typ = object.__class__ + if typ is set: + stream.write('{') + endchar = '}' + 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) + stream.write(endchar) + + _dispatch[set.__repr__] = _pprint_set + _dispatch[frozenset.__repr__] = _pprint_set + + def _pprint_str(self, object, stream, indent, allowance, context, level): + write = stream.write + if not len(object): + write(repr(object)) + return + chunks = [] + lines = object.splitlines(True) + if level == 1: + indent += 1 + allowance += 1 + max_width1 = max_width = self._width - indent + for i, line in enumerate(lines): + rep = repr(line) + if i == len(lines) - 1: + max_width1 -= allowance + if len(rep) <= max_width1: + chunks.append(rep) + else: + # A list of alternating (non-space, space) strings + parts = re.findall(r'\S*\s*', line) + assert parts + assert not parts[-1] + parts.pop() # drop empty last part + max_width2 = max_width + current = '' + for j, part in enumerate(parts): + candidate = current + part + if j == len(parts) - 1 and i == len(lines) - 1: + max_width2 -= allowance + if len(repr(candidate)) > max_width2: + if current: + chunks.append(repr(current)) + current = part + else: + current = candidate + if current: + chunks.append(repr(current)) + if len(chunks) == 1: + write(rep) + return + if level == 1: + write('(') + for i, rep in enumerate(chunks): + if i > 0: + write('\n' + ' '*indent) + write(rep) + if level == 1: + write(')') + + _dispatch[str.__repr__] = _pprint_str + + def _pprint_bytes(self, object, stream, indent, allowance, context, level): + write = stream.write + if len(object) <= 4: + write(repr(object)) + return + parens = level == 1 + if parens: + indent += 1 + allowance += 1 + write('(') + delim = '' + for rep in _wrap_bytes_repr(object, self._width - indent, allowance): + write(delim) + write(rep) + if not delim: + delim = '\n' + ' '*indent + if parens: + write(')') + + _dispatch[bytes.__repr__] = _pprint_bytes + + def _pprint_bytearray(self, object, stream, indent, allowance, context, level): + write = stream.write + write('bytearray(') + self._pprint_bytes(bytes(object), stream, indent + 10, + allowance + 1, context, level + 1) + write(')') + + _dispatch[bytearray.__repr__] = _pprint_bytearray + + def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level): + stream.write('mappingproxy(') + self._format(object.copy(), stream, indent + 13, allowance + 1, + context, level) + stream.write(')') + + _dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy + + def _pprint_simplenamespace(self, object, stream, indent, allowance, context, level): + 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) + stream.write(')') + + _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_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 + write(key) + write('=') + if id(ent) in context: + # Special-case representation of recursion to match standard + # recursive dataclass repr. + write("...") + else: + self._format(ent, stream, indent + len(key) + 1, + allowance if last else 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: + 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 + + 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. + """ + 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 + rdf = self._repr(object.default_factory, context, level) + cls = object.__class__ + indent += len(cls.__name__) + 1 + stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent)) + self._pprint_dict(object, stream, indent, allowance + 1, 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) * ' ') + items = object.most_common() + self._format_dict_items(items, stream, + indent + len(cls.__name__) + 1, allowance + 2, + context, level) + stream.write('})') + + _dispatch[_collections.Counter.__repr__] = _pprint_counter + + def _pprint_chain_map(self, object, stream, indent, allowance, context, level): + if not len(object.maps): + 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(')') + 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 + stream.write('[') + if object.maxlen is None: + self._format_items(object, stream, indent, allowance + 2, + context, level) + stream.write('])') + else: + self._format_items(object, stream, indent, 2, + context, level) + rml = self._repr(object.maxlen, context, level) + stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml)) + + _dispatch[_collections.deque.__repr__] = _pprint_deque + + def _pprint_user_dict(self, object, stream, indent, allowance, context, level): + 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): + 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): + 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). + typ = type(object) + if typ in _builtin_scalars: + return repr(object), True, False + + r = getattr(typ, "__repr__", None) + + if issubclass(typ, int) and r is int.__repr__: + if self._underscore_numbers: + return f"{object:_d}", True, False + else: + return repr(object), True, False + + if issubclass(typ, dict) and r is dict.__repr__: + if not object: + return "{}", True, False + objid = id(object) + if maxlevels and level >= maxlevels: + return "{...}", False, objid in context + if objid in context: + return _recursion(object), False, True + context[objid] = 1 + readable = True + recursive = False + components = [] + append = components.append + level += 1 + if self._sort_dicts: + items = sorted(object.items(), key=_safe_tuple) + 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) + append("%s: %s" % (krepr, vrepr)) + readable = readable and kreadable and vreadable + if krecur or vrecur: + recursive = True + del context[objid] + return "{%s}" % ", ".join(components), readable, recursive + + 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 + format = "[%s]" + elif len(object) == 1: + format = "(%s,)" + else: + if not object: + return "()", True, False + format = "(%s)" + objid = id(object) + if maxlevels and level >= maxlevels: + return format % "...", False, objid in context + if objid in context: + return _recursion(object), False, True + context[objid] = 1 + readable = True + recursive = False + components = [] + append = components.append + level += 1 + for o in object: + orepr, oreadable, orecur = 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 + + rep = repr(object) + return rep, (rep and not rep.startswith('<')), False + +_builtin_scalars = frozenset({str, bytes, bytearray, float, complex, + bool, type(None)}) + +def _recursion(object): + return ("" + % (type(object).__name__, id(object))) + + +def _wrap_bytes_repr(object, width, allowance): + current = b'' + last = len(object) // 4 * 4 + for i in range(0, len(object), 4): + part = object[i: i+4] + candidate = current + part + if i == last: + width -= allowance + if len(repr(candidate)) > width: + if current: + yield repr(current) + current = part + else: + current = candidate + if current: + yield repr(current) diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index c701872238c..50d6a303a69 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -5,6 +5,8 @@ from typing import IO from typing import Optional +from .pprint import PrettyPrinter # type: ignore + def _try_repr_or_str(obj: object) -> str: try: @@ -134,7 +136,7 @@ def saferepr_unlimited(obj: object, use_ascii: bool = True) -> str: return _format_repr_exception(exc, obj) -class AlwaysDispatchingPrettyPrinter(pprint.PrettyPrinter): +class AlwaysDispatchingPrettyPrinter(PrettyPrinter): """PrettyPrinter that always dispatches (regardless of width).""" def _format( @@ -175,6 +177,6 @@ def _pformat_dispatch( *, compact: bool = False, ) -> str: - return AlwaysDispatchingPrettyPrinter( + return AlwaysDispatchingPrettyPrinter( # type: ignore indent=indent, width=width, depth=depth, compact=compact ).pformat(object) From 23226683449ef07931e9aa5caa380ef03192db09 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Fri, 17 Nov 2023 18:54:47 +0000 Subject: [PATCH 0261/1271] Remove unneeded pprint interfaces There are parts of the original pprint module that we won't need, let's limit the surface and remove the unnecessary code --- src/_pytest/_io/pprint.py | 79 +-------------------------------------- 1 file changed, 2 insertions(+), 77 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 3875f713145..c13ae99aebe 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -6,9 +6,8 @@ # flake8: noqa # type: ignore -# -# Author: Fred L. Drake, Jr. -# fdrake@acm.org +# Original Author: Fred L. Drake, Jr. +# fdrake@acm.org # # This is a simple little module I wrote to make life easier. I didn't # see anything quite like it in the library, though I may have overlooked @@ -16,33 +15,6 @@ # tuples with fairly non-descriptive content. This is modeled very much # after Lisp/Scheme - style pretty-printing of lists. If you find it # useful, thank small children who sleep at night. - -"""Support to pretty-print lists, tuples, & dictionaries recursively. - -Very simple, but useful, especially in debugging data structures. - -Classes -------- - -PrettyPrinter() - Handle pretty-printing operations onto a stream using a configured - set of formatting parameters.htop - -Functions ---------- - -pformat() - Format a Python object into a pretty-printed representation. - -pprint() - Pretty-print a Python object to a stream [default is sys.stdout]. - -saferepr() - Generate a 'standard' repr()-like value, but protect against recursive - data structures. - -""" - import collections as _collections import dataclasses as _dataclasses import re @@ -50,41 +22,6 @@ import types as _types from io import StringIO as _StringIO -__all__ = ["pprint","pformat","isreadable","isrecursive","saferepr", - "PrettyPrinter", "pp"] - - -def pprint(object, stream=None, indent=1, width=80, depth=None, *, - compact=False, sort_dicts=True, underscore_numbers=False): - """Pretty-print a Python object to a stream [default is sys.stdout].""" - printer = PrettyPrinter( - stream=stream, indent=indent, width=width, depth=depth, - compact=compact, sort_dicts=sort_dicts, - underscore_numbers=underscore_numbers) - printer.pprint(object) - -def pformat(object, indent=1, width=80, depth=None, *, - compact=False, sort_dicts=True, underscore_numbers=False): - """Format a Python object into a pretty-printed representation.""" - return PrettyPrinter(indent=indent, width=width, depth=depth, - compact=compact, sort_dicts=sort_dicts, - underscore_numbers=underscore_numbers).pformat(object) - -def pp(object, *args, sort_dicts=False, **kwargs): - """Pretty-print a Python object""" - pprint(object, *args, sort_dicts=sort_dicts, **kwargs) - -def saferepr(object): - """Version of repr() which can handle recursive data structures.""" - return PrettyPrinter()._safe_repr(object, {}, None, 0)[0] - -def isreadable(object): - """Determine if saferepr(object) is readable by eval().""" - return PrettyPrinter()._safe_repr(object, {}, None, 0)[1] - -def isrecursive(object): - """Determine if object requires a recursive representation.""" - return PrettyPrinter()._safe_repr(object, {}, None, 0)[2] class _safe_key: """Helper function for key functions when sorting unorderable objects. @@ -157,23 +94,11 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *, self._sort_dicts = sort_dicts self._underscore_numbers = underscore_numbers - def pprint(self, object): - if self._stream is not None: - self._format(object, self._stream, 0, 0, {}, 0) - self._stream.write("\n") - def pformat(self, object): sio = _StringIO() self._format(object, sio, 0, 0, {}, 0) return sio.getvalue() - def isrecursive(self, object): - return self.format(object, {}, 0, 0)[2] - - def isreadable(self, object): - s, readable, recursive = self.format(object, {}, 0, 0) - return readable and not recursive - def _format(self, object, stream, indent, allowance, context, level): objid = id(object) if objid in context: From 66f2f20effb987e24cbf4dce2c86437bc813e57f Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Fri, 17 Nov 2023 19:05:20 +0000 Subject: [PATCH 0262/1271] Run pyupgrade on the pprint module --- src/_pytest/_io/pprint.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index c13ae99aebe..66afca58786 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -5,7 +5,8 @@ # fmt: off # flake8: noqa # type: ignore - +# +# # Original Author: Fred L. Drake, Jr. # fdrake@acm.org # @@ -408,7 +409,7 @@ def _pprint_default_dict(self, object, stream, indent, allowance, context, level rdf = self._repr(object.default_factory, context, level) cls = object.__class__ indent += len(cls.__name__) + 1 - stream.write('%s(%s,\n%s' % (cls.__name__, rdf, ' ' * indent)) + stream.write(f"{cls.__name__}({rdf},\n{' ' * indent}") self._pprint_dict(object, stream, indent, allowance + 1, context, level) stream.write(')') @@ -463,7 +464,7 @@ def _pprint_deque(self, object, stream, indent, allowance, context, level): self._format_items(object, stream, indent, 2, context, level) rml = self._repr(object.maxlen, context, level) - stream.write('],\n%smaxlen=%s)' % (' ' * indent, rml)) + stream.write(f"],\n{' ' * indent}maxlen={rml})") _dispatch[_collections.deque.__repr__] = _pprint_deque @@ -519,7 +520,7 @@ def _safe_repr(self, object, context, maxlevels, level): k, context, maxlevels, level) vrepr, vreadable, vrecur = self.format( v, context, maxlevels, level) - append("%s: %s" % (krepr, vrepr)) + append(f"{krepr}: {vrepr}") readable = readable and kreadable and vreadable if krecur or vrecur: recursive = True From 5fae5ef73e85ac6d753aa6c9d72424734cccaf3b Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Fri, 17 Nov 2023 19:06:51 +0000 Subject: [PATCH 0263/1271] Apply project-wide formatting standard to the pprint module (black) --- src/_pytest/_io/pprint.py | 268 +++++++++++++++++++++----------------- 1 file changed, 151 insertions(+), 117 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 66afca58786..3bb4a2c7d13 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -2,7 +2,6 @@ # (https://github.com/python/cpython/) at commit # c5140945c723ae6c4b7ee81ff720ac8ea4b52cfd (python3.12). # -# fmt: off # flake8: noqa # type: ignore # @@ -34,7 +33,7 @@ class _safe_key: """ - __slots__ = ['obj'] + __slots__ = ["obj"] def __init__(self, obj): self.obj = obj @@ -43,16 +42,29 @@ def __lt__(self, other): try: return self.obj < other.obj except TypeError: - return ((str(type(self.obj)), id(self.obj)) < \ - (str(type(other.obj)), id(other.obj))) + return (str(type(self.obj)), id(self.obj)) < ( + str(type(other.obj)), + id(other.obj), + ) + def _safe_tuple(t): "Helper function for comparing 2-tuples" return _safe_key(t[0]), _safe_key(t[1]) + class PrettyPrinter: - def __init__(self, indent=1, width=80, depth=None, stream=None, *, - compact=False, sort_dicts=True, underscore_numbers=False): + def __init__( + self, + indent=1, + width=80, + depth=None, + stream=None, + *, + compact=False, + sort_dicts=True, + underscore_numbers=False, + ): """Handle pretty printing operations onto a stream using a set of configured parameters. @@ -79,11 +91,11 @@ def __init__(self, indent=1, width=80, depth=None, stream=None, *, indent = int(indent) width = int(width) if indent < 0: - raise ValueError('indent must be >= 0') + raise ValueError("indent must be >= 0") if depth is not None and depth <= 0: - raise ValueError('depth must be > 0') + raise ValueError("depth must be > 0") if not width: - raise ValueError('width must be != 0') + raise ValueError("width must be != 0") self._depth = depth self._indent_per_level = indent self._width = width @@ -116,14 +128,19 @@ def _format(self, object, stream, indent, allowance, context, level): p(self, object, stream, indent, allowance, context, level + 1) del context[objid] return - elif (_dataclasses.is_dataclass(object) and - not isinstance(object, type) and - object.__dataclass_params__.repr and - # Check dataclass has generated repr method. - hasattr(object.__repr__, "__wrapped__") and - "__create_fn__" in object.__repr__.__wrapped__.__qualname__): + elif ( + _dataclasses.is_dataclass(object) + and not isinstance(object, type) + and object.__dataclass_params__.repr + and + # Check dataclass has generated repr method. + hasattr(object.__repr__, "__wrapped__") + and "__create_fn__" in object.__repr__.__wrapped__.__qualname__ + ): context[objid] = 1 - self._pprint_dataclass(object, stream, indent, allowance, context, level + 1) + self._pprint_dataclass( + object, stream, indent, allowance, context, level + 1 + ) del context[objid] return stream.write(rep) @@ -131,27 +148,32 @@ def _format(self, object, stream, indent, allowance, context, level): def _pprint_dataclass(self, object, stream, indent, allowance, context, level): cls_name = object.__class__.__name__ indent += len(cls_name) + 1 - items = [(f.name, getattr(object, f.name)) for f in _dataclasses.fields(object) if f.repr] - stream.write(cls_name + '(') + items = [ + (f.name, getattr(object, f.name)) + for f in _dataclasses.fields(object) + if f.repr + ] + stream.write(cls_name + "(") self._format_namespace_items(items, stream, indent, allowance, context, level) - stream.write(')') + stream.write(")") _dispatch = {} def _pprint_dict(self, object, stream, indent, allowance, context, level): write = stream.write - write('{') + write("{") if self._indent_per_level > 1: - write((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) - write('}') + self._format_dict_items( + items, stream, indent, allowance + 1, context, level + ) + write("}") _dispatch[dict.__repr__] = _pprint_dict @@ -160,27 +182,32 @@ def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level 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) - stream.write(')') + stream.write(cls.__name__ + "(") + self._format( + list(object.items()), + stream, + indent + len(cls.__name__) + 1, + allowance + 1, + context, + level, + ) + stream.write(")") _dispatch[_collections.OrderedDict.__repr__] = _pprint_ordered_dict def _pprint_list(self, object, stream, indent, allowance, context, level): - stream.write('[') - self._format_items(object, stream, indent, allowance + 1, - context, level) - stream.write(']') + stream.write("[") + self._format_items(object, stream, indent, allowance + 1, context, level) + stream.write("]") _dispatch[list.__repr__] = _pprint_list def _pprint_tuple(self, object, stream, indent, allowance, context, level): - stream.write('(') - endchar = ',)' if len(object) == 1 else ')' - self._format_items(object, stream, indent, allowance + len(endchar), - context, level) + stream.write("(") + endchar = ",)" if len(object) == 1 else ")" + self._format_items( + object, stream, indent, allowance + len(endchar), context, level + ) stream.write(endchar) _dispatch[tuple.__repr__] = _pprint_tuple @@ -191,15 +218,16 @@ def _pprint_set(self, object, stream, indent, allowance, context, level): return typ = object.__class__ if typ is set: - stream.write('{') - endchar = '}' + stream.write("{") + endchar = "}" else: - stream.write(typ.__name__ + '({') - endchar = '})' + 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 + len(endchar), context, level + ) stream.write(endchar) _dispatch[set.__repr__] = _pprint_set @@ -224,12 +252,12 @@ def _pprint_str(self, object, stream, indent, allowance, context, level): chunks.append(rep) else: # A list of alternating (non-space, space) strings - parts = re.findall(r'\S*\s*', line) + parts = re.findall(r"\S*\s*", line) assert parts assert not parts[-1] parts.pop() # drop empty last part max_width2 = max_width - current = '' + current = "" for j, part in enumerate(parts): candidate = current + part if j == len(parts) - 1 and i == len(lines) - 1: @@ -246,13 +274,13 @@ def _pprint_str(self, object, stream, indent, allowance, context, level): write(rep) return if level == 1: - write('(') + write("(") for i, rep in enumerate(chunks): if i > 0: - write('\n' + ' '*indent) + write("\n" + " " * indent) write(rep) if level == 1: - write(')') + write(")") _dispatch[str.__repr__] = _pprint_str @@ -265,83 +293,94 @@ def _pprint_bytes(self, object, stream, indent, allowance, context, level): if parens: indent += 1 allowance += 1 - write('(') - delim = '' + write("(") + delim = "" for rep in _wrap_bytes_repr(object, self._width - indent, allowance): write(delim) write(rep) if not delim: - delim = '\n' + ' '*indent + delim = "\n" + " " * indent if parens: - write(')') + write(")") _dispatch[bytes.__repr__] = _pprint_bytes def _pprint_bytearray(self, object, stream, indent, allowance, context, level): write = stream.write - write('bytearray(') - self._pprint_bytes(bytes(object), stream, indent + 10, - allowance + 1, context, level + 1) - write(')') + write("bytearray(") + self._pprint_bytes( + bytes(object), stream, indent + 10, allowance + 1, context, level + 1 + ) + write(")") _dispatch[bytearray.__repr__] = _pprint_bytearray def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level): - stream.write('mappingproxy(') - self._format(object.copy(), stream, indent + 13, allowance + 1, - context, level) - stream.write(')') + stream.write("mappingproxy(") + self._format(object.copy(), stream, indent + 13, allowance + 1, context, level) + stream.write(")") _dispatch[_types.MappingProxyType.__repr__] = _pprint_mappingproxy - def _pprint_simplenamespace(self, object, stream, indent, allowance, context, level): + def _pprint_simplenamespace( + self, object, stream, indent, allowance, context, level + ): 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' + cls_name = "namespace" else: cls_name = object.__class__.__name__ indent += len(cls_name) + 1 items = object.__dict__.items() - stream.write(cls_name + '(') + stream.write(cls_name + "(") self._format_namespace_items(items, stream, indent, allowance, context, level) - stream.write(')') + stream.write(")") _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace - def _format_dict_items(self, items, stream, indent, allowance, context, - level): + def _format_dict_items(self, items, stream, indent, allowance, context, level): write = stream.write indent += self._indent_per_level - delimnl = ',\n' + ' ' * indent + 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) + write(": ") + self._format( + ent, + stream, + indent + len(rep) + 2, + allowance if last else 1, + context, + level, + ) if not last: write(delimnl) def _format_namespace_items(self, items, stream, indent, allowance, context, level): write = stream.write - delimnl = ',\n' + ' ' * indent + delimnl = ",\n" + " " * indent last_index = len(items) - 1 for i, (key, ent) in enumerate(items): last = i == last_index write(key) - write('=') + write("=") if id(ent) in context: # Special-case representation of recursion to match standard # recursive dataclass repr. write("...") else: - self._format(ent, stream, indent + len(key) + 1, - allowance if last else 1, - context, level) + self._format( + ent, + stream, + indent + len(key) + 1, + allowance if last else 1, + context, + level, + ) if not last: write(delimnl) @@ -349,9 +388,9 @@ 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 = '' + write((self._indent_per_level - 1) * " ") + delimnl = ",\n" + " " * indent + delim = "" width = max_width = self._width - indent + 1 it = iter(items) try: @@ -377,18 +416,17 @@ def _format_items(self, items, stream, indent, allowance, context, level): if width >= w: width -= w write(delim) - delim = ', ' + delim = ", " write(rep) continue write(delim) delim = delimnl - self._format(ent, stream, indent, - allowance if last else 1, - context, level) + 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) + repr, readable, recursive = self.format( + object, context.copy(), self._depth, level + ) if not readable: self._readable = False if recursive: @@ -411,7 +449,7 @@ def _pprint_default_dict(self, object, stream, indent, allowance, context, level 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(')') + stream.write(")") _dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict @@ -420,14 +458,14 @@ def _pprint_counter(self, object, stream, indent, allowance, context, level): stream.write(repr(object)) return cls = object.__class__ - stream.write(cls.__name__ + '({') + stream.write(cls.__name__ + "({") if self._indent_per_level > 1: - stream.write((self._indent_per_level - 1) * ' ') + stream.write((self._indent_per_level - 1) * " ") 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 + len(cls.__name__) + 1, allowance + 2, context, level + ) + stream.write("})") _dispatch[_collections.Counter.__repr__] = _pprint_counter @@ -436,15 +474,15 @@ def _pprint_chain_map(self, object, stream, indent, allowance, context, level): stream.write(repr(object)) return cls = object.__class__ - stream.write(cls.__name__ + '(') + 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(')') + stream.write(")") else: self._format(m, stream, indent, 1, context, level) - stream.write(',\n' + ' ' * indent) + stream.write(",\n" + " " * indent) _dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map @@ -453,16 +491,14 @@ def _pprint_deque(self, object, stream, indent, allowance, context, level): stream.write(repr(object)) return cls = object.__class__ - stream.write(cls.__name__ + '(') + stream.write(cls.__name__ + "(") indent += len(cls.__name__) + 1 - stream.write('[') + stream.write("[") if object.maxlen is None: - self._format_items(object, stream, indent, allowance + 2, - context, level) - stream.write('])') + self._format_items(object, stream, indent, allowance + 2, context, level) + stream.write("])") else: - self._format_items(object, stream, indent, 2, - context, level) + self._format_items(object, stream, indent, 2, context, level) rml = self._repr(object.maxlen, context, level) stream.write(f"],\n{' ' * indent}maxlen={rml})") @@ -516,10 +552,8 @@ def _safe_repr(self, object, context, maxlevels, level): 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, kreadable, krecur = self.format(k, context, maxlevels, level) + vrepr, vreadable, vrecur = self.format(v, context, maxlevels, level) append(f"{krepr}: {vrepr}") readable = readable and kreadable and vreadable if krecur or vrecur: @@ -527,8 +561,9 @@ def _safe_repr(self, object, context, maxlevels, level): del context[objid] return "{%s}" % ", ".join(components), readable, recursive - if (issubclass(typ, list) and r is list.__repr__) or \ - (issubclass(typ, tuple) and r is tuple.__repr__): + 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 @@ -551,8 +586,7 @@ def _safe_repr(self, object, context, maxlevels, level): append = components.append level += 1 for o in object: - orepr, oreadable, orecur = self.format( - o, context, maxlevels, level) + orepr, oreadable, orecur = self.format(o, context, maxlevels, level) append(orepr) if not oreadable: readable = False @@ -562,21 +596,21 @@ def _safe_repr(self, object, context, maxlevels, level): return format % ", ".join(components), readable, recursive rep = repr(object) - return rep, (rep and not rep.startswith('<')), False + return rep, (rep and not rep.startswith("<")), False + + +_builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)}) -_builtin_scalars = frozenset({str, bytes, bytearray, float, complex, - bool, type(None)}) def _recursion(object): - return ("" - % (type(object).__name__, id(object))) + return f"" def _wrap_bytes_repr(object, width, allowance): - current = b'' + current = b"" last = len(object) // 4 * 4 for i in range(0, len(object), 4): - part = object[i: i+4] + part = object[i : i + 4] candidate = current + part if i == last: width -= allowance From 295312000338670c0d83dfb75ce16a34be851eb2 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Fri, 17 Nov 2023 19:20:55 +0000 Subject: [PATCH 0264/1271] Fix typing information for the pprint module There is more type information that could be added. We can add those later to make it easier, this is jsut the minimum to allow linting to pass --- src/_pytest/_io/pprint.py | 19 ++++++++++++------- src/_pytest/_io/saferepr.py | 10 ++++------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 3bb4a2c7d13..04f7edbbea2 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -2,9 +2,6 @@ # (https://github.com/python/cpython/) at commit # c5140945c723ae6c4b7ee81ff720ac8ea4b52cfd (python3.12). # -# flake8: noqa -# type: ignore -# # # Original Author: Fred L. Drake, Jr. # fdrake@acm.org @@ -21,6 +18,11 @@ 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 List class _safe_key: @@ -49,7 +51,7 @@ def __lt__(self, other): def _safe_tuple(t): - "Helper function for comparing 2-tuples" + """Helper function for comparing 2-tuples""" return _safe_key(t[0]), _safe_key(t[1]) @@ -107,7 +109,7 @@ def __init__( self._sort_dicts = sort_dicts self._underscore_numbers = underscore_numbers - def pformat(self, object): + def pformat(self, object: Any) -> str: sio = _StringIO() self._format(object, sio, 0, 0, {}, 0) return sio.getvalue() @@ -157,7 +159,10 @@ def _pprint_dataclass(self, object, stream, indent, allowance, context, level): self._format_namespace_items(items, stream, indent, allowance, context, level) stream.write(")") - _dispatch = {} + _dispatch: Dict[ + Callable[..., str], + Callable[["PrettyPrinter", Any, IO[str], int, int, Dict[int, int], int], str], + ] = {} def _pprint_dict(self, object, stream, indent, allowance, context, level): write = stream.write @@ -544,7 +549,7 @@ def _safe_repr(self, object, context, maxlevels, level): context[objid] = 1 readable = True recursive = False - components = [] + components: List[str] = [] append = components.append level += 1 if self._sort_dicts: diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index 50d6a303a69..ba8ea4302ac 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -5,7 +5,7 @@ from typing import IO from typing import Optional -from .pprint import PrettyPrinter # type: ignore +from .pprint import PrettyPrinter def _try_repr_or_str(obj: object) -> str: @@ -148,13 +148,11 @@ def _format( context: Dict[int, Any], level: int, ) -> None: - # Type ignored because _dispatch is private. - p = self._dispatch.get(type(object).__repr__, None) # type: ignore[attr-defined] + p = self._dispatch.get(type(object).__repr__, None) objid = id(object) if objid in context or p is None: - # Type ignored because _format is private. - super()._format( # type: ignore[misc] + super()._format( object, stream, indent, @@ -177,6 +175,6 @@ def _pformat_dispatch( *, compact: bool = False, ) -> str: - return AlwaysDispatchingPrettyPrinter( # type: ignore + return AlwaysDispatchingPrettyPrinter( indent=indent, width=width, depth=depth, compact=compact ).pformat(object) From 19934b2b0cc83eef0830b9e2adb6c5301a7201fc Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Sat, 18 Nov 2023 09:07:00 +0000 Subject: [PATCH 0265/1271] Merge the AlwaysDispathPrettyPrinter into the now vendored PrettyPrinter We don't need to keep the separation anymore, and this will make it easier to extend --- src/_pytest/_io/pprint.py | 47 ++++++++++++++++----------------- src/_pytest/_io/saferepr.py | 49 ----------------------------------- src/_pytest/assertion/util.py | 7 ++--- testing/io/test_pprint.py | 8 ++++++ testing/io/test_saferepr.py | 7 ----- 5 files changed, 34 insertions(+), 84 deletions(-) create mode 100644 testing/io/test_pprint.py diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 04f7edbbea2..9923d0a6256 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -121,31 +121,28 @@ def _format(self, object, stream, indent, allowance, context, level): self._recursive = True self._readable = False return - rep = self._repr(object, context, level) - max_width = self._width - indent - allowance - if len(rep) > max_width: - p = self._dispatch.get(type(object).__repr__, None) - if p is not None: - context[objid] = 1 - p(self, object, stream, indent, allowance, context, level + 1) - del context[objid] - return - elif ( - _dataclasses.is_dataclass(object) - and not isinstance(object, type) - and object.__dataclass_params__.repr - and - # Check dataclass has generated repr method. - hasattr(object.__repr__, "__wrapped__") - and "__create_fn__" in object.__repr__.__wrapped__.__qualname__ - ): - context[objid] = 1 - self._pprint_dataclass( - object, stream, indent, allowance, context, level + 1 - ) - del context[objid] - return - stream.write(rep) + + p = self._dispatch.get(type(object).__repr__, None) + if p is not None: + context[objid] = 1 + p(self, object, stream, indent, allowance, context, level + 1) + del context[objid] + elif ( + _dataclasses.is_dataclass(object) + and not isinstance(object, type) + and object.__dataclass_params__.repr + and + # Check dataclass has generated repr method. + hasattr(object.__repr__, "__wrapped__") + and "__create_fn__" in object.__repr__.__wrapped__.__qualname__ + ): + context[objid] = 1 + self._pprint_dataclass( + object, stream, indent, allowance, context, level + 1 + ) + del context[objid] + else: + stream.write(self._repr(object, context, level)) def _pprint_dataclass(self, object, stream, indent, allowance, context, level): cls_name = object.__class__.__name__ diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index ba8ea4302ac..c51578ed488 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -1,12 +1,7 @@ import pprint import reprlib -from typing import Any -from typing import Dict -from typing import IO from typing import Optional -from .pprint import PrettyPrinter - def _try_repr_or_str(obj: object) -> str: try: @@ -134,47 +129,3 @@ def saferepr_unlimited(obj: object, use_ascii: bool = True) -> str: return repr(obj) except Exception as exc: return _format_repr_exception(exc, obj) - - -class AlwaysDispatchingPrettyPrinter(PrettyPrinter): - """PrettyPrinter that always dispatches (regardless of width).""" - - def _format( - self, - object: object, - stream: IO[str], - indent: int, - allowance: int, - context: Dict[int, Any], - level: int, - ) -> None: - p = self._dispatch.get(type(object).__repr__, None) - - objid = id(object) - if objid in context or p is None: - super()._format( - object, - stream, - indent, - allowance, - context, - level, - ) - return - - context[objid] = 1 - p(self, object, stream, indent, allowance, context, level + 1) - del context[objid] - - -def _pformat_dispatch( - object: object, - indent: int = 1, - width: int = 80, - depth: Optional[int] = None, - *, - compact: bool = False, -) -> str: - return AlwaysDispatchingPrettyPrinter( - indent=indent, width=width, depth=depth, compact=compact - ).pformat(object) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 65abe8d238e..4d9fd114bc2 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -16,7 +16,7 @@ import _pytest._code from _pytest import outcomes -from _pytest._io.saferepr import _pformat_dispatch +from _pytest._io.pprint import PrettyPrinter from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr_unlimited from _pytest.config import Config @@ -348,8 +348,9 @@ def _compare_eq_iterable( lines_left = len(left_formatting) lines_right = len(right_formatting) if lines_left != lines_right: - left_formatting = _pformat_dispatch(left).splitlines() - right_formatting = _pformat_dispatch(right).splitlines() + 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) diff --git a/testing/io/test_pprint.py b/testing/io/test_pprint.py new file mode 100644 index 00000000000..900ccbbfa72 --- /dev/null +++ b/testing/io/test_pprint.py @@ -0,0 +1,8 @@ +from _pytest._io.pprint import PrettyPrinter + + +def test_pformat_dispatch(): + printer = PrettyPrinter(width=5) + assert printer.pformat("a") == "'a'" + assert printer.pformat("a" * 10) == "'aaaaaaaaaa'" + assert printer.pformat("foo bar") == "('foo '\n 'bar')" diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index 24746bc2235..d94faa4f194 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -1,5 +1,4 @@ import pytest -from _pytest._io.saferepr import _pformat_dispatch from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr_unlimited @@ -159,12 +158,6 @@ def test_unicode(): assert saferepr(val) == reprval -def test_pformat_dispatch(): - assert _pformat_dispatch("a") == "'a'" - assert _pformat_dispatch("a" * 10, width=5) == "'aaaaaaaaaa'" - assert _pformat_dispatch("foo bar", width=5) == "('foo '\n 'bar')" - - def test_broken_getattribute(): """saferepr() can create proper representations of classes with broken __getattribute__ (#7145) From 53d7b5ed3ef93780b866a9fea3d8afe48f36d319 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Sat, 18 Nov 2023 09:21:44 +0000 Subject: [PATCH 0266/1271] Add some tests for the pprint module --- testing/io/test_pprint.py | 332 +++++++++++++++++++++++++++++++++++++- 1 file changed, 327 insertions(+), 5 deletions(-) diff --git a/testing/io/test_pprint.py b/testing/io/test_pprint.py index 900ccbbfa72..8c15740bd41 100644 --- a/testing/io/test_pprint.py +++ b/testing/io/test_pprint.py @@ -1,8 +1,330 @@ +import textwrap +from collections import ChainMap +from collections import Counter +from collections import defaultdict +from collections import deque +from collections import OrderedDict +from dataclasses import dataclass +from types import MappingProxyType +from types import SimpleNamespace +from typing import Any + +import pytest from _pytest._io.pprint import PrettyPrinter -def test_pformat_dispatch(): - printer = PrettyPrinter(width=5) - assert printer.pformat("a") == "'a'" - assert printer.pformat("a" * 10) == "'aaaaaaaaaa'" - assert printer.pformat("foo bar") == "('foo '\n 'bar')" +@dataclass +class EmptyDataclass: + pass + + +@dataclass +class DataclassWithOneItem: + foo: str + + +@dataclass +class DataclassWithTwoItems: + foo: str + bar: str + + +@pytest.mark.parametrize( + ("data", "expected"), + ( + pytest.param( + EmptyDataclass(), + "EmptyDataclass()", + id="dataclass-empty", + ), + pytest.param( + DataclassWithOneItem(foo="bar"), + """ + DataclassWithOneItem(foo='bar') + """, + id="dataclass-one-item", + ), + pytest.param( + DataclassWithTwoItems(foo="foo", bar="bar"), + """ + DataclassWithTwoItems(foo='foo', + bar='bar') + """, + id="dataclass-two-items", + ), + pytest.param( + {}, + "{}", + id="dict-empty", + ), + pytest.param( + {"one": 1}, + """ + {'one': 1} + """, + id="dict-one-item", + ), + pytest.param( + {"one": 1, "two": 2}, + """ + {'one': 1, + 'two': 2} + """, + id="dict-two-items", + ), + pytest.param(OrderedDict(), "OrderedDict()", id="ordereddict-empty"), + pytest.param( + OrderedDict({"one": 1}), + """ + OrderedDict([('one', + 1)]) + """, + id="ordereddict-one-item", + ), + pytest.param( + OrderedDict({"one": 1, "two": 2}), + """ + OrderedDict([('one', + 1), + ('two', + 2)]) + """, + id="ordereddict-two-items", + ), + pytest.param( + [], + "[]", + id="list-empty", + ), + pytest.param( + [1], + """ + [1] + """, + id="list-one-item", + ), + pytest.param( + [1, 2], + """ + [1, + 2] + """, + id="list-two-items", + ), + pytest.param( + tuple(), + "()", + id="tuple-empty", + ), + pytest.param( + (1,), + """ + (1,) + """, + id="tuple-one-item", + ), + pytest.param( + (1, 2), + """ + (1, + 2) + """, + id="tuple-two-items", + ), + pytest.param( + set(), + "set()", + id="set-empty", + ), + pytest.param( + {1}, + """ + {1} + """, + id="set-one-item", + ), + pytest.param( + {1, 2}, + """ + {1, + 2} + """, + id="set-two-items", + ), + pytest.param( + MappingProxyType({}), + "mappingproxy({})", + id="mappingproxy-empty", + ), + pytest.param( + MappingProxyType({"one": 1}), + """ + mappingproxy({'one': 1}) + """, + id="mappingproxy-one-item", + ), + pytest.param( + MappingProxyType({"one": 1, "two": 2}), + """ + mappingproxy({'one': 1, + 'two': 2}) + """, + id="mappingproxy-two-items", + ), + pytest.param( + SimpleNamespace(), + "namespace()", + id="simplenamespace-empty", + ), + pytest.param( + SimpleNamespace(one=1), + """ + namespace(one=1) + """, + id="simplenamespace-one-item", + ), + pytest.param( + SimpleNamespace(one=1, two=2), + """ + namespace(one=1, + two=2) + """, + id="simplenamespace-two-items", + ), + pytest.param( + defaultdict(str), "defaultdict(, {})", id="defaultdict-empty" + ), + pytest.param( + defaultdict(str, {"one": "1"}), + """ + defaultdict(, + {'one': '1'}) + """, + id="defaultdict-one-item", + ), + pytest.param( + defaultdict(str, {"one": "1", "two": "2"}), + """ + defaultdict(, + {'one': '1', + 'two': '2'}) + """, + id="defaultdict-two-items", + ), + pytest.param( + Counter(), + "Counter()", + id="counter-empty", + ), + pytest.param( + Counter("1"), + """ + Counter({'1': 1}) + """, + id="counter-one-item", + ), + pytest.param( + Counter("121"), + """ + Counter({'1': 2, + '2': 1}) + """, + id="counter-two-items", + ), + pytest.param(ChainMap(), "ChainMap({})", id="chainmap-empty"), + pytest.param( + 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}) + """, + id="chainmap-two-items", + ), + pytest.param( + deque(), + "deque([])", + id="deque-empty", + ), + pytest.param( + deque([1]), + """ + deque([1]) + """, + id="deque-one-item", + ), + pytest.param( + deque([1, 2]), + """ + deque([1, + 2]) + """, + id="deque-two-items", + ), + pytest.param( + deque([1, 2], maxlen=3), + """ + deque([1, + 2], + maxlen=3) + """, + id="deque-maxlen", + ), + pytest.param( + { + "chainmap": ChainMap({"one": 1}, {"two": 2}), + "counter": Counter("122"), + "dataclass": DataclassWithTwoItems(foo="foo", bar="bar"), + "defaultdict": defaultdict(str, {"one": "1", "two": "2"}), + "deque": deque([1, 2], maxlen=3), + "dict": {"one": 1, "two": 2}, + "list": [1, 2], + "mappingproxy": MappingProxyType({"one": 1, "two": 2}), + "ordereddict": OrderedDict({"one": 1, "two": 2}), + "set": {1, 2}, + "simplenamespace": SimpleNamespace(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(, + {'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)} + """, + id="deep-example", + ), + ), +) +def test_consistent_pretty_printer(data: Any, expected: str) -> None: + assert PrettyPrinter().pformat(data) == textwrap.dedent(expected).strip() From a42530a09d657f3a6b22ad8a45ac5d29068dd8b4 Mon Sep 17 00:00:00 2001 From: Simon Blanchard Date: Wed, 22 Nov 2023 21:05:00 +0100 Subject: [PATCH 0267/1271] Fix for operation on closed file in faulthandler teardown (#11584) --- changelog/11572.bugfix.rst | 1 + src/_pytest/faulthandler.py | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 changelog/11572.bugfix.rst diff --git a/changelog/11572.bugfix.rst b/changelog/11572.bugfix.rst new file mode 100644 index 00000000000..7a235a071fe --- /dev/null +++ b/changelog/11572.bugfix.rst @@ -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. diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index a9418f34e11..1bccd18c636 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -9,8 +9,8 @@ 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()) + # Re-enable the faulthandler if it was originally enabled. + 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: From acab13fcc9f04940721b0a4aa39701100e376b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jens=20Tr=C3=B6ger?= Date: Fri, 24 Nov 2023 22:38:34 +1000 Subject: [PATCH 0268/1271] Add new filtering() method to LogCaptureFixture class (#11625) Fixes #11610 --- AUTHORS | 1 + changelog/11610.feature.rst | 2 ++ src/_pytest/logging.py | 16 ++++++++++++++++ testing/logging/test_fixture.py | 22 ++++++++++++++++++++-- 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 changelog/11610.feature.rst diff --git a/AUTHORS b/AUTHORS index e30131d1a7e..669ec537e56 100644 --- a/AUTHORS +++ b/AUTHORS @@ -188,6 +188,7 @@ Javier Romero Jeff Rackauckas Jeff Widman Jenni Rinker +Jens Tröger John Eddie Ayson John Litborn John Towler diff --git a/changelog/11610.feature.rst b/changelog/11610.feature.rst new file mode 100644 index 00000000000..34df3470509 --- /dev/null +++ b/changelog/11610.feature.rst @@ -0,0 +1,2 @@ +Added :func:`LogCaptureFixture.filtering() ` context manager that +adds a given :class:`logging.Filter` object to the caplog fixture. diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index bacca4b2aa9..246a4ab6eb0 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -564,6 +564,22 @@ def at_level( 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]: diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index 753cf5fcd03..f4912aecce4 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -144,7 +144,7 @@ def test3(caplog): 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", [ From e0d5754d5d85267be2de5eceb1ed1a7b331361ff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 26 Nov 2023 11:09:03 -0300 Subject: [PATCH 0269/1271] [automated] Update plugin list (#11640) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 160 +++++++++++++++++++------------ 1 file changed, 100 insertions(+), 60 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 2e39b41530b..6284177b912 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =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 @@ -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 23, 2023 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Nov 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Nov 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Nov 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Nov 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Nov 23, 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) @@ -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 20, 2023 4 - Beta pytest >=7.1.2 :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,9 +571,10 @@ 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 Nov 23, 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 @@ -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. Nov 21, 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 @@ -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) @@ -979,7 +982,7 @@ This list contains 1346 plugins. :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-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 @@ -1077,7 +1080,7 @@ This list contains 1346 plugins. :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-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable 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,7 +1154,7 @@ 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` A Dynamic test tool for Splunk Apps and Add-ons Nov 25, 2023 N/A pytest (>5.4.0,<8) :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Nov 15, 2023 N/A N/A :pypi:`pytest-splunk-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 @@ -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) @@ -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) @@ -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*: Nov 21, 2023, *status*: 5 - Production/Stable, *requires*: pytest ; extra == 'test' @@ -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 23, 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 23, 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 23, 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 23, 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 23, 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 23, 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 23, 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 23, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4837,8 +4842,8 @@ This list contains 1346 plugins. :pypi:`pytest-fzf` - *last release*: Nov 15, 2023, - *status*: 1 - Planning, + *last release*: Nov 20, 2023, + *status*: 4 - Beta, *requires*: pytest >=7.1.2 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*: Nov 23, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5425,7 +5444,7 @@ This list contains 1346 plugins. :pypi:`pytest-image-snapshot` - *last release*: Nov 16, 2023, + *last release*: Nov 21, 2023, *status*: 4 - Beta, *requires*: pytest >=3.5.0 @@ -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 @@ -8001,7 +8027,7 @@ This list contains 1346 plugins. 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" @@ -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 @@ -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,7 +9231,7 @@ 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) @@ -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 @@ -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 From 85e0f676c5a545f71cfedb143a75268cda0aadaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Sun, 26 Nov 2023 15:09:18 +0100 Subject: [PATCH 0270/1271] Reset color-related envvars for testing (#11638) Reset color-related environment variables in a fixture to prevent them from affecting test results. Otherwise, some of the tests fail e.g. if NO_COLOR is set in the calling environment. --- changelog/11638.trivial.rst | 1 + testing/conftest.py | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 changelog/11638.trivial.rst diff --git a/changelog/11638.trivial.rst b/changelog/11638.trivial.rst new file mode 100644 index 00000000000..374960b8925 --- /dev/null +++ b/changelog/11638.trivial.rst @@ -0,0 +1 @@ +Fixed the selftests to pass correctly if ``FORCE_COLOR``, ``NO_COLOR`` or ``PY_COLORS`` is set in the calling environment. diff --git a/testing/conftest.py b/testing/conftest.py index 6a50e810fbd..bcb05339b62 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -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. From 03220f7c9e1035772bcdb9fd983d165c374d7881 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 03:05:20 +0000 Subject: [PATCH 0271/1271] build(deps): Bump pytest-rerunfailures in /testing/plugins_integration Bumps [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) from 12.0 to 13.0. - [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/12.0...13.0) --- updated-dependencies: - dependency-name: pytest-rerunfailures dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index fcbe3f16883..6224d0b3487 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -7,7 +7,7 @@ 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 From 6053bb8d6a005ea3bd0bd534056f37d073595f83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 03:05:25 +0000 Subject: [PATCH 0272/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 4.0.0 to 4.1.0. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.0.0...4.1.0) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index fcbe3f16883..93ead0d3f50 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -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 From 2d1710e0e93983134e83e26eacff6a147164baf1 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Mon, 27 Nov 2023 14:47:18 +0000 Subject: [PATCH 0273/1271] Improve the full diff by having more consistent indentation in the PrettyPrinter (#11571) The normal default pretty printer is not great when objects are nested and it can get hard to read the diff. Instead, provide a pretty printer that behaves more like when json get indented, which allows for smaller, more meaningful differences, at the expense of a slightly longer diff. This does not touch the other places where the pretty printer is used, and only updated the full diff one. --- changelog/1531.improvement.rst | 4 + src/_pytest/_io/pprint.py | 208 +++++++++++------------------- src/_pytest/assertion/util.py | 28 +---- testing/io/test_pprint.py | 222 ++++++++++++++++++++++----------- testing/test_assertion.py | 188 +++++++++++++++++++--------- testing/test_error_diffs.py | 71 +++++++---- 6 files changed, 402 insertions(+), 319 deletions(-) create mode 100644 changelog/1531.improvement.rst diff --git a/changelog/1531.improvement.rst b/changelog/1531.improvement.rst new file mode 100644 index 00000000000..d444ea2e783 --- /dev/null +++ b/changelog/1531.improvement.rst @@ -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. diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 9923d0a6256..bb59253f70b 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -58,7 +58,7 @@ def _safe_tuple(t): class PrettyPrinter: def __init__( self, - indent=1, + indent=4, width=80, depth=None, stream=None, @@ -146,7 +146,6 @@ def _format(self, object, stream, indent, allowance, context, level): def _pprint_dataclass(self, object, stream, indent, allowance, context, level): cls_name = object.__class__.__name__ - indent += len(cls_name) + 1 items = [ (f.name, getattr(object, f.name)) for f in _dataclasses.fields(object) @@ -164,17 +163,11 @@ def _pprint_dataclass(self, object, stream, indent, allowance, context, level): def _pprint_dict(self, object, stream, indent, allowance, context, level): 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 - ) + if self._sort_dicts: + items = sorted(object.items(), key=_safe_tuple) + else: + items = object.items() + self._format_dict_items(items, stream, indent, allowance, context, level) write("}") _dispatch[dict.__repr__] = _pprint_dict @@ -185,32 +178,22 @@ def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level 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): 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): 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 @@ -225,11 +208,8 @@ def _pprint_set(self, object, stream, indent, allowance, context, level): 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 @@ -319,7 +299,7 @@ def _pprint_bytearray(self, object, stream, indent, allowance, context, level): def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level): 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 @@ -333,7 +313,6 @@ def _pprint_simplenamespace( 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) @@ -342,32 +321,30 @@ def _pprint_simplenamespace( _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace def _format_dict_items(self, items, stream, indent, allowance, context, level): + if not items: + return + 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) + 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, - indent + len(rep) + 2, - allowance if last else 1, - context, - level, - ) - if not last: - write(delimnl) + self._format(ent, stream, item_indent, 1, context, level) + write(",") + + write("\n" + " " * indent) def _format_namespace_items(self, items, stream, indent, allowance, context, level): + if not items: + return + 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(key) write("=") if id(ent) in context: @@ -378,52 +355,30 @@ def _format_namespace_items(self, items, stream, indent, allowance, context, lev 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) + + write(",") + + write("\n" + " " * indent) 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: + 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) + + write = stream.write + item_indent = indent + self._indent_per_level + delimnl = "\n" + " " * item_indent + + for item in items: + write(delimnl) + self._format(item, stream, item_indent, 1, context, level) + write(",") + + write("\n" + " " * indent) def _repr(self, object, context, level): repr, readable, recursive = self.format( @@ -443,66 +398,45 @@ def format(self, object, context, maxlevels, level): 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 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) * " ") - items = object.most_common() - self._format_dict_items( - items, stream, indent + len(cls.__name__) + 1, allowance + 2, context, level - ) - stream.write("})") + stream.write(object.__class__.__name__ + "(") + + if object: + stream.write("{") + items = object.most_common() + self._format_dict_items(items, stream, indent, allowance, context, level) + stream.write("}") + + stream.write(")") _dispatch[_collections.Counter.__repr__] = _pprint_counter def _pprint_chain_map(self, object, stream, indent, allowance, context, level): - if not len(object.maps): + 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(")") - else: - self._format(m, stream, indent, 1, context, level) - stream.write(",\n" + " " * indent) + + stream.write(object.__class__.__name__ + "(") + self._format_items(object.maps, stream, indent, allowance, context, level) + stream.write(")") _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 + 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) - 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})") + + self._format_items(object, stream, indent, allowance + 1, context, level) + stream.write("])") _dispatch[_collections.deque.__repr__] = _pprint_deque diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 4d9fd114bc2..214c321f081 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -318,18 +318,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,20 +329,8 @@ def _compare_eq_iterable( # dynamic import to speedup pytest import difflib - left_formatting = pprint.pformat(left).splitlines() - right_formatting = pprint.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) + left_formatting = PrettyPrinter().pformat(left).splitlines() + right_formatting = PrettyPrinter().pformat(right).splitlines() explanation = ["Full diff:"] # "right" is the expected base against which we compare "left", diff --git a/testing/io/test_pprint.py b/testing/io/test_pprint.py index 8c15740bd41..3432c63f688 100644 --- a/testing/io/test_pprint.py +++ b/testing/io/test_pprint.py @@ -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(, - {'one': '1'}) + defaultdict(, { + 'one': '1', + }) """, id="defaultdict-one-item", ), pytest.param( defaultdict(str, {"one": "1", "two": "2"}), """ - defaultdict(, - {'one': '1', - 'two': '2'}) + defaultdict(, { + '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(, - {'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(, { + '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", ), diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 7c8c0155681..ce10ed8c4e6 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -451,11 +451,14 @@ def test_list(self) -> None: [0, 2], """ Full diff: - - [0, 2] + [ + 0, + - 2, ? ^ - + [0, 1] + + 1, ? ^ - """, + ] + """, id="lists", ), pytest.param( @@ -463,10 +466,12 @@ def test_list(self) -> None: {0: 2}, """ Full diff: - - {0: 2} - ? ^ - + {0: 1} - ? ^ + { + - 0: 2, + ? ^ + + 0: 1, + ? ^ + } """, id="dicts", ), @@ -475,10 +480,13 @@ def test_list(self) -> None: {0, 2}, """ Full diff: - - {0, 2} + { + 0, + - 2, ? ^ - + {0, 1} + + 1, ? ^ + } """, id="sets", ), @@ -542,10 +550,10 @@ def test_list_wrap_for_multiple_lines(self) -> None: "Right contains one more item: '" + long_d + "'", "Full diff:", " [", - " 'a',", - " 'b',", - " 'c',", - "- '" + long_d + "',", + " 'a',", + " 'b',", + " 'c',", + "- '" + long_d + "',", " ]", ] @@ -555,10 +563,10 @@ def test_list_wrap_for_multiple_lines(self) -> None: "Left contains one more item: '" + long_d + "'", "Full diff:", " [", - " 'a',", - " 'b',", - " 'c',", - "+ '" + long_d + "',", + " 'a',", + " 'b',", + " 'c',", + "+ '" + long_d + "',", " ]", ] @@ -574,10 +582,10 @@ def test_list_wrap_for_width_rewrap_same_length(self) -> None: "At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", "Full diff:", " [", - "+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',", - " 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',", - " 'cccccccccccccccccccccccccccccc',", - "- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',", + "+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',", + " 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',", + " 'cccccccccccccccccccccccccccccc',", + "- 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',", " ]", ] @@ -592,15 +600,15 @@ def test_list_dont_wrap_strings(self) -> None: "Left contains 7 more items, first extra item: 'aaaaaaaaaa'", "Full diff:", " [", - "- 'should not get wrapped',", - "+ 'a',", - "+ 'aaaaaaaaaa',", - "+ 'aaaaaaaaaa',", - "+ 'aaaaaaaaaa',", - "+ 'aaaaaaaaaa',", - "+ 'aaaaaaaaaa',", - "+ 'aaaaaaaaaa',", - "+ 'aaaaaaaaaa',", + "- 'should not get wrapped',", + "+ 'a',", + "+ 'aaaaaaaaaa',", + "+ 'aaaaaaaaaa',", + "+ 'aaaaaaaaaa',", + "+ 'aaaaaaaaaa',", + "+ 'aaaaaaaaaa',", + "+ 'aaaaaaaaaa',", + "+ 'aaaaaaaaaa',", " ]", ] @@ -615,13 +623,17 @@ def test_dict_wrap(self) -> None: "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) @@ -632,10 +644,16 @@ def test_dict_wrap(self) -> None: "{'new': 1}", "Full diff:", " {", - " 'env': {'sub': {'long_a': '" + long_a + "',", - " 'sub1': {'long_a': 'substring that gets wrapped substring '", - " 'that gets wrapped '}}},", - "- 'new': 1,", + " 'env': {", + " 'sub': {", + f" 'long_a': '{long_a}',", + " 'sub1': {", + " 'long_a': 'substring that gets wrapped substring that gets wrapped '", + " 'substring that gets wrapped ',", + " },", + " },", + " },", + "- 'new': 1,", " }", ] @@ -677,8 +695,13 @@ def test_dict_different_items(self) -> None: "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 == [ @@ -688,8 +711,13 @@ def test_dict_different_items(self) -> None: "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: @@ -699,8 +727,17 @@ def test_sequence_different_items(self) -> None: "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 == [ @@ -708,8 +745,27 @@ def test_sequence_different_items(self) -> None: "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: @@ -1844,8 +1900,8 @@ def test(): 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}", ], ), ( @@ -1857,8 +1913,8 @@ def test(): """, [ "{bold}{red}E {light-gray} {hl-reset} {{{endline}{reset}", - "{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}", - "{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}", + "{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}", + "{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}", ], ), ), @@ -1917,14 +1973,32 @@ def test_long_text_fail(): f"{p.name} .FFF [100%]", "E At index 2 diff: 'grapes' != 'orange'", "E Full diff:", - "E - ['banana', 'apple', 'orange', 'melon', 'kiwi']", - "E ? ^ ^^", - "E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']", - "E ? ^ ^ +", + "E [", + "E 'banana',", + "E 'apple',", + "E - 'orange',", + "E ? ^ ^^", + "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}'", ] ) diff --git a/testing/test_error_diffs.py b/testing/test_error_diffs.py index eb781210872..cad7a17c047 100644 --- a/testing/test_error_diffs.py +++ b/testing/test_error_diffs.py @@ -21,10 +21,14 @@ def test_this(): 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 @@ def test_this(): 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 @@ def test_this(): 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 @@ def test_this(): 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 @@ def test_this(): 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 @@ def test_this(): E Right contains 1 more item: E {2: 'eggs'} E Full diff: - E - {1: 'spam', 2: 'eggs'} - E ? ^ - E + {1: 'spam', 3: 'eggs'} - E ? ^ + E { + E 1: 'spam', + E - 2: 'eggs', + E ? ^ + E + 3: 'eggs', + E ? ^ + E } """, id="Compare dicts with differing keys", ), @@ -145,10 +162,11 @@ def test_this(): 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 @@ def test_this(): 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", ), From c4375f14b86e797446d44ee11d6335ffe9251c73 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Nov 2023 20:55:06 +0000 Subject: [PATCH 0274/1271] [pre-commit.ci] pre-commit autoupdate (#11645) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/mirrors-mypy: v1.7.0 → v1.7.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.7.0...v1.7.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1fb0266024d..9b1ee9cda4b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.0 + rev: v1.7.1 hooks: - id: mypy files: ^(src/|testing/) From 64e72b79f6bd8eb0e6bf2b1a7456a026a88127fa Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Tue, 21 Nov 2023 21:35:27 +0000 Subject: [PATCH 0275/1271] pprint: Remove unused arguments on PrettyPrinter --- src/_pytest/_io/pprint.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index bb59253f70b..8dc2dc02841 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -15,7 +15,6 @@ 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 @@ -61,9 +60,7 @@ def __init__( indent=4, width=80, depth=None, - stream=None, *, - compact=False, sort_dicts=True, underscore_numbers=False, ): @@ -79,13 +76,6 @@ def __init__( 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,11 +91,6 @@ def __init__( 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 From e5a448cd5f36bb715e75efe01da89fe0fa52d6b1 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Tue, 21 Nov 2023 22:05:37 +0000 Subject: [PATCH 0276/1271] pprint: Type annotate the module This will make it easier to refactor --- src/_pytest/_io/pprint.py | 253 ++++++++++++++++++++++++++++++++------ 1 file changed, 217 insertions(+), 36 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 8dc2dc02841..876723fbb26 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -21,7 +21,10 @@ 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 Tuple class _safe_key: @@ -57,13 +60,13 @@ def _safe_tuple(t): class PrettyPrinter: def __init__( self, - indent=4, - width=80, - depth=None, + indent: int = 4, + width: int = 80, + depth: Optional[int] = None, *, - 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. @@ -99,7 +102,15 @@ def pformat(self, object: Any) -> str: self._format(object, sio, 0, 0, {}, 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: Dict[int, int], + level: int, + ) -> None: objid = id(object) if objid in context: stream.write(_recursion(object)) @@ -129,7 +140,15 @@ def _format(self, object, stream, indent, allowance, context, level): 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: Dict[int, int], + level: int, + ) -> None: cls_name = object.__class__.__name__ items = [ (f.name, getattr(object, f.name)) @@ -142,10 +161,18 @@ def _pprint_dataclass(self, object, stream, indent, allowance, context, level): _dispatch: Dict[ Callable[..., str], - Callable[["PrettyPrinter", Any, IO[str], int, int, Dict[int, int], int], str], + Callable[["PrettyPrinter", Any, IO[str], int, int, Dict[int, 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: Dict[int, int], + level: int, + ) -> None: write = stream.write write("{") if self._sort_dicts: @@ -157,7 +184,15 @@ def _pprint_dict(self, object, stream, indent, allowance, context, level): _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: Dict[int, int], + level: int, + ) -> None: if not len(object): stream.write(repr(object)) return @@ -168,21 +203,45 @@ def _pprint_ordered_dict(self, object, stream, indent, allowance, context, level _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: Dict[int, int], + level: int, + ) -> None: stream.write("[") 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: Dict[int, int], + level: int, + ) -> None: stream.write("(") 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: Dict[int, int], + level: int, + ) -> None: if not len(object): stream.write(repr(object)) return @@ -200,7 +259,15 @@ def _pprint_set(self, object, stream, indent, allowance, context, level): _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: Dict[int, int], + level: int, + ) -> None: write = stream.write if not len(object): write(repr(object)) @@ -251,7 +318,15 @@ def _pprint_str(self, object, stream, indent, allowance, context, level): _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: Dict[int, int], + level: int, + ) -> None: write = stream.write if len(object) <= 4: write(repr(object)) @@ -272,7 +347,15 @@ def _pprint_bytes(self, object, stream, indent, allowance, context, level): _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: Dict[int, int], + level: int, + ) -> None: write = stream.write write("bytearray(") self._pprint_bytes( @@ -282,7 +365,15 @@ def _pprint_bytearray(self, object, stream, indent, allowance, context, level): _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: Dict[int, int], + level: int, + ) -> None: stream.write("mappingproxy(") self._format(object.copy(), stream, indent, allowance, context, level) stream.write(")") @@ -290,8 +381,14 @@ def _pprint_mappingproxy(self, object, stream, indent, allowance, context, level _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: Dict[int, 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. @@ -305,7 +402,15 @@ def _pprint_simplenamespace( _dispatch[_types.SimpleNamespace.__repr__] = _pprint_simplenamespace - def _format_dict_items(self, items, stream, indent, allowance, context, level): + def _format_dict_items( + self, + items: List[Tuple[Any, Any]], + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not items: return @@ -321,7 +426,15 @@ def _format_dict_items(self, items, stream, indent, allowance, context, level): write("\n" + " " * indent) - def _format_namespace_items(self, items, stream, indent, allowance, context, level): + def _format_namespace_items( + self, + items: List[Tuple[Any, Any]], + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not items: return @@ -350,7 +463,15 @@ def _format_namespace_items(self, items, stream, indent, allowance, context, lev write("\n" + " " * indent) - def _format_items(self, items, stream, indent, allowance, context, level): + def _format_items( + self, + items: List[Any], + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: if not items: return @@ -365,7 +486,7 @@ def _format_items(self, items, stream, indent, allowance, context, level): write("\n" + " " * indent) - def _repr(self, object, context, level): + def _repr(self, object: Any, context: Dict[int, int], level: int) -> str: repr, readable, recursive = self.format( object, context.copy(), self._depth, level ) @@ -375,14 +496,24 @@ def _repr(self, object, context, level): self._recursive = True return repr - def format(self, object, context, maxlevels, level): + def format( + self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int + ) -> Tuple[str, bool, bool]: """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. """ return self._safe_repr(object, context, maxlevels, level) - def _pprint_default_dict(self, object, stream, indent, allowance, context, level): + def _pprint_default_dict( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: rdf = self._repr(object.default_factory, context, level) stream.write(f"{object.__class__.__name__}({rdf}, ") self._pprint_dict(object, stream, indent, allowance, context, level) @@ -390,7 +521,15 @@ def _pprint_default_dict(self, object, stream, indent, allowance, context, level _dispatch[_collections.defaultdict.__repr__] = _pprint_default_dict - def _pprint_counter(self, object, stream, indent, allowance, context, level): + def _pprint_counter( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: stream.write(object.__class__.__name__ + "(") if object: @@ -403,7 +542,15 @@ def _pprint_counter(self, object, stream, indent, allowance, context, level): _dispatch[_collections.Counter.__repr__] = _pprint_counter - def _pprint_chain_map(self, object, stream, indent, allowance, context, level): + def _pprint_chain_map( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, 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 @@ -414,7 +561,15 @@ def _pprint_chain_map(self, object, stream, indent, allowance, context, level): _dispatch[_collections.ChainMap.__repr__] = _pprint_chain_map - def _pprint_deque(self, object, stream, indent, allowance, context, level): + def _pprint_deque( + self, + object: Any, + stream: IO[str], + indent: int, + allowance: int, + context: Dict[int, int], + level: int, + ) -> None: stream.write(object.__class__.__name__ + "(") if object.maxlen is not None: stream.write("maxlen=%d, " % object.maxlen) @@ -425,22 +580,48 @@ def _pprint_deque(self, object, stream, indent, allowance, context, level): _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: Dict[int, 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: Dict[int, 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: Dict[int, 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): + def _safe_repr( + self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int + ) -> Tuple[str, bool, bool]: # Return triple (repr_string, isreadable, isrecursive). typ = type(object) if typ in _builtin_scalars: @@ -517,17 +698,17 @@ def _safe_repr(self, object, context, maxlevels, level): return format % ", ".join(components), readable, recursive rep = repr(object) - return rep, (rep and not rep.startswith("<")), False + return rep, bool(rep and not rep.startswith("<")), False _builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)}) -def _recursion(object): +def _recursion(object: Any) -> str: return f"" -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): From 767f08cecdc32b3ae11d40ab569d74f5f3fafad0 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Tue, 21 Nov 2023 22:08:15 +0000 Subject: [PATCH 0277/1271] pprint: Remove tracking of whether the object is recursive This information is not used anywhere, we can simplify by just not tracking it --- src/_pytest/_io/pprint.py | 54 +++++++++++++++------------------------ 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 876723fbb26..02f43a0bd9c 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -114,7 +114,6 @@ def _format( objid = id(object) if objid in context: stream.write(_recursion(object)) - self._recursive = True self._readable = False return @@ -487,21 +486,16 @@ def _format_items( write("\n" + " " * indent) def _repr(self, object: Any, context: Dict[int, int], level: int) -> str: - repr, readable, recursive = self.format( - object, context.copy(), self._depth, level - ) + repr, readable = self.format(object, context.copy(), self._depth, level) if not readable: self._readable = False - if recursive: - self._recursive = True return repr def format( self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int - ) -> Tuple[str, bool, bool]: + ) -> Tuple[str, bool]: """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. + and a flag indicating whether the representation is 'readable'. """ return self._safe_repr(object, context, maxlevels, level) @@ -621,31 +615,30 @@ def _pprint_user_string( def _safe_repr( self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int - ) -> Tuple[str, bool, bool]: - # Return triple (repr_string, isreadable, isrecursive). + ) -> Tuple[str, bool]: + # Return pair (repr_string, isreadable). typ = type(object) if typ in _builtin_scalars: - return repr(object), True, False + return repr(object), True 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}", True else: - return repr(object), True, False + return repr(object), True if issubclass(typ, dict) and r is dict.__repr__: if not object: - return "{}", True, False + return "{}", True objid = id(object) if maxlevels and level >= maxlevels: - return "{...}", False, objid in context + return "{...}", False if objid in context: - return _recursion(object), False, True + return _recursion(object), False context[objid] = 1 readable = True - recursive = False components: List[str] = [] append = components.append level += 1 @@ -654,51 +647,46 @@ def _safe_repr( 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, kreadable = self.format(k, context, maxlevels, level) + vrepr, vreadable = 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 + return "{%s}" % ", ".join(components), readable 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 "[]", True format = "[%s]" elif len(object) == 1: format = "(%s,)" else: if not object: - return "()", True, False + return "()", True format = "(%s)" objid = id(object) if maxlevels and level >= maxlevels: - return format % "...", False, objid in context + return format % "...", False if objid in context: - return _recursion(object), False, True + return _recursion(object), False context[objid] = 1 readable = True - recursive = False components = [] append = components.append level += 1 for o in object: - orepr, oreadable, orecur = self.format(o, context, maxlevels, level) + orepr, oreadable = 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 + return format % ", ".join(components), readable rep = repr(object) - return rep, bool(rep and not rep.startswith("<")), False + return rep, bool(rep and not rep.startswith("<")) _builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)}) From 50607297f45bae1e786217bb6ad89fc2d1748d39 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Tue, 21 Nov 2023 22:12:33 +0000 Subject: [PATCH 0278/1271] pprint: Remove tracking of whether an object is readable This information is not used anywhere --- src/_pytest/_io/pprint.py | 52 ++++++++++++++------------------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 02f43a0bd9c..c213460359a 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -114,7 +114,6 @@ def _format( objid = id(object) if objid in context: stream.write(_recursion(object)) - self._readable = False return p = self._dispatch.get(type(object).__repr__, None) @@ -486,17 +485,11 @@ def _format_items( write("\n" + " " * indent) def _repr(self, object: Any, context: Dict[int, int], level: int) -> str: - repr, readable = self.format(object, context.copy(), self._depth, level) - if not readable: - self._readable = False - return repr + return self.format(object, context.copy(), self._depth, level) def format( self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int - ) -> Tuple[str, bool]: - """Format object for a specific context, returning a string - and a flag indicating whether the representation is 'readable'. - """ + ) -> str: return self._safe_repr(object, context, maxlevels, level) def _pprint_default_dict( @@ -615,30 +608,28 @@ def _pprint_user_string( def _safe_repr( self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int - ) -> Tuple[str, bool]: - # Return pair (repr_string, isreadable). + ) -> str: typ = type(object) if typ in _builtin_scalars: - return repr(object), True + 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 + return f"{object:_d}" else: - return repr(object), True + return repr(object) if issubclass(typ, dict) and r is dict.__repr__: if not object: - return "{}", True + return "{}" objid = id(object) if maxlevels and level >= maxlevels: - return "{...}", False + return "{...}" if objid in context: - return _recursion(object), False + return _recursion(object) context[objid] = 1 - readable = True components: List[str] = [] append = components.append level += 1 @@ -647,46 +638,41 @@ def _safe_repr( else: items = object.items() for k, v in items: - krepr, kreadable = self.format(k, context, maxlevels, level) - vrepr, vreadable = 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 del context[objid] - return "{%s}" % ", ".join(components), readable + 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 + return "[]" format = "[%s]" elif len(object) == 1: format = "(%s,)" else: if not object: - return "()", True + return "()" format = "(%s)" objid = id(object) if maxlevels and level >= maxlevels: - return format % "...", False + return format % "..." if objid in context: - return _recursion(object), False + return _recursion(object) context[objid] = 1 - readable = True components = [] append = components.append level += 1 for o in object: - orepr, oreadable = self.format(o, context, maxlevels, level) + orepr = self.format(o, context, maxlevels, level) append(orepr) - if not oreadable: - readable = False del context[objid] - return format % ", ".join(components), readable + return format % ", ".join(components) - rep = repr(object) - return rep, bool(rep and not rep.startswith("<")) + return repr(object) _builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)}) From 88c35460060d7e5c5531a4b47aef3a53583d9c10 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Tue, 21 Nov 2023 22:18:13 +0000 Subject: [PATCH 0279/1271] pprint: use a set instead of a dict for the context This is really what the context is doing, we don't need to use a dict for it --- src/_pytest/_io/pprint.py | 71 ++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index c213460359a..ad1238709f4 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -24,6 +24,7 @@ from typing import Iterator from typing import List from typing import Optional +from typing import Set from typing import Tuple @@ -99,7 +100,7 @@ def __init__( 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( @@ -108,7 +109,7 @@ def _format( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: objid = id(object) @@ -118,9 +119,9 @@ def _format( 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) @@ -130,11 +131,11 @@ def _format( 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)) @@ -144,7 +145,7 @@ def _pprint_dataclass( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: cls_name = object.__class__.__name__ @@ -159,7 +160,7 @@ def _pprint_dataclass( _dispatch: Dict[ Callable[..., str], - Callable[["PrettyPrinter", Any, IO[str], int, int, Dict[int, int], int], None], + Callable[["PrettyPrinter", Any, IO[str], int, int, Set[int], int], None], ] = {} def _pprint_dict( @@ -168,7 +169,7 @@ def _pprint_dict( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: write = stream.write @@ -188,7 +189,7 @@ def _pprint_ordered_dict( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: if not len(object): @@ -207,7 +208,7 @@ def _pprint_list( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: stream.write("[") @@ -222,7 +223,7 @@ def _pprint_tuple( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: stream.write("(") @@ -237,7 +238,7 @@ def _pprint_set( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: if not len(object): @@ -263,7 +264,7 @@ def _pprint_str( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: write = stream.write @@ -322,7 +323,7 @@ def _pprint_bytes( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: write = stream.write @@ -351,7 +352,7 @@ def _pprint_bytearray( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: write = stream.write @@ -369,7 +370,7 @@ def _pprint_mappingproxy( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: stream.write("mappingproxy(") @@ -384,7 +385,7 @@ def _pprint_simplenamespace( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: if type(object) is _types.SimpleNamespace: @@ -406,7 +407,7 @@ def _format_dict_items( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: if not items: @@ -430,7 +431,7 @@ def _format_namespace_items( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: if not items: @@ -467,7 +468,7 @@ def _format_items( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: if not items: @@ -484,11 +485,11 @@ def _format_items( write("\n" + " " * indent) - def _repr(self, object: Any, context: Dict[int, int], level: int) -> str: + 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: Dict[int, int], maxlevels: Optional[int], level: int + self, object: Any, context: Set[int], maxlevels: Optional[int], level: int ) -> str: return self._safe_repr(object, context, maxlevels, level) @@ -498,7 +499,7 @@ def _pprint_default_dict( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: rdf = self._repr(object.default_factory, context, level) @@ -514,7 +515,7 @@ def _pprint_counter( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: stream.write(object.__class__.__name__ + "(") @@ -535,7 +536,7 @@ def _pprint_chain_map( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: if not len(object.maps) or (len(object.maps) == 1 and not len(object.maps[0])): @@ -554,7 +555,7 @@ def _pprint_deque( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: stream.write(object.__class__.__name__ + "(") @@ -573,7 +574,7 @@ def _pprint_user_dict( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) @@ -586,7 +587,7 @@ def _pprint_user_list( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) @@ -599,7 +600,7 @@ def _pprint_user_string( stream: IO[str], indent: int, allowance: int, - context: Dict[int, int], + context: Set[int], level: int, ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) @@ -607,7 +608,7 @@ def _pprint_user_string( _dispatch[_collections.UserString.__repr__] = _pprint_user_string def _safe_repr( - self, object: Any, context: Dict[int, int], maxlevels: Optional[int], level: int + self, object: Any, context: Set[int], maxlevels: Optional[int], level: int ) -> str: typ = type(object) if typ in _builtin_scalars: @@ -629,7 +630,7 @@ def _safe_repr( return "{...}" if objid in context: return _recursion(object) - context[objid] = 1 + context.add(objid) components: List[str] = [] append = components.append level += 1 @@ -641,7 +642,7 @@ def _safe_repr( krepr = self.format(k, context, maxlevels, level) vrepr = self.format(v, context, maxlevels, level) append(f"{krepr}: {vrepr}") - del context[objid] + context.remove(objid) return "{%s}" % ", ".join(components) if (issubclass(typ, list) and r is list.__repr__) or ( @@ -662,14 +663,14 @@ def _safe_repr( return format % "..." if objid in context: return _recursion(object) - context[objid] = 1 + context.add(objid) components = [] append = components.append level += 1 for o in object: orepr = self.format(o, context, maxlevels, level) append(orepr) - del context[objid] + context.remove(objid) return format % ", ".join(components) return repr(object) From ad1bccdeade5472434fe77e9890472287cb0969f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 28 Nov 2023 17:36:05 +0200 Subject: [PATCH 0280/1271] pytester: avoid EncodingWarning from `locale.getpreferredencoding` When running `tox -e py-lsof` I get a deluge of this warning: ``` src/pytest/.tox/py-lsof-numpy-pexpect/lib/python3.11/site-packages/_pytest/pytester.py:130: EncodingWarning: UTF-8 Mode affects locale.getpreferredencoding(). Consider locale.getencoding() instead. ``` Use `locale.getencoding` instead. --- src/_pytest/pytester.py | 7 ++++++- testing/test_parseopt.py | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 99d33954da7..f93e9c94a00 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -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: diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index b6df035aacf..1b80883ee0f 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -290,10 +290,10 @@ def test_multiple_metavar_help(self, parser: parseopt.Parser) -> None: def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: - try: + if sys.version_info >= (3, 11): # New in Python 3.11, ignores utf-8 mode - encoding = locale.getencoding() # type: ignore[attr-defined] - except AttributeError: + encoding = locale.getencoding() + else: encoding = locale.getpreferredencoding(False) try: bash_version = subprocess.run( From 968510b6aa69e2616828f643f6f2384e27f1ceb1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 28 Nov 2023 19:54:24 +0200 Subject: [PATCH 0281/1271] testing: fix isolation issue in `tr` fixture The default for `_prepareconfig` is to use `sys.argv`, which in this case are the flags passed to (top-level) `pytest`. This is not the intention, the tests themselves should not be affected by it. --- testing/test_terminal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 596c3c67ede..264ab96d8d0 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1802,7 +1802,7 @@ def test_failure(): @pytest.fixture(scope="session") def tr() -> TerminalReporter: - config = _pytest.config._prepareconfig() + config = _pytest.config._prepareconfig([]) return TerminalReporter(config) From ef699f8c1719959dfa6c32f06fc705f70672308d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 30 Nov 2023 19:53:31 +0200 Subject: [PATCH 0282/1271] testing: remove a no longer necessary skip pytest-xdist was released at 2019-02-15, seems enough time. --- testing/test_config.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/testing/test_config.py b/testing/test_config.py index 58671e6ed3c..900cccee80b 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1959,16 +1959,6 @@ class DummyPlugin: ], ) 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) From 5689d806cffa394ae3e79aff9617784bb14533c2 Mon Sep 17 00:00:00 2001 From: touilleWoman <39769383+touilleWoman@users.noreply.github.com> Date: Fri, 1 Dec 2023 15:25:01 +0100 Subject: [PATCH 0283/1271] Fix "Customizing Colors" documentation section (#11652) Fixes #11573 --- doc/en/how-to/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/how-to/logging.rst b/doc/en/how-to/logging.rst index b9f522fa4d0..bdcfbe34fa2 100644 --- a/doc/en/how-to/logging.rst +++ b/doc/en/how-to/logging.rst @@ -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") From 714ce2e872f0e1dc3b0363949d084e3e64f88c82 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 3 Dec 2023 11:49:36 -0300 Subject: [PATCH 0284/1271] [automated] Update plugin list (#11658) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 124 +++++++++++++++---------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6284177b912..2ded9bf9d4b 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -78,7 +78,7 @@ This list contains 1351 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 Nov 21, 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 1351 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 1351 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 1351 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 @@ -410,14 +410,14 @@ This list contains 1351 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 23, 2023 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Nov 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Nov 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Nov 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Nov 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Nov 23, 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 1351 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,7 +527,7 @@ This list contains 1351 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 20, 2023 4 - Beta 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 @@ -574,10 +574,10 @@ This list contains 1351 plugins. :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 23, 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) @@ -613,7 +613,7 @@ This list contains 1351 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 21, 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 @@ -622,9 +622,9 @@ This list contains 1351 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) @@ -634,7 +634,7 @@ This list contains 1351 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 @@ -960,7 +960,7 @@ This list contains 1351 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) @@ -981,7 +981,7 @@ This list contains 1351 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-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 @@ -1067,13 +1067,13 @@ This list contains 1351 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) @@ -1082,7 +1082,7 @@ This list contains 1351 plugins. :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 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 @@ -1155,7 +1155,7 @@ This list contains 1351 plugins. :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 Nov 25, 2023 N/A pytest (>5.4.0,<8) - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Nov 15, 2023 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Dec 01, 2023 N/A N/A :pypi:`pytest-splunk-env` pytest fixtures for interaction with Splunk Enterprise and Splunk Cloud Oct 22, 2020 N/A pytest (>=6.1.1,<7.0.0) :pypi:`pytest-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 @@ -1295,7 +1295,7 @@ This list contains 1351 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 @@ -1370,7 +1370,7 @@ This list contains 1351 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) @@ -1699,7 +1699,7 @@ This list contains 1351 plugins. Pytest fixtures to assert anything and something :pypi:`pytest-aoc` - *last release*: Nov 21, 2023, + *last release*: Dec 02, 2023, *status*: 5 - Production/Stable, *requires*: pytest ; extra == 'test' @@ -1776,7 +1776,7 @@ This list contains 1351 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 @@ -1888,14 +1888,14 @@ This list contains 1351 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 @@ -1923,7 +1923,7 @@ This list contains 1351 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) @@ -2602,7 +2602,7 @@ This list contains 1351 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 @@ -4023,56 +4023,56 @@ This list contains 1351 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Nov 23, 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 23, 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 23, 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 23, 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 23, 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 23, 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 23, 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 23, 2023, + *last release*: Nov 27, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4142,7 +4142,7 @@ This list contains 1351 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 @@ -4842,9 +4842,9 @@ This list contains 1351 plugins. :pypi:`pytest-fzf` - *last release*: Nov 20, 2023, + *last release*: Nov 28, 2023, *status*: 4 - Beta, - *requires*: pytest >=7.1.2 + *requires*: pytest >=6.0.0 fzf-based test selector for pytest @@ -5171,7 +5171,7 @@ This list contains 1351 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Nov 23, 2023, + *last release*: Dec 01, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5192,7 +5192,7 @@ This list contains 1351 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 @@ -5444,7 +5444,7 @@ This list contains 1351 plugins. :pypi:`pytest-image-snapshot` - *last release*: Nov 21, 2023, + *last release*: Dec 01, 2023, *status*: 4 - Beta, *requires*: pytest >=3.5.0 @@ -5507,7 +5507,7 @@ This list contains 1351 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 @@ -5521,7 +5521,7 @@ This list contains 1351 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 @@ -5591,7 +5591,7 @@ This list contains 1351 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 @@ -7873,9 +7873,9 @@ This list contains 1351 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 @@ -8020,7 +8020,7 @@ This list contains 1351 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 @@ -8622,7 +8622,7 @@ This list contains 1351 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) @@ -8664,7 +8664,7 @@ This list contains 1351 plugins. :pypi:`pytest-sbase` - *last release*: Nov 17, 2023, + *last release*: Dec 01, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8727,7 +8727,7 @@ This list contains 1351 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 @@ -9238,7 +9238,7 @@ This list contains 1351 plugins. 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 @@ -10218,7 +10218,7 @@ This list contains 1351 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 @@ -10743,7 +10743,7 @@ This list contains 1351 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 From 3e14c4b3c40830b7dd9a15826f4db36c2f73716d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:41:20 -0300 Subject: [PATCH 0285/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.8.10 to 1.8.11 (#11663) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.10 to 1.8.11. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.10...v1.8.11) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 95ec0d1749c..e1b95efa719 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -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: | From db8c6f1da8112495123a4ff0e2fcfe12ac818f8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:41:34 -0300 Subject: [PATCH 0286/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#11664) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.21.1 to 0.23.1. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.21.1...v0.23.1) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index f692838f3a8..f1e97494fc8 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.1.0 django==4.2.7 -pytest-asyncio==0.21.1 +pytest-asyncio==0.23.1 pytest-bdd==7.0.0 pytest-cov==4.1.0 pytest-django==4.7.0 From 022f1b4de546c8b3529e071965555888ecf01cb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Dec 2023 13:58:18 +0000 Subject: [PATCH 0287/1271] build(deps): Bump pytest-bdd in /testing/plugins_integration (#11665) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 7.0.0 to 7.0.1. - [Release notes](https://github.com/pytest-dev/pytest-bdd/releases) - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/7.0.0...7.0.1) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bruno Oliveira --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index f1e97494fc8..1166d14c9a5 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,7 +1,7 @@ anyio[curio,trio]==4.1.0 django==4.2.7 pytest-asyncio==0.23.1 -pytest-bdd==7.0.0 +pytest-bdd==7.0.1 pytest-cov==4.1.0 pytest-django==4.7.0 pytest-flakes==4.0.5 From b8118ab70d3e7cac1390241a67016f940e39b1c7 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 4 Dec 2023 22:41:20 +0200 Subject: [PATCH 0288/1271] Remove `setup.py` Fix #11667. --- changelog/11667.breaking.rst | 3 +++ pyproject.toml | 1 - setup.py | 4 ---- 3 files changed, 3 insertions(+), 5 deletions(-) create mode 100644 changelog/11667.breaking.rst delete mode 100644 setup.py diff --git a/changelog/11667.breaking.rst b/changelog/11667.breaking.rst new file mode 100644 index 00000000000..7c05d39b2e4 --- /dev/null +++ b/changelog/11667.breaking.rst @@ -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 `_ for alternatives. diff --git a/pyproject.toml b/pyproject.toml index cdbdd3880e4..d45597b77c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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", ] diff --git a/setup.py b/setup.py deleted file mode 100644 index 7f1a1763ca9..00000000000 --- a/setup.py +++ /dev/null @@ -1,4 +0,0 @@ -from setuptools import setup - -if __name__ == "__main__": - setup() From a536f49d910eda84cbd0608e6edb1b70bb0868b2 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Wed, 6 Dec 2023 09:25:00 +0000 Subject: [PATCH 0289/1271] Separate the various parts of the error report with newlines (#11659) Previously the error report would have all sections glued together: - The assertion representation - The error explanation - The full diff This makes it hard to see at a glance where which one starts and ends. One of the representation (dataclasses, tuples, attrs) does display a newlines at the start already. Let's add a newlines before the error explanation and before the full diff, so we get an easier to read report. This has one disadvantage: we get one line less in the least verbose mode, where the output gets truncated. --- changelog/11520.improvement.rst | 2 ++ src/_pytest/assertion/util.py | 4 ++- testing/python/approx.py | 32 +++++++++++++----- testing/test_assertion.py | 59 +++++++++++++++++++++++++-------- 4 files changed, 74 insertions(+), 23 deletions(-) diff --git a/changelog/11520.improvement.rst b/changelog/11520.improvement.rst index 46e4992dd39..d9b7b493339 100644 --- a/changelog/11520.improvement.rst +++ b/changelog/11520.improvement.rst @@ -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. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 214c321f081..fe8904e15dc 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -230,6 +230,8 @@ def assertrepr_compare( if not explanation: return None + if explanation[0] != "": + explanation = [""] + explanation return [summary] + explanation @@ -332,7 +334,7 @@ def _compare_eq_iterable( left_formatting = PrettyPrinter().pformat(left).splitlines() right_formatting = PrettyPrinter().pformat(right).splitlines() - 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( diff --git a/testing/python/approx.py b/testing/python/approx.py index 6ad411a3e07..3b87e58f91a 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -99,6 +99,7 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): 2.0, 1.0, [ + "", " comparison failed", f" Obtained: {SOME_FLOAT}", f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}", @@ -113,6 +114,7 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): "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 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): "c": None, }, [ + r"", r" comparison failed. Mismatched elements: 2 / 3:", r" Max absolute difference: -inf", r" Max relative difference: -inf", @@ -143,6 +146,7 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): [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 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): (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 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): [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 @@ def test_error_messages_numpy_dtypes(self, assert_approx_raises_regex): 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 @@ def test_error_messages_numpy_dtypes(self, assert_approx_raises_regex): ] ), [ + r"", r" comparison failed. Mismatched elements: 3 / 8:", rf" Max absolute difference: {SOME_FLOAT}", rf" Max relative difference: {SOME_FLOAT}", @@ -224,6 +232,7 @@ def test_error_messages_numpy_dtypes(self, assert_approx_raises_regex): 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 @@ def test_error_messages_invalid_args(self, assert_approx_raises_regex): 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 @@ def test_error_messages_invalid_args(self, assert_approx_raises_regex): 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 @@ def test_error_messages_with_different_verbosity(self, assert_approx_raises_rege 2.0, 1.0, [ + "", " comparison failed", f" Obtained: {SOME_FLOAT}", f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}", @@ -277,15 +289,15 @@ def test_error_messages_with_different_verbosity(self, assert_approx_raises_rege 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 @@ def test_error_messages_with_different_verbosity(self, assert_approx_raises_rege 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 @@ def test_dict_for_div_by_zero(self, assert_approx_raises_regex): {"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", diff --git a/testing/test_assertion.py b/testing/test_assertion.py index ce10ed8c4e6..4d751f8dbfc 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -392,6 +392,7 @@ def test_summary(self) -> None: def test_text_diff(self) -> None: assert callequal("spam", "eggs") == [ "'spam' == 'eggs'", + "", "- eggs", "+ spam", ] @@ -399,7 +400,7 @@ def test_text_diff(self) -> None: 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 @@ def test_bytes_diff_normal(self) -> None: assert diff == [ "b'spam' == b'eggs'", + "", "At index 0 diff: b's' != b'e'", "Use -v to get more diff", ] @@ -432,7 +434,9 @@ def test_bytes_diff_verbose(self) -> None: 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'", @@ -509,6 +513,7 @@ def test_iterable_quiet(self) -> None: 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", ] @@ -547,7 +552,9 @@ def test_list_wrap_for_multiple_lines(self) -> None: 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',", @@ -560,7 +567,9 @@ def test_list_wrap_for_multiple_lines(self) -> None: 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',", @@ -579,7 +588,9 @@ def test_list_wrap_for_width_rewrap_same_length(self) -> None: diff = callequal(l1, l2, verbose=True) assert diff == [ "['aaaaaaaaaaa...cccccccccccc'] == ['bbbbbbbbbbb...aaaaaaaaaaaa']", + "", "At index 0 diff: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' != 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", + "", "Full diff:", " [", "+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',", @@ -596,8 +607,10 @@ def test_list_dont_wrap_strings(self) -> None: 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',", @@ -619,9 +632,11 @@ def test_dict_wrap(self) -> None: 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,", @@ -639,9 +654,11 @@ def test_dict_wrap(self) -> None: 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': {", @@ -665,7 +682,7 @@ def test_dict(self) -> None: 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 @@ -674,26 +691,29 @@ def test_dict_omitting_with_verbosity_1(self) -> None: """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,", @@ -706,10 +726,12 @@ def test_dict_different_items(self) -> None: 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,", @@ -724,8 +746,10 @@ 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,", @@ -742,8 +766,10 @@ def test_sequence_different_items(self) -> None: 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,", @@ -757,7 +783,9 @@ def test_sequence_different_items(self) -> None: 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,", @@ -823,7 +851,7 @@ def __repr__(self): 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 @@ -849,6 +877,7 @@ def test_repr_no_exc(self) -> None: def test_unicode(self) -> None: assert callequal("£€", "£") == [ "'£€' == '£'", + "", "- £", "+ £€", ] @@ -864,7 +893,7 @@ def __repr__(self): 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("λ") @@ -887,6 +916,7 @@ def test_nfc_nfd_same_string(self) -> None: expl = callequal(left, right) assert expl == [ r"'hyv\xe4' == 'hyva\u0308'", + "", f"- {str(right)}", f"+ {str(left)}", ] @@ -894,6 +924,7 @@ def test_nfc_nfd_same_string(self) -> None: expl = callequal(left, right, verbose=2) assert expl == [ r"'hyv\xe4' == 'hyva\u0308'", + "", f"- {str(right)}", f"+ {str(left)}", ] @@ -1182,6 +1213,7 @@ def test_comparing_two_different_namedtuple(self) -> None: # 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", ] @@ -1369,7 +1401,7 @@ def test_full_output_truncated(self, monkeypatch, pytester: Pytester) -> None: line_count = 7 line_len = 100 - expected_truncated_lines = 1 + expected_truncated_lines = 2 pytester.makepyfile( r""" def test_many_lines(): @@ -1389,8 +1421,7 @@ def test_many_lines(): [ "*+ 1*", "*+ 3*", - "*+ 5*", - "*truncated (%d line hidden)*use*-vv*" % expected_truncated_lines, + "*truncated (%d lines hidden)*use*-vv*" % expected_truncated_lines, ] ) @@ -1433,6 +1464,7 @@ def test_rewritten(): def test_reprcompare_notin() -> None: assert callop("not in", "foo", "aaafoobbb") == [ "'foo' not in 'aaafoobbb'", + "", "'foo' is contained here:", " aaafoobbb", "? +++", @@ -1442,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'", From a5ee9f2ecd22576ef6e91a00c957ec190ce87dc6 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 6 Dec 2023 23:58:07 +0200 Subject: [PATCH 0290/1271] doc: document `pytest.{hookspec,hookimpl}` in the API Reference Makes sense for them to be there; also allows for Sphinx refs. --- doc/en/how-to/writing_hook_functions.rst | 5 +---- doc/en/reference/reference.rst | 24 ++++++++++++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/doc/en/how-to/writing_hook_functions.rst b/doc/en/how-to/writing_hook_functions.rst index 527aeec8170..ec290349c6b 100644 --- a/doc/en/how-to/writing_hook_functions.rst +++ b/doc/en/how-to/writing_hook_functions.rst @@ -59,10 +59,6 @@ The remaining hook functions will not be called in this case. hook wrappers: executing around other hooks ------------------------------------------------- -.. currentmodule:: _pytest.core - - - pytest plugins can implement hook wrappers which wrap the execution of other hook implementations. A hook wrapper is a generator function which yields exactly once. When pytest invokes hooks it first executes @@ -165,6 +161,7 @@ Here is the order of execution: It's possible to use ``tryfirst`` and ``trylast`` also on hook wrappers in which case it will influence the ordering of hook wrappers among each other. +.. _`declaringhooks`: Declaring new hooks ------------------------ diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 254973709af..2dcad7d58d4 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -612,10 +612,30 @@ Hooks **Tutorial**: :ref:`writing-plugins` -.. currentmodule:: _pytest.hookspec - Reference to all hooks which can be implemented by :ref:`conftest.py files ` and :ref:`plugins `. +@pytest.hookimpl +~~~~~~~~~~~~~~~~ + +.. function:: pytest.hookimpl + :decorator: + + pytest's decorator for marking functions as hook implementations. + + See :ref:`writinghooks` and :func:`pluggy.HookimplMarker`. + +@pytest.hookspec +~~~~~~~~~~~~~~~~ + +.. function:: pytest.hookspec + :decorator: + + pytest's decorator for marking functions as hook specifications. + + See :ref:`declaringhooks` and :func:`pluggy.HookspecMarker`. + +.. currentmodule:: _pytest.hookspec + Bootstrapping hooks ~~~~~~~~~~~~~~~~~~~ From 9056db4de56cd6a2bd061209d2ecd88783309ba0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 6 Dec 2023 23:37:52 +0200 Subject: [PATCH 0291/1271] doc: fix some broken Sphinx references --- changelog/9288.breaking.rst | 2 +- doc/en/backwards-compatibility.rst | 2 +- doc/en/changelog.rst | 58 ++++++++++++------------ doc/en/deprecations.rst | 8 ++-- doc/en/example/parametrize.rst | 4 +- doc/en/explanation/fixtures.rst | 2 +- doc/en/funcarg_compare.rst | 2 - doc/en/historical-notes.rst | 2 +- doc/en/how-to/capture-warnings.rst | 2 - doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/writing_hook_functions.rst | 4 +- doc/en/reference/fixtures.rst | 9 +--- src/_pytest/capture.py | 4 +- src/_pytest/config/argparsing.py | 4 +- src/_pytest/hookspec.py | 4 +- src/_pytest/legacypath.py | 7 ++- src/_pytest/logging.py | 4 +- src/_pytest/pytester.py | 4 +- src/_pytest/python_api.py | 2 - 19 files changed, 55 insertions(+), 71 deletions(-) diff --git a/changelog/9288.breaking.rst b/changelog/9288.breaking.rst index 053af8013ec..c344b83c764 100644 --- a/changelog/9288.breaking.rst +++ b/changelog/9288.breaking.rst @@ -1,4 +1,4 @@ -:func:`pytest.warns ` now re-emits unmatched warnings when the context +:func:`~pytest.warns` now re-emits unmatched warnings when the context closes -- previously it would consume all warnings, hiding those that were not matched by the function. diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index 4ffb9fe9756..e04e64a76f9 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -22,7 +22,7 @@ b) transitional: the old and new API don't conflict We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0). - A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationwarning`). + A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationWarning`). When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn `PytestRemovedInXWarning` (e.g. `PytestRemovedIn4Warning`) into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 121d1708da7..7c2162d62c6 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -413,7 +413,7 @@ Improvements - `#8508 `_: Introduce multiline display for warning matching via :py:func:`pytest.warns` and - enhance match comparison for :py:func:`_pytest._code.ExceptionInfo.match` as returned by :py:func:`pytest.raises`. + enhance match comparison for :py:func:`pytest.ExceptionInfo.match` as returned by :py:func:`pytest.raises`. - `#8646 `_: Improve :py:func:`pytest.raises`. Previously passing an empty tuple would give a confusing @@ -422,7 +422,7 @@ Improvements - `#9741 `_: On Python 3.11, use the standard library's :mod:`tomllib` to parse TOML. - :mod:`tomli` is no longer a dependency on Python 3.11. + `tomli` is no longer a dependency on Python 3.11. - `#9742 `_: Display assertion message without escaped newline characters with ``-vv``. @@ -457,7 +457,7 @@ Bug Fixes When inheriting marks from super-classes, marks from the sub-classes are now ordered before marks from the super-classes, in MRO order. Previously it was the reverse. - When inheriting marks from super-classes, the `pytestmark` attribute of the sub-class now only contains the marks directly applied to it. Previously, it also contained marks from its super-classes. Please note that this attribute should not normally be accessed directly; use :func:`pytest.Node.iter_markers` instead. + When inheriting marks from super-classes, the `pytestmark` attribute of the sub-class now only contains the marks directly applied to it. Previously, it also contained marks from its super-classes. Please note that this attribute should not normally be accessed directly; use :func:`Node.iter_markers <_pytest.nodes.Node.iter_markers>` instead. - `#9159 `_: Showing inner exceptions by forcing native display in ``ExceptionGroups`` even when using display options other than ``--tb=native``. A temporary step before full implementation of pytest-native display for inner exceptions in ``ExceptionGroups``. @@ -710,7 +710,7 @@ Bug Fixes - `#9355 `_: Fixed error message prints function decorators when using assert in Python 3.8 and above. -- `#9396 `_: Ensure :attr:`pytest.Config.inifile` is available during the :func:`pytest_cmdline_main <_pytest.hookspec.pytest_cmdline_main>` hook (regression during ``7.0.0rc1``). +- `#9396 `_: Ensure `pytest.Config.inifile` is available during the :hook:`pytest_cmdline_main` hook (regression during ``7.0.0rc1``). @@ -855,7 +855,7 @@ Deprecations - ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead. -- `#8447 `_: Defining a custom pytest node type which is both an :class:`pytest.Item ` and a :class:`pytest.Collector ` (e.g. :class:`pytest.File `) now issues a warning. +- `#8447 `_: Defining a custom pytest node type which is both an :class:`~pytest.Item` and a :class:`~pytest.Collector` (e.g. :class:`~pytest.File`) now issues a warning. It was never sanely supported and triggers hard to debug errors. See :ref:`the deprecation note ` for full details. @@ -897,7 +897,7 @@ Features - `#7132 `_: Added two environment variables :envvar:`PYTEST_THEME` and :envvar:`PYTEST_THEME_MODE` to let the users customize the pygments theme used. -- `#7259 `_: Added :meth:`cache.mkdir() `, which is similar to the existing :meth:`cache.makedir() `, +- `#7259 `_: Added :meth:`cache.mkdir() `, which is similar to the existing ``cache.makedir()``, but returns a :class:`pathlib.Path` instead of a legacy ``py.path.local``. Added a ``paths`` type to :meth:`parser.addini() `, @@ -923,7 +923,7 @@ Features - ``pytest.HookRecorder`` for the :class:`HookRecorder ` type returned from :class:`~pytest.Pytester`. - ``pytest.RecordedHookCall`` for the :class:`RecordedHookCall ` type returned from :class:`~pytest.HookRecorder`. - ``pytest.RunResult`` for the :class:`RunResult ` type returned from :class:`~pytest.Pytester`. - - ``pytest.LineMatcher`` for the :class:`LineMatcher ` type used in :class:`~pytest.RunResult` and others. + - ``pytest.LineMatcher`` for the :class:`LineMatcher ` type used in :class:`~pytest.RunResult` and others. - ``pytest.TestReport`` for the :class:`TestReport ` type used in various hooks. - ``pytest.CollectReport`` for the :class:`CollectReport ` type used in various hooks. @@ -956,7 +956,7 @@ Features - `#8251 `_: Implement ``Node.path`` as a ``pathlib.Path``. Both the old ``fspath`` and this new attribute gets set no matter whether ``path`` or ``fspath`` (deprecated) is passed to the constructor. It is a replacement for the ``fspath`` attribute (which represents the same path as ``py.path.local``). While ``fspath`` is not deprecated yet - due to the ongoing migration of methods like :meth:`~_pytest.Item.reportinfo`, we expect to deprecate it in a future release. + due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo`, we expect to deprecate it in a future release. .. note:: The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the @@ -988,7 +988,7 @@ Features See :ref:`plugin-stash` for details. -- `#8953 `_: :class:`RunResult <_pytest.pytester.RunResult>` method :meth:`assert_outcomes <_pytest.pytester.RunResult.assert_outcomes>` now accepts a +- `#8953 `_: :class:`~pytest.RunResult` method :meth:`~pytest.RunResult.assert_outcomes` now accepts a ``warnings`` argument to assert the total number of warnings captured. @@ -1000,7 +1000,7 @@ Features used. -- `#9113 `_: :class:`RunResult <_pytest.pytester.RunResult>` method :meth:`assert_outcomes <_pytest.pytester.RunResult.assert_outcomes>` now accepts a +- `#9113 `_: :class:`~pytest.RunResult` method :meth:`~pytest.RunResult.assert_outcomes` now accepts a ``deselected`` argument to assert the total number of deselected tests. @@ -1013,7 +1013,7 @@ Improvements - `#7480 `_: A deprecation scheduled to be removed in a major version X (e.g. pytest 7, 8, 9, ...) now uses warning category `PytestRemovedInXWarning`, a subclass of :class:`~pytest.PytestDeprecationWarning`, - instead of :class:`PytestDeprecationWarning` directly. + instead of :class:`~pytest.PytestDeprecationWarning` directly. See :ref:`backwards-compatibility` for more details. @@ -1052,7 +1052,7 @@ Improvements - `#8803 `_: It is now possible to add colors to custom log levels on cli log. - By using :func:`add_color_level <_pytest.logging.add_color_level>` from a ``pytest_configure`` hook, colors can be added:: + By using ``add_color_level`` from a :hook:`pytest_configure` hook, colors can be added:: logging_plugin = config.pluginmanager.get_plugin('logging-plugin') logging_plugin.log_cli_handler.formatter.add_color_level(logging.INFO, 'cyan') @@ -1117,7 +1117,7 @@ Bug Fixes - `#8503 `_: :meth:`pytest.MonkeyPatch.syspath_prepend` no longer fails when ``setuptools`` is not installed. - It now only calls :func:`pkg_resources.fixup_namespace_packages` if + It now only calls ``pkg_resources.fixup_namespace_packages`` if ``pkg_resources`` was previously imported, because it is not needed otherwise. @@ -1344,7 +1344,7 @@ Features This is part of the movement to use :class:`pathlib.Path` objects internally, in order to remove the dependency to ``py`` in the future. - Internally, the old :class:`Testdir <_pytest.pytester.Testdir>` is now a thin wrapper around :class:`Pytester <_pytest.pytester.Pytester>`, preserving the old interface. + Internally, the old :class:`~pytest.Testdir` is now a thin wrapper around :class:`~pytest.Pytester`, preserving the old interface. - :issue:`7695`: A new hook was added, `pytest_markeval_namespace` which should return a dictionary. @@ -1382,7 +1382,7 @@ Features Improvements ------------ -- :issue:`1265`: Added an ``__str__`` implementation to the :class:`~pytest.pytester.LineMatcher` class which is returned from ``pytester.run_pytest().stdout`` and similar. It returns the entire output, like the existing ``str()`` method. +- :issue:`1265`: Added an ``__str__`` implementation to the :class:`~pytest.LineMatcher` class which is returned from ``pytester.run_pytest().stdout`` and similar. It returns the entire output, like the existing ``str()`` method. - :issue:`2044`: Verbose mode now shows the reason that a test was skipped in the test's terminal line after the "SKIPPED", "XFAIL" or "XPASS". @@ -1446,7 +1446,7 @@ Bug Fixes - :issue:`7911`: Directories created by by :fixture:`tmp_path` and :fixture:`tmpdir` are now considered stale after 3 days without modification (previous value was 3 hours) to avoid deleting directories still in use in long running test suites. -- :issue:`7913`: Fixed a crash or hang in :meth:`pytester.spawn <_pytest.pytester.Pytester.spawn>` when the :mod:`readline` module is involved. +- :issue:`7913`: Fixed a crash or hang in :meth:`pytester.spawn ` when the :mod:`readline` module is involved. - :issue:`7951`: Fixed handling of recursive symlinks when collecting tests. @@ -1563,7 +1563,7 @@ Deprecations if you use this and want a replacement. -- :issue:`7255`: The :hook:`pytest_warning_captured` hook is deprecated in favor +- :issue:`7255`: The ``pytest_warning_captured`` hook is deprecated in favor of :hook:`pytest_warning_recorded`, and will be removed in a future version. @@ -1591,8 +1591,8 @@ Improvements - :issue:`7572`: When a plugin listed in ``required_plugins`` is missing or an unknown config key is used with ``--strict-config``, a simple error message is now shown instead of a stacktrace. -- :issue:`7685`: Added two new attributes :attr:`rootpath <_pytest.config.Config.rootpath>` and :attr:`inipath <_pytest.config.Config.inipath>` to :class:`Config <_pytest.config.Config>`. - These attributes are :class:`pathlib.Path` versions of the existing :attr:`rootdir <_pytest.config.Config.rootdir>` and :attr:`inifile <_pytest.config.Config.inifile>` attributes, +- :issue:`7685`: Added two new attributes :attr:`rootpath ` and :attr:`inipath ` to :class:`~pytest.Config`. + These attributes are :class:`pathlib.Path` versions of the existing :attr:`rootdir ` and :attr:`inifile ` attributes, and should be preferred over them when possible. @@ -1663,7 +1663,7 @@ Trivial/Internal Changes - :issue:`7587`: The dependency on the ``more-itertools`` package has been removed. -- :issue:`7631`: The result type of :meth:`capfd.readouterr() <_pytest.capture.CaptureFixture.readouterr>` (and similar) is no longer a namedtuple, +- :issue:`7631`: The result type of :meth:`capfd.readouterr() ` (and similar) is no longer a namedtuple, but should behave like one in all respects. This was done for technical reasons. @@ -2041,10 +2041,10 @@ Improvements - :issue:`7128`: `pytest --version` now displays just the pytest version, while `pytest --version --version` displays more verbose information including plugins. This is more consistent with how other tools show `--version`. -- :issue:`7133`: :meth:`caplog.set_level() <_pytest.logging.LogCaptureFixture.set_level>` will now override any :confval:`log_level` set via the CLI or configuration file. +- :issue:`7133`: :meth:`caplog.set_level() ` will now override any :confval:`log_level` set via the CLI or configuration file. -- :issue:`7159`: :meth:`caplog.set_level() <_pytest.logging.LogCaptureFixture.set_level>` and :meth:`caplog.at_level() <_pytest.logging.LogCaptureFixture.at_level>` no longer affect +- :issue:`7159`: :meth:`caplog.set_level() ` and :meth:`caplog.at_level() ` no longer affect the level of logs that are shown in the *Captured log report* report section. @@ -2390,7 +2390,7 @@ Improvements - :issue:`6384`: Make `--showlocals` work also with `--tb=short`. -- :issue:`6653`: Add support for matching lines consecutively with :attr:`LineMatcher <_pytest.pytester.LineMatcher>`'s :func:`~_pytest.pytester.LineMatcher.fnmatch_lines` and :func:`~_pytest.pytester.LineMatcher.re_match_lines`. +- :issue:`6653`: Add support for matching lines consecutively with :class:`~pytest.LineMatcher`'s :func:`~pytest.LineMatcher.fnmatch_lines` and :func:`~pytest.LineMatcher.re_match_lines`. - :issue:`6658`: Code is now highlighted in tracebacks when ``pygments`` is installed. @@ -2458,7 +2458,7 @@ Bug Fixes - :issue:`6597`: Fix node ids which contain a parametrized empty-string variable. -- :issue:`6646`: Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's :func:`testdir.runpytest <_pytest.pytester.Testdir.runpytest>` etc. +- :issue:`6646`: Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's :func:`testdir.runpytest ` etc. - :issue:`6660`: :py:func:`pytest.exit` is handled when emitted from the :hook:`pytest_sessionfinish` hook. This includes quitting from a debugger. @@ -2524,7 +2524,7 @@ Bug Fixes ``multiprocessing`` module. -- :issue:`6436`: :class:`FixtureDef <_pytest.fixtures.FixtureDef>` objects now properly register their finalizers with autouse and +- :issue:`6436`: :class:`~pytest.FixtureDef` objects now properly register their finalizers with autouse and parameterized fixtures that execute before them in the fixture stack so they are torn down at the right times, and in the right order. @@ -2580,7 +2580,7 @@ Improvements Bug Fixes --------- -- :issue:`5914`: pytester: fix :py:func:`~_pytest.pytester.LineMatcher.no_fnmatch_line` when used after positive matching. +- :issue:`5914`: pytester: fix :py:func:`~pytest.LineMatcher.no_fnmatch_line` when used after positive matching. - :issue:`6082`: Fix line detection for doctest samples inside :py:class:`python:property` docstrings, as a workaround to :bpo:`17446`. @@ -2644,8 +2644,8 @@ Features rather than implicitly. -- :issue:`5914`: :fixture:`testdir` learned two new functions, :py:func:`~_pytest.pytester.LineMatcher.no_fnmatch_line` and - :py:func:`~_pytest.pytester.LineMatcher.no_re_match_line`. +- :issue:`5914`: :fixture:`testdir` learned two new functions, :py:func:`~pytest.LineMatcher.no_fnmatch_line` and + :py:func:`~pytest.LineMatcher.no_re_match_line`. The functions are used to ensure the captured text *does not* match the given pattern. @@ -6497,7 +6497,7 @@ Changes * fix :issue:`2013`: turn RecordedWarning into ``namedtuple``, to give it a comprehensible repr while preventing unwarranted modification. -* fix :issue:`2208`: ensure an iteration limit for _pytest.compat.get_real_func. +* fix :issue:`2208`: ensure an iteration limit for ``_pytest.compat.get_real_func``. Thanks :user:`RonnyPfannschmidt` for the report and PR. * Hooks are now verified after collection is complete, rather than right after loading installed plugins. This diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 0e47bdb0958..ad051fc6228 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -177,7 +177,7 @@ arguments they only pass on to the superclass. resolved in future versions as we slowly get rid of the :pypi:`py` dependency (see :issue:`9283` for a longer discussion). -Due to the ongoing migration of methods like :meth:`~_pytest.Item.reportinfo` +Due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo` which still is expected to return a ``py.path.local`` object, nodes still have both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes, no matter what argument was used in the constructor. We expect to deprecate the @@ -336,7 +336,7 @@ Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item` .. deprecated:: 7.0 -Defining a custom pytest node type which is both an :class:`pytest.Item ` and a :class:`pytest.Collector ` (e.g. :class:`pytest.File `) now issues a warning. +Defining a custom pytest node type which is both an :class:`~pytest.Item` and a :class:`~pytest.Collector` (e.g. :class:`~pytest.File`) now issues a warning. It was never sanely supported and triggers hard to debug errors. Some plugins providing linting/code analysis have been using this as a hack. @@ -348,8 +348,8 @@ Instead, a separate collector node should be used, which collects the item. See .. _uncooperative-constructors-deprecated: -Constructors of custom :class:`pytest.Node` subclasses should take ``**kwargs`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Constructors of custom :class:`~_pytest.nodes.Node` subclasses should take ``**kwargs`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. deprecated:: 7.0 diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 4ea6f6e6512..8c129ddfe7a 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -4,8 +4,6 @@ Parametrizing tests ================================================= -.. currentmodule:: _pytest.python - ``pytest`` allows to easily parametrize test functions. For basic docs, see :ref:`parametrize-basics`. @@ -185,7 +183,7 @@ A quick port of "testscenarios" Here is a quick port to run tests configured with :pypi:`testscenarios`, an add-on from Robert Collins for the standard unittest framework. We only have to work a bit to construct the correct arguments for pytest's -:py:func:`Metafunc.parametrize`: +:py:func:`Metafunc.parametrize `: .. code-block:: python diff --git a/doc/en/explanation/fixtures.rst b/doc/en/explanation/fixtures.rst index 194e576493e..322718873e0 100644 --- a/doc/en/explanation/fixtures.rst +++ b/doc/en/explanation/fixtures.rst @@ -162,7 +162,7 @@ A note about fixture cleanup ---------------------------- pytest does not do any special processing for :data:`SIGTERM ` and -:data:`SIGQUIT ` signals (:data:`SIGINT ` is handled naturally +``SIGQUIT`` signals (:data:`SIGINT ` is handled naturally by the Python runtime via :class:`KeyboardInterrupt`), so fixtures that manage external resources which are important to be cleared when the Python process is terminated (by those signals) might leak resources. diff --git a/doc/en/funcarg_compare.rst b/doc/en/funcarg_compare.rst index 3bf4527cfb5..43260815bc4 100644 --- a/doc/en/funcarg_compare.rst +++ b/doc/en/funcarg_compare.rst @@ -11,8 +11,6 @@ funcarg mechanism, see :ref:`historical funcargs and pytest.funcargs`. If you are new to pytest, then you can simply ignore this section and read the other sections. -.. currentmodule:: _pytest - Shortcomings of the previous ``pytest_funcarg__`` mechanism -------------------------------------------------------------- diff --git a/doc/en/historical-notes.rst b/doc/en/historical-notes.rst index 29ebbd5d199..ae32c28f3ec 100644 --- a/doc/en/historical-notes.rst +++ b/doc/en/historical-notes.rst @@ -112,7 +112,7 @@ More details can be found in the :pull:`original PR <3317>`. .. note:: in a future major release of pytest we will introduce class based markers, - at which point markers will no longer be limited to instances of :py:class:`~_pytest.mark.Mark`. + at which point markers will no longer be limited to instances of :py:class:`~pytest.Mark`. cache plugin integrated into the core diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 0390230b8ea..ba6730587ce 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -382,8 +382,6 @@ warnings: a WarningsRecorder instance. To view the recorded warnings, you can iterate over this instance, call ``len`` on it to get the number of recorded warnings, or index into it to get a particular recorded warning. -.. currentmodule:: _pytest.warnings - Full API: :class:`~_pytest.recwarn.WarningsRecorder`. .. _`warns use cases`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index b2fb24b3fbe..35b06c5191d 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1271,7 +1271,7 @@ configured in multiple ways. Extending the previous example, we can flag the fixture to create two ``smtp_connection`` fixture instances which will cause all tests using the fixture to run twice. The fixture function gets access to each parameter -through the special :py:class:`request ` object: +through the special :py:class:`request ` object: .. code-block:: python diff --git a/doc/en/how-to/writing_hook_functions.rst b/doc/en/how-to/writing_hook_functions.rst index ec290349c6b..5d0a52f9d38 100644 --- a/doc/en/how-to/writing_hook_functions.rst +++ b/doc/en/how-to/writing_hook_functions.rst @@ -171,13 +171,11 @@ Declaring new hooks This is a quick overview on how to add new hooks and how they work in general, but a more complete overview can be found in `the pluggy documentation `__. -.. currentmodule:: _pytest.hookspec - Plugins and ``conftest.py`` files may declare new hooks that can then be implemented by other plugins in order to alter behaviour or interact with the new plugin: -.. autofunction:: pytest_addhooks +.. autofunction:: _pytest.hookspec.pytest_addhooks :noindex: Hooks are usually declared as do-nothing functions that contain only diff --git a/doc/en/reference/fixtures.rst b/doc/en/reference/fixtures.rst index 01f825222ea..078933de663 100644 --- a/doc/en/reference/fixtures.rst +++ b/doc/en/reference/fixtures.rst @@ -11,9 +11,6 @@ Fixtures reference .. seealso:: :ref:`about-fixtures` .. seealso:: :ref:`how-to-fixtures` - -.. currentmodule:: _pytest.python - .. _`Dependency injection`: https://en.wikipedia.org/wiki/Dependency_injection @@ -76,15 +73,13 @@ Built-in fixtures :class:`pathlib.Path` objects. :fixture:`tmpdir` - Provide a :class:`py.path.local` object to a temporary + Provide a `py.path.local `_ object to a temporary directory which is unique to each test function; replaced by :fixture:`tmp_path`. - .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html - :fixture:`tmpdir_factory` Make session-scoped temporary directories and return - :class:`py.path.local` objects; + ``py.path.local`` objects; replaced by :fixture:`tmp_path_factory`. diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 81b8bffbcf7..ebdcaedcea1 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -588,7 +588,7 @@ def writeorg(self, data: str) -> None: @final class CaptureResult(NamedTuple, Generic[AnyStr]): - """The result of :method:`CaptureFixture.readouterr`.""" + """The result of :method:`caplog.readouterr() `.""" out: AnyStr err: AnyStr @@ -598,7 +598,7 @@ class CaptureResult(NamedTuple, Generic[AnyStr]): class CaptureResult( collections.namedtuple("CaptureResult", ["out", "err"]), Generic[AnyStr] ): - """The result of :method:`CaptureFixture.readouterr`.""" + """The result of :method:`caplog.readouterr() `.""" __slots__ = () diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 461b8afdff9..331abb85d00 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -98,7 +98,7 @@ def addoption(self, *opts: str, **attrs: Any) -> None: :param opts: Option names, can be short or long options. :param attrs: - Same attributes as the argparse library's :py:func:`add_argument() + Same attributes as the argparse library's :meth:`add_argument() ` function accepts. After command line parsing, options are available on the pytest config @@ -400,7 +400,7 @@ def addoption(self, *opts: str, **attrs: Any) -> None: :param opts: Option names, can be short or long options. :param attrs: - Same attributes as the argparse library's :py:func:`add_argument() + Same attributes as the argparse library's :meth:`add_argument() ` function accepts. """ conflict = set(opts).intersection( diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 11878d1b07c..014ce47ad7a 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -96,8 +96,8 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> `. :param pytest.PytestPluginManager pluginmanager: - The pytest plugin manager, which can be used to install :py:func:`hookspec`'s - or :py:func:`hookimpl`'s and allow one plugin to call another plugin's hooks + The pytest plugin manager, which can be used to install :py:func:`~pytest.hookspec`'s + or :py:func:`~pytest.hookimpl`'s and allow one plugin to call another plugin's hooks to change how command line options are added. Options can later be accessed through the diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index 8df0a516318..4876a083a67 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -88,7 +88,6 @@ def chdir(self) -> None: return self._pytester.chdir() def finalize(self) -> None: - """See :meth:`Pytester._finalize`.""" return self._pytester._finalize() def makefile(self, ext, *args, **kwargs) -> LEGACY_PATH: @@ -269,7 +268,7 @@ def testdir(pytester: Pytester) -> Testdir: @final @dataclasses.dataclass class TempdirFactory: - """Backward compatibility wrapper that implements :class:`py.path.local` + """Backward compatibility wrapper that implements ``py.path.local`` for :class:`TempPathFactory`. .. note:: @@ -288,11 +287,11 @@ def __init__( self._tmppath_factory = tmppath_factory def mktemp(self, basename: str, numbered: bool = True) -> LEGACY_PATH: - """Same as :meth:`TempPathFactory.mktemp`, but returns a :class:`py.path.local` object.""" + """Same as :meth:`TempPathFactory.mktemp`, but returns a ``py.path.local`` object.""" return legacy_path(self._tmppath_factory.mktemp(basename, numbered).resolve()) def getbasetemp(self) -> LEGACY_PATH: - """Same as :meth:`TempPathFactory.getbasetemp`, but returns a :class:`py.path.local` object.""" + """Same as :meth:`TempPathFactory.getbasetemp`, but returns a ``py.path.local`` object.""" return legacy_path(self._tmppath_factory.getbasetemp().resolve()) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 246a4ab6eb0..1c6bb923bd3 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -522,7 +522,7 @@ def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> Non The levels of the loggers changed by this function will be restored to their initial values at the end of the test. - Will enable the requested logging level if it was disabled via :meth:`logging.disable`. + Will enable the requested logging level if it was disabled via :func:`logging.disable`. :param level: The level. :param logger: The logger to update. If not given, the root logger. @@ -546,7 +546,7 @@ def at_level( the end of the 'with' statement the level is restored to its original value. - Will enable the requested logging level if it was disabled via :meth:`logging.disable`. + Will enable the requested logging level if it was disabled via :func:`logging.disable`. :param level: The level. :param logger: The logger to update. If not given, the root logger. diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index f93e9c94a00..d388758a2d0 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1044,7 +1044,7 @@ def runitem(self, source: str) -> Any: The calling test instance (class containing the test method) must provide a ``.getrunner()`` method which should return a runner which can run the test protocol for a single item, e.g. - :py:func:`_pytest.runner.runtestprotocol`. + ``_pytest.runner.runtestprotocol``. """ # used from runner functional tests item = self.getitem(source) @@ -1395,7 +1395,7 @@ def run( :param stdin: Optional standard input. - - If it is :py:attr:`CLOSE_STDIN` (Default), then this method calls + - If it is ``CLOSE_STDIN`` (Default), then this method calls :py:class:`subprocess.Popen` with ``stdin=subprocess.PIPE``, and the standard input is closed immediately after the new command is started. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 07db0f234d4..53e23ebff5a 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -825,8 +825,6 @@ def raises( # noqa: F811 When using :py:func:`pytest.raises` as a function, you can use: ``pytest.raises(Exc, func, match="passed on").match("my pattern")``.) - .. currentmodule:: _pytest._code - Use ``pytest.raises`` as a context manager, which will capture the exception of the given type, or any of its subclasses:: From b92fde37cee08ac018f17f41913f2cf9d98d0fe4 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 24 Sep 2022 23:36:50 +0200 Subject: [PATCH 0292/1271] Introduce a gate/check GHA job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a GHA job that reliably determines if all the required dependencies have succeeded or not. It also allows to reduce the list of required branch protection CI statuses to just one — `check`. This reduces the maintenance burden by a lot and have been battle-tested across a small bunch of projects in its action form and in-house implementations of other people. I was curious about the spread of use. And I've just discovered that it is now in use in aiohttp (and other aio-libs projects), CherryPy, some of the Ansible repositories, all of the jaraco's projects (like `setuptools`, `importlib_metadata`), some PyCQA, PyCA and pytest projects, a few AWS Labs projects. Admittedly, I maintain a few of these but it seems to address some of the pain folks have: https://github.com/jaraco/skeleton/pull/55#issuecomment-1106638475. The story behind this is explained in more detail at https://github.com/marketplace/actions/alls-green#why. --- .github/workflows/test.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5f5832475d3..80e747400e3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -211,3 +211,17 @@ jobs: fail_ci_if_error: true files: ./coverage.xml verbose: true + + check: # This job does nothing and is only used for the branch protection + if: always() + + needs: + - build + + runs-on: ubuntu-latest + + steps: + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@release/v1 + with: + jobs: ${{ toJSON(needs) }} From 30ce631fb9f306e81d70de03d2328162a8717933 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 24 Sep 2022 23:39:20 +0200 Subject: [PATCH 0293/1271] Securely pin re-actors/alls-green to v1.2 commit --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 80e747400e3..9e646e53ab4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -222,6 +222,6 @@ jobs: steps: - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@release/v1 + uses: re-actors/alls-green@198badcb65a1a44528f27d5da555c4be9f12eac6 with: jobs: ${{ toJSON(needs) }} From 49188833367829edabb0e90ba4cc39e2dfacb70f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 7 Dec 2023 11:03:52 +0200 Subject: [PATCH 0294/1271] python_api: remove unused function `_non_numeric_type_error` --- src/_pytest/python_api.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 53e23ebff5a..643f04b970c 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -30,15 +30,6 @@ from numpy import ndarray -def _non_numeric_type_error(value, at: Optional[str]) -> TypeError: - at_str = f" at {at}" if at else "" - return TypeError( - "cannot make approximate comparisons to non-numeric values: {!r} {}".format( - value, at_str - ) - ) - - def _compare_approx( full_object: object, message_data: Sequence[Tuple[str, str, str]], From f76af423b08719a26a6505f61ced12f39a911d4d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 7 Dec 2023 10:41:51 +0200 Subject: [PATCH 0295/1271] doc/reference: document `FixtureLookupError` --- doc/en/example/simple.rst | 2 +- doc/en/reference/reference.rst | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index b798e711a11..943342ff107 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -168,7 +168,7 @@ Now we'll get feedback on a bad argument: If you need to provide more detailed error messages, you can use the -``type`` parameter and raise ``pytest.UsageError``: +``type`` parameter and raise :exc:`pytest.UsageError`: .. code-block:: python diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 2dcad7d58d4..473d71e0eff 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1157,7 +1157,10 @@ When set (regardless of value), pytest will use color in terminal output. Exceptions ---------- -.. autoclass:: pytest.UsageError() +.. autoexception:: pytest.UsageError() + :show-inheritance: + +.. autoexception:: pytest.FixtureLookupError() :show-inheritance: .. _`warnings ref`: From ee91d095f6121c119d0ea42b5ee34b46172779ec Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 7 Dec 2023 10:30:17 +0200 Subject: [PATCH 0296/1271] doc: fix more broken Sphinx references --- doc/en/changelog.rst | 8 ++++---- doc/en/funcarg_compare.rst | 4 ++-- src/_pytest/config/__init__.py | 2 ++ src/_pytest/hookspec.py | 10 +++++----- src/_pytest/nodes.py | 7 ++++--- src/_pytest/python_api.py | 10 +++++----- 6 files changed, 22 insertions(+), 19 deletions(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 7c2162d62c6..35ea4fa3280 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -1344,7 +1344,7 @@ Features This is part of the movement to use :class:`pathlib.Path` objects internally, in order to remove the dependency to ``py`` in the future. - Internally, the old :class:`~pytest.Testdir` is now a thin wrapper around :class:`~pytest.Pytester`, preserving the old interface. + Internally, the old ``pytest.Testdir`` is now a thin wrapper around :class:`~pytest.Pytester`, preserving the old interface. - :issue:`7695`: A new hook was added, `pytest_markeval_namespace` which should return a dictionary. @@ -1592,7 +1592,7 @@ Improvements - :issue:`7685`: Added two new attributes :attr:`rootpath ` and :attr:`inipath ` to :class:`~pytest.Config`. - These attributes are :class:`pathlib.Path` versions of the existing :attr:`rootdir ` and :attr:`inifile ` attributes, + These attributes are :class:`pathlib.Path` versions of the existing ``rootdir`` and ``inifile`` attributes, and should be preferred over them when possible. @@ -2139,7 +2139,7 @@ Bug Fixes parameter when Python is called with the ``-bb`` flag. -- :issue:`7143`: Fix :meth:`pytest.File.from_parent` so it forwards extra keyword arguments to the constructor. +- :issue:`7143`: Fix :meth:`pytest.File.from_parent <_pytest.nodes.Node.from_parent>` so it forwards extra keyword arguments to the constructor. - :issue:`7145`: Classes with broken ``__getattribute__`` methods are displayed correctly during failures. @@ -2458,7 +2458,7 @@ Bug Fixes - :issue:`6597`: Fix node ids which contain a parametrized empty-string variable. -- :issue:`6646`: Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's :func:`testdir.runpytest ` etc. +- :issue:`6646`: Assertion rewriting hooks are (re)stored for the current item, which fixes them being still used after e.g. pytester's ``testdir.runpytest`` etc. - :issue:`6660`: :py:func:`pytest.exit` is handled when emitted from the :hook:`pytest_sessionfinish` hook. This includes quitting from a debugger. diff --git a/doc/en/funcarg_compare.rst b/doc/en/funcarg_compare.rst index 43260815bc4..27def534b54 100644 --- a/doc/en/funcarg_compare.rst +++ b/doc/en/funcarg_compare.rst @@ -44,7 +44,7 @@ There are several limitations and difficulties with this approach: 2. parametrizing the "db" resource is not straight forward: you need to apply a "parametrize" decorator or implement a - :py:func:`~hookspec.pytest_generate_tests` hook + :hook:`pytest_generate_tests` hook calling :py:func:`~pytest.Metafunc.parametrize` which performs parametrization at the places where the resource is used. Moreover, you need to modify the factory to use an @@ -92,7 +92,7 @@ Direct parametrization of funcarg resource factories Previously, funcarg factories could not directly cause parametrization. You needed to specify a ``@parametrize`` decorator on your test function -or implement a ``pytest_generate_tests`` hook to perform +or implement a :hook:`pytest_generate_tests` hook to perform parametrization, i.e. calling a test multiple times with different value sets. pytest-2.3 introduces a decorator for use on the factory itself: diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index ea23c77421a..adf1bfd9a67 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -449,6 +449,7 @@ def __init__(self) -> None: def parse_hookimpl_opts( self, plugin: _PluggyPlugin, name: str ) -> Optional[HookimplOpts]: + """:meta private:""" # pytest hooks are always prefixed with "pytest_", # so we avoid accessing possibly non-readable attributes # (see issue #1073). @@ -472,6 +473,7 @@ def parse_hookimpl_opts( ) def parse_hookspec_opts(self, module_or_class, name: str) -> Optional[HookspecOpts]: + """:meta private:""" opts = super().parse_hookspec_opts(module_or_class, name) if opts is None: method = getattr(module_or_class, name) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 014ce47ad7a..8a4e29e672f 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -55,7 +55,7 @@ @hookspec(historic=True) def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: """Called at plugin registration time to allow adding new hooks via a call to - ``pluginmanager.add_hookspecs(module_or_class, prefix)``. + :func:`pluginmanager.add_hookspecs(module_or_class, prefix) `. :param pytest.PytestPluginManager pluginmanager: The pytest plugin manager. @@ -858,8 +858,8 @@ def pytest_warning_recorded( """Process a warning captured by the internal pytest warnings plugin. :param warning_message: - The captured warning. This is the same object produced by :py:func:`warnings.catch_warnings`, and contains - the same attributes as the parameters of :py:func:`warnings.showwarning`. + The captured warning. This is the same object produced by :class:`warnings.catch_warnings`, + and contains the same attributes as the parameters of :py:func:`warnings.showwarning`. :param when: Indicates when the warning was captured. Possible values: @@ -940,10 +940,10 @@ def pytest_exception_interact( interactively handled. May be called during collection (see :hook:`pytest_make_collect_report`), - in which case ``report`` is a :class:`CollectReport`. + in which case ``report`` is a :class:`~pytest.CollectReport`. May be called during runtest of an item (see :hook:`pytest_runtest_protocol`), - in which case ``report`` is a :class:`TestReport`. + in which case ``report`` is a :class:`~pytest.TestReport`. This hook is not called if the exception that was raised is an internal exception like ``skip.Exception``. diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 4b94f413bb7..e4eb639967f 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -1,4 +1,5 @@ import os +import pathlib import warnings from functools import cached_property from inspect import signature @@ -176,8 +177,8 @@ class Node(metaclass=NodeMeta): # Implemented in the legacypath plugin. #: A ``LEGACY_PATH`` copy of the :attr:`path` attribute. Intended for usage #: for methods not migrated to ``pathlib.Path`` yet, such as - #: :meth:`Item.reportinfo`. Will be deprecated in a future release, prefer - #: using :attr:`path` instead. + #: :meth:`Item.reportinfo `. Will be deprecated in + #: a future release, prefer using :attr:`path` instead. fspath: LEGACY_PATH # Use __slots__ to make attribute access faster. @@ -228,7 +229,7 @@ def __init__( if path is None and fspath is None: path = getattr(parent, "path", None) #: Filesystem path where this node was collected from (can be None). - self.path: Path = _imply_path(type(self), path, fspath=fspath) + self.path: pathlib.Path = _imply_path(type(self), path, fspath=fspath) # The explicit annotation is to avoid publicly exposing NodeKeywords. #: Keywords/markers collected from all scopes. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 643f04b970c..f914d70e83f 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -797,23 +797,23 @@ def raises( # noqa: F811 ) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]: r"""Assert that a code block/function call raises an exception type, or one of its subclasses. - :param typing.Type[E] | typing.Tuple[typing.Type[E], ...] expected_exception: + :param expected_exception: The expected exception type, or a tuple if one of multiple possible exception types are expected. Note that subclasses of the passed exceptions will also match. - :kwparam str | typing.Pattern[str] | None match: + :kwparam str | re.Pattern[str] | None match: If specified, a string containing a regular expression, or a regular expression object, that is tested against the string - representation of the exception and its `PEP-678 ` `__notes__` + representation of the exception and its :pep:`678` `__notes__` using :func:`re.search`. To match a literal string that may contain :ref:`special characters `, the pattern can first be escaped with :func:`re.escape`. - (This is only used when :py:func:`pytest.raises` is used as a context manager, + (This is only used when ``pytest.raises`` is used as a context manager, and passed through to the function otherwise. - When using :py:func:`pytest.raises` as a function, you can use: + When using ``pytest.raises`` as a function, you can use: ``pytest.raises(Exc, func, match="passed on").match("my pattern")``.) Use ``pytest.raises`` as a context manager, which will capture the exception of the given From 2aa8743bbeff8a983bc3e26e4f0cac155d112731 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 7 Dec 2023 10:30:21 +0200 Subject: [PATCH 0297/1271] doc: enable Sphinx nitpicky mode See: https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-nitpicky This ensures we have no more broken references. --- doc/en/conf.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/doc/en/conf.py b/doc/en/conf.py index 92607a15a9a..d3a98015a68 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -169,6 +169,50 @@ } +nitpicky = True +nitpick_ignore = [ + # TODO (fix in pluggy?) + ("py:class", "HookCaller"), + ("py:class", "HookspecMarker"), + ("py:exc", "PluginValidationError"), + # Might want to expose/TODO (https://github.com/pytest-dev/pytest/issues/7469) + ("py:class", "ExceptionRepr"), + ("py:class", "Exit"), + ("py:class", "SubRequest"), + ("py:class", "SubRequest"), + ("py:class", "TerminalReporter"), + ("py:class", "_pytest._code.code.TerminalRepr"), + ("py:class", "_pytest.fixtures.FixtureFunctionMarker"), + ("py:class", "_pytest.logging.LogCaptureHandler"), + ("py:class", "_pytest.mark.structures.ParameterSet"), + # Intentionally undocumented/private + ("py:class", "_pytest._code.code.Traceback"), + ("py:class", "_pytest._py.path.LocalPath"), + ("py:class", "_pytest.capture.CaptureResult"), + ("py:class", "_pytest.compat.NotSetType"), + ("py:class", "_pytest.python.PyCollector"), + ("py:class", "_pytest.python.PyobjMixin"), + ("py:class", "_pytest.python_api.RaisesContext"), + ("py:class", "_pytest.recwarn.WarningsChecker"), + ("py:class", "_pytest.reports.BaseReport"), + # Undocumented third parties + ("py:class", "_tracing.TagTracerSub"), + ("py:class", "warnings.WarningMessage"), + # Undocumented type aliases + ("py:class", "LEGACY_PATH"), + ("py:class", "_PluggyPlugin"), + # TypeVars + ("py:class", "_pytest._code.code.E"), + ("py:class", "_pytest.fixtures.FixtureFunction"), + ("py:class", "_pytest.nodes._NodeType"), + ("py:class", "_pytest.python_api.E"), + ("py:class", "_pytest.recwarn.T"), + ("py:class", "_pytest.runner.TResult"), + ("py:obj", "_pytest.fixtures.FixtureValue"), + ("py:obj", "_pytest.stash.T"), +] + + # -- Options for HTML output --------------------------------------------------- sys.path.append(os.path.abspath("_themes")) From 0ae02e2165264dc05d727906023fb21c036ecb0d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 6 Dec 2023 18:27:17 +0200 Subject: [PATCH 0298/1271] nodes,python: mark abstract node classes as ABCs Fixes #11676 --- changelog/11676.breaking.rst | 3 +++ doc/en/reference/reference.rst | 1 + src/_pytest/fixtures.py | 4 +++- src/_pytest/nodes.py | 15 +++++++++------ src/_pytest/python.py | 3 ++- testing/deprecated_test.py | 10 ++++++++-- .../issue88_initial_file_multinodes/conftest.py | 3 ++- testing/test_collection.py | 6 +++++- testing/test_nodes.py | 6 ++++++ 9 files changed, 39 insertions(+), 12 deletions(-) create mode 100644 changelog/11676.breaking.rst diff --git a/changelog/11676.breaking.rst b/changelog/11676.breaking.rst new file mode 100644 index 00000000000..f20efa80db0 --- /dev/null +++ b/changelog/11676.breaking.rst @@ -0,0 +1,3 @@ +The classes :class:`~_pytest.nodes.Node`, :class:`~pytest.Collector`, :class:`~pytest.Item`, :class:`~pytest.File`, :class:`~_pytest.nodes.FSCollector` are now marked abstract (see :mod:`abc`). + +We do not expect this change to affect users and plugin authors, it will only cause errors when the code is already wrong or problematic. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 254973709af..923ffc69f74 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -801,6 +801,7 @@ Node .. autoclass:: _pytest.nodes.Node() :members: + :show-inheritance: Collector ~~~~~~~~~ diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index d56274629a8..89046ddd0bd 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -135,7 +135,9 @@ def get_scope_node( import _pytest.python if scope is Scope.Function: - return node.getparent(nodes.Item) + # Type ignored because this is actually safe, see: + # https://github.com/python/mypy/issues/4717 + return node.getparent(nodes.Item) # type: ignore[type-abstract] elif scope is Scope.Class: return node.getparent(_pytest.python.Class) elif scope is Scope.Module: diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 4b94f413bb7..6472c2ac6f4 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -1,3 +1,4 @@ +import abc import os import warnings from functools import cached_property @@ -121,7 +122,7 @@ def _imply_path( _NodeType = TypeVar("_NodeType", bound="Node") -class NodeMeta(type): +class NodeMeta(abc.ABCMeta): """Metaclass used by :class:`Node` to enforce that direct construction raises :class:`Failed`. @@ -165,7 +166,7 @@ def _create(self, *k, **kw): return super().__call__(*k, **known_kw) -class Node(metaclass=NodeMeta): +class Node(abc.ABC, metaclass=NodeMeta): r"""Base class of :class:`Collector` and :class:`Item`, the components of the test collection tree. @@ -534,7 +535,7 @@ def get_fslocation_from_item(node: "Node") -> Tuple[Union[str, Path], Optional[i return getattr(node, "fspath", "unknown location"), -1 -class Collector(Node): +class Collector(Node, abc.ABC): """Base class of all collectors. Collector create children through `collect()` and thus iteratively build @@ -544,6 +545,7 @@ class Collector(Node): class CollectError(Exception): """An error during collection, contains a custom message.""" + @abc.abstractmethod def collect(self) -> Iterable[Union["Item", "Collector"]]: """Collect children (items and collectors) for this collector.""" raise NotImplementedError("abstract") @@ -588,7 +590,7 @@ def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[ return None -class FSCollector(Collector): +class FSCollector(Collector, abc.ABC): """Base class for filesystem collectors.""" def __init__( @@ -666,14 +668,14 @@ def isinitpath(self, path: Union[str, "os.PathLike[str]"]) -> bool: return self.session.isinitpath(path) -class File(FSCollector): +class File(FSCollector, abc.ABC): """Base class for collecting tests from a file. :ref:`non-python tests`. """ -class Item(Node): +class Item(Node, abc.ABC): """Base class of all test invocation items. Note that for a single function there might be multiple test invocation items. @@ -739,6 +741,7 @@ def _check_item_and_collector_diamond_inheritance(self) -> None: PytestWarning, ) + @abc.abstractmethod def runtest(self) -> None: """Run the test case for this item. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 0985c871d3b..3dd3026fb50 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1,4 +1,5 @@ """Python test discovery, setup and run of test functions.""" +import abc import dataclasses import enum import fnmatch @@ -380,7 +381,7 @@ class _EmptyClass: pass # noqa: E701 # fmt: on -class PyCollector(PyobjMixin, nodes.Collector): +class PyCollector(PyobjMixin, nodes.Collector, abc.ABC): def funcnamefilter(self, name: str) -> bool: return self._matches_prefix_or_glob_option("python_functions", name) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 08e193b5cec..fcd824d5f57 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -257,11 +257,17 @@ def pytest_cmdline_preparse(config, args): def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: mod = pytester.getmodulecol("") + class MyFile(pytest.File): + def collect(self): + raise NotImplementedError() + with pytest.warns( pytest.PytestDeprecationWarning, - match=re.escape("The (fspath: py.path.local) argument to File is deprecated."), + match=re.escape( + "The (fspath: py.path.local) argument to MyFile is deprecated." + ), ): - pytest.File.from_parent( + MyFile.from_parent( parent=mod.parent, fspath=legacy_path("bla"), ) diff --git a/testing/example_scripts/issue88_initial_file_multinodes/conftest.py b/testing/example_scripts/issue88_initial_file_multinodes/conftest.py index cb8f5d671ea..0598eb841a4 100644 --- a/testing/example_scripts/issue88_initial_file_multinodes/conftest.py +++ b/testing/example_scripts/issue88_initial_file_multinodes/conftest.py @@ -11,4 +11,5 @@ def pytest_collect_file(file_path, parent): class MyItem(pytest.Item): - pass + def runtest(self): + raise NotImplementedError() diff --git a/testing/test_collection.py b/testing/test_collection.py index ca2e2b7313f..b2492f7f28f 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -99,7 +99,8 @@ def test_getcustomfile_roundtrip(self, pytester: Pytester) -> None: conftest=""" import pytest class CustomFile(pytest.File): - pass + def collect(self): + return [] def pytest_collect_file(file_path, parent): if file_path.suffix == ".xxx": return CustomFile.from_parent(path=file_path, parent=parent) @@ -1509,6 +1510,9 @@ def __init__(self, *k, x, **kw): super().__init__(*k, **kw) self.x = x + def collect(self): + raise NotImplementedError() + collector = MyCollector.from_parent( parent=request.session, path=pytester.path / "foo", x=10 ) diff --git a/testing/test_nodes.py b/testing/test_nodes.py index df1439e1c49..84c377cf990 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -73,6 +73,12 @@ def __init__(self, fspath, parent): """Legacy ctor with legacy call # don't wana see""" super().__init__(fspath, parent) + def collect(self): + raise NotImplementedError() + + def runtest(self): + raise NotImplementedError() + with pytest.warns(PytestWarning) as rec: SoWrong.from_parent( request.session, fspath=legacy_path(tmp_path / "broken.txt") From 5381cd083f26b07f38adb41a9837142b0345402b Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 10 Dec 2023 00:20:38 +0000 Subject: [PATCH 0299/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 186 +++++++++++++++++-------------- 1 file changed, 105 insertions(+), 81 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 2ded9bf9d4b..dea19eae694 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Nov 08, 2023 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Dec 06, 2023 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -105,7 +105,7 @@ This list contains 1351 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 27, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-asyncio` Pytest support for asyncio Dec 09, 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) @@ -132,7 +132,7 @@ This list contains 1351 plugins. :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) - :pypi:`pytest-bdd` BDD for pytest Oct 10, 2023 6 - Mature pytest (>=6.2.0) + :pypi:`pytest-bdd` BDD for pytest Dec 02, 2023 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0) :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 15, 2023 N/A pytest >=7.1.3 @@ -190,7 +190,7 @@ This list contains 1351 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest May 06, 2021 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Dec 07, 2023 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A @@ -200,7 +200,7 @@ This list contains 1351 plugins. :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Sep 22, 2023 N/A pytest :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' - :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Jul 22, 2020 5 - Production/Stable pytest (>=2.9.2) + :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest>=7.0 @@ -252,7 +252,7 @@ This list contains 1351 plugins. :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Nov 14, 2023 3 - Alpha pytest - :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Jun 23, 2023 4 - Beta pytest>=7.1.2 + :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 08, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A :pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6) @@ -328,7 +328,7 @@ This list contains 1351 plugins. :pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all' :pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0) - :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Jun 23, 2023 4 - Beta pytest>=7.1.2 + :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 05, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 @@ -379,7 +379,7 @@ This list contains 1351 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 Nov 20, 2023 N/A N/A + :pypi:`pytest-dogu-sdk` pytest plugin for the Dogu Dec 05, 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) @@ -403,21 +403,21 @@ This list contains 1351 plugins. :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A - :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Jan 08, 2020 5 - Production/Stable N/A + :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Sep 13, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest - :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-embedded` A pytest plugin that designed for embedded testing. Dec 04, 2023 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Dec 04, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Dec 04, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Dec 04, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Dec 04, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Dec 04, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Dec 04, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Dec 04, 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) @@ -531,12 +531,12 @@ This list contains 1351 plugins. :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-gee` The Python plugin for your GEE based packages. Dec 04, 2023 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-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 20, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Dec 05, 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 @@ -574,7 +574,7 @@ This list contains 1351 plugins. :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 Dec 01, 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 09, 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` Dec 01, 2023 N/A N/A @@ -606,7 +606,7 @@ This list contains 1351 plugins. :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Aug 31, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 - :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Sep 20, 2023 4 - Beta pytest + :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A @@ -634,7 +634,7 @@ This list contains 1351 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. Nov 29, 2023 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Dec 05, 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 @@ -661,7 +661,7 @@ This list contains 1351 plugins. :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Mar 30, 2023 4 - Beta pytest + :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Dec 05, 2023 4 - Beta pytest :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest @@ -690,7 +690,7 @@ This list contains 1351 plugins. :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Jul 11, 2022 4 - Beta N/A + :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 06, 2023 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest @@ -738,7 +738,7 @@ This list contains 1351 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Oct 08, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 - :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Nov 06, 2023 N/A pytest (>=7.4.3) + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Dec 07, 2023 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 @@ -749,10 +749,11 @@ This list contains 1351 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 Nov 21, 2023 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Dec 07, 2023 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Dec 06, 2023 N/A pytest >=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) @@ -832,6 +833,7 @@ This list contains 1351 plugins. :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 May 16, 2023 N/A N/A :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" + :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 05, 2023 4 - Beta N/A :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Oct 01, 2023 N/A pytest @@ -942,7 +944,7 @@ This list contains 1351 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 18, 2023 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Dec 09, 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) @@ -983,7 +985,7 @@ This list contains 1351 plugins. :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable 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-recording` A pytest plugin that allows you recording of network interactions via VCR.py Dec 06, 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) :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest @@ -1013,7 +1015,7 @@ This list contains 1351 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Oct 17, 2023 N/A pytest >=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Dec 06, 2023 N/A pytest >=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) @@ -1059,7 +1061,6 @@ This list contains 1351 plugins. :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Oct 31, 2023 4 - Beta N/A :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A - :pypi:`pytest-runner` Invoke py.test as distutils command with dependency resolution Feb 25, 2022 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 @@ -1073,7 +1074,7 @@ This list contains 1351 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 01, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 08, 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) @@ -1082,7 +1083,7 @@ This list contains 1351 plugins. :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 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. Dec 01, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Dec 08, 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 @@ -1125,6 +1126,7 @@ This list contains 1351 plugins. :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest + :pypi:`pytest-smtp-test-server` pytest plugin for using \`smtp-test-server\` as a fixture Dec 03, 2023 2 - Pre-Alpha pytest (>=7.4.3,<8.0.0) :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) @@ -1203,6 +1205,7 @@ This list contains 1351 plugins. :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) + :pypi:`pytest-tcp` A Pytest plugin for test prioritization Dec 04, 2023 4 - Beta pytest >=7.4.3 :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A @@ -1264,7 +1267,7 @@ This list contains 1351 plugins. :pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-tm4j-reporter` Cloud Jira Test Management (TM4J) PyTest reporter plugin Sep 01, 2020 N/A pytest :pypi:`pytest-tmnet` A small example package Mar 01, 2022 N/A N/A - :pypi:`pytest-tmp-files` Utilities to create temporary file hierarchies in pytest. Apr 03, 2022 N/A pytest + :pypi:`pytest-tmp-files` Utilities to create temporary file hierarchies in pytest. Dec 08, 2023 N/A pytest :pypi:`pytest-tmpfs` A pytest plugin that helps you on using a temporary filesystem for testing. Aug 29, 2022 N/A pytest :pypi:`pytest-tmreport` this is a vue-element ui report for pytest Aug 12, 2022 N/A N/A :pypi:`pytest-tmux` A pytest plugin that enables tmux driven tests Apr 22, 2023 4 - Beta N/A @@ -1289,7 +1292,7 @@ This list contains 1351 plugins. :pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A - :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Jun 12, 2023 4 - Beta N/A + :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A :pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3) @@ -1622,7 +1625,7 @@ This list contains 1351 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Nov 08, 2023, + *last release*: Dec 06, 2023, *status*: N/A, *requires*: pytest >=7.3.1 @@ -1888,9 +1891,9 @@ This list contains 1351 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Nov 27, 2023, + *last release*: Dec 09, 2023, *status*: 4 - Beta, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 Pytest support for asyncio @@ -2077,7 +2080,7 @@ This list contains 1351 plugins. pytest plugin for URL based testing :pypi:`pytest-bdd` - *last release*: Oct 10, 2023, + *last release*: Dec 02, 2023, *status*: 6 - Mature, *requires*: pytest (>=6.2.0) @@ -2483,7 +2486,7 @@ This list contains 1351 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: May 06, 2021, + *last release*: Dec 07, 2023, *status*: N/A, *requires*: N/A @@ -2553,9 +2556,9 @@ This list contains 1351 plugins. check the README when running tests :pypi:`pytest-checkipdb` - *last release*: Jul 22, 2020, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=2.9.2) + *requires*: pytest >=2.9.2 plugin to check if there are ipdb debugs left @@ -2917,9 +2920,9 @@ This list contains 1351 plugins. The pytest plugin for your copier templates 📒 :pypi:`pytest-copier` - *last release*: Jun 23, 2023, + *last release*: Dec 08, 2023, *status*: 4 - Beta, - *requires*: pytest>=7.1.2 + *requires*: pytest>=7.3.2 A pytest plugin to help testing Copier templates @@ -3449,9 +3452,9 @@ This list contains 1351 plugins. PyTest plugin for generating Difido reports :pypi:`pytest-dir-equal` - *last release*: Jun 23, 2023, + *last release*: Dec 05, 2023, *status*: 4 - Beta, - *requires*: pytest>=7.1.2 + *requires*: pytest>=7.3.2 pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing @@ -3806,7 +3809,7 @@ This list contains 1351 plugins. pytest plugin for dogu report :pypi:`pytest-dogu-sdk` - *last release*: Nov 20, 2023, + *last release*: Dec 05, 2023, *status*: N/A, *requires*: N/A @@ -3974,9 +3977,9 @@ This list contains 1351 plugins. Pytest execution on EC2 instance :pypi:`pytest-echo` - *last release*: Jan 08, 2020, + *last release*: Dec 05, 2023, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest >=2.2 pytest plugin with mechanisms for echoing environment variables, package version and generic attributes @@ -4023,56 +4026,56 @@ This list contains 1351 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Nov 27, 2023, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Nov 27, 2023, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Nov 27, 2023, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Nov 27, 2023, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Nov 27, 2023, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Nov 27, 2023, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Nov 27, 2023, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Nov 27, 2023, + *last release*: Dec 04, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4870,9 +4873,9 @@ This list contains 1351 plugins. Uses gcov to measure test coverage of a C library :pypi:`pytest-gee` - *last release*: Nov 22, 2023, + *last release*: Dec 04, 2023, *status*: 3 - Alpha, - *requires*: pytest; extra == 'test' + *requires*: pytest The Python plugin for your GEE based packages. @@ -4905,7 +4908,7 @@ This list contains 1351 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Nov 20, 2023, + *last release*: Dec 05, 2023, *status*: N/A, *requires*: N/A @@ -5171,7 +5174,7 @@ This list contains 1351 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Dec 01, 2023, + *last release*: Dec 09, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5395,7 +5398,7 @@ This list contains 1351 plugins. A plugin to sent pytest results to an Ibutsu server :pypi:`pytest-icdiff` - *last release*: Sep 20, 2023, + *last release*: Dec 05, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5591,7 +5594,7 @@ This list contains 1351 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Nov 29, 2023, + *last release*: Dec 05, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5780,7 +5783,7 @@ This list contains 1351 plugins. pytest plugin supporting json test report output :pypi:`pytest-jupyter` - *last release*: Mar 30, 2023, + *last release*: Dec 05, 2023, *status*: 4 - Beta, *requires*: pytest @@ -5983,7 +5986,7 @@ This list contains 1351 plugins. A python-libfaketime plugin for pytest. :pypi:`pytest-libiio` - *last release*: Jul 11, 2022, + *last release*: Dec 06, 2023, *status*: 4 - Beta, *requires*: N/A @@ -6319,7 +6322,7 @@ This list contains 1351 plugins. A pytest plugin to make a test results report with Markdown table format. :pypi:`pytest-meilisearch` - *last release*: Nov 06, 2023, + *last release*: Dec 07, 2023, *status*: N/A, *requires*: pytest (>=7.4.3) @@ -6396,7 +6399,7 @@ This list contains 1351 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Nov 21, 2023, + *last release*: Dec 07, 2023, *status*: N/A, *requires*: pytest @@ -6423,6 +6426,13 @@ This list contains 1351 plugins. A plugin to test mp + :pypi:`pytest-minio-mock` + *last release*: Dec 06, 2023, + *status*: N/A, + *requires*: pytest >=5.0.0 + + A pytest plugin for mocking Minio S3 interactions + :pypi:`pytest-missing-fixtures` *last release*: Oct 14, 2020, *status*: 4 - Beta, @@ -6976,6 +6986,13 @@ This list contains 1351 plugins. Use @pytest.mark.only to run a single test + :pypi:`pytest-oof` + *last release*: Dec 05, 2023, + *status*: 4 - Beta, + *requires*: N/A + + A Pytest plugin providing structured, programmatic access to a test run's results + :pypi:`pytest-oot` *last release*: Sep 18, 2016, *status*: 4 - Beta, @@ -7747,7 +7764,7 @@ This list contains 1351 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Nov 18, 2023, + *last release*: Dec 09, 2023, *status*: N/A, *requires*: pytest @@ -8034,7 +8051,7 @@ This list contains 1351 plugins. Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. :pypi:`pytest-recording` - *last release*: Jul 31, 2023, + *last release*: Dec 06, 2023, *status*: 4 - Beta, *requires*: pytest>=3.5.0 @@ -8244,7 +8261,7 @@ This list contains 1351 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Oct 17, 2023, + *last release*: Dec 06, 2023, *status*: N/A, *requires*: pytest >=3.8.0 @@ -8565,13 +8582,6 @@ This list contains 1351 plugins. implement a --failed option for pytest - :pypi:`pytest-runner` - *last release*: Feb 25, 2022, - *status*: 5 - Production/Stable, - *requires*: pytest (>=6) ; extra == 'testing' - - Invoke py.test as distutils command with dependency resolution - :pypi:`pytest-run-subprocess` *last release*: Nov 12, 2022, *status*: 5 - Production/Stable, @@ -8664,7 +8674,7 @@ This list contains 1351 plugins. :pypi:`pytest-sbase` - *last release*: Dec 01, 2023, + *last release*: Dec 08, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8727,7 +8737,7 @@ This list contains 1351 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Dec 01, 2023, + *last release*: Dec 08, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -9027,6 +9037,13 @@ This list contains 1351 plugins. An SMTP server for testing built on aiosmtpd + :pypi:`pytest-smtp-test-server` + *last release*: Dec 03, 2023, + *status*: 2 - Pre-Alpha, + *requires*: pytest (>=7.4.3,<8.0.0) + + pytest plugin for using \`smtp-test-server\` as a fixture + :pypi:`pytest-snail` *last release*: Nov 04, 2019, *status*: 3 - Alpha, @@ -9573,6 +9590,13 @@ This list contains 1351 plugins. tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used + :pypi:`pytest-tcp` + *last release*: Dec 04, 2023, + *status*: 4 - Beta, + *requires*: pytest >=7.4.3 + + A Pytest plugin for test prioritization + :pypi:`pytest-tcpclient` *last release*: Nov 16, 2022, *status*: N/A, @@ -10001,7 +10025,7 @@ This list contains 1351 plugins. A small example package :pypi:`pytest-tmp-files` - *last release*: Apr 03, 2022, + *last release*: Dec 08, 2023, *status*: N/A, *requires*: pytest @@ -10176,7 +10200,7 @@ This list contains 1351 plugins. Test Class Base :pypi:`pytest-tui` - *last release*: Jun 12, 2023, + *last release*: Dec 08, 2023, *status*: 4 - Beta, *requires*: N/A From f411c8d6d786f6fe53e32eb5c132312da10e2182 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 30 Jun 2023 10:56:58 +0300 Subject: [PATCH 0300/1271] main: add `with_parents` parameter to `isinitpath` Will be used in upcoming commit. --- src/_pytest/main.py | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 5cee8e89b26..f7b34ded8a2 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -499,6 +499,7 @@ def __init__(self, config: Config) -> None: self.shouldfail: Union[bool, str] = False self.trace = config.trace.root.get("collection") self._initialpaths: FrozenSet[Path] = frozenset() + self._initialpaths_with_parents: FrozenSet[Path] = frozenset() self._bestrelpathcache: Dict[Path, str] = _bestrelpath_cache(config.rootpath) @@ -549,10 +550,29 @@ def pytest_runtest_logreport( pytest_collectreport = pytest_runtest_logreport - def isinitpath(self, path: Union[str, "os.PathLike[str]"]) -> bool: + def isinitpath( + self, + path: Union[str, "os.PathLike[str]"], + *, + with_parents: bool = False, + ) -> bool: + """Is path an initial path? + + An initial path is a path pytest starts with, e.g. given on the command + line. + + :param with_parents: + If set, also return True if the path is a parent of an initial path. + + .. versionchanged:: 8.0 + Added the ``with_parents`` parameter. + """ # Optimization: Path(Path(...)) is much slower than isinstance. path_ = path if isinstance(path, Path) else Path(path) - return path_ in self._initialpaths + if with_parents: + return path_ in self._initialpaths_with_parents + else: + return path_ in self._initialpaths def gethookproxy(self, fspath: "os.PathLike[str]") -> pluggy.HookRelay: # Optimization: Path(Path(...)) is much slower than isinstance. @@ -667,6 +687,7 @@ def perform_collect( # noqa: F811 items: Sequence[Union[nodes.Item, nodes.Collector]] = self.items try: initialpaths: List[Path] = [] + initialpaths_with_parents: List[Path] = [] for arg in args: fspath, parts = resolve_collection_argument( self.config.invocation_params.dir, @@ -675,7 +696,10 @@ def perform_collect( # noqa: F811 ) self._initial_parts.append((fspath, parts)) initialpaths.append(fspath) + initialpaths_with_parents.append(fspath) + initialpaths_with_parents.extend(fspath.parents) self._initialpaths = frozenset(initialpaths) + self._initialpaths_with_parents = frozenset(initialpaths_with_parents) rep = collect_one_node(self) self.ihook.pytest_collectreport(report=rep) self.trace.root.indent -= 1 From 385796ba494e7ae65d55892d4a358b371ac7a6b6 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 2 Jun 2023 16:03:39 +0300 Subject: [PATCH 0301/1271] Rework Session and Package collection Fix #7777. --- changelog/7777.breaking.rst | 90 ++++ doc/en/deprecations.rst | 85 ++++ doc/en/example/conftest.py | 2 +- doc/en/example/customdirectory.rst | 77 ++++ doc/en/example/customdirectory/conftest.py | 28 ++ doc/en/example/customdirectory/pytest.ini | 0 .../customdirectory/tests/manifest.json | 6 + .../customdirectory/tests/test_first.py | 3 + .../customdirectory/tests/test_second.py | 3 + .../customdirectory/tests/test_third.py | 3 + doc/en/example/index.rst | 1 + doc/en/reference/reference.rst | 14 + src/_pytest/cacheprovider.py | 4 +- src/_pytest/config/__init__.py | 2 - src/_pytest/hookspec.py | 24 ++ src/_pytest/main.py | 396 +++++++++++------- src/_pytest/mark/__init__.py | 13 +- src/_pytest/nodes.py | 18 + src/_pytest/pathlib.py | 10 +- src/_pytest/python.py | 119 +++--- src/pytest/__init__.py | 4 + testing/acceptance_test.py | 5 +- .../customdirectory/conftest.py | 22 + .../customdirectory/pytest.ini | 0 .../customdirectory/tests/manifest.json | 6 + .../customdirectory/tests/test_first.py | 3 + .../customdirectory/tests/test_second.py | 3 + .../customdirectory/tests/test_third.py | 3 + testing/python/collect.py | 105 +++++ testing/python/metafunc.py | 20 +- testing/test_assertion.py | 10 +- testing/test_cacheprovider.py | 36 +- testing/test_collection.py | 107 +++-- testing/test_config.py | 3 +- testing/test_mark.py | 33 +- testing/test_reports.py | 6 +- testing/test_runner.py | 2 +- testing/test_session.py | 23 +- testing/test_terminal.py | 31 +- 39 files changed, 985 insertions(+), 335 deletions(-) create mode 100644 changelog/7777.breaking.rst create mode 100644 doc/en/example/customdirectory.rst create mode 100644 doc/en/example/customdirectory/conftest.py create mode 100644 doc/en/example/customdirectory/pytest.ini create mode 100644 doc/en/example/customdirectory/tests/manifest.json create mode 100644 doc/en/example/customdirectory/tests/test_first.py create mode 100644 doc/en/example/customdirectory/tests/test_second.py create mode 100644 doc/en/example/customdirectory/tests/test_third.py create mode 100644 testing/example_scripts/customdirectory/conftest.py create mode 100644 testing/example_scripts/customdirectory/pytest.ini create mode 100644 testing/example_scripts/customdirectory/tests/manifest.json create mode 100644 testing/example_scripts/customdirectory/tests/test_first.py create mode 100644 testing/example_scripts/customdirectory/tests/test_second.py create mode 100644 testing/example_scripts/customdirectory/tests/test_third.py diff --git a/changelog/7777.breaking.rst b/changelog/7777.breaking.rst new file mode 100644 index 00000000000..d38fea33096 --- /dev/null +++ b/changelog/7777.breaking.rst @@ -0,0 +1,90 @@ +Added a new :class:`pytest.Directory` base collection node, which all collector nodes for filesystem directories are expected to subclass. +This is analogous to the existing :class:`pytest.File` for file nodes. + +Changed :class:`pytest.Package` to be a subclass of :class:`pytest.Directory`. +A ``Package`` represents a filesystem directory which is a Python package, +i.e. contains an ``__init__.py`` file. + +:class:`pytest.Package` now only collects files in its own directory; previously it collected recursively. +Sub-directories are collected as sub-collector nodes, thus creating a collection tree which mirrors the filesystem hierarchy. + +Added a new :class:`pytest.Dir` concrete collection node, a subclass of :class:`pytest.Directory`. +This node represents a filesystem directory, which is not a :class:`pytest.Package`, +i.e. does not contain an ``__init__.py`` file. +Similarly to ``Package``, it only collects the files in its own directory, +while collecting sub-directories as sub-collector nodes. + +Added a new hook :hook:`pytest_collect_directory`, +which is called by filesystem-traversing collector nodes, +such as :class:`pytest.Session`, :class:`pytest.Dir` and :class:`pytest.Package`, +to create a collector node for a sub-directory. +It is expected to return a subclass of :class:`pytest.Directory`. +This hook allows plugins to :ref:`customize the collection of directories `. + +:class:`pytest.Session` now only collects the initial arguments, without recursing into directories. +This work is now done by the :func:`recursive expansion process ` of directory collector nodes. + +:attr:`session.name ` is now ``""``; previously it was the rootdir directory name. +This matches :attr:`session.nodeid <_pytest.nodes.Node.nodeid>` which has always been `""`. + +Files and directories are now collected in alphabetical order jointly, unless changed by a plugin. +Previously, files were collected before directories. + +The collection tree now contains directories/packages up to the :ref:`rootdir `, +for initial arguments that are found within the rootdir. +For files outside the rootdir, only the immediate directory/package is collected -- +note however that collecting from outside the rootdir is discouraged. + +As an example, given the following filesystem tree:: + + myroot/ + pytest.ini + top/ + ├── aaa + │ └── test_aaa.py + ├── test_a.py + ├── test_b + │ ├── __init__.py + │ └── test_b.py + ├── test_c.py + └── zzz + ├── __init__.py + └── test_zzz.py + +the collection tree, as shown by `pytest --collect-only top/` but with the otherwise-hidden :class:`~pytest.Session` node added for clarity, +is now the following:: + + + + + + + + + + + + + + + + + + +Previously, it was:: + + + + + + + + + + + + + + + +Code/plugins which rely on a specific shape of the collection tree might need to update. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index ad051fc6228..caa7cb3e760 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -495,6 +495,91 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +Collection changes in pytest 8 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Added a new :class:`pytest.Directory` base collection node, which all collector nodes for filesystem directories are expected to subclass. +This is analogous to the existing :class:`pytest.File` for file nodes. + +Changed :class:`pytest.Package` to be a subclass of :class:`pytest.Directory`. +A ``Package`` represents a filesystem directory which is a Python package, +i.e. contains an ``__init__.py`` file. + +:class:`pytest.Package` now only collects files in its own directory; previously it collected recursively. +Sub-directories are collected as sub-collector nodes, thus creating a collection tree which mirrors the filesystem hierarchy. + +:attr:`session.name ` is now ``""``; previously it was the rootdir directory name. +This matches :attr:`session.nodeid <_pytest.nodes.Node.nodeid>` which has always been `""`. + +Added a new :class:`pytest.Dir` concrete collection node, a subclass of :class:`pytest.Directory`. +This node represents a filesystem directory, which is not a :class:`pytest.Package`, +i.e. does not contain an ``__init__.py`` file. +Similarly to ``Package``, it only collects the files in its own directory, +while collecting sub-directories as sub-collector nodes. + +Files and directories are now collected in alphabetical order jointly, unless changed by a plugin. +Previously, files were collected before directories. + +The collection tree now contains directories/packages up to the :ref:`rootdir `, +for initial arguments that are found within the rootdir. +For files outside the rootdir, only the immediate directory/package is collected -- +note however that collecting from outside the rootdir is discouraged. + +As an example, given the following filesystem tree:: + + myroot/ + pytest.ini + top/ + ├── aaa + │ └── test_aaa.py + ├── test_a.py + ├── test_b + │ ├── __init__.py + │ └── test_b.py + ├── test_c.py + └── zzz + ├── __init__.py + └── test_zzz.py + +the collection tree, as shown by `pytest --collect-only top/` but with the otherwise-hidden :class:`~pytest.Session` node added for clarity, +is now the following:: + + + + + + + + + + + + + + + + + + +Previously, it was:: + + + + + + + + + + + + + + + +Code/plugins which rely on a specific shape of the collection tree might need to update. + + :class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/en/example/conftest.py b/doc/en/example/conftest.py index f905738c4f6..66e70f14dd7 100644 --- a/doc/en/example/conftest.py +++ b/doc/en/example/conftest.py @@ -1 +1 @@ -collect_ignore = ["nonpython"] +collect_ignore = ["nonpython", "customdirectory"] diff --git a/doc/en/example/customdirectory.rst b/doc/en/example/customdirectory.rst new file mode 100644 index 00000000000..1e4d7e370de --- /dev/null +++ b/doc/en/example/customdirectory.rst @@ -0,0 +1,77 @@ +.. _`custom directory collectors`: + +Using a custom directory collector +==================================================== + +By default, pytest collects directories using :class:`pytest.Package`, for directories with ``__init__.py`` files, +and :class:`pytest.Dir` for other directories. +If you want to customize how a directory is collected, you can write your own :class:`pytest.Directory` collector, +and use :hook:`pytest_collect_directory` to hook it up. + +.. _`directory manifest plugin`: + +A basic example for a directory manifest file +-------------------------------------------------------------- + +Suppose you want to customize how collection is done on a per-directory basis. +Here is an example ``conftest.py`` plugin that allows directories to contain a ``manifest.json`` file, +which defines how the collection should be done for the directory. +In this example, only a simple list of files is supported, +however you can imagine adding other keys, such as exclusions and globs. + +.. include:: customdirectory/conftest.py + :literal: + +You can create a ``manifest.json`` file and some test files: + +.. include:: customdirectory/tests/manifest.json + :literal: + +.. include:: customdirectory/tests/test_first.py + :literal: + +.. include:: customdirectory/tests/test_second.py + :literal: + +.. include:: customdirectory/tests/test_third.py + :literal: + +An you can now execute the test specification: + +.. code-block:: pytest + + customdirectory $ pytest + =========================== test session starts ============================ + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + rootdir: /home/sweet/project/customdirectory + configfile: pytest.ini + collected 2 items + + tests/test_first.py . [ 50%] + tests/test_second.py . [100%] + + ============================ 2 passed in 0.12s ============================= + +.. regendoc:wipe + +Notice how ``test_three.py`` was not executed, because it is not listed in the manifest. + +You can verify that your custom collector appears in the collection tree: + +.. code-block:: pytest + + customdirectory $ pytest --collect-only + =========================== test session starts ============================ + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y + rootdir: /home/sweet/project/customdirectory + configfile: pytest.ini + collected 2 items + + + + + + + + + ======================== 2 tests collected in 0.12s ======================== diff --git a/doc/en/example/customdirectory/conftest.py b/doc/en/example/customdirectory/conftest.py new file mode 100644 index 00000000000..350893cab43 --- /dev/null +++ b/doc/en/example/customdirectory/conftest.py @@ -0,0 +1,28 @@ +# content of conftest.py +import json + +import pytest + + +class ManifestDirectory(pytest.Directory): + def collect(self): + # The standard pytest behavior is to loop over all `test_*.py` files and + # call `pytest_collect_file` on each file. This collector instead reads + # the `manifest.json` file and only calls `pytest_collect_file` for the + # files defined there. + manifest_path = self.path / "manifest.json" + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + ihook = self.ihook + for file in manifest["files"]: + yield from ihook.pytest_collect_file( + file_path=self.path / file, parent=self + ) + + +@pytest.hookimpl +def pytest_collect_directory(path, parent): + # Use our custom collector for directories containing a `mainfest.json` file. + if path.joinpath("manifest.json").is_file(): + return ManifestDirectory.from_parent(parent=parent, path=path) + # Otherwise fallback to the standard behavior. + return None diff --git a/doc/en/example/customdirectory/pytest.ini b/doc/en/example/customdirectory/pytest.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/doc/en/example/customdirectory/tests/manifest.json b/doc/en/example/customdirectory/tests/manifest.json new file mode 100644 index 00000000000..6ab6d0a5222 --- /dev/null +++ b/doc/en/example/customdirectory/tests/manifest.json @@ -0,0 +1,6 @@ +{ + "files": [ + "test_first.py", + "test_second.py" + ] +} diff --git a/doc/en/example/customdirectory/tests/test_first.py b/doc/en/example/customdirectory/tests/test_first.py new file mode 100644 index 00000000000..0a78de59945 --- /dev/null +++ b/doc/en/example/customdirectory/tests/test_first.py @@ -0,0 +1,3 @@ +# content of test_first.py +def test_1(): + pass diff --git a/doc/en/example/customdirectory/tests/test_second.py b/doc/en/example/customdirectory/tests/test_second.py new file mode 100644 index 00000000000..eed724a7d96 --- /dev/null +++ b/doc/en/example/customdirectory/tests/test_second.py @@ -0,0 +1,3 @@ +# content of test_second.py +def test_2(): + pass diff --git a/doc/en/example/customdirectory/tests/test_third.py b/doc/en/example/customdirectory/tests/test_third.py new file mode 100644 index 00000000000..61cf59dc16c --- /dev/null +++ b/doc/en/example/customdirectory/tests/test_third.py @@ -0,0 +1,3 @@ +# content of test_third.py +def test_3(): + pass diff --git a/doc/en/example/index.rst b/doc/en/example/index.rst index 71e855534ff..e8835aae9d3 100644 --- a/doc/en/example/index.rst +++ b/doc/en/example/index.rst @@ -32,3 +32,4 @@ The following examples aim at various use cases you might encounter. special pythoncollection nonpython + customdirectory diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index d6f942ad0e2..a360e16120c 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -682,6 +682,8 @@ Collection hooks .. autofunction:: pytest_collection .. hook:: pytest_ignore_collect .. autofunction:: pytest_ignore_collect +.. hook:: pytest_collect_directory +.. autofunction:: pytest_collect_directory .. hook:: pytest_collect_file .. autofunction:: pytest_collect_file .. hook:: pytest_pycollect_makemodule @@ -921,6 +923,18 @@ Config .. autoclass:: pytest.Config() :members: +Dir +~~~ + +.. autoclass:: pytest.Dir() + :members: + +Directory +~~~~~~~~~ + +.. autoclass:: pytest.Directory() + :members: + ExceptionInfo ~~~~~~~~~~~~~ diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 50a474a2920..793e796de69 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -27,8 +27,8 @@ from _pytest.fixtures import fixture from _pytest.fixtures import FixtureRequest from _pytest.main import Session +from _pytest.nodes import Directory from _pytest.nodes import File -from _pytest.python import Package from _pytest.reports import TestReport README_CONTENT = """\ @@ -222,7 +222,7 @@ def pytest_make_collect_report( self, collector: nodes.Collector ) -> Generator[None, CollectReport, CollectReport]: res = yield - if isinstance(collector, (Session, Package)): + if isinstance(collector, (Session, Directory)): # Sort any lf-paths to the beginning. lf_paths = self.lfplugin._last_failed_paths diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index adf1bfd9a67..e5775546dde 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -415,8 +415,6 @@ def __init__(self) -> None: # session (#9478), often with the same path, so cache it. self._get_directory = lru_cache(256)(_get_directory) - self._duplicatepaths: Set[Path] = set() - # plugins that were explicitly skipped with pytest.skip # list of (module name, skip reason) # previously we would issue a warning when a plugin was skipped, but diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 8a4e29e672f..3c65234daa7 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -284,11 +284,35 @@ def pytest_ignore_collect( """ +@hookspec(firstresult=True) +def pytest_collect_directory(path: Path, parent: "Collector") -> "Optional[Collector]": + """Create a :class:`~pytest.Collector` for the given directory, or None if + not relevant. + + .. versionadded:: 8.0 + + For best results, the returned collector should be a subclass of + :class:`~pytest.Directory`, but this is not required. + + The new node needs to have the specified ``parent`` as a parent. + + Stops at first non-None result, see :ref:`firstresult`. + + :param path: The path to analyze. + + See :ref:`custom directory collectors` for a simple example of use of this + hook. + """ + + def pytest_collect_file( file_path: Path, path: "LEGACY_PATH", parent: "Collector" ) -> "Optional[Collector]": """Create a :class:`~pytest.Collector` for the given path, or None if not relevant. + For best results, the returned collector should be a subclass of + :class:`~pytest.File`, but this is not required. + The new node needs to have the specified ``parent`` as a parent. :param file_path: The path to analyze. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index f7b34ded8a2..e4ca05aac95 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -12,6 +12,8 @@ from typing import Dict from typing import final from typing import FrozenSet +from typing import Generator +from typing import Iterable from typing import Iterator from typing import List from typing import Literal @@ -19,8 +21,6 @@ from typing import overload from typing import Sequence from typing import Tuple -from typing import Type -from typing import TYPE_CHECKING from typing import Union import pluggy @@ -41,17 +41,13 @@ from _pytest.pathlib import bestrelpath from _pytest.pathlib import fnmatch_ex from _pytest.pathlib import safe_exists -from _pytest.pathlib import visit +from _pytest.pathlib import scandir from _pytest.reports import CollectReport from _pytest.reports import TestReport from _pytest.runner import collect_one_node from _pytest.runner import SetupState -if TYPE_CHECKING: - from _pytest.python import Package - - def pytest_addoption(parser: Parser) -> None: parser.addini( "norecursedirs", @@ -414,6 +410,12 @@ def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[boo return None +def pytest_collect_directory( + path: Path, parent: nodes.Collector +) -> Optional[nodes.Collector]: + return Dir.from_parent(parent, path=path) + + def pytest_collection_modifyitems(items: List[nodes.Item], config: Config) -> None: deselect_prefixes = tuple(config.getoption("deselect") or []) if not deselect_prefixes: @@ -470,7 +472,61 @@ def __missing__(self, path: Path) -> str: @final -class Session(nodes.FSCollector): +class Dir(nodes.Directory): + """Collector of files in a file system directory. + + .. versionadded:: 8.0 + + .. note:: + + Python directories with an `__init__.py` file are instead collected by + :class:`~pytest.Package` by default. Both are :class:`~pytest.Directory` + collectors. + """ + + @classmethod + def from_parent( # type: ignore[override] + cls, + parent: nodes.Collector, # type: ignore[override] + *, + path: Path, + ) -> "Dir": + """The public constructor. + + :param parent: The parent collector of this Dir. + :param path: The directory's path. + """ + return super().from_parent(parent=parent, path=path) # type: ignore[no-any-return] + + def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: + config = self.config + col: Optional[nodes.Collector] + cols: Sequence[nodes.Collector] + for direntry in scandir(self.path): + if direntry.is_dir(): + if direntry.name == "__pycache__": + continue + ihook = self.ihook + path = Path(direntry.path) + if not self.session.isinitpath(path, with_parents=True): + if ihook.pytest_ignore_collect(collection_path=path, config=config): + continue + col = ihook.pytest_collect_directory(path=path, parent=self) + if col is not None: + yield col + + elif direntry.is_file(): + ihook = self.ihook + path = Path(direntry.path) + if not self.session.isinitpath(path): + if ihook.pytest_ignore_collect(collection_path=path, config=config): + continue + cols = ihook.pytest_collect_file(file_path=path, parent=self) + yield from cols + + +@final +class Session(nodes.Collector): """The root of the collection tree. ``Session`` collects the initial paths given as arguments to pytest. @@ -486,6 +542,7 @@ class Session(nodes.FSCollector): def __init__(self, config: Config) -> None: super().__init__( + name="", path=config.rootpath, fspath=None, parent=None, @@ -500,6 +557,11 @@ def __init__(self, config: Config) -> None: self.trace = config.trace.root.get("collection") self._initialpaths: FrozenSet[Path] = frozenset() self._initialpaths_with_parents: FrozenSet[Path] = frozenset() + self._notfound: List[Tuple[str, Sequence[nodes.Collector]]] = [] + self._initial_parts: List[Tuple[Path, List[str]]] = [] + self._in_genitems = False + self._collection_cache: Dict[nodes.Collector, CollectReport] = {} + self.items: List[nodes.Item] = [] self._bestrelpathcache: Dict[Path, str] = _bestrelpath_cache(config.rootpath) @@ -550,6 +612,29 @@ def pytest_runtest_logreport( pytest_collectreport = pytest_runtest_logreport + @hookimpl(wrapper=True) + def pytest_collect_directory( + self, + ) -> Generator[None, Optional[nodes.Collector], Optional[nodes.Collector]]: + col = yield + + # Eagerly load conftests for the directory. + # This is needed because a conftest error needs to happen while + # collecting a collector, so it is caught by its CollectReport. + # Without this, the conftests are loaded inside of genitems itself + # which leads to an internal error. + # This should only be done for genitems; if done unconditionally, it + # will load conftests for non-selected directories which is to be + # avoided. + if self._in_genitems and col is not None: + self.config.pluginmanager._loadconftestmodules( + col.path, + self.config.getoption("importmode"), + rootpath=self.config.rootpath, + ) + + return col + def isinitpath( self, path: Union[str, "os.PathLike[str]"], @@ -558,7 +643,7 @@ def isinitpath( ) -> bool: """Is path an initial path? - An initial path is a path pytest starts with, e.g. given on the command + An initial path is a path explicitly given to pytest on the command line. :param with_parents: @@ -600,49 +685,36 @@ def gethookproxy(self, fspath: "os.PathLike[str]") -> pluggy.HookRelay: proxy = self.config.hook return proxy - def _recurse(self, direntry: "os.DirEntry[str]") -> bool: - if direntry.name == "__pycache__": - return False - fspath = Path(direntry.path) - ihook = self.gethookproxy(fspath.parent) - if ihook.pytest_ignore_collect(collection_path=fspath, config=self.config): - return False - return True - - def _collectpackage(self, fspath: Path) -> Optional["Package"]: - from _pytest.python import Package + def _collect_path( + self, + path: Path, + path_cache: Dict[Path, Sequence[nodes.Collector]], + ) -> Sequence[nodes.Collector]: + """Create a Collector for the given path. - ihook = self.gethookproxy(fspath) - if not self.isinitpath(fspath): - if ihook.pytest_ignore_collect(collection_path=fspath, config=self.config): - return None + `path_cache` makes it so the same Collectors are returned for the same + path. + """ + if path in path_cache: + return path_cache[path] - pkg: Package = Package.from_parent(self, path=fspath) - return pkg + if path.is_dir(): + ihook = self.gethookproxy(path.parent) + col: Optional[nodes.Collector] = ihook.pytest_collect_directory( + path=path, parent=self + ) + cols: Sequence[nodes.Collector] = (col,) if col is not None else () - def _collectfile( - self, fspath: Path, handle_dupes: bool = True - ) -> Sequence[nodes.Collector]: - assert ( - fspath.is_file() - ), "{!r} is not a file (isdir={!r}, exists={!r}, islink={!r})".format( - fspath, fspath.is_dir(), fspath.exists(), fspath.is_symlink() - ) - ihook = self.gethookproxy(fspath) - if not self.isinitpath(fspath): - if ihook.pytest_ignore_collect(collection_path=fspath, config=self.config): - return () + elif path.is_file(): + ihook = self.gethookproxy(path) + cols = ihook.pytest_collect_file(file_path=path, parent=self) - if handle_dupes: - keepduplicates = self.config.getoption("keepduplicates") - if not keepduplicates: - duplicate_paths = self.config.pluginmanager._duplicatepaths - if fspath in duplicate_paths: - return () - else: - duplicate_paths.add(fspath) + else: + # Broken symlink or invalid/missing file. + cols = () - return ihook.pytest_collect_file(file_path=fspath, parent=self) # type: ignore[no-any-return] + path_cache[path] = cols + return cols @overload def perform_collect( @@ -678,12 +750,13 @@ def perform_collect( # noqa: F811 self.trace("perform_collect", self, args) self.trace.root.indent += 1 - self._notfound: List[Tuple[str, Sequence[nodes.Collector]]] = [] - self._initial_parts: List[Tuple[Path, List[str]]] = [] - self.items: List[nodes.Item] = [] - hook = self.config.hook + self._notfound = [] + self._initial_parts = [] + self._in_genitems = False + self._collection_cache = {} + self.items = [] items: Sequence[Union[nodes.Item, nodes.Collector]] = self.items try: initialpaths: List[Path] = [] @@ -700,6 +773,7 @@ def perform_collect( # noqa: F811 initialpaths_with_parents.extend(fspath.parents) self._initialpaths = frozenset(initialpaths) self._initialpaths_with_parents = frozenset(initialpaths_with_parents) + rep = collect_one_node(self) self.ihook.pytest_collectreport(report=rep) self.trace.root.indent -= 1 @@ -708,12 +782,14 @@ def perform_collect( # noqa: F811 for arg, collectors in self._notfound: if collectors: errors.append( - f"not found: {arg}\n(no name {arg!r} in any of {collectors!r})" + f"not found: {arg}\n(no match in any of {collectors!r})" ) else: errors.append(f"found no collectors for {arg}") raise UsageError(*errors) + + self._in_genitems = True if not genitems: items = rep.result else: @@ -726,22 +802,35 @@ def perform_collect( # noqa: F811 session=self, config=self.config, items=items ) finally: + self._notfound = [] + self._initial_parts = [] + self._in_genitems = False + self._collection_cache = {} hook.pytest_collection_finish(session=self) - self.testscollected = len(items) - return items + if genitems: + self.testscollected = len(items) - def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: - # Keep track of any collected nodes in here, so we don't duplicate fixtures. - node_cache1: Dict[Path, Sequence[nodes.Collector]] = {} - node_cache2: Dict[Tuple[Type[nodes.Collector], Path], nodes.Collector] = {} + return items - # Keep track of any collected collectors in matchnodes paths, so they - # are not collected more than once. - matchnodes_cache: Dict[Tuple[Type[nodes.Collector], str], CollectReport] = {} + def _collect_one_node( + self, + node: nodes.Collector, + handle_dupes: bool = True, + ) -> Tuple[CollectReport, bool]: + if node in self._collection_cache and handle_dupes: + rep = self._collection_cache[node] + return rep, True + else: + rep = collect_one_node(node) + self._collection_cache[node] = rep + return rep, False - # Directories of pkgs with dunder-init files. - pkg_roots: Dict[Path, "Package"] = {} + def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: + # This is a cache for the root directories of the initial paths. + # We can't use collection_cache for Session because of its special + # role as the bootstrapping collector. + path_cache: Dict[Path, Sequence[nodes.Collector]] = {} pm = self.config.pluginmanager @@ -749,108 +838,87 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: self.trace("processing argument", (argpath, names)) self.trace.root.indent += 1 - # Start with a Session root, and delve to argpath item (dir or file) - # and stack all Packages found on the way. - for parent in (argpath, *argpath.parents): - if not pm._is_in_confcutdir(argpath): - break - - if parent.is_dir(): - pkginit = parent / "__init__.py" - if pkginit.is_file() and parent not in node_cache1: - pkg = self._collectpackage(parent) - if pkg is not None: - pkg_roots[parent] = pkg - node_cache1[pkg.path] = [pkg] - - # If it's a directory argument, recurse and look for any Subpackages. - # Let the Package collector deal with subnodes, don't collect here. + # resolve_collection_argument() ensures this. if argpath.is_dir(): assert not names, f"invalid arg {(argpath, names)!r}" - if argpath in pkg_roots: - yield pkg_roots[argpath] - - for direntry in visit(argpath, self._recurse): - path = Path(direntry.path) - if direntry.is_dir() and self._recurse(direntry): - pkginit = path / "__init__.py" - if pkginit.is_file(): - pkg = self._collectpackage(path) - if pkg is not None: - yield pkg - pkg_roots[path] = pkg - - elif direntry.is_file(): - if path.parent in pkg_roots: - # Package handles this file. - continue - for x in self._collectfile(path): - key2 = (type(x), x.path) - if key2 in node_cache2: - yield node_cache2[key2] - else: - node_cache2[key2] = x - yield x - else: - assert argpath.is_file() + # Match the argpath from the root, e.g. + # /a/b/c.py -> [/, /a, /a/b, /a/b/c.py] + paths = [*reversed(argpath.parents), argpath] + # Paths outside of the confcutdir should not be considered, unless + # it's the argpath itself. + while len(paths) > 1 and not pm._is_in_confcutdir(paths[0]): + paths = paths[1:] + + # Start going over the parts from the root, collecting each level + # and discarding all nodes which don't match the level's part. + any_matched_in_initial_part = False + notfound_collectors = [] + work: List[ + Tuple[Union[nodes.Collector, nodes.Item], List[Union[Path, str]]] + ] = [(self, paths + names)] + while work: + matchnode, matchparts = work.pop() + + # Pop'd all of the parts, this is a match. + if not matchparts: + yield matchnode + any_matched_in_initial_part = True + continue - if argpath in node_cache1: - col = node_cache1[argpath] - else: - collect_root = pkg_roots.get(argpath.parent, self) - col = collect_root._collectfile(argpath, handle_dupes=False) - if col: - node_cache1[argpath] = col - - matching = [] - work: List[ - Tuple[Sequence[Union[nodes.Item, nodes.Collector]], Sequence[str]] - ] = [(col, names)] - while work: - self.trace("matchnodes", col, names) - self.trace.root.indent += 1 - - matchnodes, matchnames = work.pop() - for node in matchnodes: - if not matchnames: - matching.append(node) - continue - if not isinstance(node, nodes.Collector): - continue - key = (type(node), node.nodeid) - if key in matchnodes_cache: - rep = matchnodes_cache[key] - else: - rep = collect_one_node(node) - matchnodes_cache[key] = rep - if rep.passed: - submatchnodes = [] - for r in rep.result: - # TODO: Remove parametrized workaround once collection structure contains - # parametrization. - if ( - r.name == matchnames[0] - or r.name.split("[")[0] == matchnames[0] - ): - submatchnodes.append(r) - if submatchnodes: - work.append((submatchnodes, matchnames[1:])) - else: - # Report collection failures here to avoid failing to run some test - # specified in the command line because the module could not be - # imported (#134). - node.ihook.pytest_collectreport(report=rep) - - self.trace("matchnodes finished -> ", len(matching), "nodes") - self.trace.root.indent -= 1 - - if not matching: - report_arg = "::".join((str(argpath), *names)) - self._notfound.append((report_arg, col)) + # Should have been matched by now, discard. + if not isinstance(matchnode, nodes.Collector): continue - yield from matching + # Collect this level of matching. + # Collecting Session (self) is done directly to avoid endless + # recursion to this function. + subnodes: Sequence[Union[nodes.Collector, nodes.Item]] + if isinstance(matchnode, Session): + assert isinstance(matchparts[0], Path) + subnodes = matchnode._collect_path(matchparts[0], path_cache) + else: + # For backward compat, files given directly multiple + # times on the command line should not be deduplicated. + handle_dupes = not ( + len(matchparts) == 1 + and isinstance(matchparts[0], Path) + and matchparts[0].is_file() + ) + rep, duplicate = self._collect_one_node(matchnode, handle_dupes) + if not duplicate and not rep.passed: + # Report collection failures here to avoid failing to + # run some test specified in the command line because + # the module could not be imported (#134). + matchnode.ihook.pytest_collectreport(report=rep) + if not rep.passed: + continue + subnodes = rep.result + + # Prune this level. + any_matched_in_collector = False + for node in subnodes: + # Path part e.g. `/a/b/` in `/a/b/test_file.py::TestIt::test_it`. + if isinstance(matchparts[0], Path): + is_match = node.path == matchparts[0] + # Name part e.g. `TestIt` in `/a/b/test_file.py::TestIt::test_it`. + else: + # TODO: Remove parametrized workaround once collection structure contains + # parametrization. + is_match = ( + node.name == matchparts[0] + or node.name.split("[")[0] == matchparts[0] + ) + if is_match: + work.append((node, matchparts[1:])) + any_matched_in_collector = True + + if not any_matched_in_collector: + notfound_collectors.append(matchnode) + + if not any_matched_in_initial_part: + report_arg = "::".join((str(argpath), *names)) + self._notfound.append((report_arg, notfound_collectors)) self.trace.root.indent -= 1 @@ -863,11 +931,17 @@ def genitems( yield node else: assert isinstance(node, nodes.Collector) - rep = collect_one_node(node) + keepduplicates = self.config.getoption("keepduplicates") + # For backward compat, dedup only applies to files. + handle_dupes = not (keepduplicates and isinstance(node, nodes.File)) + rep, duplicate = self._collect_one_node(node, handle_dupes) + if duplicate and not keepduplicates: + return if rep.passed: for subnode in rep.result: yield from self.genitems(subnode) - node.ihook.pytest_collectreport(report=rep) + if not duplicate: + node.ihook.pytest_collectreport(report=rep) def search_pypath(module_name: str) -> str: diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index de46b4c8a75..3f97299ea70 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -152,12 +152,19 @@ class KeywordMatcher: def from_item(cls, item: "Item") -> "KeywordMatcher": mapped_names = set() - # Add the names of the current item and any parent items. + # Add the names of the current item and any parent items, + # except the Session and root Directory's which are not + # interesting for matching. import pytest for node in item.listchain(): - if not isinstance(node, pytest.Session): - mapped_names.add(node.name) + if isinstance(node, pytest.Session): + continue + if isinstance(node, pytest.Directory) and isinstance( + node.parent, pytest.Session + ): + continue + mapped_names.add(node.name) # Add the names added as extra keywords to current or parent items. mapped_names.update(item.listextrakeywords()) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 183f3c9d958..29efd56f49e 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -676,6 +676,24 @@ class File(FSCollector, abc.ABC): """ +class Directory(FSCollector, abc.ABC): + """Base class for collecting files from a directory. + + A basic directory collector does the following: goes over the files and + sub-directories in the directory and creates collectors for them by calling + the hooks :hook:`pytest_collect_directory` and :hook:`pytest_collect_file`, + after checking that they are not ignored using + :hook:`pytest_ignore_collect`. + + The default directory collectors are :class:`~pytest.Dir` and + :class:`~pytest.Package`. + + .. versionadded:: 8.0 + + :ref:`custom directory collectors`. + """ + + class Item(Node, abc.ABC): """Base class of all test invocation items. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index e39b3dc8eec..4cd635ed7e1 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -689,10 +689,14 @@ def resolve_package_path(path: Path) -> Optional[Path]: return result -def scandir(path: Union[str, "os.PathLike[str]"]) -> List["os.DirEntry[str]"]: +def scandir( + path: Union[str, "os.PathLike[str]"], + sort_key: Callable[["os.DirEntry[str]"], object] = lambda entry: entry.name, +) -> List["os.DirEntry[str]"]: """Scan a directory recursively, in breadth-first order. - The returned entries are sorted. + The returned entries are sorted according to the given key. + The default is to sort by name. """ entries = [] with os.scandir(path) as s: @@ -706,7 +710,7 @@ def scandir(path: Union[str, "os.PathLike[str]"]) -> List["os.DirEntry[str]"]: continue raise entries.append(entry) - entries.sort(key=lambda entry: entry.name) + entries.sort(key=sort_key) # type: ignore[arg-type] return entries diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 3dd3026fb50..09adb2b9c81 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -76,8 +76,7 @@ from _pytest.pathlib import fnmatch_ex from _pytest.pathlib import import_path from _pytest.pathlib import ImportPathMismatchError -from _pytest.pathlib import parts -from _pytest.pathlib import visit +from _pytest.pathlib import scandir from _pytest.scope import _ScopeName from _pytest.scope import Scope from _pytest.stash import StashKey @@ -204,6 +203,16 @@ def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]: return True +def pytest_collect_directory( + path: Path, parent: nodes.Collector +) -> Optional[nodes.Collector]: + pkginit = path / "__init__.py" + if pkginit.is_file(): + pkg: Package = Package.from_parent(parent, path=path) + return pkg + return None + + def pytest_collect_file(file_path: Path, parent: nodes.Collector) -> Optional["Module"]: if file_path.suffix == ".py": if not parent.session.isinitpath(file_path): @@ -659,9 +668,20 @@ def xunit_setup_function_fixture(request) -> Generator[None, None, None]: self.obj.__pytest_setup_function = xunit_setup_function_fixture -class Package(nodes.FSCollector): +class Package(nodes.Directory): """Collector for files and directories in a Python packages -- directories - with an `__init__.py` file.""" + with an `__init__.py` file. + + .. note:: + + Directories without an `__init__.py` file are instead collected by + :class:`~pytest.Dir` by default. Both are :class:`~pytest.Directory` + collectors. + + .. versionchanged:: 8.0 + + Now inherits from :class:`~pytest.Directory`. + """ def __init__( self, @@ -674,10 +694,9 @@ def __init__( path: Optional[Path] = None, ) -> None: # NOTE: Could be just the following, but kept as-is for compat. - # nodes.FSCollector.__init__(self, fspath, parent=parent) + # super().__init__(self, fspath, parent=parent) session = parent.session - nodes.FSCollector.__init__( - self, + super().__init__( fspath=fspath, path=path, parent=parent, @@ -685,7 +704,6 @@ def __init__( session=session, nodeid=nodeid, ) - self.name = self.path.name def setup(self) -> None: init_mod = importtestmodule(self.path / "__init__.py", self.config) @@ -705,66 +723,35 @@ def setup(self) -> None: func = partial(_call_with_optional_argument, teardown_module, init_mod) self.addfinalizer(func) - def _recurse(self, direntry: "os.DirEntry[str]") -> bool: - if direntry.name == "__pycache__": - return False - fspath = Path(direntry.path) - ihook = self.session.gethookproxy(fspath.parent) - if ihook.pytest_ignore_collect(collection_path=fspath, config=self.config): - return False - return True - - def _collectfile( - self, fspath: Path, handle_dupes: bool = True - ) -> Sequence[nodes.Collector]: - assert ( - fspath.is_file() - ), "{!r} is not a file (isdir={!r}, exists={!r}, islink={!r})".format( - fspath, fspath.is_dir(), fspath.exists(), fspath.is_symlink() - ) - ihook = self.session.gethookproxy(fspath) - if not self.session.isinitpath(fspath): - if ihook.pytest_ignore_collect(collection_path=fspath, config=self.config): - return () - - if handle_dupes: - keepduplicates = self.config.getoption("keepduplicates") - if not keepduplicates: - duplicate_paths = self.config.pluginmanager._duplicatepaths - if fspath in duplicate_paths: - return () - else: - duplicate_paths.add(fspath) - - return ihook.pytest_collect_file(file_path=fspath, parent=self) # type: ignore[no-any-return] - def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: - # Always collect the __init__ first. - yield from self._collectfile(self.path / "__init__.py") - - pkg_prefixes: Set[Path] = set() - for direntry in visit(self.path, recurse=self._recurse): - path = Path(direntry.path) - - # Already handled above. - if direntry.is_file(): - if direntry.name == "__init__.py" and path.parent == self.path: + # Always collect __init__.py first. + def sort_key(entry: "os.DirEntry[str]") -> object: + return (entry.name != "__init__.py", entry.name) + + config = self.config + col: Optional[nodes.Collector] + cols: Sequence[nodes.Collector] + for direntry in scandir(self.path, sort_key): + if direntry.is_dir(): + if direntry.name == "__pycache__": continue - - parts_ = parts(direntry.path) - if any( - str(pkg_prefix) in parts_ and pkg_prefix / "__init__.py" != path - for pkg_prefix in pkg_prefixes - ): - continue - - if direntry.is_file(): - yield from self._collectfile(path) - elif not direntry.is_dir(): - # Broken symlink or invalid/missing file. - continue - elif self._recurse(direntry) and path.joinpath("__init__.py").is_file(): - pkg_prefixes.add(path) + path = Path(direntry.path) + ihook = self.ihook + if not self.session.isinitpath(path, with_parents=True): + if ihook.pytest_ignore_collect(collection_path=path, config=config): + continue + col = ihook.pytest_collect_directory(path=path, parent=self) + if col is not None: + yield col + + elif direntry.is_file(): + path = Path(direntry.path) + ihook = self.ihook + if not self.session.isinitpath(path): + if ihook.pytest_ignore_collect(collection_path=path, config=config): + continue + cols = ihook.pytest_collect_file(file_path=path, parent=self) + yield from cols def _call_with_optional_argument(func, arg) -> None: diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 0aa496a2fa7..4e0c23ddbe7 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -30,6 +30,7 @@ from _pytest.legacypath import TempdirFactory from _pytest.legacypath import Testdir from _pytest.logging import LogCaptureFixture +from _pytest.main import Dir from _pytest.main import Session from _pytest.mark import Mark from _pytest.mark import MARK_GEN as mark @@ -38,6 +39,7 @@ from _pytest.mark import param from _pytest.monkeypatch import MonkeyPatch from _pytest.nodes import Collector +from _pytest.nodes import Directory from _pytest.nodes import File from _pytest.nodes import Item from _pytest.outcomes import exit @@ -98,6 +100,8 @@ "Config", "console_main", "deprecated_call", + "Dir", + "Directory", "DoctestItem", "exit", "ExceptionInfo", diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index d597311ae38..43390ab83ae 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -185,7 +185,8 @@ def test_not_collectable_arguments(self, pytester: Pytester) -> None: assert result.ret == ExitCode.USAGE_ERROR result.stderr.fnmatch_lines( [ - f"ERROR: found no collectors for {p2}", + f"ERROR: not found: {p2}", + "(no match in any of *)", "", ] ) @@ -238,7 +239,7 @@ def test_issue88_initial_file_multinodes(self, pytester: Pytester) -> None: pytester.copy_example("issue88_initial_file_multinodes") p = pytester.makepyfile("def test_hello(): pass") result = pytester.runpytest(p, "--collect-only") - result.stdout.fnmatch_lines(["*MyFile*test_issue88*", "*Module*test_issue88*"]) + result.stdout.fnmatch_lines(["*Module*test_issue88*", "*MyFile*test_issue88*"]) def test_issue93_initialnode_importing_capturing(self, pytester: Pytester) -> None: pytester.makeconftest( diff --git a/testing/example_scripts/customdirectory/conftest.py b/testing/example_scripts/customdirectory/conftest.py new file mode 100644 index 00000000000..5357014d7ab --- /dev/null +++ b/testing/example_scripts/customdirectory/conftest.py @@ -0,0 +1,22 @@ +# content of conftest.py +import json + +import pytest + + +class ManifestDirectory(pytest.Directory): + def collect(self): + manifest_path = self.path / "manifest.json" + manifest = json.loads(manifest_path.read_text(encoding="utf-8")) + ihook = self.ihook + for file in manifest["files"]: + yield from ihook.pytest_collect_file( + file_path=self.path / file, parent=self + ) + + +@pytest.hookimpl +def pytest_collect_directory(path, parent): + if path.joinpath("manifest.json").is_file(): + return ManifestDirectory.from_parent(parent=parent, path=path) + return None diff --git a/testing/example_scripts/customdirectory/pytest.ini b/testing/example_scripts/customdirectory/pytest.ini new file mode 100644 index 00000000000..e69de29bb2d diff --git a/testing/example_scripts/customdirectory/tests/manifest.json b/testing/example_scripts/customdirectory/tests/manifest.json new file mode 100644 index 00000000000..6ab6d0a5222 --- /dev/null +++ b/testing/example_scripts/customdirectory/tests/manifest.json @@ -0,0 +1,6 @@ +{ + "files": [ + "test_first.py", + "test_second.py" + ] +} diff --git a/testing/example_scripts/customdirectory/tests/test_first.py b/testing/example_scripts/customdirectory/tests/test_first.py new file mode 100644 index 00000000000..0a78de59945 --- /dev/null +++ b/testing/example_scripts/customdirectory/tests/test_first.py @@ -0,0 +1,3 @@ +# content of test_first.py +def test_1(): + pass diff --git a/testing/example_scripts/customdirectory/tests/test_second.py b/testing/example_scripts/customdirectory/tests/test_second.py new file mode 100644 index 00000000000..eed724a7d96 --- /dev/null +++ b/testing/example_scripts/customdirectory/tests/test_second.py @@ -0,0 +1,3 @@ +# content of test_second.py +def test_2(): + pass diff --git a/testing/example_scripts/customdirectory/tests/test_third.py b/testing/example_scripts/customdirectory/tests/test_third.py new file mode 100644 index 00000000000..61cf59dc16c --- /dev/null +++ b/testing/example_scripts/customdirectory/tests/test_third.py @@ -0,0 +1,3 @@ +# content of test_third.py +def test_3(): + pass diff --git a/testing/python/collect.py b/testing/python/collect.py index 309d7e6801a..da11dd34a9a 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1514,3 +1514,108 @@ def test_package_ordering(pytester: Pytester) -> None: # Execute from . result = pytester.runpytest("-v", "-s") result.assert_outcomes(passed=3) + + +def test_collection_hierarchy(pytester: Pytester) -> None: + """A general test checking that a filesystem hierarchy is collected as + expected in various scenarios. + + top/ + ├── aaa + │ ├── pkg + │ │ ├── __init__.py + │ │ └── test_pkg.py + │ └── test_aaa.py + ├── test_a.py + ├── test_b + │ ├── __init__.py + │ └── test_b.py + ├── test_c.py + └── zzz + ├── dir + │ └── test_dir.py + ├── __init__.py + └── test_zzz.py + """ + pytester.makepyfile( + **{ + "top/aaa/test_aaa.py": "def test_it(): pass", + "top/aaa/pkg/__init__.py": "", + "top/aaa/pkg/test_pkg.py": "def test_it(): pass", + "top/test_a.py": "def test_it(): pass", + "top/test_b/__init__.py": "", + "top/test_b/test_b.py": "def test_it(): pass", + "top/test_c.py": "def test_it(): pass", + "top/zzz/__init__.py": "", + "top/zzz/test_zzz.py": "def test_it(): pass", + "top/zzz/dir/test_dir.py": "def test_it(): pass", + } + ) + + full = [ + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ] + result = pytester.runpytest("--collect-only") + result.stdout.fnmatch_lines(full, consecutive=True) + result = pytester.runpytest("top", "--collect-only") + result.stdout.fnmatch_lines(full, consecutive=True) + result = pytester.runpytest("top", "top", "--collect-only") + result.stdout.fnmatch_lines(full, consecutive=True) + + result = pytester.runpytest( + "top/aaa", "top/aaa/pkg", "--collect-only", "--keep-duplicates" + ) + result.stdout.fnmatch_lines( + [ + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ], + consecutive=True, + ) + + result = pytester.runpytest( + "top/aaa/pkg", "top/aaa", "--collect-only", "--keep-duplicates" + ) + result.stdout.fnmatch_lines( + [ + "", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + ], + consecutive=True, + ) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index e93363a787e..9768c82ffa7 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1005,16 +1005,16 @@ def test3(arg1): result = pytester.runpytest("--collect-only") result.stdout.re_match_lines( [ - r" ", - r" ", - r" ", - r" ", - r" ", - r" ", - r" ", - r" ", - r" ", - r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", + r" ", ] ) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 4d751f8dbfc..c08c1cd8200 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1574,12 +1574,12 @@ def test_assertrepr_loaded_per_dir(pytester: Pytester) -> None: result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "*def test_base():*", - "*E*assert 1 == 2*", "*def test_a():*", "*E*assert summary a*", "*def test_b():*", "*E*assert summary b*", + "*def test_base():*", + "*E*assert 1 == 2*", ] ) @@ -1744,9 +1744,9 @@ def test_something(): ) result = pytester.runpytest("--collect-only") result.stdout.fnmatch_lines( - """ - - """ + [ + " ", + ] ) diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index e2e195ca7f5..21c1957cfeb 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -422,7 +422,7 @@ def test_fail(val): result = pytester.runpytest() result.stdout.fnmatch_lines(["*1 failed in*"]) - @pytest.mark.parametrize("parent", ("session", "package")) + @pytest.mark.parametrize("parent", ("directory", "package")) def test_terminal_report_lastfailed(self, pytester: Pytester, parent: str) -> None: if parent == "package": pytester.makepyfile( @@ -936,8 +936,10 @@ def test_lastfailed_with_known_failures_not_being_selected( "collected 1 item", "run-last-failure: rerun previous 1 failure (skipped 1 file)", "", - "", - " ", + "", + " ", + " ", + " ", ] ) @@ -966,8 +968,10 @@ def test_fail(): assert 0 "*collected 1 item", "run-last-failure: 1 known failures not in selected tests", "", - "", - " ", + "", + " ", + " ", + " ", ], consecutive=True, ) @@ -981,8 +985,10 @@ def test_fail(): assert 0 "collected 2 items / 1 deselected / 1 selected", "run-last-failure: rerun previous 1 failure", "", - "", - " ", + "", + " ", + " ", + " ", "*= 1/2 tests collected (1 deselected) in *", ], ) @@ -1011,10 +1017,12 @@ def test_other(): assert 0 "collected 3 items / 1 deselected / 2 selected", "run-last-failure: rerun previous 2 failures", "", - "", - " ", - " ", - " ", + "", + " ", + " ", + " ", + " ", + " ", "", "*= 2/3 tests collected (1 deselected) in *", ], @@ -1048,8 +1056,10 @@ def test_pass(): pass "collected 1 item", "run-last-failure: 1 known failures not in selected tests", "", - "", - " ", + "", + " ", + " ", + " ", "", "*= 1 test collected in*", ], diff --git a/testing/test_collection.py b/testing/test_collection.py index b2492f7f28f..deed4bda522 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -490,7 +490,7 @@ def test_collect_topdir(self, pytester: Pytester) -> None: # assert root2 == rcol, rootid colitems = rcol.perform_collect([rcol.nodeid], genitems=False) assert len(colitems) == 1 - assert colitems[0].path == p + assert colitems[0].path == topdir def get_reported_items(self, hookrec: HookRecorder) -> List[Item]: """Return pytest.Item instances reported by the pytest_collectreport hook""" @@ -568,12 +568,12 @@ def pytest_collect_file(file_path, parent): hookrec.assert_contains( [ ("pytest_collectstart", "collector.path == collector.session.path"), + ("pytest_collectstart", "collector.__class__.__name__ == 'Module'"), + ("pytest_pycollect_makeitem", "name == 'test_func'"), ( "pytest_collectstart", "collector.__class__.__name__ == 'SpecialFile'", ), - ("pytest_collectstart", "collector.__class__.__name__ == 'Module'"), - ("pytest_pycollect_makeitem", "name == 'test_func'"), ("pytest_collectreport", "report.nodeid.startswith(p.name)"), ] ) @@ -657,7 +657,8 @@ def test_global_file(self, pytester: Pytester) -> None: assert isinstance(col, pytest.Module) assert col.name == "x.py" assert col.parent is not None - assert col.parent.parent is None + assert col.parent.parent is not None + assert col.parent.parent.parent is None for parent in col.listchain(): assert parent.config is config @@ -937,6 +938,46 @@ def test_method(self): pass assert "baz" not in mod.keywords +class TestCollectDirectoryHook: + def test_custom_directory_example(self, pytester: Pytester) -> None: + """Verify the example from the customdirectory.rst doc.""" + pytester.copy_example("customdirectory") + + reprec = pytester.inline_run() + + reprec.assertoutcome(passed=2, failed=0) + calls = reprec.getcalls("pytest_collect_directory") + assert len(calls) == 2 + assert calls[0].path == pytester.path + assert isinstance(calls[0].parent, pytest.Session) + assert calls[1].path == pytester.path / "tests" + assert isinstance(calls[1].parent, pytest.Dir) + + def test_directory_ignored_if_none(self, pytester: Pytester) -> None: + """If the (entire) hook returns None, it's OK, the directory is ignored.""" + pytester.makeconftest( + """ + import pytest + + @pytest.hookimpl(wrapper=True) + def pytest_collect_directory(): + yield + return None + """, + ) + pytester.makepyfile( + **{ + "tests/test_it.py": """ + import pytest + + def test_it(): pass + """, + }, + ) + reprec = pytester.inline_run() + reprec.assertoutcome(passed=0, failed=0) + + COLLECTION_ERROR_PY_FILES = dict( test_01_failure=""" def test_1(): @@ -1098,22 +1139,24 @@ def test_collect_init_tests(pytester: Pytester) -> None: result.stdout.fnmatch_lines( [ "collected 2 items", - "", - " ", - " ", - " ", - " ", + "", + " ", + " ", + " ", + " ", + " ", ] ) result = pytester.runpytest("./tests", "--collect-only") result.stdout.fnmatch_lines( [ "collected 2 items", - "", - " ", - " ", - " ", - " ", + "", + " ", + " ", + " ", + " ", + " ", ] ) # Ignores duplicates with "." and pkginit (#4310). @@ -1121,11 +1164,12 @@ def test_collect_init_tests(pytester: Pytester) -> None: result.stdout.fnmatch_lines( [ "collected 2 items", - "", - " ", - " ", - " ", - " ", + "", + " ", + " ", + " ", + " ", + " ", ] ) # Same as before, but different order. @@ -1133,21 +1177,32 @@ def test_collect_init_tests(pytester: Pytester) -> None: result.stdout.fnmatch_lines( [ "collected 2 items", - "", - " ", - " ", - " ", - " ", + "", + " ", + " ", + " ", + " ", + " ", ] ) result = pytester.runpytest("./tests/test_foo.py", "--collect-only") result.stdout.fnmatch_lines( - ["", " ", " "] + [ + "", + " ", + " ", + " ", + ] ) result.stdout.no_fnmatch_line("*test_init*") result = pytester.runpytest("./tests/__init__.py", "--collect-only") result.stdout.fnmatch_lines( - ["", " ", " "] + [ + "", + " ", + " ", + " ", + ] ) result.stdout.no_fnmatch_line("*test_foo*") diff --git a/testing/test_config.py b/testing/test_config.py index 900cccee80b..18022977ca3 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1966,7 +1966,8 @@ def test_config_blocked_default_plugins(pytester: Pytester, plugin: str) -> None assert result.ret == ExitCode.USAGE_ERROR result.stderr.fnmatch_lines( [ - "ERROR: found no collectors for */test_config_blocked_default_plugins.py", + "ERROR: not found: */test_config_blocked_default_plugins.py", + "(no match in any of **", ] ) return diff --git a/testing/test_mark.py b/testing/test_mark.py index 7415b393ef2..609f73d68eb 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -871,17 +871,30 @@ def test_one(): assert 1 deselected_tests = dlist[0].items assert len(deselected_tests) == 1 - def test_no_match_directories_outside_the_suite(self, pytester: Pytester) -> None: + def test_no_match_directories_outside_the_suite( + self, + pytester: Pytester, + monkeypatch: pytest.MonkeyPatch, + ) -> None: """`-k` should not match against directories containing the test suite (#7040).""" - test_contents = """ - def test_aaa(): pass - def test_ddd(): pass - """ + pytester.makefile( + **{ + "suite/pytest": """[pytest]""", + }, + ext=".ini", + ) pytester.makepyfile( - **{"ddd/tests/__init__.py": "", "ddd/tests/test_foo.py": test_contents} + **{ + "suite/ddd/tests/__init__.py": "", + "suite/ddd/tests/test_foo.py": """ + def test_aaa(): pass + def test_ddd(): pass + """, + } ) + monkeypatch.chdir(pytester.path / "suite") - def get_collected_names(*args): + def get_collected_names(*args: str) -> List[str]: _, rec = pytester.inline_genitems(*args) calls = rec.getcalls("pytest_collection_finish") assert len(calls) == 1 @@ -893,12 +906,6 @@ def get_collected_names(*args): # do not collect anything based on names outside the collection tree assert get_collected_names("-k", pytester._name) == [] - # "-k ddd" should only collect "test_ddd", but not - # 'test_aaa' just because one of its parent directories is named "ddd"; - # this was matched previously because Package.name would contain the full path - # to the package - assert get_collected_names("-k", "ddd") == ["test_ddd"] - class TestMarkDecorator: @pytest.mark.parametrize( diff --git a/testing/test_reports.py b/testing/test_reports.py index 387d2e807ce..627ea1ed24f 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -304,9 +304,9 @@ def test_a(): report = reports[1] else: assert report_class is CollectReport - # two collection reports: session and test file + # three collection reports: session, test file, directory reports = reprec.getreports("pytest_collectreport") - assert len(reports) == 2 + assert len(reports) == 3 report = reports[1] def check_longrepr(longrepr: ExceptionChainRepr) -> None: @@ -471,7 +471,7 @@ def test_b(): pass ) reprec = pytester.inline_run() reports = reprec.getreports("pytest_collectreport") - assert len(reports) == 2 + assert len(reports) == 3 for rep in reports: data = pytestconfig.hook.pytest_report_to_serializable( config=pytestconfig, report=rep diff --git a/testing/test_runner.py b/testing/test_runner.py index cab631ee12e..c8b646857e7 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1006,7 +1006,7 @@ def test_longreprtext_collect_skip(self, pytester: Pytester) -> None: ) rec = pytester.inline_run() calls = rec.getcalls("pytest_collectreport") - _, call = calls + _, call, _ = calls assert isinstance(call.report.longrepr, tuple) assert "Skipped" in call.report.longreprtext diff --git a/testing/test_session.py b/testing/test_session.py index 48dc08e8c8f..136e85eb640 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -172,8 +172,9 @@ def test_one(): pass except pytest.skip.Exception: # pragma: no cover pytest.fail("wrong skipped caught") reports = reprec.getreports("pytest_collectreport") - assert len(reports) == 1 - assert reports[0].skipped + # Session, Dir + assert len(reports) == 2 + assert reports[1].skipped class TestNewSession(SessionTests): @@ -357,9 +358,10 @@ def test_2(): pass ) result.stdout.fnmatch_lines( [ - "", - " ", - " ", + " ", + " ", + " ", + " ", ], consecutive=True, ) @@ -373,11 +375,12 @@ def test_2(): pass ) result.stdout.fnmatch_lines( [ - "", - " ", - " ", - " ", - " ", + " ", + " ", + " ", + " ", + " ", + " ", ], consecutive=True, ) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 264ab96d8d0..12c80f9b8b8 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -451,7 +451,11 @@ def test_func(): ) result = pytester.runpytest("--collect-only") result.stdout.fnmatch_lines( - ["", " "] + [ + "", + " ", + " ", + ] ) def test_collectonly_skipped_module(self, pytester: Pytester) -> None: @@ -480,14 +484,15 @@ def test_with_description(): result = pytester.runpytest("--collect-only", "--verbose") result.stdout.fnmatch_lines( [ - "", - " ", - "", - " ", - " This test has a description.", - " ", - " more1.", - " more2.", + "", + " ", + " ", + " ", + " ", + " This test has a description.", + " ", + " more1.", + " more2.", ], consecutive=True, ) @@ -2001,9 +2006,9 @@ def test_normal_verbosity(self, pytester: Pytester, test_files) -> None: result = pytester.runpytest("-o", "console_output_style=classic") result.stdout.fnmatch_lines( [ + f"sub{os.sep}test_three.py .F.", "test_one.py .", "test_two.py F", - f"sub{os.sep}test_three.py .F.", "*2 failed, 3 passed in*", ] ) @@ -2012,18 +2017,18 @@ def test_verbose(self, pytester: Pytester, test_files) -> None: result = pytester.runpytest("-o", "console_output_style=classic", "-v") result.stdout.fnmatch_lines( [ - "test_one.py::test_one PASSED", - "test_two.py::test_two FAILED", f"sub{os.sep}test_three.py::test_three_1 PASSED", f"sub{os.sep}test_three.py::test_three_2 FAILED", f"sub{os.sep}test_three.py::test_three_3 PASSED", + "test_one.py::test_one PASSED", + "test_two.py::test_two FAILED", "*2 failed, 3 passed in*", ] ) def test_quiet(self, pytester: Pytester, test_files) -> None: result = pytester.runpytest("-o", "console_output_style=classic", "-q") - result.stdout.fnmatch_lines([".F.F.", "*2 failed, 3 passed in*"]) + result.stdout.fnmatch_lines([".F..F", "*2 failed, 3 passed in*"]) class TestProgressOutputStyle: From e1c66ab0ad8eda13e5552dfc939e07d7290ecd39 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 5 Dec 2023 23:07:06 +0200 Subject: [PATCH 0302/1271] Different fix for conftest loading --- Current main In current main (before pervious commit), calls to gethookproxy/ihook are the trigger for loading non-initial conftests. This basically means that conftest loading is done almost as a random side-effect, uncontrolled and very non-obvious. And it also dashes any hope of making gethookproxy faster (gethookproxy shows up prominently in pytest profiles). I've wanted to improve this for a while, #11268 was the latest step towards that. --- PR before change In this PR, I ran into a problem. Previously, Session and Package did all of the directory traversals inside of their collect, which loaded the conftests as a side effect. If the conftest loading failed, it will occur inside of the collect() and cause it to be reported as a failure. Now I've changed things such that Session.collect and Package.collect no longer recurse, but just collect their immediate descendants, and genitems does the recursive expansion work. The problem though is that genitems() doesn't run inside of specific collector's collect context. So when it loads a conftest, and the conftest loading fails, the exception isn't handled by any CollectReport and causes an internal error instead. The way I've fixed this problem is by loading the conftests eagerly in a pytest_collect_directory post-wrapper, but only during genitems to make sure the directory is actually selected. This solution in turn caused the conftests to be collected too early; specifically, the plugins are loaded during the parent's collect(), one after the other as the directory entries are collected. So when the ihook is hoisted out of the loop, new plugins are loaded inside the loop, and due to the way the hook proxy works, they are added to the ihook even though they're supposed to be scoped to the child collectors. So no hoisting. --- PR after change Now I've come up with a better solution: since now the collection tree actually reflects the filesystem tree, what we really want is to load the conftest of a directory right before we run its collect(). A conftest can affect a directory's collect() (e.g. with a pytest_ignore_collect hookimpl), but it cannot affect how the directory node itself is collected. So I just moved the conftest loading to be done right before calling collect, but still inside the CollectReport context. This allows the hoisting, and also removes conftest loading from gethookproxy since it's no longer necessary. And it will probably enable further cleanups. So I'm happy with it. --- src/_pytest/main.py | 40 +--------------------------------------- src/_pytest/python.py | 3 +-- src/_pytest/runner.py | 19 ++++++++++++++++++- 3 files changed, 20 insertions(+), 42 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index e4ca05aac95..3672df05a01 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -12,7 +12,6 @@ from typing import Dict from typing import final from typing import FrozenSet -from typing import Generator from typing import Iterable from typing import Iterator from typing import List @@ -502,11 +501,11 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: config = self.config col: Optional[nodes.Collector] cols: Sequence[nodes.Collector] + ihook = self.ihook for direntry in scandir(self.path): if direntry.is_dir(): if direntry.name == "__pycache__": continue - ihook = self.ihook path = Path(direntry.path) if not self.session.isinitpath(path, with_parents=True): if ihook.pytest_ignore_collect(collection_path=path, config=config): @@ -516,7 +515,6 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: yield col elif direntry.is_file(): - ihook = self.ihook path = Path(direntry.path) if not self.session.isinitpath(path): if ihook.pytest_ignore_collect(collection_path=path, config=config): @@ -559,7 +557,6 @@ def __init__(self, config: Config) -> None: self._initialpaths_with_parents: FrozenSet[Path] = frozenset() self._notfound: List[Tuple[str, Sequence[nodes.Collector]]] = [] self._initial_parts: List[Tuple[Path, List[str]]] = [] - self._in_genitems = False self._collection_cache: Dict[nodes.Collector, CollectReport] = {} self.items: List[nodes.Item] = [] @@ -612,29 +609,6 @@ def pytest_runtest_logreport( pytest_collectreport = pytest_runtest_logreport - @hookimpl(wrapper=True) - def pytest_collect_directory( - self, - ) -> Generator[None, Optional[nodes.Collector], Optional[nodes.Collector]]: - col = yield - - # Eagerly load conftests for the directory. - # This is needed because a conftest error needs to happen while - # collecting a collector, so it is caught by its CollectReport. - # Without this, the conftests are loaded inside of genitems itself - # which leads to an internal error. - # This should only be done for genitems; if done unconditionally, it - # will load conftests for non-selected directories which is to be - # avoided. - if self._in_genitems and col is not None: - self.config.pluginmanager._loadconftestmodules( - col.path, - self.config.getoption("importmode"), - rootpath=self.config.rootpath, - ) - - return col - def isinitpath( self, path: Union[str, "os.PathLike[str]"], @@ -665,15 +639,6 @@ def gethookproxy(self, fspath: "os.PathLike[str]") -> pluggy.HookRelay: pm = self.config.pluginmanager # Check if we have the common case of running # hooks with all conftest.py files. - # - # TODO: pytest relies on this call to load non-initial conftests. This - # is incidental. It will be better to load conftests at a more - # well-defined place. - pm._loadconftestmodules( - path, - self.config.getoption("importmode"), - rootpath=self.config.rootpath, - ) my_conftestmodules = pm._getconftestmodules(path) remove_mods = pm._conftest_plugins.difference(my_conftestmodules) proxy: pluggy.HookRelay @@ -754,7 +719,6 @@ def perform_collect( # noqa: F811 self._notfound = [] self._initial_parts = [] - self._in_genitems = False self._collection_cache = {} self.items = [] items: Sequence[Union[nodes.Item, nodes.Collector]] = self.items @@ -789,7 +753,6 @@ def perform_collect( # noqa: F811 raise UsageError(*errors) - self._in_genitems = True if not genitems: items = rep.result else: @@ -804,7 +767,6 @@ def perform_collect( # noqa: F811 finally: self._notfound = [] self._initial_parts = [] - self._in_genitems = False self._collection_cache = {} hook.pytest_collection_finish(session=self) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 09adb2b9c81..e0f7a447a61 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -731,12 +731,12 @@ def sort_key(entry: "os.DirEntry[str]") -> object: config = self.config col: Optional[nodes.Collector] cols: Sequence[nodes.Collector] + ihook = self.ihook for direntry in scandir(self.path, sort_key): if direntry.is_dir(): if direntry.name == "__pycache__": continue path = Path(direntry.path) - ihook = self.ihook if not self.session.isinitpath(path, with_parents=True): if ihook.pytest_ignore_collect(collection_path=path, config=config): continue @@ -746,7 +746,6 @@ def sort_key(entry: "os.DirEntry[str]") -> object: elif direntry.is_file(): path = Path(direntry.path) - ihook = self.ihook if not self.session.isinitpath(path): if ihook.pytest_ignore_collect(collection_path=path, config=config): continue diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 1b39f93cf13..dcfc6b7d0e2 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -28,6 +28,7 @@ from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest from _pytest.nodes import Collector +from _pytest.nodes import Directory from _pytest.nodes import Item from _pytest.nodes import Node from _pytest.outcomes import Exit @@ -368,7 +369,23 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> TestReport: def pytest_make_collect_report(collector: Collector) -> CollectReport: - call = CallInfo.from_call(lambda: list(collector.collect()), "collect") + def collect() -> List[Union[Item, Collector]]: + # Before collecting, if this is a Directory, load the conftests. + # If a conftest import fails to load, it is considered a collection + # error of the Directory collector. This is why it's done inside of the + # CallInfo wrapper. + # + # Note: initial conftests are loaded early, not here. + if isinstance(collector, Directory): + collector.config.pluginmanager._loadconftestmodules( + collector.path, + collector.config.getoption("importmode"), + rootpath=collector.config.rootpath, + ) + + return list(collector.collect()) + + call = CallInfo.from_call(collect, "collect") longrepr: Union[None, Tuple[str, int, str], str, TerminalRepr] = None if not call.excinfo: outcome: Literal["passed", "skipped", "failed"] = "passed" From ef8bf82a780c6a1ca69eae6dbc2cc251f1f59506 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:24:52 +0100 Subject: [PATCH 0303/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#11693) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.1 to 0.23.2. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.1...v0.23.2) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 1166d14c9a5..f65ed3c7f0d 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.1.0 django==4.2.7 -pytest-asyncio==0.23.1 +pytest-asyncio==0.23.2 pytest-bdd==7.0.1 pytest-cov==4.1.0 pytest-django==4.7.0 From 8ce76c307e8e2a99ba6664dd95f8f37e0fc3bd8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:28:50 +0100 Subject: [PATCH 0304/1271] build(deps): Bump actions/stale from 8 to 9 (#11691) Bumps [actions/stale](https://github.com/actions/stale) from 8 to 9. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v8...v9) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3f8ca186f0e..3f83839cd02 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,7 @@ jobs: permissions: issues: write steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: debug-only: false days-before-issue-stale: 14 From ab307b3402cf37e06123d5ff2758369f5cbada27 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 09:46:13 +0100 Subject: [PATCH 0305/1271] build(deps): Bump actions/setup-python from 4 to 5 (#11690) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/prepare-release-pr.yml | 2 +- .github/workflows/test.yml | 2 +- .github/workflows/update-plugin-list.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e1b95efa719..ca65662c128 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -73,7 +73,7 @@ jobs: persist-credentials: false - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.11" diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index ce8130c86a2..1bb23fab844 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -32,7 +32,7 @@ jobs: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.8" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5f5832475d3..9f8e4eacbde 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -179,7 +179,7 @@ jobs: path: dist - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} check-latest: ${{ endsWith(matrix.python, '-dev') }} diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index ff148e10891..349d5f52977 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -25,7 +25,7 @@ jobs: fetch-depth: 0 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.11" cache: pip From dfc910ee90cbe70d8d8b079190fa75ca2a5ef067 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:18:43 +0000 Subject: [PATCH 0306/1271] build(deps): Bump django from 4.2.7 to 5.0 in /testing/plugins_integration (#11692) * build(deps): Bump django in /testing/plugins_integration Bumps [django](https://github.com/django/django) from 4.2.7 to 5.0. - [Commits](https://github.com/django/django/compare/4.2.7...5.0) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Bump python version on the plugin job https://github.com/pytest-dev/pytest/pull/11692#issuecomment-1849963332 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas --- .github/workflows/test.yml | 2 +- testing/plugins_integration/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9f8e4eacbde..9fbd273bcfa 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -156,7 +156,7 @@ jobs: tox_env: "py312-xdist" - name: "plugins" - python: "3.9" + python: "3.12" os: ubuntu-latest tox_env: "plugins" diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index f65ed3c7f0d..9e5955d6afa 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.1.0 -django==4.2.7 +django==5.0 pytest-asyncio==0.23.2 pytest-bdd==7.0.1 pytest-cov==4.1.0 From 2b86d2bddc3eda0a1b342ddb7d7d3aed7b29501f Mon Sep 17 00:00:00 2001 From: Tom Mortimer-Jones Date: Wed, 13 Dec 2023 12:24:43 +0000 Subject: [PATCH 0307/1271] Typo in fixtures.rst (#11699) --- doc/en/reference/fixtures.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/reference/fixtures.rst b/doc/en/reference/fixtures.rst index 078933de663..8ba59395e3e 100644 --- a/doc/en/reference/fixtures.rst +++ b/doc/en/reference/fixtures.rst @@ -93,7 +93,7 @@ Fixture availability is determined from the perspective of the test. A fixture is only available for tests to request if they are in the scope that fixture is defined in. If a fixture is defined inside a class, it can only be requested by tests inside that class. But if a fixture is defined inside the global scope of -the module, than every test in that module, even if it's defined inside a class, +the module, then every test in that module, even if it's defined inside a class, can request it. Similarly, a test can also only be affected by an autouse fixture if that test From 047ba83dabe492af938104fe0058597f67a672be Mon Sep 17 00:00:00 2001 From: Arthur Richard Date: Thu, 14 Dec 2023 12:14:36 +0100 Subject: [PATCH 0308/1271] Improve pytest.exit docs (#11698) Fixes #11695 --- AUTHORS | 1 + doc/en/reference/reference.rst | 2 +- src/_pytest/outcomes.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 669ec537e56..bb273edcc30 100644 --- a/AUTHORS +++ b/AUTHORS @@ -48,6 +48,7 @@ Ariel Pillemer Armin Rigo Aron Coyle Aron Curzon +Arthur Richard Ashish Kurmi Aviral Verma Aviv Palivoda diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index d6f942ad0e2..3054109ba50 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -79,7 +79,7 @@ pytest.xfail pytest.exit ~~~~~~~~~~~ -.. autofunction:: pytest.exit(reason, [returncode=False, msg=None]) +.. autofunction:: pytest.exit(reason, [returncode=None, msg=None]) pytest.main ~~~~~~~~~~~ diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index a8984c5b97b..0f64f91d9ff 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -112,7 +112,7 @@ def exit( only because `msg` is deprecated. :param returncode: - Return code to be used when exiting pytest. + Return code to be used when exiting pytest. None means the same as ``0`` (no error), same as :func:`sys.exit`. :param msg: Same as ``reason``, but deprecated. Will be removed in a future version, use ``reason`` instead. From 27f7cee23876dc3eb77a60dcc768d65ccc3020e8 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 17 Dec 2023 00:20:43 +0000 Subject: [PATCH 0309/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 94 +++++++++++++++++--------------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index dea19eae694..8317af7ca49 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.0.1) - :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Sep 06, 2023 5 - Production/Stable pytest + :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Dec 12, 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 27, 2023 4 - Beta pytest >=4.6 @@ -252,7 +252,7 @@ This list contains 1354 plugins. :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Nov 14, 2023 3 - Alpha pytest - :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 08, 2023 4 - Beta pytest>=7.3.2 + :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A :pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6) @@ -328,7 +328,7 @@ This list contains 1354 plugins. :pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A :pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all' :pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0) - :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 05, 2023 4 - Beta pytest>=7.3.2 + :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 @@ -377,9 +377,9 @@ This list contains 1354 plugins. :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Aug 11, 2023 3 - Alpha pytest >=4.6 + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Dec 13, 2023 5 - Production/Stable 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 Dec 05, 2023 N/A N/A + :pypi:`pytest-dogu-sdk` pytest plugin for the Dogu Dec 14, 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) @@ -527,7 +527,7 @@ This list contains 1354 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 28, 2023 4 - Beta pytest >=6.0.0 + :pypi:`pytest-fzf` fzf-based test selector for pytest Dec 15, 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 @@ -536,7 +536,7 @@ This list contains 1354 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Dec 05, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Dec 14, 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 @@ -574,10 +574,10 @@ This list contains 1354 plugins. :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 Dec 09, 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 15, 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` Dec 01, 2023 N/A N/A + :pypi:`pytest-hot-reloading` Dec 13, 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) @@ -594,7 +594,7 @@ This list contains 1354 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Nov 03, 2023 3 - Alpha pytest >=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Dec 09, 2023 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A @@ -604,11 +604,11 @@ This list contains 1354 plugins. :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Aug 31, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Dec 15, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A - :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Jun 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Dec 13, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A :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 @@ -622,8 +622,8 @@ This list contains 1354 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. 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` A py.test plugin providing fixtures to simplify inmanta modules testing. Dec 13, 2023 5 - Production/Stable pytest + :pypi:`pytest-inmanta-extensions` Inmanta tests package Dec 11, 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 @@ -833,7 +833,7 @@ This list contains 1354 plugins. :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 May 16, 2023 N/A N/A :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" - :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 05, 2023 4 - Beta N/A + :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 11, 2023 4 - Beta N/A :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Oct 01, 2023 N/A pytest @@ -1028,7 +1028,7 @@ This list contains 1354 plugins. :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 Nov 22, 2023 N/A pytest ~=4.6 ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Dec 11, 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 @@ -1091,7 +1091,7 @@ This list contains 1354 plugins. :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Oct 31, 2023 3 - Alpha pytest >=6.2 + :pypi:`pytest-servers` pytest servers Dec 15, 2023 3 - Alpha pytest >=6.2 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1156,7 +1156,7 @@ This list contains 1354 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 Nov 25, 2023 N/A pytest (>5.4.0,<8) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Dec 14, 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 @@ -1205,7 +1205,7 @@ This list contains 1354 plugins. :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) - :pypi:`pytest-tcp` A Pytest plugin for test prioritization Dec 04, 2023 4 - Beta pytest >=7.4.3 + :pypi:`pytest-tcp` A Pytest plugin for test prioritization Dec 10, 2023 4 - Beta pytest >=7.4.3 :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A @@ -1255,6 +1255,7 @@ This list contains 1354 plugins. :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest + :pypi:`pytest-timeassert-ethan` execution duration Dec 12, 2023 N/A pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A :pypi:`pytest-timeout` pytest plugin to abort hanging tests Oct 08, 2023 5 - Production/Stable pytest >=5.0.0 :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A @@ -1324,7 +1325,7 @@ This list contains 1354 plugins. :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 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-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Dec 12, 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 @@ -1758,7 +1759,7 @@ This list contains 1354 plugins. A plugin to use approvaltests with pytest :pypi:`pytest-approvaltests-geo` - *last release*: Sep 06, 2023, + *last release*: Dec 12, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -2920,7 +2921,7 @@ This list contains 1354 plugins. The pytest plugin for your copier templates 📒 :pypi:`pytest-copier` - *last release*: Dec 08, 2023, + *last release*: Dec 11, 2023, *status*: 4 - Beta, *requires*: pytest>=7.3.2 @@ -3452,7 +3453,7 @@ This list contains 1354 plugins. PyTest plugin for generating Difido reports :pypi:`pytest-dir-equal` - *last release*: Dec 05, 2023, + *last release*: Dec 11, 2023, *status*: 4 - Beta, *requires*: pytest>=7.3.2 @@ -3795,8 +3796,8 @@ This list contains 1354 plugins. A simple pytest plugin to import names and add them to the doctest namespace. :pypi:`pytest-doctestplus` - *last release*: Aug 11, 2023, - *status*: 3 - Alpha, + *last release*: Dec 13, 2023, + *status*: 5 - Production/Stable, *requires*: pytest >=4.6 Pytest plugin with advanced doctest features. @@ -3809,7 +3810,7 @@ This list contains 1354 plugins. pytest plugin for dogu report :pypi:`pytest-dogu-sdk` - *last release*: Dec 05, 2023, + *last release*: Dec 14, 2023, *status*: N/A, *requires*: N/A @@ -4845,7 +4846,7 @@ This list contains 1354 plugins. :pypi:`pytest-fzf` - *last release*: Nov 28, 2023, + *last release*: Dec 15, 2023, *status*: 4 - Beta, *requires*: pytest >=6.0.0 @@ -4908,7 +4909,7 @@ This list contains 1354 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Dec 05, 2023, + *last release*: Dec 14, 2023, *status*: N/A, *requires*: N/A @@ -5174,7 +5175,7 @@ This list contains 1354 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Dec 09, 2023, + *last release*: Dec 15, 2023, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5195,7 +5196,7 @@ This list contains 1354 plugins. Report on tests that honor constraints, and guard against regressions :pypi:`pytest-hot-reloading` - *last release*: Dec 01, 2023, + *last release*: Dec 13, 2023, *status*: N/A, *requires*: N/A @@ -5314,7 +5315,7 @@ This list contains 1354 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Nov 03, 2023, + *last release*: Dec 09, 2023, *status*: 3 - Alpha, *requires*: pytest >=7.0.0 @@ -5384,7 +5385,7 @@ This list contains 1354 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Aug 31, 2023, + *last release*: Dec 15, 2023, *status*: 3 - Alpha, *requires*: pytest (>=7.0.0,<8.0.0) @@ -5412,7 +5413,7 @@ This list contains 1354 plugins. A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api :pypi:`pytest-idem` - *last release*: Jun 23, 2023, + *last release*: Dec 13, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -5510,14 +5511,14 @@ This list contains 1354 plugins. A pytest plugin for writing inline tests. :pypi:`pytest-inmanta` - *last release*: Nov 29, 2023, + *last release*: Dec 13, 2023, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Oct 13, 2023, + *last release*: Dec 11, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -6987,7 +6988,7 @@ This list contains 1354 plugins. Use @pytest.mark.only to run a single test :pypi:`pytest-oof` - *last release*: Dec 05, 2023, + *last release*: Dec 11, 2023, *status*: 4 - Beta, *requires*: N/A @@ -8352,7 +8353,7 @@ This list contains 1354 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Nov 22, 2023, + *last release*: Dec 11, 2023, *status*: N/A, *requires*: pytest ~=4.6 ; python_version == "2.7" @@ -8793,7 +8794,7 @@ This list contains 1354 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Oct 31, 2023, + *last release*: Dec 15, 2023, *status*: 3 - Alpha, *requires*: pytest >=6.2 @@ -9248,7 +9249,7 @@ This list contains 1354 plugins. :pypi:`pytest-splunk-addon` - *last release*: Nov 25, 2023, + *last release*: Dec 14, 2023, *status*: N/A, *requires*: pytest (>5.4.0,<8) @@ -9591,7 +9592,7 @@ This list contains 1354 plugins. tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used :pypi:`pytest-tcp` - *last release*: Dec 04, 2023, + *last release*: Dec 10, 2023, *status*: 4 - Beta, *requires*: pytest >=7.4.3 @@ -9940,6 +9941,13 @@ This list contains 1354 plugins. + :pypi:`pytest-timeassert-ethan` + *last release*: Dec 12, 2023, + *status*: N/A, + *requires*: pytest + + execution duration + :pypi:`pytest-timeit` *last release*: Oct 13, 2016, *status*: 4 - Beta, @@ -10424,7 +10432,7 @@ This list contains 1354 plugins. py.test fixture for creating a virtual environment :pypi:`pytest-ver` - *last release*: Nov 23, 2023, + *last release*: Dec 12, 2023, *status*: 4 - Beta, *requires*: pytest From 7541c5a999e17d7c5841a94fcc522f486c5179cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 06:33:59 +0100 Subject: [PATCH 0310/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#11717) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 4.1.0 to 4.2.0. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.1.0...4.2.0) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 9e5955d6afa..dfdeeb7a8fc 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==4.1.0 +anyio[curio,trio]==4.2.0 django==5.0 pytest-asyncio==0.23.2 pytest-bdd==7.0.1 From 03b24e5b306e4f43edd4b1162a0bd7f94e5ae8fd Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Sun, 3 Dec 2023 13:23:42 +0000 Subject: [PATCH 0311/1271] pprint: Remove the `format` method, it's not used outside of pprint Let's reduce the API surface for the bundled PrettyPrinter to what we really need and use --- src/_pytest/_io/pprint.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index ad1238709f4..7b45ae95f05 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -486,12 +486,7 @@ def _format_items( write("\n" + " " * indent) def _repr(self, object: Any, context: Set[int], level: int) -> str: - return self.format(object, context.copy(), self._depth, level) - - def format( - self, object: Any, context: Set[int], maxlevels: Optional[int], level: int - ) -> str: - return self._safe_repr(object, context, maxlevels, level) + return self._safe_repr(object, context.copy(), self._depth, level) def _pprint_default_dict( self, @@ -639,8 +634,8 @@ def _safe_repr( else: items = object.items() for k, v in items: - krepr = self.format(k, context, maxlevels, level) - vrepr = self.format(v, context, maxlevels, level) + krepr = self._safe_repr(k, context, maxlevels, level) + vrepr = self._safe_repr(v, context, maxlevels, level) append(f"{krepr}: {vrepr}") context.remove(objid) return "{%s}" % ", ".join(components) @@ -668,7 +663,7 @@ def _safe_repr( append = components.append level += 1 for o in object: - orepr = self.format(o, context, maxlevels, level) + orepr = self._safe_repr(o, context, maxlevels, level) append(orepr) context.remove(objid) return format % ", ".join(components) From 6aa35f772fd62ad6c5dd9f761974ab44cd224d58 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Sun, 3 Dec 2023 13:48:12 +0000 Subject: [PATCH 0312/1271] pprint: Remove the option to sort dictionaries, we always do it --- src/_pytest/_io/pprint.py | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 7b45ae95f05..4512d39370c 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -65,7 +65,6 @@ def __init__( width: int = 80, depth: Optional[int] = None, *, - sort_dicts: bool = True, underscore_numbers: bool = False, ) -> None: """Handle pretty printing operations onto a stream using a set of @@ -80,9 +79,6 @@ def __init__( depth The maximum depth to print out nested structures. - sort_dicts - If true, dict keys are sorted. - """ indent = int(indent) width = int(width) @@ -95,7 +91,6 @@ def __init__( self._depth = depth self._indent_per_level = indent self._width = width - self._sort_dicts = sort_dicts self._underscore_numbers = underscore_numbers def pformat(self, object: Any) -> str: @@ -174,10 +169,7 @@ def _pprint_dict( ) -> None: write = stream.write write("{") - if self._sort_dicts: - items = sorted(object.items(), key=_safe_tuple) - else: - items = object.items() + items = sorted(object.items(), key=_safe_tuple) self._format_dict_items(items, stream, indent, allowance, context, level) write("}") @@ -629,11 +621,7 @@ def _safe_repr( components: List[str] = [] append = components.append level += 1 - if self._sort_dicts: - items = sorted(object.items(), key=_safe_tuple) - else: - items = object.items() - for k, v in items: + for k, v in sorted(object.items(), key=_safe_tuple): krepr = self._safe_repr(k, context, maxlevels, level) vrepr = self._safe_repr(v, context, maxlevels, level) append(f"{krepr}: {vrepr}") From 64b5b665cf477a8e920e0e8b57f6b96a2d40f365 Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Sun, 3 Dec 2023 13:49:46 +0000 Subject: [PATCH 0313/1271] pprint: Remove the option to add underscore for numbers This is never used, we can remove this. If we wanted instead, we could always enable it --- src/_pytest/_io/pprint.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 4512d39370c..ea1073af686 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -64,8 +64,6 @@ def __init__( indent: int = 4, width: int = 80, depth: Optional[int] = None, - *, - underscore_numbers: bool = False, ) -> None: """Handle pretty printing operations onto a stream using a set of configured parameters. @@ -91,7 +89,6 @@ def __init__( self._depth = depth self._indent_per_level = indent self._width = width - self._underscore_numbers = underscore_numbers def pformat(self, object: Any) -> str: sio = _StringIO() @@ -603,12 +600,6 @@ def _safe_repr( r = getattr(typ, "__repr__", None) - if issubclass(typ, int) and r is int.__repr__: - if self._underscore_numbers: - return f"{object:_d}" - else: - return repr(object) - if issubclass(typ, dict) and r is dict.__repr__: if not object: return "{}" @@ -659,7 +650,9 @@ def _safe_repr( return repr(object) -_builtin_scalars = frozenset({str, bytes, bytearray, float, complex, bool, type(None)}) +_builtin_scalars = frozenset( + {str, bytes, bytearray, float, complex, bool, type(None), int} +) def _recursion(object: Any) -> str: From 283a746dad7a3d88c35783bd4da595e507b855bd Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Sun, 3 Dec 2023 13:50:44 +0000 Subject: [PATCH 0314/1271] pprint: Remove conversion to int, we only accept those --- src/_pytest/_io/pprint.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index ea1073af686..7559c6778df 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -78,8 +78,6 @@ def __init__( The maximum depth to print out nested structures. """ - indent = int(indent) - width = int(width) if indent < 0: raise ValueError("indent must be >= 0") if depth is not None and depth <= 0: From 581762fcba64336aff6feaaaebe12387328f7f4e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 21:43:27 +0000 Subject: [PATCH 0315/1271] [pre-commit.ci] pre-commit autoupdate (#11722) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.11.0 → 23.12.0](https://github.com/psf/black/compare/23.11.0...23.12.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9b1ee9cda4b..c55c649471a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 23.11.0 + rev: 23.12.0 hooks: - id: black args: [--safe, --quiet] From 75f292d9df38827d40d444371428f092e7321c27 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 19 Dec 2023 23:29:27 +0200 Subject: [PATCH 0316/1271] Some minor typing tweaks --- src/_pytest/logging.py | 20 ++++++++++++++------ src/_pytest/runner.py | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 1c6bb923bd3..5426c35131f 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -11,15 +11,18 @@ from io import StringIO from logging import LogRecord from pathlib import Path +from types import TracebackType from typing import AbstractSet from typing import Dict from typing import final from typing import Generator +from typing import Generic from typing import List from typing import Literal from typing import Mapping from typing import Optional from typing import Tuple +from typing import Type from typing import TYPE_CHECKING from typing import TypeVar from typing import Union @@ -62,7 +65,7 @@ class DatetimeFormatter(logging.Formatter): :func:`time.strftime` in case of microseconds in format string. """ - def formatTime(self, record: LogRecord, datefmt=None) -> str: + def formatTime(self, record: LogRecord, datefmt: Optional[str] = None) -> str: if datefmt and "%f" in datefmt: ct = self.converter(record.created) tz = timezone(timedelta(seconds=ct.tm_gmtoff), ct.tm_zone) @@ -331,7 +334,7 @@ def add_option_ini(option, dest, default=None, type=None, **kwargs): # Not using @contextmanager for performance reasons. -class catching_logs: +class catching_logs(Generic[_HandlerType]): """Context manager that prepares the whole logging machinery properly.""" __slots__ = ("handler", "level", "orig_level") @@ -340,7 +343,7 @@ def __init__(self, handler: _HandlerType, level: Optional[int] = None) -> None: self.handler = handler self.level = level - def __enter__(self): + def __enter__(self) -> _HandlerType: root_logger = logging.getLogger() if self.level is not None: self.handler.setLevel(self.level) @@ -350,7 +353,12 @@ def __enter__(self): root_logger.setLevel(min(self.orig_level, self.level)) return self.handler - def __exit__(self, type, value, traceback): + def __exit__( + self, + exc_type: Optional[Type[BaseException]], + exc_val: Optional[BaseException], + exc_tb: Optional[TracebackType], + ) -> None: root_logger = logging.getLogger() if self.level is not None: root_logger.setLevel(self.orig_level) @@ -421,7 +429,7 @@ def handler(self) -> LogCaptureHandler: return self._item.stash[caplog_handler_key] def get_records( - self, when: "Literal['setup', 'call', 'teardown']" + self, when: Literal["setup", "call", "teardown"] ) -> List[logging.LogRecord]: """Get the logging records for one of the possible test phases. @@ -742,7 +750,7 @@ def set_log_path(self, fname: str) -> None: if old_stream: old_stream.close() - def _log_cli_enabled(self): + def _log_cli_enabled(self) -> bool: """Return whether live logging is enabled.""" enabled = self._config.getoption( "--log-cli-level" diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 1b39f93cf13..c03d707dca7 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -317,7 +317,7 @@ def result(self) -> TResult: @classmethod def from_call( cls, - func: "Callable[[], TResult]", + func: Callable[[], TResult], when: Literal["collect", "setup", "call", "teardown"], reraise: Optional[ Union[Type[BaseException], Tuple[Type[BaseException], ...]] From 88ae27da085da7d59d34736234b57a280dcc9dfc Mon Sep 17 00:00:00 2001 From: Benjamin Schubert Date: Thu, 21 Dec 2023 17:11:56 +0000 Subject: [PATCH 0317/1271] Add syntactic highlights to the error explanations (#11661) * Put a 'reset' color in front of the highlighting When doing the highlighting, some lexers will not set the initial color explicitly, which may lead to the red from the errors being propagated to the start of the expression * Add syntactic highlighting to the error explanations This updates the various error reporting to highlight python code when displayed, to increase readability and make it easier to understand --- changelog/11520.improvement.rst | 2 + src/_pytest/_io/terminalwriter.py | 10 ++- src/_pytest/assertion/util.py | 103 ++++++++++++++++++++---------- testing/io/test_terminalwriter.py | 2 +- testing/test_assertion.py | 11 +++- testing/test_terminal.py | 14 ++-- 6 files changed, 96 insertions(+), 46 deletions(-) diff --git a/changelog/11520.improvement.rst b/changelog/11520.improvement.rst index d9b7b493339..548d52a12ba 100644 --- a/changelog/11520.improvement.rst +++ b/changelog/11520.improvement.rst @@ -1,3 +1,5 @@ Improved very verbose diff output to color it as a diff instead of only red. Improved the error reporting to better separate each section. + +Improved the error reporting to syntax-highlight Python code when Pygments is available. diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 934278b93ed..2b2f49e9a27 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -223,7 +223,15 @@ def _highlight( style=os.getenv("PYTEST_THEME"), ), ) - return highlighted + # pygments terminal formatter may add a newline when there wasn't one. + # We don't want this, remove. + if highlighted[-1] == "\n" and source[-1] != "\n": + highlighted = highlighted[:-1] + + # Some lexers will not set the initial color explicitly + # which may lead to the previous color being propagated to the + # start of the expression, so reset first. + return "\x1b[0m" + highlighted except pygments.util.ClassNotFound: raise UsageError( "PYTEST_THEME environment variable had an invalid value: '{}'. " diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index fe8904e15dc..6f97101a932 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -192,12 +192,12 @@ def assertrepr_compare( right_repr = saferepr(right, maxsize=maxsize, use_ascii=use_ascii) summary = f"{left_repr} {op} {right_repr}" + highlighter = config.get_terminal_writer()._highlight explanation = None try: if op == "==": - writer = config.get_terminal_writer() - explanation = _compare_eq_any(left, right, writer._highlight, verbose) + explanation = _compare_eq_any(left, right, highlighter, verbose) elif op == "not in": if istext(left) and istext(right): explanation = _notin_text(left, right, verbose) @@ -206,16 +206,16 @@ def assertrepr_compare( explanation = ["Both sets are equal"] elif op == ">=": if isset(left) and isset(right): - explanation = _compare_gte_set(left, right, verbose) + explanation = _compare_gte_set(left, right, highlighter, verbose) elif op == "<=": if isset(left) and isset(right): - explanation = _compare_lte_set(left, right, verbose) + explanation = _compare_lte_set(left, right, highlighter, verbose) elif op == ">": if isset(left) and isset(right): - explanation = _compare_gt_set(left, right, verbose) + explanation = _compare_gt_set(left, right, highlighter, verbose) elif op == "<": if isset(left) and isset(right): - explanation = _compare_lt_set(left, right, verbose) + explanation = _compare_lt_set(left, right, highlighter, verbose) except outcomes.Exit: raise @@ -259,11 +259,11 @@ def _compare_eq_any( # used in older code bases before dataclasses/attrs were available. explanation = _compare_eq_cls(left, right, highlighter, verbose) elif issequence(left) and issequence(right): - explanation = _compare_eq_sequence(left, right, verbose) + explanation = _compare_eq_sequence(left, right, highlighter, verbose) elif isset(left) and isset(right): - explanation = _compare_eq_set(left, right, verbose) + explanation = _compare_eq_set(left, right, highlighter, verbose) elif isdict(left) and isdict(right): - explanation = _compare_eq_dict(left, right, verbose) + explanation = _compare_eq_dict(left, right, highlighter, verbose) if isiterable(left) and isiterable(right): expl = _compare_eq_iterable(left, right, highlighter, verbose) @@ -350,7 +350,10 @@ def _compare_eq_iterable( def _compare_eq_sequence( - left: Sequence[Any], right: Sequence[Any], verbose: int = 0 + left: Sequence[Any], + right: Sequence[Any], + highlighter: _HighlightFunc, + verbose: int = 0, ) -> List[str]: comparing_bytes = isinstance(left, bytes) and isinstance(right, bytes) explanation: List[str] = [] @@ -373,7 +376,10 @@ def _compare_eq_sequence( left_value = left[i] right_value = right[i] - explanation += [f"At index {i} diff: {left_value!r} != {right_value!r}"] + explanation.append( + f"At index {i} diff:" + f" {highlighter(repr(left_value))} != {highlighter(repr(right_value))}" + ) break if comparing_bytes: @@ -393,68 +399,91 @@ def _compare_eq_sequence( extra = saferepr(right[len_left]) if len_diff == 1: - explanation += [f"{dir_with_more} contains one more item: {extra}"] + explanation += [ + f"{dir_with_more} contains one more item: {highlighter(extra)}" + ] else: explanation += [ "%s contains %d more items, first extra item: %s" - % (dir_with_more, len_diff, extra) + % (dir_with_more, len_diff, highlighter(extra)) ] return explanation def _compare_eq_set( - left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 + left: AbstractSet[Any], + right: AbstractSet[Any], + highlighter: _HighlightFunc, + verbose: int = 0, ) -> List[str]: explanation = [] - explanation.extend(_set_one_sided_diff("left", left, right)) - explanation.extend(_set_one_sided_diff("right", right, left)) + explanation.extend(_set_one_sided_diff("left", left, right, highlighter)) + explanation.extend(_set_one_sided_diff("right", right, left, highlighter)) return explanation def _compare_gt_set( - left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 + left: AbstractSet[Any], + right: AbstractSet[Any], + highlighter: _HighlightFunc, + verbose: int = 0, ) -> List[str]: - explanation = _compare_gte_set(left, right, verbose) + explanation = _compare_gte_set(left, right, highlighter) if not explanation: return ["Both sets are equal"] return explanation def _compare_lt_set( - left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 + left: AbstractSet[Any], + right: AbstractSet[Any], + highlighter: _HighlightFunc, + verbose: int = 0, ) -> List[str]: - explanation = _compare_lte_set(left, right, verbose) + explanation = _compare_lte_set(left, right, highlighter) if not explanation: return ["Both sets are equal"] return explanation def _compare_gte_set( - left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 + left: AbstractSet[Any], + right: AbstractSet[Any], + highlighter: _HighlightFunc, + verbose: int = 0, ) -> List[str]: - return _set_one_sided_diff("right", right, left) + return _set_one_sided_diff("right", right, left, highlighter) def _compare_lte_set( - left: AbstractSet[Any], right: AbstractSet[Any], verbose: int = 0 + left: AbstractSet[Any], + right: AbstractSet[Any], + highlighter: _HighlightFunc, + verbose: int = 0, ) -> List[str]: - return _set_one_sided_diff("left", left, right) + return _set_one_sided_diff("left", left, right, highlighter) def _set_one_sided_diff( - posn: str, set1: AbstractSet[Any], set2: AbstractSet[Any] + posn: str, + set1: AbstractSet[Any], + set2: AbstractSet[Any], + highlighter: _HighlightFunc, ) -> List[str]: explanation = [] diff = set1 - set2 if diff: explanation.append(f"Extra items in the {posn} set:") for item in diff: - explanation.append(saferepr(item)) + explanation.append(highlighter(saferepr(item))) return explanation def _compare_eq_dict( - left: Mapping[Any, Any], right: Mapping[Any, Any], verbose: int = 0 + left: Mapping[Any, Any], + right: Mapping[Any, Any], + highlighter: _HighlightFunc, + verbose: int = 0, ) -> List[str]: explanation: List[str] = [] set_left = set(left) @@ -465,12 +494,16 @@ def _compare_eq_dict( explanation += ["Omitting %s identical items, use -vv to show" % len(same)] elif same: explanation += ["Common items:"] - explanation += pprint.pformat(same).splitlines() + explanation += highlighter(pprint.pformat(same)).splitlines() diff = {k for k in common if left[k] != right[k]} if diff: explanation += ["Differing items:"] for k in diff: - explanation += [saferepr({k: left[k]}) + " != " + saferepr({k: right[k]})] + explanation += [ + highlighter(saferepr({k: left[k]})) + + " != " + + highlighter(saferepr({k: right[k]})) + ] extra_left = set_left - set_right len_extra_left = len(extra_left) if len_extra_left: @@ -479,7 +512,7 @@ def _compare_eq_dict( % (len_extra_left, "" if len_extra_left == 1 else "s") ) explanation.extend( - pprint.pformat({k: left[k] for k in extra_left}).splitlines() + highlighter(pprint.pformat({k: left[k] for k in extra_left})).splitlines() ) extra_right = set_right - set_left len_extra_right = len(extra_right) @@ -489,7 +522,7 @@ def _compare_eq_dict( % (len_extra_right, "" if len_extra_right == 1 else "s") ) explanation.extend( - pprint.pformat({k: right[k] for k in extra_right}).splitlines() + highlighter(pprint.pformat({k: right[k] for k in extra_right})).splitlines() ) return explanation @@ -528,17 +561,17 @@ def _compare_eq_cls( explanation.append("Omitting %s identical items, use -vv to show" % len(same)) elif same: explanation += ["Matching attributes:"] - explanation += pprint.pformat(same).splitlines() + explanation += highlighter(pprint.pformat(same)).splitlines() if diff: explanation += ["Differing attributes:"] - explanation += pprint.pformat(diff).splitlines() + explanation += highlighter(pprint.pformat(diff)).splitlines() for field in diff: field_left = getattr(left, field) field_right = getattr(right, field) explanation += [ "", - "Drill down into differing attribute %s:" % field, - ("%s%s: %r != %r") % (indent, field, field_left, field_right), + f"Drill down into differing attribute {field}:", + f"{indent}{field}: {highlighter(repr(field_left))} != {highlighter(repr(field_right))}", ] explanation += [ indent + line diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index b5a04a99f18..a2d730b0711 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -254,7 +254,7 @@ def test_combining(self) -> None: pytest.param( True, True, - "{kw}assert{hl-reset} {number}0{hl-reset}{endline}\n", + "{reset}{kw}assert{hl-reset} {number}0{hl-reset}{endline}\n", id="with markup and code_highlight", ), pytest.param( diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 4d751f8dbfc..8a4b2c62e08 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -20,7 +20,7 @@ def mock_config(verbose: int = 0, assertion_override: Optional[int] = None): class TerminalWriter: - def _highlight(self, source, lexer): + def _highlight(self, source, lexer="python"): return source class Config: @@ -1933,6 +1933,7 @@ def test(): assert [0, 1] == [0, 2] """, [ + "{bold}{red}E At index 1 diff: {reset}{number}1{hl-reset}{endline} != {reset}{number}2*", "{bold}{red}E {light-red}- 2,{hl-reset}{endline}{reset}", "{bold}{red}E {light-green}+ 1,{hl-reset}{endline}{reset}", ], @@ -1945,7 +1946,13 @@ def test(): } """, [ - "{bold}{red}E {light-gray} {hl-reset} {{{endline}{reset}", + "{bold}{red}E Common items:{reset}", + "{bold}{red}E {reset}{{{str}'{hl-reset}{str}number-is-1{hl-reset}{str}'{hl-reset}: {number}1*", + "{bold}{red}E Left contains 1 more item:{reset}", + "{bold}{red}E {reset}{{{str}'{hl-reset}{str}number-is-5{hl-reset}{str}'{hl-reset}: {number}5*", + "{bold}{red}E Right contains 1 more item:{reset}", + "{bold}{red}E {reset}{{{str}'{hl-reset}{str}number-is-0{hl-reset}{str}'{hl-reset}: {number}0*", + "{bold}{red}E {reset}{light-gray} {hl-reset} {{{endline}{reset}", "{bold}{red}E {light-gray} {hl-reset} 'number-is-1': 1,{endline}{reset}", "{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}", ], diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 264ab96d8d0..80958f2107f 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1268,13 +1268,13 @@ def test_this(): "=*= FAILURES =*=", "{red}{bold}_*_ test_this _*_{reset}", "", - " {kw}def{hl-reset} {function}test_this{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset} {function}test_this{hl-reset}():{endline}", "> fail(){endline}", "", "{bold}{red}test_color_yes.py{reset}:5: ", "_ _ * _ _*", "", - " {kw}def{hl-reset} {function}fail{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset} {function}fail{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}0{hl-reset}{endline}", "{bold}{red}E assert 0{reset}", "", @@ -1295,9 +1295,9 @@ def test_this(): "=*= FAILURES =*=", "{red}{bold}_*_ test_this _*_{reset}", "{bold}{red}test_color_yes.py{reset}:5: in test_this", - " fail(){endline}", + " {reset}fail(){endline}", "{bold}{red}test_color_yes.py{reset}:2: in fail", - " {kw}assert{hl-reset} {number}0{hl-reset}{endline}", + " {reset}{kw}assert{hl-reset} {number}0{hl-reset}{endline}", "{bold}{red}E assert 0{reset}", "{red}=*= {red}{bold}1 failed{reset}{red} in *s{reset}{red} =*={reset}", ] @@ -2507,7 +2507,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}1{hl-reset} == {number}10{hl-reset}{endline}", "{bold}{red}E assert 1 == 10{reset}", ] @@ -2529,7 +2529,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", " {print}print{hl-reset}({str}'''{hl-reset}{str}{hl-reset}", "> {str} {hl-reset}{str}'''{hl-reset}); {kw}assert{hl-reset} {number}0{hl-reset}{endline}", "{bold}{red}E assert 0{reset}", @@ -2552,7 +2552,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}1{hl-reset} == {number}10{hl-reset}{endline}", "{bold}{red}E assert 1 == 10{reset}", ] From 52db918a27b2eb5043de6e80215076a98b0b9fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Sat, 23 Dec 2023 09:12:13 +0100 Subject: [PATCH 0318/1271] Fix handling empty values of NO_COLOR and FORCE_COLOR (#11712) * Fix handling empty values of NO_COLOR and FORCE_COLOR Fix handling NO_COLOR and FORCE_COLOR environment variables to correctly be ignored when they are set to an empty value, as defined in the specification: > Command-line software which adds ANSI color to its output by default > should check for a NO_COLOR environment variable that, when present > *and not an empty string* (regardless of its value), prevents > the addition of ANSI color. (emphasis mine, https://no-color.org/) The same is true of FORCE_COLOR, https://force-color.org/. * Streamline testing for FORCE_COLOR and NO_COLOR Streamline the tests for FORCE_COLOR and NO_COLOR variables, and cover all possible cases (unset, set to empty, set to "1"). Combine the two assert functions into one taking boolean parameters. Mock file.isatty in all circumstances to ensure that the environment variables take precedence over the fallback value resulting from isatty check (or that the fallback is actually used, in the case of both FORCE_COLOR and NO_COLOR being unset). --- AUTHORS | 1 + changelog/11712.bugfix.rst | 1 + doc/en/reference/reference.rst | 4 +- src/_pytest/_io/terminalwriter.py | 4 +- testing/io/test_terminalwriter.py | 63 +++++++++++++++++++------------ 5 files changed, 45 insertions(+), 28 deletions(-) create mode 100644 changelog/11712.bugfix.rst diff --git a/AUTHORS b/AUTHORS index bb273edcc30..42cfd0be249 100644 --- a/AUTHORS +++ b/AUTHORS @@ -266,6 +266,7 @@ Michael Goerz Michael Krebs Michael Seifert Michal Wajszczuk +Michał Górny Michał Zięba Mickey Pashov Mihai Capotă diff --git a/changelog/11712.bugfix.rst b/changelog/11712.bugfix.rst new file mode 100644 index 00000000000..416d761493d --- /dev/null +++ b/changelog/11712.bugfix.rst @@ -0,0 +1 @@ +Fixed handling ``NO_COLOR`` and ``FORCE_COLOR`` to ignore an empty value. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 3054109ba50..b2b63a89edc 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1146,13 +1146,13 @@ When set to ``0``, pytest will not use color. .. envvar:: NO_COLOR -When set (regardless of value), pytest will not use color in terminal output. +When set to a non-empty string (regardless of value), pytest will not use color in terminal output. ``PY_COLORS`` takes precedence over ``NO_COLOR``, which takes precedence over ``FORCE_COLOR``. See `no-color.org `__ for other libraries supporting this community standard. .. envvar:: FORCE_COLOR -When set (regardless of value), pytest will use color in terminal output. +When set to a non-empty string (regardless of value), pytest will use color in terminal output. ``PY_COLORS`` and ``NO_COLOR`` take precedence over ``FORCE_COLOR``. Exceptions diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 2b2f49e9a27..bf9b7665194 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -29,9 +29,9 @@ def should_do_markup(file: TextIO) -> bool: return True if os.environ.get("PY_COLORS") == "0": return False - if "NO_COLOR" in os.environ: + if os.environ.get("NO_COLOR"): return False - if "FORCE_COLOR" in os.environ: + if os.environ.get("FORCE_COLOR"): return True return ( hasattr(file, "isatty") and file.isatty() and os.environ.get("TERM") != "dumb" diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index a2d730b0711..96e7366e543 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -5,6 +5,7 @@ import sys from pathlib import Path from typing import Generator +from typing import Optional from unittest import mock import pytest @@ -164,53 +165,67 @@ def test_attr_hasmarkup() -> None: assert "\x1b[0m" in s -def assert_color_set(): +def assert_color(expected: bool, default: Optional[bool] = None) -> None: file = io.StringIO() - tw = terminalwriter.TerminalWriter(file) - assert tw.hasmarkup + if default is None: + default = not expected + file.isatty = lambda: default # type: ignore + tw = terminalwriter.TerminalWriter(file=file) + assert tw.hasmarkup is expected tw.line("hello", bold=True) s = file.getvalue() - assert len(s) > len("hello\n") - assert "\x1b[1m" in s - assert "\x1b[0m" in s - - -def assert_color_not_set(): - f = io.StringIO() - f.isatty = lambda: True # type: ignore - tw = terminalwriter.TerminalWriter(file=f) - assert not tw.hasmarkup - tw.line("hello", bold=True) - s = f.getvalue() - assert s == "hello\n" + if expected: + assert len(s) > len("hello\n") + assert "\x1b[1m" in s + assert "\x1b[0m" in s + else: + assert s == "hello\n" def test_should_do_markup_PY_COLORS_eq_1(monkeypatch: MonkeyPatch) -> None: monkeypatch.setitem(os.environ, "PY_COLORS", "1") - assert_color_set() + assert_color(True) def test_should_not_do_markup_PY_COLORS_eq_0(monkeypatch: MonkeyPatch) -> None: monkeypatch.setitem(os.environ, "PY_COLORS", "0") - assert_color_not_set() + assert_color(False) def test_should_not_do_markup_NO_COLOR(monkeypatch: MonkeyPatch) -> None: monkeypatch.setitem(os.environ, "NO_COLOR", "1") - assert_color_not_set() + assert_color(False) def test_should_do_markup_FORCE_COLOR(monkeypatch: MonkeyPatch) -> None: monkeypatch.setitem(os.environ, "FORCE_COLOR", "1") - assert_color_set() + assert_color(True) -def test_should_not_do_markup_NO_COLOR_and_FORCE_COLOR( +@pytest.mark.parametrize( + ["NO_COLOR", "FORCE_COLOR", "expected"], + [ + ("1", "1", False), + ("", "1", True), + ("1", "", False), + ], +) +def test_NO_COLOR_and_FORCE_COLOR( monkeypatch: MonkeyPatch, + NO_COLOR: str, + FORCE_COLOR: str, + expected: bool, ) -> None: - monkeypatch.setitem(os.environ, "NO_COLOR", "1") - monkeypatch.setitem(os.environ, "FORCE_COLOR", "1") - assert_color_not_set() + monkeypatch.setitem(os.environ, "NO_COLOR", NO_COLOR) + monkeypatch.setitem(os.environ, "FORCE_COLOR", FORCE_COLOR) + assert_color(expected) + + +def test_empty_NO_COLOR_and_FORCE_COLOR_ignored(monkeypatch: MonkeyPatch) -> None: + monkeypatch.setitem(os.environ, "NO_COLOR", "") + monkeypatch.setitem(os.environ, "FORCE_COLOR", "") + assert_color(True, True) + assert_color(False, False) class TestTerminalWriterLineWidth: From f93c0fc34eff371ecae3cd82aa362de2edf7be74 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 24 Dec 2023 00:20:08 +0000 Subject: [PATCH 0319/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 86 +++++++++++++++++--------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 8317af7ca49..7e766c41c96 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.0.1) :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Dec 12, 2023 5 - Production/Stable pytest - :pypi:`pytest-archon` Rule your architecture like a real developer Jul 11, 2023 5 - Production/Stable pytest (>=7.2) + :pypi:`pytest-archon` Rule your architecture like a real developer Dec 18, 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 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-aspec` A rspec format reporter for pytest Dec 20, 2023 4 - Beta N/A :pypi:`pytest-asptest` test Answer Set Programming programs Apr 28, 2018 4 - Beta N/A :pypi:`pytest-assertcount` Plugin to count actual number of asserts in pytest Oct 23, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-assertions` Pytest Assertions Apr 27, 2022 N/A N/A @@ -207,7 +207,7 @@ This list contains 1355 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 30, 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 Dec 19, 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 @@ -531,12 +531,12 @@ This list contains 1355 plugins. :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. Dec 04, 2023 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Dec 18, 2023 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-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. Dec 14, 2023 N/A N/A + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Dec 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 @@ -599,12 +599,12 @@ This list contains 1355 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Nov 13, 2023 5 - Production/Stable pytest ==7.* + :pypi:`pytest-httpx` Send responses to httpx. Dec 21, 2023 5 - Production/Stable pytest ==7.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Dec 15, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Dec 22, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A @@ -690,7 +690,7 @@ This list contains 1355 plugins. :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 06, 2023 4 - Beta N/A + :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest @@ -753,7 +753,7 @@ This list contains 1355 plugins. :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Dec 06, 2023 N/A pytest >=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Dec 20, 2023 N/A pytest >=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) @@ -911,6 +911,7 @@ This list contains 1355 plugins. :pypi:`pytest-ponyorm` PonyORM in Pytest Oct 31, 2018 N/A pytest (>=3.1.1) :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A + :pypi:`pytest-pook` Pytest plugin for pook Dec 23, 2023 4 - Beta pytest :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest :pypi:`pytest-porringer` Oct 03, 2023 N/A pytest>=7.4.0 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) @@ -965,7 +966,7 @@ This list contains 1355 plugins. :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) + :pypi:`pytest-qt` pytest support for PyQt and PySide applications Dec 22, 2023 5 - Production/Stable pytest >=3.0.0 :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) @@ -1074,7 +1075,7 @@ This list contains 1355 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 08, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 23, 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) @@ -1083,15 +1084,15 @@ This list contains 1355 plugins. :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 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. Dec 08, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Dec 23, 2023 5 - Production/Stable N/A :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-server-fixtures` Extensible server fixures for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Dec 15, 2023 3 - Alpha pytest >=6.2 + :pypi:`pytest-servers` pytest servers Dec 19, 2023 3 - Alpha pytest >=6.2 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1138,7 +1139,7 @@ This list contains 1355 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Oct 06, 2023 N/A pytest >=7.4.0 + :pypi:`pytest-sort` Tools for sorting test cases Dec 22, 2023 N/A pytest >=7.4.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest @@ -1156,7 +1157,7 @@ This list contains 1355 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 Dec 14, 2023 N/A pytest (>5.4.0,<8) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Dec 21, 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 @@ -1325,7 +1326,7 @@ This list contains 1355 plugins. :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 Nov 23, 2023 4 - Beta pytest - :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Dec 12, 2023 4 - Beta pytest + :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Dec 19, 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 @@ -1374,7 +1375,7 @@ This list contains 1355 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 Nov 30, 2023 N/A pytest>=7.4.0 + :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Dec 18, 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) @@ -1766,9 +1767,9 @@ This list contains 1355 plugins. Extension for ApprovalTests.Python specific to geo data verification :pypi:`pytest-archon` - *last release*: Jul 11, 2023, + *last release*: Dec 18, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.2) + *requires*: pytest >=7.2 Rule your architecture like a real developer @@ -1794,7 +1795,7 @@ This list contains 1355 plugins. Convenient ASGI client/server fixtures for Pytest :pypi:`pytest-aspec` - *last release*: Oct 23, 2023, + *last release*: Dec 20, 2023, *status*: 4 - Beta, *requires*: N/A @@ -2606,7 +2607,7 @@ This list contains 1355 plugins. A pytest plugin to send a report and printing summary of tests. :pypi:`pytest-choose` - *last release*: Nov 30, 2023, + *last release*: Dec 19, 2023, *status*: N/A, *requires*: pytest >=7.0.0 @@ -4874,7 +4875,7 @@ This list contains 1355 plugins. Uses gcov to measure test coverage of a C library :pypi:`pytest-gee` - *last release*: Dec 04, 2023, + *last release*: Dec 18, 2023, *status*: 3 - Alpha, *requires*: pytest @@ -4909,7 +4910,7 @@ This list contains 1355 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Dec 14, 2023, + *last release*: Dec 20, 2023, *status*: N/A, *requires*: N/A @@ -5350,7 +5351,7 @@ This list contains 1355 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Nov 13, 2023, + *last release*: Dec 21, 2023, *status*: 5 - Production/Stable, *requires*: pytest ==7.* @@ -5385,7 +5386,7 @@ This list contains 1355 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Dec 15, 2023, + *last release*: Dec 22, 2023, *status*: 3 - Alpha, *requires*: pytest (>=7.0.0,<8.0.0) @@ -5987,7 +5988,7 @@ This list contains 1355 plugins. A python-libfaketime plugin for pytest. :pypi:`pytest-libiio` - *last release*: Dec 06, 2023, + *last release*: Dec 22, 2023, *status*: 4 - Beta, *requires*: N/A @@ -6428,7 +6429,7 @@ This list contains 1355 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: Dec 06, 2023, + *last release*: Dec 20, 2023, *status*: N/A, *requires*: pytest >=5.0.0 @@ -7533,6 +7534,13 @@ This list contains 1355 plugins. Visualize your failed tests with poo + :pypi:`pytest-pook` + *last release*: Dec 23, 2023, + *status*: 4 - Beta, + *requires*: pytest + + Pytest plugin for pook + :pypi:`pytest-pop` *last release*: May 09, 2023, *status*: 5 - Production/Stable, @@ -7912,9 +7920,9 @@ This list contains 1355 plugins. pytest plugin to generate test result QR codes :pypi:`pytest-qt` - *last release*: Oct 25, 2022, + *last release*: Dec 22, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.0.0) + *requires*: pytest >=3.0.0 pytest support for PyQt and PySide applications @@ -8675,7 +8683,7 @@ This list contains 1355 plugins. :pypi:`pytest-sbase` - *last release*: Dec 08, 2023, + *last release*: Dec 23, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8738,7 +8746,7 @@ This list contains 1355 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Dec 08, 2023, + *last release*: Dec 23, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -8780,7 +8788,7 @@ This list contains 1355 plugins. Pytest plugin for sequencing markers for execution of tests :pypi:`pytest-server-fixtures` - *last release*: May 28, 2019, + *last release*: Dec 19, 2023, *status*: 5 - Production/Stable, *requires*: pytest @@ -8794,7 +8802,7 @@ This list contains 1355 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Dec 15, 2023, + *last release*: Dec 19, 2023, *status*: 3 - Alpha, *requires*: pytest >=6.2 @@ -9123,7 +9131,7 @@ This list contains 1355 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Oct 06, 2023, + *last release*: Dec 22, 2023, *status*: N/A, *requires*: pytest >=7.4.0 @@ -9249,7 +9257,7 @@ This list contains 1355 plugins. :pypi:`pytest-splunk-addon` - *last release*: Dec 14, 2023, + *last release*: Dec 21, 2023, *status*: N/A, *requires*: pytest (>5.4.0,<8) @@ -10432,7 +10440,7 @@ This list contains 1355 plugins. py.test fixture for creating a virtual environment :pypi:`pytest-ver` - *last release*: Dec 12, 2023, + *last release*: Dec 19, 2023, *status*: 4 - Beta, *requires*: pytest @@ -10775,7 +10783,7 @@ This list contains 1355 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Nov 30, 2023, + *last release*: Dec 18, 2023, *status*: N/A, *requires*: pytest>=7.4.0 From 1e5aab1b2b8900ec6287ff168951184f9a7abecd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Dec 2023 20:43:18 +0000 Subject: [PATCH 0320/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/psf/black: 23.12.0 → 23.12.1](https://github.com/psf/black/compare/23.12.0...23.12.1) - [github.com/pre-commit/mirrors-mypy: v1.7.1 → v1.8.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.7.1...v1.8.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c55c649471a..7c328ad48b6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 23.12.0 + rev: 23.12.1 hooks: - id: black args: [--safe, --quiet] @@ -56,7 +56,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.7.1 + rev: v1.8.0 hooks: - id: mypy files: ^(src/|testing/) From a71a95b54cac6afd14ea36ede39b86b28155110e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 30 Dec 2023 22:12:45 +0200 Subject: [PATCH 0321/1271] Change "Marks applied to fixtures" removal from 8 to 9 The deprecation has only been added in 8.0, so can't be removed in 8. That will have to wait for 9. --- src/_pytest/deprecated.py | 3 ++- testing/deprecated_test.py | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 3fcf99ba417..77279d6342a 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -12,6 +12,7 @@ from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestRemovedIn8Warning +from _pytest.warning_types import PytestRemovedIn9Warning from _pytest.warning_types import UnformattedWarning # set of plugins which have been integrated into the core; we use this list to ignore @@ -122,7 +123,7 @@ "#configuring-hook-specs-impls-using-markers", ) -MARKED_FIXTURE = PytestRemovedIn8Warning( +MARKED_FIXTURE = PytestRemovedIn9Warning( "Marks applied to fixtures have no effect\n" "See docs: https://docs.pytest.org/en/stable/deprecations.html#applying-a-mark-to-a-fixture-function" ) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index fcd824d5f57..0736ed1dcc1 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -290,7 +290,7 @@ def test_importing_instance_is_deprecated(pytester: Pytester) -> None: def test_fixture_disallow_on_marked_functions(): """Test that applying @pytest.fixture to a marked function warns (#3364).""" with pytest.warns( - pytest.PytestRemovedIn8Warning, + pytest.PytestRemovedIn9Warning, match=r"Marks applied to fixtures have no effect", ) as record: @@ -309,7 +309,7 @@ def foo(): def test_fixture_disallow_marks_on_fixtures(): """Test that applying a mark to a fixture warns (#3364).""" with pytest.warns( - pytest.PytestRemovedIn8Warning, + pytest.PytestRemovedIn9Warning, match=r"Marks applied to fixtures have no effect", ) as record: @@ -325,7 +325,7 @@ def foo(): def test_fixture_disallowed_between_marks(): """Test that applying a mark to a fixture warns (#3364).""" with pytest.warns( - pytest.PytestRemovedIn8Warning, + pytest.PytestRemovedIn9Warning, match=r"Marks applied to fixtures have no effect", ) as record: From 460c38915d5bf5b52e8d6f99bb3fb2dc2c861bbb Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 31 Dec 2023 00:20:30 +0000 Subject: [PATCH 0322/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 82 ++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 7e766c41c96..a967a33bda4 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Dec 07, 2023 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Dec 28, 2023 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A @@ -207,7 +207,7 @@ This list contains 1356 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 Dec 19, 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 Dec 26, 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 @@ -410,18 +410,18 @@ This list contains 1356 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. Dec 04, 2023 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Dec 04, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Dec 04, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Dec 04, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Dec 04, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Dec 04, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Dec 04, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Dec 04, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Dec 29, 2023 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Dec 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Dec 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Dec 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Dec 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Dec 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Dec 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Dec 29, 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) - :pypi:`pytest-enabler` Enable installed pytest plugins Jul 14, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-enabler` Enable installed pytest plugins Dec 23, 2023 5 - Production/Stable pytest >=6 ; extra == 'testing' :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest @@ -577,9 +577,9 @@ This list contains 1356 plugins. :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Dec 15, 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` Dec 13, 2023 N/A N/A + :pypi:`pytest-hot-reloading` Dec 27, 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-houdini` pytest plugin for testing code in Houdini. Dec 25, 2023 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) @@ -753,7 +753,7 @@ This list contains 1356 plugins. :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Dec 20, 2023 N/A pytest >=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Dec 24, 2023 N/A pytest >=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) @@ -1256,13 +1256,14 @@ This list contains 1356 plugins. :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest - :pypi:`pytest-timeassert-ethan` execution duration Dec 12, 2023 N/A pytest + :pypi:`pytest-timeassert-ethan` execution duration Dec 25, 2023 N/A pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A :pypi:`pytest-timeout` pytest plugin to abort hanging tests Oct 08, 2023 5 - Production/Stable pytest >=5.0.0 :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A - :pypi:`pytest-timer` A timer plugin for pytest Jun 02, 2021 N/A N/A + :pypi:`pytest-timer` A timer plugin for pytest Dec 26, 2023 N/A pytest :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) + :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Dec 28, 2023 5 - Production/Stable pytest :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) :pypi:`pytest-tipsi-django` Nov 17, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Nov 04, 2020 4 - Beta pytest (>=3.3.0) @@ -1365,7 +1366,7 @@ This list contains 1356 plugins. :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jul 03, 2023 N/A pytest<8,>=7.4.0 + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Dec 28, 2023 N/A pytest<8,>=7.4.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Sep 23, 2023 4 - Beta pytest (>=2.8) :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A @@ -2488,7 +2489,7 @@ This list contains 1356 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Dec 07, 2023, + *last release*: Dec 28, 2023, *status*: N/A, *requires*: N/A @@ -2607,7 +2608,7 @@ This list contains 1356 plugins. A pytest plugin to send a report and printing summary of tests. :pypi:`pytest-choose` - *last release*: Dec 19, 2023, + *last release*: Dec 26, 2023, *status*: N/A, *requires*: pytest >=7.0.0 @@ -4028,56 +4029,56 @@ This list contains 1356 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Dec 04, 2023, + *last release*: Dec 29, 2023, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Dec 04, 2023, + *last release*: Dec 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Dec 04, 2023, + *last release*: Dec 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Dec 04, 2023, + *last release*: Dec 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Dec 04, 2023, + *last release*: Dec 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Dec 04, 2023, + *last release*: Dec 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Dec 04, 2023, + *last release*: Dec 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Dec 04, 2023, + *last release*: Dec 29, 2023, *status*: 5 - Production/Stable, *requires*: N/A @@ -4105,9 +4106,9 @@ This list contains 1356 plugins. Pytest plugin to represent test output with emoji support :pypi:`pytest-enabler` - *last release*: Jul 14, 2023, + *last release*: Dec 23, 2023, *status*: 5 - Production/Stable, - *requires*: pytest (>=6) ; extra == 'testing' + *requires*: pytest >=6 ; extra == 'testing' Enable installed pytest plugins @@ -5197,7 +5198,7 @@ This list contains 1356 plugins. Report on tests that honor constraints, and guard against regressions :pypi:`pytest-hot-reloading` - *last release*: Dec 13, 2023, + *last release*: Dec 27, 2023, *status*: N/A, *requires*: N/A @@ -5211,7 +5212,7 @@ This list contains 1356 plugins. A plugin that tracks test changes :pypi:`pytest-houdini` - *last release*: Nov 10, 2023, + *last release*: Dec 25, 2023, *status*: N/A, *requires*: pytest @@ -6429,7 +6430,7 @@ This list contains 1356 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: Dec 20, 2023, + *last release*: Dec 24, 2023, *status*: N/A, *requires*: pytest >=5.0.0 @@ -9950,7 +9951,7 @@ This list contains 1356 plugins. :pypi:`pytest-timeassert-ethan` - *last release*: Dec 12, 2023, + *last release*: Dec 25, 2023, *status*: N/A, *requires*: pytest @@ -9978,9 +9979,9 @@ This list contains 1356 plugins. Linux-only Pytest plugin to control durations of various test case execution phases :pypi:`pytest-timer` - *last release*: Jun 02, 2021, + *last release*: Dec 26, 2023, *status*: N/A, - *requires*: N/A + *requires*: pytest A timer plugin for pytest @@ -9998,6 +9999,13 @@ This list contains 1356 plugins. A simple plugin to view timestamps for each test + :pypi:`pytest-tiny-api-client` + *last release*: Dec 28, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest + + The companion pytest plugin for tiny-api-client + :pypi:`pytest-tinybird` *last release*: Jun 26, 2023, *status*: 4 - Beta, @@ -10713,7 +10721,7 @@ This list contains 1356 plugins. Extended logging for test and decorators :pypi:`pytest-xlsx` - *last release*: Jul 03, 2023, + *last release*: Dec 28, 2023, *status*: N/A, *requires*: pytest<8,>=7.4.0 From d220880924c7ba827ff8b4d68f991fb3e67a1cd0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 31 Dec 2023 10:14:23 +0200 Subject: [PATCH 0323/1271] nodes: fix tracebacks from collection errors are not getting pruned (#11711) Fix #11710. --- changelog/11710.bugfix.rst | 1 + src/_pytest/nodes.py | 2 +- testing/test_collection.py | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 changelog/11710.bugfix.rst diff --git a/changelog/11710.bugfix.rst b/changelog/11710.bugfix.rst new file mode 100644 index 00000000000..4bbf9fa2e7d --- /dev/null +++ b/changelog/11710.bugfix.rst @@ -0,0 +1 @@ +Fixed tracebacks from collection errors not getting pruned. diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 29efd56f49e..5307141080d 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -579,7 +579,7 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: ntraceback = traceback.cut(path=self.path) if ntraceback == traceback: ntraceback = ntraceback.cut(excludepath=tracebackcutdir) - return excinfo.traceback.filter(excinfo) + return ntraceback.filter(excinfo) return excinfo.traceback diff --git a/testing/test_collection.py b/testing/test_collection.py index deed4bda522..be65169f75c 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -345,6 +345,29 @@ def pytest_make_collect_report(): result = pytester.runpytest(p) result.stdout.fnmatch_lines(["*ERROR collecting*", "*header1*"]) + def test_collection_error_traceback_is_clean(self, pytester: Pytester) -> None: + """When a collection error occurs, the report traceback doesn't contain + internal pytest stack entries. + + Issue #11710. + """ + pytester.makepyfile( + """ + raise Exception("LOUSY") + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*ERROR collecting*", + "test_*.py:1: in ", + ' raise Exception("LOUSY")', + "E Exception: LOUSY", + "*= short test summary info =*", + ], + consecutive=True, + ) + class TestCustomConftests: def test_ignore_collect_path(self, pytester: Pytester) -> None: From a1b6b7473b103b6dfa6c2b4bf8d680713d3f6047 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 31 Dec 2023 14:10:58 +0200 Subject: [PATCH 0324/1271] Merge pull request #11752 from pytest-dev/release-7.4.4 Prepare release 7.4.4 (cherry picked from commit 18dcd9d38d18fc01bf1f7f5f60db69f785957101) --- changelog/11091.doc.rst | 1 - changelog/11146.bugfix.rst | 1 - changelog/11572.bugfix.rst | 1 - changelog/11710.bugfix.rst | 1 - changelog/7966.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-7.4.4.rst | 20 ++++++++++++++++++++ doc/en/changelog.rst | 25 +++++++++++++++++++++++++ doc/en/getting-started.rst | 2 +- 9 files changed, 47 insertions(+), 6 deletions(-) delete mode 100644 changelog/11091.doc.rst delete mode 100644 changelog/11146.bugfix.rst delete mode 100644 changelog/11572.bugfix.rst delete mode 100644 changelog/11710.bugfix.rst delete mode 100644 changelog/7966.bugfix.rst create mode 100644 doc/en/announce/release-7.4.4.rst diff --git a/changelog/11091.doc.rst b/changelog/11091.doc.rst deleted file mode 100644 index 429f2ac283b..00000000000 --- a/changelog/11091.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Updated documentation and tests to refer to hyphonated options: replaced ``--junitxml`` with ``--junit-xml`` and ``--collectonly`` with ``--collect-only``. diff --git a/changelog/11146.bugfix.rst b/changelog/11146.bugfix.rst deleted file mode 100644 index 03b468f3018..00000000000 --- a/changelog/11146.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -- Prevent constants at the top of file from being detected as docstrings. diff --git a/changelog/11572.bugfix.rst b/changelog/11572.bugfix.rst deleted file mode 100644 index 7a235a071fe..00000000000 --- a/changelog/11572.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Handle an edge case where :data:`sys.stderr` and :data:`sys.__stderr__` might already be closed when :ref:`faulthandler` is tearing down. diff --git a/changelog/11710.bugfix.rst b/changelog/11710.bugfix.rst deleted file mode 100644 index 4bbf9fa2e7d..00000000000 --- a/changelog/11710.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed tracebacks from collection errors not getting pruned. diff --git a/changelog/7966.bugfix.rst b/changelog/7966.bugfix.rst deleted file mode 100644 index de055768066..00000000000 --- a/changelog/7966.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Removes unhelpful error message from assertion rewrite mechanism when exceptions raised in __iter__ methods, and instead treats them as un-iterable. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 854666f6725..35fd2c814e2 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-7.4.4 release-7.4.3 release-7.4.2 release-7.4.1 diff --git a/doc/en/announce/release-7.4.4.rst b/doc/en/announce/release-7.4.4.rst new file mode 100644 index 00000000000..c9633678d2e --- /dev/null +++ b/doc/en/announce/release-7.4.4.rst @@ -0,0 +1,20 @@ +pytest-7.4.4 +======================================= + +pytest 7.4.4 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Ran Benita +* Zac Hatfield-Dodds + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 35ea4fa3280..4a3b9cdf652 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,31 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 7.4.4 (2023-12-31) +========================= + +Bug Fixes +--------- + +- `#11140 `_: Fix non-string constants at the top of file being detected as docstrings on Python>=3.8. + + +- `#11572 `_: Handle an edge case where :data:`sys.stderr` and :data:`sys.__stderr__` might already be closed when :ref:`faulthandler` is tearing down. + + +- `#11710 `_: Fixed tracebacks from collection errors not getting pruned. + + +- `#7966 `_: Removed unhelpful error message from assertion rewrite mechanism when exceptions are raised in ``__iter__`` methods. Now they are treated un-iterable instead. + + + +Improved Documentation +---------------------- + +- `#11091 `_: Updated documentation to refer to hyphenated options: replaced ``--junitxml`` with ``--junit-xml`` and ``--collectonly`` with ``--collect-only``. + + pytest 7.4.3 (2023-10-24) ========================= diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 3b9d773b00c..c1de6271ed0 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 7.4.3 + pytest 7.4.4 .. _`simpletest`: From d3c7ba310ceafe05f1115fa5b6770d1329504aae Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 2 Jan 2024 10:58:20 +0200 Subject: [PATCH 0325/1271] Merge pull request #11744 from pytest-dev/release-8.0.0rc1 Prepare release 8.0.0rc1 (cherry picked from commit 665e4e58d3fba8319e922674c286e92f070e6ec3) --- changelog/10441.feature.rst | 2 - changelog/10465.deprecation.rst | 1 - changelog/10617.feature.rst | 2 - changelog/10701.bugfix.rst | 2 - changelog/11011.doc.rst | 1 - changelog/11065.doc.rst | 3 - changelog/11122.improvement.rst | 6 - changelog/11137.breaking.rst | 11 - changelog/11151.breaking.rst | 1 - changelog/11208.trivial.rst | 2 - changelog/11216.improvement.rst | 1 - changelog/11218.trivial.rst | 5 - changelog/11227.improvement.rst | 1 - changelog/11255.bugfix.rst | 1 - changelog/11277.bugfix.rst | 2 - changelog/11282.breaking.rst | 11 - changelog/11314.improvement.rst | 2 - changelog/11315.trivial.rst | 3 - changelog/11333.trivial.rst | 2 - changelog/11353.trivial.rst | 1 - changelog/11387.feature.rst | 5 - changelog/11447.improvement.rst | 1 - changelog/11456.bugfix.rst | 4 - changelog/11520.improvement.rst | 5 - changelog/11563.bugfix.rst | 1 - changelog/11600.improvement.rst | 1 - changelog/11610.feature.rst | 2 - changelog/11638.trivial.rst | 1 - changelog/11667.breaking.rst | 3 - changelog/11676.breaking.rst | 3 - changelog/11712.bugfix.rst | 1 - changelog/1531.improvement.rst | 4 - changelog/3664.deprecation.rst | 3 - changelog/7363.breaking.rst | 22 -- changelog/7469.feature.rst | 1 - changelog/7777.breaking.rst | 90 ------ changelog/8976.breaking.rst | 5 - changelog/9036.bugfix.rst | 1 - changelog/9288.breaking.rst | 7 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.0.0rc1.rst | 82 ++++++ doc/en/builtin.rst | 26 +- doc/en/changelog.rst | 371 ++++++++++++++++++++++++ doc/en/example/markers.rst | 28 +- doc/en/example/nonpython.rst | 6 +- doc/en/example/parametrize.rst | 62 ++-- doc/en/example/pythoncollection.rst | 27 +- doc/en/example/reportingdemo.rst | 19 +- doc/en/example/simple.rst | 58 ++-- doc/en/getting-started.rst | 6 +- doc/en/how-to/assert.rst | 9 +- doc/en/how-to/cache.rst | 8 +- doc/en/how-to/capture-stdout-stderr.rst | 2 +- doc/en/how-to/capture-warnings.rst | 2 +- doc/en/how-to/doctest.rst | 4 +- doc/en/how-to/fixtures.rst | 49 ++-- doc/en/how-to/output.rst | 63 ++-- doc/en/how-to/parametrize.rst | 4 +- doc/en/how-to/tmp_path.rst | 2 +- doc/en/how-to/unittest.rst | 2 +- doc/en/how-to/writing_plugins.rst | 2 +- doc/en/index.rst | 2 +- doc/en/reference/reference.rst | 4 + 63 files changed, 673 insertions(+), 386 deletions(-) delete mode 100644 changelog/10441.feature.rst delete mode 100644 changelog/10465.deprecation.rst delete mode 100644 changelog/10617.feature.rst delete mode 100644 changelog/10701.bugfix.rst delete mode 100644 changelog/11011.doc.rst delete mode 100644 changelog/11065.doc.rst delete mode 100644 changelog/11122.improvement.rst delete mode 100644 changelog/11137.breaking.rst delete mode 100644 changelog/11151.breaking.rst delete mode 100644 changelog/11208.trivial.rst delete mode 100644 changelog/11216.improvement.rst delete mode 100644 changelog/11218.trivial.rst delete mode 100644 changelog/11227.improvement.rst delete mode 100644 changelog/11255.bugfix.rst delete mode 100644 changelog/11277.bugfix.rst delete mode 100644 changelog/11282.breaking.rst delete mode 100644 changelog/11314.improvement.rst delete mode 100644 changelog/11315.trivial.rst delete mode 100644 changelog/11333.trivial.rst delete mode 100644 changelog/11353.trivial.rst delete mode 100644 changelog/11387.feature.rst delete mode 100644 changelog/11447.improvement.rst delete mode 100644 changelog/11456.bugfix.rst delete mode 100644 changelog/11520.improvement.rst delete mode 100644 changelog/11563.bugfix.rst delete mode 100644 changelog/11600.improvement.rst delete mode 100644 changelog/11610.feature.rst delete mode 100644 changelog/11638.trivial.rst delete mode 100644 changelog/11667.breaking.rst delete mode 100644 changelog/11676.breaking.rst delete mode 100644 changelog/11712.bugfix.rst delete mode 100644 changelog/1531.improvement.rst delete mode 100644 changelog/3664.deprecation.rst delete mode 100644 changelog/7363.breaking.rst delete mode 100644 changelog/7469.feature.rst delete mode 100644 changelog/7777.breaking.rst delete mode 100644 changelog/8976.breaking.rst delete mode 100644 changelog/9036.bugfix.rst delete mode 100644 changelog/9288.breaking.rst create mode 100644 doc/en/announce/release-8.0.0rc1.rst diff --git a/changelog/10441.feature.rst b/changelog/10441.feature.rst deleted file mode 100644 index 0019926ac4d..00000000000 --- a/changelog/10441.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added :func:`ExceptionInfo.group_contains() `, an assertion -helper that tests if an `ExceptionGroup` contains a matching exception. diff --git a/changelog/10465.deprecation.rst b/changelog/10465.deprecation.rst deleted file mode 100644 index a715af5e624..00000000000 --- a/changelog/10465.deprecation.rst +++ /dev/null @@ -1 +0,0 @@ -Test functions returning a value other than None will now issue a :class:`pytest.PytestWarning` instead of :class:`pytest.PytestRemovedIn8Warning`, meaning this will stay a warning instead of becoming an error in the future. diff --git a/changelog/10617.feature.rst b/changelog/10617.feature.rst deleted file mode 100644 index c99ec488912..00000000000 --- a/changelog/10617.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added more comprehensive set assertion rewrites for comparisons other than equality ``==``, with -the following operations now providing better failure messages: ``!=``, ``<=``, ``>=``, ``<``, and ``>``. diff --git a/changelog/10701.bugfix.rst b/changelog/10701.bugfix.rst deleted file mode 100644 index f33fa7fb28b..00000000000 --- a/changelog/10701.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -:meth:`pytest.WarningsRecorder.pop` will return the most-closely-matched warning in the list, -rather than the first warning which is an instance of the requested type. diff --git a/changelog/11011.doc.rst b/changelog/11011.doc.rst deleted file mode 100644 index 5faabba9c8f..00000000000 --- a/changelog/11011.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Added a warning about modifying the root logger during tests when using ``caplog``. diff --git a/changelog/11065.doc.rst b/changelog/11065.doc.rst deleted file mode 100644 index 70a3db92c09..00000000000 --- a/changelog/11065.doc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Use pytestconfig instead of request.config in cache example - -to be consistent with the API documentation. diff --git a/changelog/11122.improvement.rst b/changelog/11122.improvement.rst deleted file mode 100644 index dedaa7d087b..00000000000 --- a/changelog/11122.improvement.rst +++ /dev/null @@ -1,6 +0,0 @@ -``pluggy>=1.2.0`` is now required. - -pytest now uses "new-style" hook wrappers internally, available since pluggy 1.2.0. -See `pluggy's 1.2.0 changelog `_ and the :ref:`updated docs ` for details. - -Plugins which want to use new-style wrappers can do so if they require this version of pytest or later. diff --git a/changelog/11137.breaking.rst b/changelog/11137.breaking.rst deleted file mode 100644 index a92df326a49..00000000000 --- a/changelog/11137.breaking.rst +++ /dev/null @@ -1,11 +0,0 @@ -:class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File`. - -The ``Package`` collector node designates a Python package, that is, a directory with an `__init__.py` file. -Previously ``Package`` was a subtype of ``pytest.Module`` (which represents a single Python module), -the module being the `__init__.py` file. -This has been deemed a design mistake (see :issue:`11137` and :issue:`7777` for details). - -The ``path`` property of ``Package`` nodes now points to the package directory instead of the ``__init__.py`` file. - -Note that a ``Module`` node for ``__init__.py`` (which is not a ``Package``) may still exist, -if it is picked up during collection (e.g. if you configured :confval:`python_files` to include ``__init__.py`` files). diff --git a/changelog/11151.breaking.rst b/changelog/11151.breaking.rst deleted file mode 100644 index 114a7d8e20b..00000000000 --- a/changelog/11151.breaking.rst +++ /dev/null @@ -1 +0,0 @@ -Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27 `__. diff --git a/changelog/11208.trivial.rst b/changelog/11208.trivial.rst deleted file mode 100644 index fced57b2084..00000000000 --- a/changelog/11208.trivial.rst +++ /dev/null @@ -1,2 +0,0 @@ -The (internal) ``FixtureDef.cached_result`` type has changed. -Now the third item ``cached_result[2]``, when set, is an exception instance instead of an exception triplet. diff --git a/changelog/11216.improvement.rst b/changelog/11216.improvement.rst deleted file mode 100644 index 80761de5c6e..00000000000 --- a/changelog/11216.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -If a test is skipped from inside an :ref:`xunit setup fixture `, the test summary now shows the test location instead of the fixture location. diff --git a/changelog/11218.trivial.rst b/changelog/11218.trivial.rst deleted file mode 100644 index 772054856d2..00000000000 --- a/changelog/11218.trivial.rst +++ /dev/null @@ -1,5 +0,0 @@ -(This entry is meant to assist plugins which access private pytest internals to instantiate ``FixtureRequest`` objects.) - -:class:`~pytest.FixtureRequest` is now an abstract class which can't be instantiated directly. -A new concrete ``TopRequest`` subclass of ``FixtureRequest`` has been added for the ``request`` fixture in test functions, -as counterpart to the existing ``SubRequest`` subclass for the ``request`` fixture in fixture functions. diff --git a/changelog/11227.improvement.rst b/changelog/11227.improvement.rst deleted file mode 100644 index 3c6748c3d3f..00000000000 --- a/changelog/11227.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Allow :func:`pytest.raises` ``match`` argument to match against `PEP-678 ` ``__notes__``. diff --git a/changelog/11255.bugfix.rst b/changelog/11255.bugfix.rst deleted file mode 100644 index 2a2a42667a3..00000000000 --- a/changelog/11255.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed crash on `parametrize(..., scope="package")` without a package present. diff --git a/changelog/11277.bugfix.rst b/changelog/11277.bugfix.rst deleted file mode 100644 index 43370561e3b..00000000000 --- a/changelog/11277.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed a bug that when there are multiple fixtures for an indirect parameter, -the scope of the highest-scope fixture is picked for the parameter set, instead of that of the one with the narrowest scope. diff --git a/changelog/11282.breaking.rst b/changelog/11282.breaking.rst deleted file mode 100644 index cee9788ef1c..00000000000 --- a/changelog/11282.breaking.rst +++ /dev/null @@ -1,11 +0,0 @@ -Sanitized the handling of the ``default`` parameter when defining configuration options. - -Previously if ``default`` was not supplied for :meth:`parser.addini ` and the configuration option value was not defined in a test session, then calls to :func:`config.getini ` returned an *empty list* or an *empty string* depending on whether ``type`` was supplied or not respectively, which is clearly incorrect. Also, ``None`` was not honored even if ``default=None`` was used explicitly while defining the option. - -Now the behavior of :meth:`parser.addini ` is as follows: - -* If ``default`` is NOT passed but ``type`` is provided, then a type-specific default will be returned. For example ``type=bool`` will return ``False``, ``type=str`` will return ``""``, etc. -* If ``default=None`` is passed and the option is not defined in a test session, then ``None`` will be returned, regardless of the ``type``. -* If neither ``default`` nor ``type`` are provided, assume ``type=str`` and return ``""`` as default (this is as per previous behavior). - -The team decided to not introduce a deprecation period for this change, as doing so would be complicated both in terms of communicating this to the community as well as implementing it, and also because the team believes this change should not break existing plugins except in rare cases. diff --git a/changelog/11314.improvement.rst b/changelog/11314.improvement.rst deleted file mode 100644 index 272af21f528..00000000000 --- a/changelog/11314.improvement.rst +++ /dev/null @@ -1,2 +0,0 @@ -Logging to a file using the ``--log-file`` option will use ``--log-level``, ``--log-format`` and ``--log-date-format`` as fallback -if ``--log-file-level``, ``--log-file-format`` and ``--log-file-date-format`` are not provided respectively. diff --git a/changelog/11315.trivial.rst b/changelog/11315.trivial.rst deleted file mode 100644 index 309dccd8b40..00000000000 --- a/changelog/11315.trivial.rst +++ /dev/null @@ -1,3 +0,0 @@ -The :fixture:`pytester` fixture now uses the :fixture:`monkeypatch` fixture to manage the current working directory. -If you use ``pytester`` in combination with :func:`monkeypatch.undo() `, the CWD might get restored. -Use :func:`monkeypatch.context() ` instead. diff --git a/changelog/11333.trivial.rst b/changelog/11333.trivial.rst deleted file mode 100644 index 846f79e34a7..00000000000 --- a/changelog/11333.trivial.rst +++ /dev/null @@ -1,2 +0,0 @@ -Corrected the spelling of ``Config.ArgsSource.INVOCATION_DIR``. -The previous spelling ``INCOVATION_DIR`` remains as an alias. diff --git a/changelog/11353.trivial.rst b/changelog/11353.trivial.rst deleted file mode 100644 index 10a6b46927f..00000000000 --- a/changelog/11353.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -pluggy>=1.3.0 is now required. This adds typing to :class:`~pytest.PytestPluginManager`. diff --git a/changelog/11387.feature.rst b/changelog/11387.feature.rst deleted file mode 100644 index 90f20885b0a..00000000000 --- a/changelog/11387.feature.rst +++ /dev/null @@ -1,5 +0,0 @@ -Added the new :confval:`verbosity_assertions` configuration option for fine-grained control of failed assertions verbosity. - -See :ref:`Fine-grained verbosity ` for more details. - -For plugin authors, :attr:`config.get_verbosity ` can be used to retrieve the verbosity level for a specific verbosity type. diff --git a/changelog/11447.improvement.rst b/changelog/11447.improvement.rst deleted file mode 100644 index 96be8dffe60..00000000000 --- a/changelog/11447.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`pytest.deprecated_call` now also considers warnings of type :class:`FutureWarning`. diff --git a/changelog/11456.bugfix.rst b/changelog/11456.bugfix.rst deleted file mode 100644 index 77a2ccfb002..00000000000 --- a/changelog/11456.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -Parametrized tests now *really do* ensure that the ids given to each input are unique - for -example, ``a, a, a0`` now results in ``a1, a2, a0`` instead of the previous (buggy) ``a0, a1, a0``. -This necessarily means changing nodeids where these were previously colliding, and for -readability adds an underscore when non-unique ids end in a number. diff --git a/changelog/11520.improvement.rst b/changelog/11520.improvement.rst deleted file mode 100644 index 548d52a12ba..00000000000 --- a/changelog/11520.improvement.rst +++ /dev/null @@ -1,5 +0,0 @@ -Improved very verbose diff output to color it as a diff instead of only red. - -Improved the error reporting to better separate each section. - -Improved the error reporting to syntax-highlight Python code when Pygments is available. diff --git a/changelog/11563.bugfix.rst b/changelog/11563.bugfix.rst deleted file mode 100644 index 35b5e4f15a1..00000000000 --- a/changelog/11563.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed crash when using an empty string for the same parametrized value more than once. diff --git a/changelog/11600.improvement.rst b/changelog/11600.improvement.rst deleted file mode 100644 index 7082e2c1e10..00000000000 --- a/changelog/11600.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Improved the documentation and type signature for :func:`pytest.mark.xfail `'s ``condition`` param to use ``False`` as the default value. diff --git a/changelog/11610.feature.rst b/changelog/11610.feature.rst deleted file mode 100644 index 34df3470509..00000000000 --- a/changelog/11610.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added :func:`LogCaptureFixture.filtering() ` context manager that -adds a given :class:`logging.Filter` object to the caplog fixture. diff --git a/changelog/11638.trivial.rst b/changelog/11638.trivial.rst deleted file mode 100644 index 374960b8925..00000000000 --- a/changelog/11638.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the selftests to pass correctly if ``FORCE_COLOR``, ``NO_COLOR`` or ``PY_COLORS`` is set in the calling environment. diff --git a/changelog/11667.breaking.rst b/changelog/11667.breaking.rst deleted file mode 100644 index 7c05d39b2e4..00000000000 --- a/changelog/11667.breaking.rst +++ /dev/null @@ -1,3 +0,0 @@ -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 `_ for alternatives. diff --git a/changelog/11676.breaking.rst b/changelog/11676.breaking.rst deleted file mode 100644 index f20efa80db0..00000000000 --- a/changelog/11676.breaking.rst +++ /dev/null @@ -1,3 +0,0 @@ -The classes :class:`~_pytest.nodes.Node`, :class:`~pytest.Collector`, :class:`~pytest.Item`, :class:`~pytest.File`, :class:`~_pytest.nodes.FSCollector` are now marked abstract (see :mod:`abc`). - -We do not expect this change to affect users and plugin authors, it will only cause errors when the code is already wrong or problematic. diff --git a/changelog/11712.bugfix.rst b/changelog/11712.bugfix.rst deleted file mode 100644 index 416d761493d..00000000000 --- a/changelog/11712.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed handling ``NO_COLOR`` and ``FORCE_COLOR`` to ignore an empty value. diff --git a/changelog/1531.improvement.rst b/changelog/1531.improvement.rst deleted file mode 100644 index d444ea2e783..00000000000 --- a/changelog/1531.improvement.rst +++ /dev/null @@ -1,4 +0,0 @@ -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. diff --git a/changelog/3664.deprecation.rst b/changelog/3664.deprecation.rst deleted file mode 100644 index 0a00e26c19f..00000000000 --- a/changelog/3664.deprecation.rst +++ /dev/null @@ -1,3 +0,0 @@ -Applying a mark to a fixture function now issues a warning: marks in fixtures never had any effect, but it is a common user error to apply a mark to a fixture (for example ``usefixtures``) and expect it to work. - -This will become an error in the future. diff --git a/changelog/7363.breaking.rst b/changelog/7363.breaking.rst deleted file mode 100644 index 93d87b1b104..00000000000 --- a/changelog/7363.breaking.rst +++ /dev/null @@ -1,22 +0,0 @@ -**PytestRemovedIn8Warning deprecation warnings are now errors by default.** - -Following our plan to remove deprecated features with as little disruption as -possible, all warnings of type ``PytestRemovedIn8Warning`` now generate errors -instead of warning messages by default. - -**The affected features will be effectively removed in pytest 8.1**, so please consult the -:ref:`deprecations` section in the docs for directions on how to update existing code. - -In the pytest ``8.0.X`` series, it is possible to change the errors back into warnings as a -stopgap measure by adding this to your ``pytest.ini`` file: - -.. code-block:: ini - - [pytest] - filterwarnings = - ignore::pytest.PytestRemovedIn8Warning - -But this will stop working when pytest ``8.1`` is released. - -**If you have concerns** about the removal of a specific feature, please add a -comment to :issue:`7363`. diff --git a/changelog/7469.feature.rst b/changelog/7469.feature.rst deleted file mode 100644 index 8e9df72697c..00000000000 --- a/changelog/7469.feature.rst +++ /dev/null @@ -1 +0,0 @@ -:class:`~pytest.FixtureDef` is now exported as ``pytest.FixtureDef`` for typing purposes. diff --git a/changelog/7777.breaking.rst b/changelog/7777.breaking.rst deleted file mode 100644 index d38fea33096..00000000000 --- a/changelog/7777.breaking.rst +++ /dev/null @@ -1,90 +0,0 @@ -Added a new :class:`pytest.Directory` base collection node, which all collector nodes for filesystem directories are expected to subclass. -This is analogous to the existing :class:`pytest.File` for file nodes. - -Changed :class:`pytest.Package` to be a subclass of :class:`pytest.Directory`. -A ``Package`` represents a filesystem directory which is a Python package, -i.e. contains an ``__init__.py`` file. - -:class:`pytest.Package` now only collects files in its own directory; previously it collected recursively. -Sub-directories are collected as sub-collector nodes, thus creating a collection tree which mirrors the filesystem hierarchy. - -Added a new :class:`pytest.Dir` concrete collection node, a subclass of :class:`pytest.Directory`. -This node represents a filesystem directory, which is not a :class:`pytest.Package`, -i.e. does not contain an ``__init__.py`` file. -Similarly to ``Package``, it only collects the files in its own directory, -while collecting sub-directories as sub-collector nodes. - -Added a new hook :hook:`pytest_collect_directory`, -which is called by filesystem-traversing collector nodes, -such as :class:`pytest.Session`, :class:`pytest.Dir` and :class:`pytest.Package`, -to create a collector node for a sub-directory. -It is expected to return a subclass of :class:`pytest.Directory`. -This hook allows plugins to :ref:`customize the collection of directories `. - -:class:`pytest.Session` now only collects the initial arguments, without recursing into directories. -This work is now done by the :func:`recursive expansion process ` of directory collector nodes. - -:attr:`session.name ` is now ``""``; previously it was the rootdir directory name. -This matches :attr:`session.nodeid <_pytest.nodes.Node.nodeid>` which has always been `""`. - -Files and directories are now collected in alphabetical order jointly, unless changed by a plugin. -Previously, files were collected before directories. - -The collection tree now contains directories/packages up to the :ref:`rootdir `, -for initial arguments that are found within the rootdir. -For files outside the rootdir, only the immediate directory/package is collected -- -note however that collecting from outside the rootdir is discouraged. - -As an example, given the following filesystem tree:: - - myroot/ - pytest.ini - top/ - ├── aaa - │ └── test_aaa.py - ├── test_a.py - ├── test_b - │ ├── __init__.py - │ └── test_b.py - ├── test_c.py - └── zzz - ├── __init__.py - └── test_zzz.py - -the collection tree, as shown by `pytest --collect-only top/` but with the otherwise-hidden :class:`~pytest.Session` node added for clarity, -is now the following:: - - - - - - - - - - - - - - - - - - -Previously, it was:: - - - - - - - - - - - - - - - -Code/plugins which rely on a specific shape of the collection tree might need to update. diff --git a/changelog/8976.breaking.rst b/changelog/8976.breaking.rst deleted file mode 100644 index bd9a63982b9..00000000000 --- a/changelog/8976.breaking.rst +++ /dev/null @@ -1,5 +0,0 @@ -Running `pytest pkg/__init__.py` now collects the `pkg/__init__.py` file (module) only. -Previously, it collected the entire `pkg` package, including other test files in the directory, but excluding tests in the `__init__.py` file itself -(unless :confval:`python_files` was changed to allow `__init__.py` file). - -To collect the entire package, specify just the directory: `pytest pkg`. diff --git a/changelog/9036.bugfix.rst b/changelog/9036.bugfix.rst deleted file mode 100644 index 4f25f82e292..00000000000 --- a/changelog/9036.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -``pytest.warns`` and similar functions now capture warnings when an exception is raised inside a ``with`` block. diff --git a/changelog/9288.breaking.rst b/changelog/9288.breaking.rst deleted file mode 100644 index c344b83c764..00000000000 --- a/changelog/9288.breaking.rst +++ /dev/null @@ -1,7 +0,0 @@ -:func:`~pytest.warns` now re-emits unmatched warnings when the context -closes -- previously it would consume all warnings, hiding those that were not -matched by the function. - -While this is a new feature, we decided to announce this as a breaking change -because many test suites are configured to error-out on warnings, and will -therefore fail on the newly-re-emitted warnings. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 35fd2c814e2..740767c017e 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.0.0rc1 release-7.4.4 release-7.4.3 release-7.4.2 diff --git a/doc/en/announce/release-8.0.0rc1.rst b/doc/en/announce/release-8.0.0rc1.rst new file mode 100644 index 00000000000..547c8cbc53b --- /dev/null +++ b/doc/en/announce/release-8.0.0rc1.rst @@ -0,0 +1,82 @@ +pytest-8.0.0rc1 +======================================= + +The pytest team is proud to announce the 8.0.0rc1 release! + +This release contains new features, improvements, bug fixes, and breaking changes, so users +are encouraged to take a look at the CHANGELOG carefully: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Akhilesh Ramakrishnan +* Aleksandr Brodin +* Anthony Sottile +* Arthur Richard +* Avasam +* Benjamin Schubert +* Bruno Oliveira +* Carsten Grohmann +* Cheukting +* Chris Mahoney +* Christoph Anton Mitterer +* DetachHead +* Erik Hasse +* Florian Bruhin +* Fraser Stark +* Ha Pam +* Hugo van Kemenade +* Isaac Virshup +* Israel Fruchter +* Jens Tröger +* Jon Parise +* Kenny Y +* Lesnek +* Marc Mueller +* Michał Górny +* Mihail Milushev +* Milan Lesnek +* Miro Hrončok +* Patrick Lannigan +* Ran Benita +* Reagan Lee +* Ronny Pfannschmidt +* Sadra Barikbin +* Sean Malloy +* Sean Patrick Malloy +* Sharad Nair +* Simon Blanchard +* Sourabh Beniwal +* Stefaan Lippens +* Tanya Agarwal +* Thomas Grainger +* Tom Mortimer-Jones +* Tushar Sadhwani +* Tyler Smart +* Uday Kumar +* Warren Markham +* WarrenTheRabbit +* Zac Hatfield-Dodds +* Ziad Kermadi +* akhilramkee +* antosikv +* bowugit +* mickeypash +* neilmartin2000 +* pomponchik +* ryanpudd +* touilleWoman +* ubaumann + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 405289444a8..2acbce96606 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -18,11 +18,11 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a $ pytest --fixtures -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:532 + cache -- .../_pytest/cacheprovider.py:526 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1001 + capsysbinary -- .../_pytest/capture.py:1008 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -51,7 +51,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1029 + capfd -- .../_pytest/capture.py:1036 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -69,7 +69,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1057 + capfdbinary -- .../_pytest/capture.py:1064 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -87,7 +87,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - capsys -- .../_pytest/capture.py:973 + capsys -- .../_pytest/capture.py:980 Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsys.readouterr()`` method @@ -105,7 +105,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:757 + doctest_namespace [session scope] -- .../_pytest/doctest.py:743 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -119,7 +119,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1353 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1365 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -174,10 +174,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a `pytest-xdist `__ plugin. See :issue:`7767` for details. - tmpdir_factory [session scope] -- .../_pytest/legacypath.py:302 + tmpdir_factory [session scope] -- .../_pytest/legacypath.py:300 Return a :class:`pytest.TempdirFactory` instance for the test session. - tmpdir -- .../_pytest/legacypath.py:309 + tmpdir -- .../_pytest/legacypath.py:307 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. @@ -196,7 +196,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:570 + caplog -- .../_pytest/logging.py:593 Access and control log capturing. Captured logs are available through the following properties/methods:: @@ -237,10 +237,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information on warning categories. - tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:245 + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:239 Return a :class:`pytest.TempPathFactory` instance for the test session. - tmp_path -- .../_pytest/tmpdir.py:260 + tmp_path -- .../_pytest/tmpdir.py:254 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 4a3b9cdf652..85ba6140ac3 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,377 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.0.0rc1 (2023-12-30) +============================ + +Breaking Changes +---------------- + +Old Deprecations Are Now Errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- `#7363 `_: **PytestRemovedIn8Warning deprecation warnings are now errors by default.** + + Following our plan to remove deprecated features with as little disruption as + possible, all warnings of type ``PytestRemovedIn8Warning`` now generate errors + instead of warning messages by default. + + **The affected features will be effectively removed in pytest 8.1**, so please consult the + :ref:`deprecations` section in the docs for directions on how to update existing code. + + In the pytest ``8.0.X`` series, it is possible to change the errors back into warnings as a + stopgap measure by adding this to your ``pytest.ini`` file: + + .. code-block:: ini + + [pytest] + filterwarnings = + ignore::pytest.PytestRemovedIn8Warning + + But this will stop working when pytest ``8.1`` is released. + + **If you have concerns** about the removal of a specific feature, please add a + comment to :issue:`7363`. + + +Version Compatibility +^^^^^^^^^^^^^^^^^^^^^ + +- `#11151 `_: Dropped support for Python 3.7, which `reached end-of-life on 2023-06-27 `__. + + +- ``pluggy>=1.3.0`` is now required. + + +Collection Changes +^^^^^^^^^^^^^^^^^^ + +In this version we've made several breaking changes to pytest's collection phase, +particularly around how filesystem directories and Python packages are collected, +fixing deficiencies and allowing for cleanups and improvements to pytest's internals. +A deprecation period for these changes was not possible. + + +- `#7777 `_: Files and directories are now collected in alphabetical order jointly, unless changed by a plugin. + Previously, files were collected before directories. + See below for an example. + + +- `#8976 `_: Running `pytest pkg/__init__.py` now collects the `pkg/__init__.py` file (module) only. + Previously, it collected the entire `pkg` package, including other test files in the directory, but excluding tests in the `__init__.py` file itself + (unless :confval:`python_files` was changed to allow `__init__.py` file). + + To collect the entire package, specify just the directory: `pytest pkg`. + + +- `#11137 `_: :class:`pytest.Package` is no longer a :class:`pytest.Module` or :class:`pytest.File`. + + The ``Package`` collector node designates a Python package, that is, a directory with an `__init__.py` file. + Previously ``Package`` was a subtype of ``pytest.Module`` (which represents a single Python module), + the module being the `__init__.py` file. + This has been deemed a design mistake (see :issue:`11137` and :issue:`7777` for details). + + The ``path`` property of ``Package`` nodes now points to the package directory instead of the ``__init__.py`` file. + + Note that a ``Module`` node for ``__init__.py`` (which is not a ``Package``) may still exist, + if it is picked up during collection (e.g. if you configured :confval:`python_files` to include ``__init__.py`` files). + + +- `#7777 `_: Added a new :class:`pytest.Directory` base collection node, which all collector nodes for filesystem directories are expected to subclass. + This is analogous to the existing :class:`pytest.File` for file nodes. + + Changed :class:`pytest.Package` to be a subclass of :class:`pytest.Directory`. + A ``Package`` represents a filesystem directory which is a Python package, + i.e. contains an ``__init__.py`` file. + + :class:`pytest.Package` now only collects files in its own directory; previously it collected recursively. + Sub-directories are collected as their own collector nodes, which then collect themselves, thus creating a collection tree which mirrors the filesystem hierarchy. + + Added a new :class:`pytest.Dir` concrete collection node, a subclass of :class:`pytest.Directory`. + This node represents a filesystem directory, which is not a :class:`pytest.Package`, + that is, does not contain an ``__init__.py`` file. + Similarly to ``Package``, it only collects the files in its own directory. + + :class:`pytest.Session` now only collects the initial arguments, without recursing into directories. + This work is now done by the :func:`recursive expansion process ` of directory collector nodes. + + :attr:`session.name ` is now ``""``; previously it was the rootdir directory name. + This matches :attr:`session.nodeid <_pytest.nodes.Node.nodeid>` which has always been `""`. + + The collection tree now contains directories/packages up to the :ref:`rootdir `, + for initial arguments that are found within the rootdir. + For files outside the rootdir, only the immediate directory/package is collected -- + note however that collecting from outside the rootdir is discouraged. + + As an example, given the following filesystem tree:: + + myroot/ + pytest.ini + top/ + ├── aaa + │ └── test_aaa.py + ├── test_a.py + ├── test_b + │ ├── __init__.py + │ └── test_b.py + ├── test_c.py + └── zzz + ├── __init__.py + └── test_zzz.py + + the collection tree, as shown by `pytest --collect-only top/` but with the otherwise-hidden :class:`~pytest.Session` node added for clarity, + is now the following:: + + + + + + + + + + + + + + + + + + + Previously, it was:: + + + + + + + + + + + + + + + + Code/plugins which rely on a specific shape of the collection tree might need to update. + + +- `#11676 `_: The classes :class:`~_pytest.nodes.Node`, :class:`~pytest.Collector`, :class:`~pytest.Item`, :class:`~pytest.File`, :class:`~_pytest.nodes.FSCollector` are now marked abstract (see :mod:`abc`). + + We do not expect this change to affect users and plugin authors, it will only cause errors when the code is already wrong or problematic. + + +Other breaking changes +^^^^^^^^^^^^^^^^^^^^^^ + +These are breaking changes where deprecation was not possible. + + +- `#11282 `_: Sanitized the handling of the ``default`` parameter when defining configuration options. + + Previously if ``default`` was not supplied for :meth:`parser.addini ` and the configuration option value was not defined in a test session, then calls to :func:`config.getini ` returned an *empty list* or an *empty string* depending on whether ``type`` was supplied or not respectively, which is clearly incorrect. Also, ``None`` was not honored even if ``default=None`` was used explicitly while defining the option. + + Now the behavior of :meth:`parser.addini ` is as follows: + + * If ``default`` is NOT passed but ``type`` is provided, then a type-specific default will be returned. For example ``type=bool`` will return ``False``, ``type=str`` will return ``""``, etc. + * If ``default=None`` is passed and the option is not defined in a test session, then ``None`` will be returned, regardless of the ``type``. + * If neither ``default`` nor ``type`` are provided, assume ``type=str`` and return ``""`` as default (this is as per previous behavior). + + The team decided to not introduce a deprecation period for this change, as doing so would be complicated both in terms of communicating this to the community as well as implementing it, and also because the team believes this change should not break existing plugins except in rare cases. + + +- `#11667 `_: 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 `_ for alternatives. + + +- `#9288 `_: :func:`~pytest.warns` now re-emits unmatched warnings when the context + closes -- previously it would consume all warnings, hiding those that were not + matched by the function. + + While this is a new feature, we announce it as a breaking change + because many test suites are configured to error-out on warnings, and will + therefore fail on the newly-re-emitted warnings. + + + +Deprecations +------------ + +- `#10465 `_: Test functions returning a value other than ``None`` will now issue a :class:`pytest.PytestWarning` instead of :class:`pytest.PytestRemovedIn8Warning`, meaning this will stay a warning instead of becoming an error in the future. + + +- `#3664 `_: Applying a mark to a fixture function now issues a warning: marks in fixtures never had any effect, but it is a common user error to apply a mark to a fixture (for example ``usefixtures``) and expect it to work. + + This will become an error in pytest 9.0. + + + +Features and Improvements +------------------------- + +Improved Diffs +^^^^^^^^^^^^^^ + +These changes improve the diffs that pytest prints when an assertion fails. +Note that syntax highlighting requires the ``pygments`` package. + + +- `#11520 `_: The very verbose (``-vv``) diff output is now colored as a diff instead of a big chunk of red. + + Python code in error reports is now syntax-highlighted as Python. + + The sections in the error reports are now better separated. + + +- `#1531 `_: The very verbose diff (``-vv``) for every standard library container type is improved. The indentation is now consistent and the markers are on their own separate lines, which should reduce the diffs shown to users. + + Previously, the standard 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. + + +- `#10617 `_: Added more comprehensive set assertion rewrites for comparisons other than equality ``==``, with + the following operations now providing better failure messages: ``!=``, ``<=``, ``>=``, ``<``, and ``>``. + + +Separate Control For Assertion Verbosity +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- `#11387 `_: Added the new :confval:`verbosity_assertions` configuration option for fine-grained control of failed assertions verbosity. + + If you've ever wished that pytest always show you full diffs, but without making everything else verbose, this is for you. + + See :ref:`Fine-grained verbosity ` for more details. + + For plugin authors, :attr:`config.get_verbosity ` can be used to retrieve the verbosity level for a specific verbosity type. + + +Additional Support For Exception Groups and ``__notes__`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These changes improve pytest's support for exception groups. + + +- `#10441 `_: Added :func:`ExceptionInfo.group_contains() `, an assertion helper that tests if an :class:`ExceptionGroup` contains a matching exception. + + See :ref:`assert-matching-exception-groups` for an example. + + +- `#11227 `_: Allow :func:`pytest.raises` ``match`` argument to match against `PEP-678 ` ``__notes__``. + + +Custom Directory collectors +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- `#7777 `_: Added a new hook :hook:`pytest_collect_directory`, + which is called by filesystem-traversing collector nodes, + such as :class:`pytest.Session`, :class:`pytest.Dir` and :class:`pytest.Package`, + to create a collector node for a sub-directory. + It is expected to return a subclass of :class:`pytest.Directory`. + This hook allows plugins to :ref:`customize the collection of directories `. + + +"New-style" Hook Wrappers +^^^^^^^^^^^^^^^^^^^^^^^^^ + +- `#11122 `_: pytest now uses "new-style" hook wrappers internally, available since pluggy 1.2.0. + See `pluggy's 1.2.0 changelog `_ and the :ref:`updated docs ` for details. + + Plugins which want to use new-style wrappers can do so if they require ``pytest>=8``. + + +Other Improvements +^^^^^^^^^^^^^^^^^^ + +- `#11216 `_: If a test is skipped from inside an :ref:`xunit setup fixture `, the test summary now shows the test location instead of the fixture location. + + +- `#11314 `_: Logging to a file using the ``--log-file`` option will use ``--log-level``, ``--log-format`` and ``--log-date-format`` as fallback + if ``--log-file-level``, ``--log-file-format`` and ``--log-file-date-format`` are not provided respectively. + + +- `#11610 `_: Added the :func:`LogCaptureFixture.filtering() ` context manager which + adds a given :class:`logging.Filter` object to the :fixture:`caplog` fixture. + + +- `#11447 `_: :func:`pytest.deprecated_call` now also considers warnings of type :class:`FutureWarning`. + + +- `#11600 `_: Improved the documentation and type signature for :func:`pytest.mark.xfail `'s ``condition`` param to use ``False`` as the default value. + + +- `#7469 `_: :class:`~pytest.FixtureDef` is now exported as ``pytest.FixtureDef`` for typing purposes. + + +- `#11353 `_: Added typing to :class:`~pytest.PytestPluginManager`. + + +Bug Fixes +--------- + +- `#10701 `_: :meth:`pytest.WarningsRecorder.pop` will return the most-closely-matched warning in the list, + rather than the first warning which is an instance of the requested type. + + +- `#11255 `_: Fixed crash on `parametrize(..., scope="package")` without a package present. + + +- `#11277 `_: Fixed a bug that when there are multiple fixtures for an indirect parameter, + the scope of the highest-scope fixture is picked for the parameter set, instead of that of the one with the narrowest scope. + + +- `#11456 `_: Parametrized tests now *really do* ensure that the ids given to each input are unique - for + example, ``a, a, a0`` now results in ``a1, a2, a0`` instead of the previous (buggy) ``a0, a1, a0``. + This necessarily means changing nodeids where these were previously colliding, and for + readability adds an underscore when non-unique ids end in a number. + + +- `#11563 `_: Fixed a crash when using an empty string for the same parametrized value more than once. + + +- `#11712 `_: Fixed handling ``NO_COLOR`` and ``FORCE_COLOR`` to ignore an empty value. + + +- `#9036 `_: ``pytest.warns`` and similar functions now capture warnings when an exception is raised inside a ``with`` block. + + + +Improved Documentation +---------------------- + +- `#11011 `_: Added a warning about modifying the root logger during tests when using ``caplog``. + + +- `#11065 `_: Use ``pytestconfig`` instead of ``request.config`` in cache example to be consistent with the API documentation. + + +Trivial/Internal Changes +------------------------ + +- `#11208 `_: The (internal) ``FixtureDef.cached_result`` type has changed. + Now the third item ``cached_result[2]``, when set, is an exception instance instead of an exception triplet. + + +- `#11218 `_: (This entry is meant to assist plugins which access private pytest internals to instantiate ``FixtureRequest`` objects.) + + :class:`~pytest.FixtureRequest` is now an abstract class which can't be instantiated directly. + A new concrete ``TopRequest`` subclass of ``FixtureRequest`` has been added for the ``request`` fixture in test functions, + as counterpart to the existing ``SubRequest`` subclass for the ``request`` fixture in fixture functions. + + +- `#11315 `_: The :fixture:`pytester` fixture now uses the :fixture:`monkeypatch` fixture to manage the current working directory. + If you use ``pytester`` in combination with :func:`monkeypatch.undo() `, the CWD might get restored. + Use :func:`monkeypatch.context() ` instead. + + +- `#11333 `_: Corrected the spelling of ``Config.ArgsSource.INVOCATION_DIR``. + The previous spelling ``INCOVATION_DIR`` remains as an alias. + + +- `#11638 `_: Fixed the selftests to pass correctly if ``FORCE_COLOR``, ``NO_COLOR`` or ``PY_COLORS`` is set in the calling environment. + pytest 7.4.4 (2023-12-31) ========================= diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 6cdf4eb42d8..c04d2a078dd 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -45,7 +45,7 @@ You can then restrict a test run to only run tests marked with ``webtest``: $ pytest -v -m webtest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 3 deselected / 1 selected @@ -60,7 +60,7 @@ Or the inverse, running all tests except the webtest ones: $ pytest -v -m "not webtest" =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 1 deselected / 3 selected @@ -82,7 +82,7 @@ tests based on their module, class, method, or function name: $ pytest -v test_server.py::TestClass::test_method =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 1 item @@ -97,7 +97,7 @@ You can also select on the class: $ pytest -v test_server.py::TestClass =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 1 item @@ -112,7 +112,7 @@ Or select multiple nodes: $ pytest -v test_server.py::TestClass test_server.py::test_send_http =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 2 items @@ -156,7 +156,7 @@ The expression matching is now case-insensitive. $ pytest -v -k http # running with the above defined example module =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 3 deselected / 1 selected @@ -171,7 +171,7 @@ And you can also run all tests except the ones that match the keyword: $ pytest -k "not send_http" -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 1 deselected / 3 selected @@ -188,7 +188,7 @@ Or to select "http" and "quick" tests: $ pytest -k "http or quick" -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 4 items / 2 deselected / 2 selected @@ -397,7 +397,7 @@ the test needs: $ pytest -E stage2 =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -411,7 +411,7 @@ and here is one that specifies exactly the environment needed: $ pytest -E stage1 =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -604,7 +604,7 @@ then you will see two tests skipped and two executed tests as expected: $ pytest -rs # this option reports skip reasons =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items @@ -620,7 +620,7 @@ Note that if you specify a platform via the marker-command line option like this $ pytest -m linux =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items / 3 deselected / 1 selected @@ -683,7 +683,7 @@ We can now use the ``-m option`` to select one set: $ pytest -m interface --tb=short =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items / 2 deselected / 2 selected @@ -709,7 +709,7 @@ or to select both "event" and "interface" tests: $ pytest -m "interface or event" --tb=short =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items / 1 deselected / 3 selected diff --git a/doc/en/example/nonpython.rst b/doc/en/example/nonpython.rst index efb701b1f16..aa463e2416b 100644 --- a/doc/en/example/nonpython.rst +++ b/doc/en/example/nonpython.rst @@ -28,7 +28,7 @@ now execute the test specification: nonpython $ pytest test_simple.yaml =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project/nonpython collected 2 items @@ -64,7 +64,7 @@ consulted when reporting in ``verbose`` mode: nonpython $ pytest -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project/nonpython collecting ... collected 2 items @@ -90,7 +90,7 @@ interesting to just look at the collection tree: nonpython $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project/nonpython collected 2 items diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 8c129ddfe7a..0426266e581 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -158,19 +158,20 @@ objects, they are still using the default pytest representation: $ pytest test_time.py --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 8 items - - - - - - - - - + + + + + + + + + + ======================== 8 tests collected in 0.12s ======================== @@ -220,7 +221,7 @@ this is a fully self-contained example which you can run with: $ pytest test_scenarios.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items @@ -234,16 +235,17 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia $ pytest --collect-only test_scenarios.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items - - - - - - + + + + + + + ======================== 4 tests collected in 0.12s ======================== @@ -312,13 +314,14 @@ Let's first see how it looks like at collection time: $ pytest test_backends.py --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items - - - + + + + ======================== 2 tests collected in 0.12s ======================== @@ -410,7 +413,7 @@ The result of this test will be successful: $ pytest -v test_indirect_list.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 1 item @@ -500,12 +503,11 @@ Running it results in some skips if we don't have all the python interpreters in .. code-block:: pytest . $ pytest -rs -q multipython.py - sssssssssssssssssssssssssss [100%] + ssssssssssss...ssssssssssss [100%] ========================= short test summary info ========================== - SKIPPED [9] multipython.py:69: 'python3.5' not found - SKIPPED [9] multipython.py:69: 'python3.6' not found - SKIPPED [9] multipython.py:69: 'python3.7' not found - 27 skipped in 0.12s + SKIPPED [12] multipython.py:68: 'python3.9' not found + SKIPPED [12] multipython.py:68: 'python3.11' not found + 3 passed, 24 skipped in 0.12s Parametrization of optional implementations/imports --------------------------------------------------- @@ -565,7 +567,7 @@ If you run this with reporting for skips enabled: $ pytest -rs test_module.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -626,7 +628,7 @@ Then run ``pytest`` with verbose mode and with only the ``basic`` marker: $ pytest -v -m basic =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 24 items / 21 deselected / 3 selected diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 2451e3cab49..dbc2c239fdd 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -147,15 +147,16 @@ The test collection would look like this: $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project configfile: pytest.ini collected 2 items - - - - + + + + + ======================== 2 tests collected in 0.12s ======================== @@ -209,16 +210,18 @@ You can always peek at the collection tree without running tests like this: . $ pytest --collect-only pythoncollection.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project configfile: pytest.ini collected 3 items - - - - - + + + + + + + ======================== 3 tests collected in 0.12s ======================== @@ -291,7 +294,7 @@ file will be left out: $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project configfile: pytest.ini collected 0 items diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index cb59c4b42e1..2e8d4824c3c 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -9,7 +9,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: assertion $ pytest failure_demo.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project/assertion collected 44 items @@ -80,6 +80,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_eq_text(self): > assert "spam" == "eggs" E AssertionError: assert 'spam' == 'eggs' + E E - eggs E + spam @@ -91,6 +92,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_eq_similar_text(self): > assert "foo 1 bar" == "foo 2 bar" E AssertionError: assert 'foo 1 bar' == 'foo 2 bar' + E E - foo 2 bar E ? ^ E + foo 1 bar @@ -104,6 +106,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_eq_multiline_text(self): > assert "foo\nspam\nbar" == "foo\neggs\nbar" E AssertionError: assert 'foo\nspam\nbar' == 'foo\neggs\nbar' + E E foo E - eggs E + spam @@ -119,6 +122,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: b = "1" * 100 + "b" + "2" * 100 > assert a == b E AssertionError: assert '111111111111...2222222222222' == '111111111111...2222222222222' + E E Skipping 90 identical leading characters in diff, use -v to show E Skipping 91 identical trailing characters in diff, use -v to show E - 1111111111b222222222 @@ -136,15 +140,15 @@ Here is a nice run of several failures and how ``pytest`` presents things: b = "1\n" * 100 + "b" + "2\n" * 100 > assert a == b E AssertionError: assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n...n2\n2\n2\n2\n' + E E Skipping 190 identical leading characters in diff, use -v to show E Skipping 191 identical trailing characters in diff, use -v to show E 1 E 1 E 1 - E 1 E 1... E - E ...Full output truncated (6 lines hidden), use '-vv' to show + E ...Full output truncated (7 lines hidden), use '-vv' to show failure_demo.py:60: AssertionError _________________ TestSpecialisedExplanations.test_eq_list _________________ @@ -154,6 +158,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_eq_list(self): > assert [0, 1, 2] == [0, 1, 3] E assert [0, 1, 2] == [0, 1, 3] + E E At index 2 diff: 2 != 3 E Use -v to get more diff @@ -167,6 +172,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: b = [0] * 100 + [2] + [3] * 100 > assert a == b E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...] + E E At index 100 diff: 1 != 2 E Use -v to get more diff @@ -178,6 +184,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_eq_dict(self): > assert {"a": 0, "b": 1, "c": 0} == {"a": 0, "b": 2, "d": 0} E AssertionError: assert {'a': 0, 'b': 1, 'c': 0} == {'a': 0, 'b': 2, 'd': 0} + E E Omitting 1 identical items, use -vv to show E Differing items: E {'b': 1} != {'b': 2} @@ -195,6 +202,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_eq_set(self): > assert {0, 10, 11, 12} == {0, 20, 21} E assert {0, 10, 11, 12} == {0, 20, 21} + E E Extra items in the left set: E 10 E 11 @@ -212,6 +220,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_eq_longer_list(self): > assert [1, 2] == [1, 2, 3] E assert [1, 2] == [1, 2, 3] + E E Right contains one more item: 3 E Use -v to get more diff @@ -233,6 +242,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: text = "some multiline\ntext\nwhich\nincludes foo\nand a\ntail" > assert "foo" not in text E AssertionError: assert 'foo' not in 'some multil...nand a\ntail' + E E 'foo' is contained here: E some multiline E text @@ -251,6 +261,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: text = "single foo line" > assert "foo" not in text E AssertionError: assert 'foo' not in 'single foo line' + E E 'foo' is contained here: E single foo line E ? +++ @@ -264,6 +275,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: text = "head " * 50 + "foo " + "tail " * 20 > assert "foo" not in text E AssertionError: assert 'foo' not in 'head head h...l tail tail ' + E E 'foo' is contained here: E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail E ? +++ @@ -277,6 +289,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: text = "head " * 50 + "f" * 70 + "tail " * 20 > assert "f" * 70 not in text E AssertionError: assert 'fffffffffff...ffffffffffff' not in 'head head h...l tail tail ' + E E 'ffffffffffffffffff...fffffffffffffffffff' is contained here: E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 943342ff107..21e5f4a09a5 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -232,7 +232,7 @@ directory with the above conftest.py: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 0 items @@ -296,7 +296,7 @@ and when running it will see a skipped "slow" test: $ pytest -rs # "-rs" means report details on the little 's' =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -312,7 +312,7 @@ Or run it including the ``slow`` marked test: $ pytest --runslow =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -456,7 +456,7 @@ which will add the string to the test header accordingly: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y project deps: mylib-1.1 rootdir: /home/sweet/project collected 0 items @@ -484,7 +484,7 @@ which will add info only when run with "--v": $ pytest -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache info1: did you know that ... did you? @@ -499,7 +499,7 @@ and nothing when run plainly: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 0 items @@ -538,7 +538,7 @@ Now we can profile which test functions execute the slowest: $ pytest --durations=3 =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 3 items @@ -644,7 +644,7 @@ If we run this: $ pytest -rx =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 4 items @@ -726,14 +726,14 @@ We can run this: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 7 items - test_step.py .Fx. [ 57%] - a/test_db.py F [ 71%] - a/test_db2.py F [ 85%] - b/test_error.py E [100%] + a/test_db.py F [ 14%] + a/test_db2.py F [ 28%] + b/test_error.py E [ 42%] + test_step.py .Fx. [100%] ================================== ERRORS ================================== _______________________ ERROR at setup of test_root ________________________ @@ -745,39 +745,39 @@ We can run this: /home/sweet/project/b/test_error.py:1 ================================= FAILURES ================================= - ____________________ TestUserHandling.test_modification ____________________ - - self = - - def test_modification(self): - > assert 0 - E assert 0 - - test_step.py:11: AssertionError _________________________________ test_a1 __________________________________ - db = + db = def test_a1(db): > assert 0, db # to show value - E AssertionError: + E AssertionError: E assert 0 a/test_db.py:2: AssertionError _________________________________ test_a2 __________________________________ - db = + db = def test_a2(db): > assert 0, db # to show value - E AssertionError: + E AssertionError: E assert 0 a/test_db2.py:2: AssertionError + ____________________ TestUserHandling.test_modification ____________________ + + self = + + def test_modification(self): + > assert 0 + E assert 0 + + test_step.py:11: AssertionError ========================= short test summary info ========================== - FAILED test_step.py::TestUserHandling::test_modification - assert 0 FAILED a/test_db.py::test_a1 - AssertionError: ` helper to assert that some code raises an e f() You can also use the context provided by :ref:`raises ` to -assert that an expected exception is part of a raised ``ExceptionGroup``: +assert that an expected exception is part of a raised :class:`ExceptionGroup`: .. code-block:: python diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 7d5076a50a0..5c7d125febe 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -29,7 +29,7 @@ you will see the return value of the function call: $ pytest test_assert1.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -143,11 +143,13 @@ Notes: * The ``match`` parameter also matches against `PEP-678 `__ ``__notes__``. +.. _`assert-matching-exception-groups`: + Matching exception groups ~~~~~~~~~~~~~~~~~~~~~~~~~ You can also use the :func:`excinfo.group_contains() ` -method to test for exceptions returned as part of an ``ExceptionGroup``: +method to test for exceptions returned as part of an :class:`ExceptionGroup`: .. code-block:: python @@ -278,7 +280,7 @@ if you run this module: $ pytest test_assert2.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -292,6 +294,7 @@ if you run this module: set2 = set("8035") > assert set1 == set2 E AssertionError: assert {'0', '1', '3', '8'} == {'0', '3', '5', '8'} + E E Extra items in the left set: E '1' E Extra items in the right set: diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index 1b2a454cc2e..40cd3f00dd6 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -86,7 +86,7 @@ If you then run it with ``--lf``: $ pytest --lf =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items run-last-failure: rerun previous 2 failures @@ -132,7 +132,7 @@ of ``FF`` and dots): $ pytest --ff =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 50 items run-last-failure: rerun previous 2 failures first @@ -281,7 +281,7 @@ You can always peek at the content of the cache using the $ pytest --cache-show =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project cachedir: /home/sweet/project/.pytest_cache --------------------------- cache values for '*' --------------------------- @@ -303,7 +303,7 @@ filtering: $ pytest --cache-show example/* =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project cachedir: /home/sweet/project/.pytest_cache ----------------------- cache values for 'example/*' ----------------------- diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index 9ccea719b64..5e23f0c024e 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -83,7 +83,7 @@ of the failing function and hide the other one: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index ba6730587ce..afabad5da14 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -28,7 +28,7 @@ Running pytest now produces this output: $ pytest test_show_warnings.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item diff --git a/doc/en/how-to/doctest.rst b/doc/en/how-to/doctest.rst index 021ba274fbc..f70d28ce135 100644 --- a/doc/en/how-to/doctest.rst +++ b/doc/en/how-to/doctest.rst @@ -30,7 +30,7 @@ then you can just invoke ``pytest`` directly: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -58,7 +58,7 @@ and functions, including from test modules: $ pytest --doctest-modules =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 35b06c5191d..a8fea574a33 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -433,7 +433,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this: $ pytest test_module.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items @@ -771,7 +771,7 @@ For yield fixtures, the first teardown code to run is from the right-most fixtur $ pytest -s test_finalizers.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -805,7 +805,7 @@ For finalizers, the first fixture to run is last call to `request.addfinalizer`. $ pytest -s test_finalizers.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item @@ -1414,27 +1414,28 @@ Running the above tests results in the following test IDs being used: $ pytest --collect-only =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 12 items - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + ======================= 12 tests collected in 0.12s ======================== @@ -1468,7 +1469,7 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``: $ pytest test_fixture_marks.py -v =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 3 items @@ -1518,7 +1519,7 @@ Here we declare an ``app`` fixture which receives the previously defined $ pytest -v test_appsetup.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 2 items @@ -1598,7 +1599,7 @@ Let's run the tests in verbose mode and with looking at the print-output: $ pytest -v -s test_module.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache rootdir: /home/sweet/project collecting ... collected 8 items diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index 8af9a38b768..95c3a89b5a2 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -100,6 +100,7 @@ Executing pytest normally gives us this output (we are skipping the header to fo fruits2 = ["banana", "apple", "orange", "melon", "kiwi"] > assert fruits1 == fruits2 E AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi'] + E E At index 2 diff: 'grapes' != 'orange' E Use -v to get more diff @@ -111,6 +112,7 @@ Executing pytest normally gives us this output (we are skipping the header to fo number_to_text2 = {str(x * 10): x * 10 for x in range(5)} > assert number_to_text1 == number_to_text2 E AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...} + E E Omitting 1 identical items, use -vv to show E Left contains 4 more items: E {'1': 1, '2': 2, '3': 3, '4': 4} @@ -162,12 +164,15 @@ Now we can increase pytest's verbosity: fruits2 = ["banana", "apple", "orange", "melon", "kiwi"] > assert fruits1 == fruits2 E AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi'] + E E At index 2 diff: 'grapes' != 'orange' + E E Full diff: - E - ['banana', 'apple', 'orange', 'melon', 'kiwi'] - E ? ^ ^^ - E + ['banana', 'apple', 'grapes', 'melon', 'kiwi'] - E ? ^ ^ + + E [ + E 'banana', + E 'apple',... + E + E ...Full output truncated (7 lines hidden), use '-vv' to show test_verbosity_example.py:8: AssertionError ____________________________ test_numbers_fail _____________________________ @@ -177,15 +182,15 @@ Now we can increase pytest's verbosity: number_to_text2 = {str(x * 10): x * 10 for x in range(5)} > assert number_to_text1 == number_to_text2 E AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...} + E E Omitting 1 identical items, use -vv to show E Left contains 4 more items: E {'1': 1, '2': 2, '3': 3, '4': 4} E Right contains 4 more items: E {'10': 10, '20': 20, '30': 30, '40': 40} - 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 + E ...Full output truncated (16 lines hidden), use '-vv' to show test_verbosity_example.py:14: AssertionError ___________________________ test_long_text_fail ____________________________ @@ -231,12 +236,20 @@ Now if we increase verbosity even more: fruits2 = ["banana", "apple", "orange", "melon", "kiwi"] > assert fruits1 == fruits2 E AssertionError: assert ['banana', 'apple', 'grapes', 'melon', 'kiwi'] == ['banana', 'apple', 'orange', 'melon', 'kiwi'] + E E At index 2 diff: 'grapes' != 'orange' + E E Full diff: - E - ['banana', 'apple', 'orange', 'melon', 'kiwi'] - E ? ^ ^^ - E + ['banana', 'apple', 'grapes', 'melon', 'kiwi'] - E ? ^ ^ + + E [ + E 'banana', + E 'apple', + E - 'orange', + E ? ^ ^^ + E + 'grapes', + E ? ^ ^ + + E 'melon', + E 'kiwi', + E ] test_verbosity_example.py:8: AssertionError ____________________________ test_numbers_fail _____________________________ @@ -246,16 +259,30 @@ Now if we increase verbosity even more: number_to_text2 = {str(x * 10): x * 10 for x in range(5)} > assert number_to_text1 == number_to_text2 E AssertionError: assert {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4} == {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40} + E E Common items: E {'0': 0} E Left contains 4 more items: E {'1': 1, '2': 2, '3': 3, '4': 4} E Right contains 4 more items: E {'10': 10, '20': 20, '30': 30, '40': 40} + 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 } test_verbosity_example.py:14: AssertionError ___________________________ test_long_text_fail ____________________________ @@ -354,7 +381,7 @@ Example: $ pytest -ra =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 6 items @@ -410,7 +437,7 @@ More than one character can be used, so for example to only see failed and skipp $ pytest -rfs =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 6 items @@ -445,7 +472,7 @@ captured output: $ pytest -rpP =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 6 items diff --git a/doc/en/how-to/parametrize.rst b/doc/en/how-to/parametrize.rst index a0c9968428c..b6466c491b4 100644 --- a/doc/en/how-to/parametrize.rst +++ b/doc/en/how-to/parametrize.rst @@ -56,7 +56,7 @@ them in turn: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 3 items @@ -167,7 +167,7 @@ Let's run this: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 3 items diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index 3b49d63a5be..b75fb59641f 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -36,7 +36,7 @@ Running this would result in a passed test except for the last $ pytest test_tmp_path.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item diff --git a/doc/en/how-to/unittest.rst b/doc/en/how-to/unittest.rst index 7856c1a49c0..508aebde016 100644 --- a/doc/en/how-to/unittest.rst +++ b/doc/en/how-to/unittest.rst @@ -140,7 +140,7 @@ the ``self.db`` values in the traceback: $ pytest test_unittest_db.py =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 2 items diff --git a/doc/en/how-to/writing_plugins.rst b/doc/en/how-to/writing_plugins.rst index 6f321110718..d907ae398b4 100644 --- a/doc/en/how-to/writing_plugins.rst +++ b/doc/en/how-to/writing_plugins.rst @@ -448,7 +448,7 @@ in our ``pytest.ini`` to tell pytest where to look for example files. $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project configfile: pytest.ini collected 2 items diff --git a/doc/en/index.rst b/doc/en/index.rst index b9331eb9adf..50c84f6ae05 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -42,7 +42,7 @@ To execute it: $ pytest =========================== test session starts ============================ - platform linux -- Python 3.x.y, pytest-7.x.y, pluggy-1.x.y + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y rootdir: /home/sweet/project collected 1 item diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 49459dd857c..33aff0f7c5c 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2141,6 +2141,10 @@ All the command-line flags can be obtained by running ``pytest --help``:: enable_assertion_pass_hook (bool): Enables the pytest_assertion_pass hook. Make sure to delete any previously generated pyc cache files. + verbosity_assertions (string): + Specify a verbosity level for assertions, overriding + the main level. Higher levels will provide more + detailed explanation when an assertion fails. junit_suite_name (string): Test suite name for JUnit report junit_logging (string): From f13724e2e3e7b66b09cca4608a57e68f7d303b6d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 13:10:56 +0200 Subject: [PATCH 0326/1271] Remove deprecated {FSCollector,Package}.{gethookproxy,isinitpath} --- src/_pytest/deprecated.py | 5 ----- src/_pytest/nodes.py | 9 --------- testing/deprecated_test.py | 26 -------------------------- 3 files changed, 40 deletions(-) diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 77279d6342a..4750bec5dfc 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -51,11 +51,6 @@ "Please use pytest_load_initial_conftests hook instead." ) -FSCOLLECTOR_GETHOOKPROXY_ISINITPATH = PytestRemovedIn8Warning( - "The gethookproxy() and isinitpath() methods of FSCollector and Package are deprecated; " - "use self.session.gethookproxy() and self.session.isinitpath() instead. " -) - STRICT_OPTION = PytestRemovedIn8Warning( "The --strict option is deprecated, use --strict-markers instead." ) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 5307141080d..eefe690de3f 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -32,7 +32,6 @@ from _pytest.config import Config from _pytest.config import ConftestImportFailure from _pytest.config.compat import _check_path -from _pytest.deprecated import FSCOLLECTOR_GETHOOKPROXY_ISINITPATH from _pytest.deprecated import NODE_CTOR_FSPATH_ARG from _pytest.mark.structures import Mark from _pytest.mark.structures import MarkDecorator @@ -660,14 +659,6 @@ def from_parent( """The public constructor.""" return super().from_parent(parent=parent, fspath=fspath, path=path, **kw) - def gethookproxy(self, fspath: "os.PathLike[str]"): - warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2) - return self.session.gethookproxy(fspath) - - def isinitpath(self, path: Union[str, "os.PathLike[str]"]) -> bool: - warnings.warn(FSCOLLECTOR_GETHOOKPROXY_ISINITPATH, stacklevel=2) - return self.session.isinitpath(path) - class File(FSCollector, abc.ABC): """Base class for collecting tests from a file. diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 0736ed1dcc1..c1d8ad59df4 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -1,6 +1,5 @@ import re import sys -import warnings from pathlib import Path import pytest @@ -68,31 +67,6 @@ def pytest_runtest_call(self): assert record.filename == __file__ -def test_fscollector_gethookproxy_isinitpath(pytester: Pytester) -> None: - module = pytester.getmodulecol( - """ - def test_foo(): pass - """, - withinit=True, - ) - assert isinstance(module, pytest.Module) - package = module.parent - assert isinstance(package, pytest.Package) - - with pytest.warns(pytest.PytestDeprecationWarning, match="gethookproxy"): - package.gethookproxy(pytester.path) - - with pytest.warns(pytest.PytestDeprecationWarning, match="isinitpath"): - package.isinitpath(pytester.path) - - # The methods on Session are *not* deprecated. - session = module.session - with warnings.catch_warnings(record=True) as rec: - session.gethookproxy(pytester.path) - session.isinitpath(pytester.path) - assert len(rec) == 0 - - def test_strict_option_is_deprecated(pytester: Pytester) -> None: """--strict is a deprecated alias to --strict-markers (#7530).""" pytester.makepyfile( From f4e7b0d6e00aff21d1c4aadfb51fb0f1f4c4bd94 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 13:14:06 +0200 Subject: [PATCH 0327/1271] Remove deprecated `pytest_cmdline_preparse` hook --- doc/en/changelog.rst | 2 +- doc/en/deprecations.rst | 51 +++++++++++++++++----------------- doc/en/reference/reference.rst | 2 -- src/_pytest/config/__init__.py | 2 -- src/_pytest/deprecated.py | 5 ---- src/_pytest/hookspec.py | 17 ------------ testing/deprecated_test.py | 17 ------------ testing/test_config.py | 11 -------- 8 files changed, 27 insertions(+), 80 deletions(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 85ba6140ac3..c097202ef78 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -1257,7 +1257,7 @@ Deprecations See :ref:`the deprecation note ` for full details. -- `#8592 `_: :hook:`pytest_cmdline_preparse` has been officially deprecated. It will be removed in a future release. Use :hook:`pytest_load_initial_conftests` instead. +- `#8592 `_: ``pytest_cmdline_preparse`` has been officially deprecated. It will be removed in a future release. Use :hook:`pytest_load_initial_conftests` instead. See :ref:`the deprecation note ` for full details. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index caa7cb3e760..c8189b1bbbe 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -273,8 +273,6 @@ Directly constructing the following classes is now deprecated: These constructors have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 8. -.. _cmdline-preparse-deprecated: - Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -306,29 +304,6 @@ functions and the ``@pytest.mark.skip`` and ``@pytest.mark.xfail`` markers which # new pytest.exit(reason="bar") - -Implementing the ``pytest_cmdline_preparse`` hook -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.0 - -Implementing the :hook:`pytest_cmdline_preparse` hook has been officially deprecated. -Implement the :hook:`pytest_load_initial_conftests` hook instead. - -.. code-block:: python - - def pytest_cmdline_preparse(config: Config, args: List[str]) -> None: - ... - - - # becomes: - - - def pytest_load_initial_conftests( - early_config: Config, parser: Parser, args: List[str] - ) -> None: - ... - .. _diamond-inheritance-deprecated: Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item` @@ -495,6 +470,32 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +.. _cmdline-preparse-deprecated: + +Implementing the ``pytest_cmdline_preparse`` hook +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 +.. versionremoved:: 8.0 + +Implementing the ``pytest_cmdline_preparse`` hook has been officially deprecated. +Implement the :hook:`pytest_load_initial_conftests` hook instead. + +.. code-block:: python + + def pytest_cmdline_preparse(config: Config, args: List[str]) -> None: + ... + + + # becomes: + + + def pytest_load_initial_conftests( + early_config: Config, parser: Parser, args: List[str] + ) -> None: + ... + + Collection changes in pytest 8 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 33aff0f7c5c..bd64bac411c 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -643,8 +643,6 @@ Bootstrapping hooks called for plugins registered early enough (internal and set .. hook:: pytest_load_initial_conftests .. autofunction:: pytest_load_initial_conftests -.. hook:: pytest_cmdline_preparse -.. autofunction:: pytest_cmdline_preparse .. hook:: pytest_cmdline_parse .. autofunction:: pytest_cmdline_parse .. hook:: pytest_cmdline_main diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index e5775546dde..9f25b67abdf 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1432,8 +1432,6 @@ def parse(self, args: List[str], addopts: bool = True) -> None: kwargs=dict(pluginmanager=self.pluginmanager) ) self._preparse(args, addopts=addopts) - # XXX deprecated hook: - self.hook.pytest_cmdline_preparse(config=self, args=args) self._parser.after_preparse = True # type: ignore try: args = self._parser.parse_setoption( diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 4750bec5dfc..b7beb353182 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -46,11 +46,6 @@ "Use @pytest.fixture instead; they are the same." ) -WARNING_CMDLINE_PREPARSE_HOOK = PytestRemovedIn8Warning( - "The pytest_cmdline_preparse hook is deprecated and will be removed in a future release. \n" - "Please use pytest_load_initial_conftests hook instead." -) - STRICT_OPTION = PytestRemovedIn8Warning( "The --strict option is deprecated, use --strict-markers instead." ) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 3c65234daa7..14f7f45fa1f 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -13,8 +13,6 @@ from pluggy import HookspecMarker -from _pytest.deprecated import WARNING_CMDLINE_PREPARSE_HOOK - if TYPE_CHECKING: import pdb import warnings @@ -159,21 +157,6 @@ def pytest_cmdline_parse( """ -@hookspec(warn_on_impl=WARNING_CMDLINE_PREPARSE_HOOK) -def pytest_cmdline_preparse(config: "Config", args: List[str]) -> None: - """(**Deprecated**) modify command line arguments before option parsing. - - This hook is considered deprecated and will be removed in a future pytest version. Consider - using :hook:`pytest_load_initial_conftests` instead. - - .. note:: - This hook will not be called for ``conftest.py`` files, only for setuptools plugins. - - :param config: The pytest config object. - :param args: Arguments passed on the command line. - """ - - @hookspec(firstresult=True) def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]: """Called for performing the main command line action. The default diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index c1d8ad59df4..042be826491 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -211,23 +211,6 @@ def test_exit_msg(): result.assert_outcomes(warnings=1) -def test_deprecation_of_cmdline_preparse(pytester: Pytester) -> None: - pytester.makeconftest( - """ - def pytest_cmdline_preparse(config, args): - ... - - """ - ) - result = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning") - result.stdout.fnmatch_lines( - [ - "*PytestRemovedIn8Warning: The pytest_cmdline_preparse hook is deprecated*", - "*Please use pytest_load_initial_conftests hook instead.*", - ] - ) - - def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: mod = pytester.getmodulecol("") diff --git a/testing/test_config.py b/testing/test_config.py index 18022977ca3..2d95fb4cc82 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1253,17 +1253,6 @@ def pytest_sessionstart(session): assert result.ret == 0 -def test_cmdline_processargs_simple(pytester: Pytester) -> None: - pytester.makeconftest( - """ - def pytest_cmdline_preparse(args): - args.append("-h") - """ - ) - result = pytester.runpytest("-Wignore::pytest.PytestRemovedIn8Warning") - result.stdout.fnmatch_lines(["*pytest*", "*-h*"]) - - def test_invalid_options_show_extra_information(pytester: Pytester) -> None: """Display extra information when pytest exits due to unrecognized options in the command-line.""" From 1f8b39ed328a395c073db603bf4063fb3ec97218 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 13:17:58 +0200 Subject: [PATCH 0328/1271] Remove deprecated `--strict` option --- doc/en/deprecations.rst | 27 ++++++++++++++------------- src/_pytest/config/__init__.py | 5 ----- src/_pytest/deprecated.py | 4 ---- testing/deprecated_test.py | 19 ------------------- 4 files changed, 14 insertions(+), 41 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index c8189b1bbbe..7562f98eb50 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -438,19 +438,6 @@ The proper fix is to change the `return` to an `assert`: assert foo(a, b) == result -The ``--strict`` command-line option -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 6.2 - -The ``--strict`` command-line option has been deprecated in favor of ``--strict-markers``, which -better conveys what the option does. - -We have plans to maybe in the future to reintroduce ``--strict`` and make it an encompassing -flag for all strictness related options (``--strict-markers`` and ``--strict-config`` -at the moment, more might be introduced in the future). - - The ``yield_fixture`` function/decorator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -470,6 +457,20 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +The ``--strict`` command-line option +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 6.2 +.. versionremoved:: 8.0 + +The ``--strict`` command-line option has been deprecated in favor of ``--strict-markers``, which +better conveys what the option does. + +We have plans to maybe in the future to reintroduce ``--strict`` and make it an encompassing +flag for all strictness related options (``--strict-markers`` and ``--strict-config`` +at the moment, more might be introduced in the future). + + .. _cmdline-preparse-deprecated: Implementing the ``pytest_cmdline_preparse`` hook diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 9f25b67abdf..2d5db172412 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1319,11 +1319,6 @@ def _preparse(self, args: List[str], addopts: bool = True) -> None: self._validate_plugins() self._warn_about_skipped_plugins() - if self.known_args_namespace.strict: - self.issue_config_time_warning( - _pytest.deprecated.STRICT_OPTION, stacklevel=2 - ) - if self.known_args_namespace.confcutdir is None: if self.inipath is not None: confcutdir = str(self.inipath.parent) diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index b7beb353182..1ead61e8c07 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -46,10 +46,6 @@ "Use @pytest.fixture instead; they are the same." ) -STRICT_OPTION = PytestRemovedIn8Warning( - "The --strict option is deprecated, use --strict-markers instead." -) - # This deprecation is never really meant to be removed. PRIVATE = PytestDeprecationWarning("A private pytest class or function was used.") diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 042be826491..dd6a6dfcfc7 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -67,25 +67,6 @@ def pytest_runtest_call(self): assert record.filename == __file__ -def test_strict_option_is_deprecated(pytester: Pytester) -> None: - """--strict is a deprecated alias to --strict-markers (#7530).""" - pytester.makepyfile( - """ - import pytest - - @pytest.mark.unknown - def test_foo(): pass - """ - ) - result = pytester.runpytest("--strict", "-Wdefault::pytest.PytestRemovedIn8Warning") - result.stdout.fnmatch_lines( - [ - "'unknown' not found in `markers` configuration option", - "*PytestRemovedIn8Warning: The --strict option is deprecated, use --strict-markers instead.", - ] - ) - - def test_yield_fixture_is_deprecated() -> None: with pytest.warns(DeprecationWarning, match=r"yield_fixture is deprecated"): From 10fbb2325f66fb1834c02b04dd07089cca13985f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 13:22:02 +0200 Subject: [PATCH 0329/1271] Remove deprecated `Parser.addoption` backward compatibilities --- doc/en/deprecations.rst | 25 ++++++++++++----------- src/_pytest/config/argparsing.py | 35 +------------------------------- src/_pytest/deprecated.py | 19 ----------------- testing/test_parseopt.py | 3 --- 4 files changed, 14 insertions(+), 68 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 7562f98eb50..982470cb231 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -374,18 +374,6 @@ Users expected in this case that the ``usefixtures`` mark would have its intende Now pytest will issue a warning when it encounters this problem, and will raise an error in the future versions. -Backward compatibilities in ``Parser.addoption`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 2.4 - -Several behaviors of :meth:`Parser.addoption ` are now -scheduled for removal in pytest 8 (deprecated since pytest 2.4.0): - -- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead. -- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead. - - Using ``pytest.warns(None)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -457,6 +445,19 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +Backward compatibilities in ``Parser.addoption`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 2.4 +.. versionremoved:: 8.0 + +Several behaviors of :meth:`Parser.addoption ` are now +removed in pytest 8 (deprecated since pytest 2.4.0): + +- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead. +- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead. + + The ``--strict`` command-line option ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 331abb85d00..39e41760518 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -1,7 +1,6 @@ import argparse import os import sys -import warnings from gettext import gettext from typing import Any from typing import Callable @@ -19,9 +18,6 @@ import _pytest._io from _pytest.config.exceptions import UsageError -from _pytest.deprecated import ARGUMENT_PERCENT_DEFAULT -from _pytest.deprecated import ARGUMENT_TYPE_STR -from _pytest.deprecated import ARGUMENT_TYPE_STR_CHOICE from _pytest.deprecated import check_ispytest FILE_OR_DIR = "file_or_dir" @@ -259,39 +255,15 @@ class Argument: https://docs.python.org/3/library/optparse.html#optparse-standard-option-types """ - _typ_map = {"int": int, "string": str, "float": float, "complex": complex} - def __init__(self, *names: str, **attrs: Any) -> None: """Store params in private vars for use in add_argument.""" self._attrs = attrs self._short_opts: List[str] = [] self._long_opts: List[str] = [] - if "%default" in (attrs.get("help") or ""): - warnings.warn(ARGUMENT_PERCENT_DEFAULT, stacklevel=3) try: - typ = attrs["type"] + self.type = attrs["type"] except KeyError: pass - else: - # This might raise a keyerror as well, don't want to catch that. - if isinstance(typ, str): - if typ == "choice": - warnings.warn( - ARGUMENT_TYPE_STR_CHOICE.format(typ=typ, names=names), - stacklevel=4, - ) - # argparse expects a type here take it from - # the type of the first element - attrs["type"] = type(attrs["choices"][0]) - else: - warnings.warn( - ARGUMENT_TYPE_STR.format(typ=typ, names=names), stacklevel=4 - ) - attrs["type"] = Argument._typ_map[typ] - # Used in test_parseopt -> test_parse_defaultgetter. - self.type = attrs["type"] - else: - self.type = typ try: # Attribute existence is tested in Config._processopt. self.default = attrs["default"] @@ -322,11 +294,6 @@ def attrs(self) -> Mapping[str, Any]: self._attrs[attr] = getattr(self, attr) except AttributeError: pass - if self._attrs.get("help"): - a = self._attrs["help"] - a = a.replace("%default", "%(default)s") - # a = a.replace('%prog', '%(prog)s') - self._attrs["help"] = a return self._attrs def _set_opt_strings(self, opts: Sequence[str]) -> None: diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 1ead61e8c07..a41fb378f40 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -49,25 +49,6 @@ # This deprecation is never really meant to be removed. PRIVATE = PytestDeprecationWarning("A private pytest class or function was used.") -ARGUMENT_PERCENT_DEFAULT = PytestRemovedIn8Warning( - 'pytest now uses argparse. "%default" should be changed to "%(default)s"', -) - -ARGUMENT_TYPE_STR_CHOICE = UnformattedWarning( - PytestRemovedIn8Warning, - "`type` argument to addoption() is the string {typ!r}." - " For choices this is optional and can be omitted, " - " but when supplied should be a type (for example `str` or `int`)." - " (options: {names})", -) - -ARGUMENT_TYPE_STR = UnformattedWarning( - PytestRemovedIn8Warning, - "`type` argument to addoption() is the string {typ!r}, " - " but when supplied should be a type (for example `str` or `int`)." - " (options: {names})", -) - HOOK_LEGACY_PATH_ARG = UnformattedWarning( PytestRemovedIn8Warning, diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 1b80883ee0f..2a629198438 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -54,9 +54,6 @@ def test_argument_type(self) -> None: assert argument.type is str argument = parseopt.Argument("-t", dest="abc", type=float) assert argument.type is float - with pytest.warns(DeprecationWarning): - with pytest.raises(KeyError): - argument = parseopt.Argument("-t", dest="abc", type="choice") argument = parseopt.Argument( "-t", dest="abc", type=str, choices=["red", "blue"] ) From 4147c92b21c0fc393a59e42cab2b2511fcb60e06 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 13:32:01 +0200 Subject: [PATCH 0330/1271] Remove deprecated `pytest.warns(None)` --- doc/en/deprecations.rst | 25 +++++++++++++------------ src/_pytest/deprecated.py | 7 ------- src/_pytest/recwarn.py | 18 +++++------------- testing/deprecated_test.py | 14 -------------- testing/test_recwarn.py | 14 +++----------- testing/test_tmpdir.py | 12 +++++------- 6 files changed, 26 insertions(+), 64 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 982470cb231..70f8b09aa5b 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -374,18 +374,6 @@ Users expected in this case that the ``usefixtures`` mark would have its intende Now pytest will issue a warning when it encounters this problem, and will raise an error in the future versions. -Using ``pytest.warns(None)`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.0 - -:func:`pytest.warns(None) ` is now deprecated because it was frequently misused. -Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()`` -or ``pytest.warns(Warning)``. - -See :ref:`warns use cases` for examples. - - Returning non-None value in test functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -445,6 +433,19 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +Using ``pytest.warns(None)`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 +.. versionremoved:: 8.0 + +:func:`pytest.warns(None) ` is now deprecated because it was frequently misused. +Its correct usage was checking that the code emits at least one warning of any type - like ``pytest.warns()`` +or ``pytest.warns(Warning)``. + +See :ref:`warns use cases` for examples. + + Backward compatibilities in ``Parser.addoption`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index a41fb378f40..4ea2c39a2b4 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -65,13 +65,6 @@ "#fspath-argument-for-node-constructors-replaced-with-pathlib-path", ) -WARNS_NONE_ARG = PytestRemovedIn8Warning( - "Passing None has been deprecated.\n" - "See https://docs.pytest.org/en/latest/how-to/capture-warnings.html" - "#additional-use-cases-of-warnings-in-tests" - " for alternatives in common use cases." -) - KEYWORD_MSG_ARG = UnformattedWarning( PytestRemovedIn8Warning, "pytest.{func}(msg=...) is now deprecated, use pytest.{func}(reason=...) instead", diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index d1d83ea2a13..175d545b9b9 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -18,7 +18,6 @@ from typing import Union from _pytest.deprecated import check_ispytest -from _pytest.deprecated import WARNS_NONE_ARG from _pytest.fixtures import fixture from _pytest.outcomes import fail @@ -264,9 +263,7 @@ def __exit__( class WarningsChecker(WarningsRecorder): def __init__( self, - expected_warning: Optional[ - Union[Type[Warning], Tuple[Type[Warning], ...]] - ] = Warning, + expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning, match_expr: Optional[Union[str, Pattern[str]]] = None, *, _ispytest: bool = False, @@ -275,15 +272,14 @@ def __init__( super().__init__(_ispytest=True) msg = "exceptions must be derived from Warning, not %s" - if expected_warning is None: - warnings.warn(WARNS_NONE_ARG, stacklevel=4) - expected_warning_tup = None - elif isinstance(expected_warning, tuple): + if isinstance(expected_warning, tuple): for exc in expected_warning: if not issubclass(exc, Warning): raise TypeError(msg % type(exc)) expected_warning_tup = expected_warning - elif issubclass(expected_warning, Warning): + elif isinstance(expected_warning, type) and issubclass( + expected_warning, Warning + ): expected_warning_tup = (expected_warning,) else: raise TypeError(msg % type(expected_warning)) @@ -307,10 +303,6 @@ def __exit__( __tracebackhide__ = True - if self.expected_warning is None: - # nothing to do in this deprecated case, see WARNS_NONE_ARG above - return - def found_str(): return pformat([record.message for record in self], indent=2) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index dd6a6dfcfc7..6fd592aa1b0 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -120,20 +120,6 @@ def test_hookproxy_warnings_for_pathlib(tmp_path, hooktype, request): ) -def test_warns_none_is_deprecated(): - with pytest.warns( - PytestDeprecationWarning, - match=re.escape( - "Passing None has been deprecated.\n" - "See https://docs.pytest.org/en/latest/how-to/capture-warnings.html" - "#additional-use-cases-of-warnings-in-tests" - " for alternatives in common use cases." - ), - ): - with pytest.warns(None): # type: ignore[call-overload] - pass - - class TestSkipMsgArgumentDeprecated: def test_skip_with_msg_is_deprecated(self, pytester: Pytester) -> None: p = pytester.makepyfile( diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 19a1cd534f1..2508e22a2db 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -345,17 +345,9 @@ def test_record_only(self) -> None: assert str(record[0].message) == "user" assert str(record[1].message) == "runtime" - def test_record_only_none_deprecated_warn(self) -> None: - # This should become an error when WARNS_NONE_ARG is removed in Pytest 8.0 - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - with pytest.warns(None) as record: # type: ignore[call-overload] - warnings.warn("user", UserWarning) - warnings.warn("runtime", RuntimeWarning) - - assert len(record) == 2 - assert str(record[0].message) == "user" - assert str(record[1].message) == "runtime" + def test_record_only_none_type_error(self) -> None: + with pytest.raises(TypeError): + pytest.warns(None) # type: ignore[call-overload] def test_record_by_subclass(self) -> None: with pytest.warns(Warning) as record: diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 1e1446af127..2215e978a60 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -530,13 +530,11 @@ def test_on_rm_rf_error(self, tmp_path: Path) -> None: assert fn.is_file() # ignored function - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - with pytest.warns(None) as warninfo: # type: ignore[call-overload] - exc_info4 = PermissionError() - on_rm_rf_error(os.open, str(fn), exc_info4, start_path=tmp_path) - assert fn.is_file() - assert not [x.message for x in warninfo] + with warnings.catch_warnings(record=True) as w: + exc_info4 = PermissionError() + on_rm_rf_error(os.open, str(fn), exc_info4, start_path=tmp_path) + assert fn.is_file() + assert not [x.message for x in w] exc_info5 = PermissionError() on_rm_rf_error(os.unlink, str(fn), exc_info5, start_path=tmp_path) From 477959ef7dc9f8491a80ba4d585d737a68f0a34c Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 13:37:04 +0200 Subject: [PATCH 0331/1271] Remove deprecated `pytest.Instance` backward compat --- doc/en/deprecations.rst | 36 ++++++++++++++++++------------------ src/_pytest/deprecated.py | 4 ---- src/_pytest/python.py | 15 --------------- src/pytest/__init__.py | 12 ------------ testing/deprecated_test.py | 14 -------------- 5 files changed, 18 insertions(+), 63 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 70f8b09aa5b..436a29e969b 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -125,24 +125,6 @@ Will also need to be ported to a supported pytest style. One way to do it is usi .. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup -.. _instance-collector-deprecation: - -The ``pytest.Instance`` collector -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionremoved:: 7.0 - -The ``pytest.Instance`` collector type has been removed. - -Previously, Python test methods were collected as :class:`~pytest.Class` -> ``Instance`` -> :class:`~pytest.Function`. -Now :class:`~pytest.Class` collects the test methods directly. - -Most plugins which reference ``Instance`` do so in order to ignore or skip it, -using a check such as ``if isinstance(node, Instance): return``. -Such plugins should simply remove consideration of ``Instance`` on pytest>=7. -However, to keep such uses working, a dummy type has been instanted in ``pytest.Instance`` and ``_pytest.python.Instance``, -and importing it emits a deprecation warning. This will be removed in pytest 8. - .. _node-ctor-fspath-deprecation: @@ -432,6 +414,24 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +.. _instance-collector-deprecation: + +The ``pytest.Instance`` collector +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionremoved:: 7.0 + +The ``pytest.Instance`` collector type has been removed. + +Previously, Python test methods were collected as :class:`~pytest.Class` -> ``Instance`` -> :class:`~pytest.Function`. +Now :class:`~pytest.Class` collects the test methods directly. + +Most plugins which reference ``Instance`` do so in order to ignore or skip it, +using a check such as ``if isinstance(node, Instance): return``. +Such plugins should simply remove consideration of ``Instance`` on pytest>=7. +However, to keep such uses working, a dummy type has been instanted in ``pytest.Instance`` and ``_pytest.python.Instance``, +and importing it emits a deprecation warning. This was removed in pytest 8. + Using ``pytest.warns(None)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 4ea2c39a2b4..798cf7d34d6 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -70,10 +70,6 @@ "pytest.{func}(msg=...) is now deprecated, use pytest.{func}(reason=...) instead", ) -INSTANCE_COLLECTOR = PytestRemovedIn8Warning( - "The pytest.Instance collector type is deprecated and is no longer used. " - "See https://docs.pytest.org/en/latest/deprecations.html#the-pytest-instance-collector", -) HOOK_LEGACY_MARKING = UnformattedWarning( PytestDeprecationWarning, "The hook{type} {fullname} uses old-style configuration options (marks or attributes).\n" diff --git a/src/_pytest/python.py b/src/_pytest/python.py index e0f7a447a61..f7e0a30b5f2 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -57,7 +57,6 @@ from _pytest.config import hookimpl from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest -from _pytest.deprecated import INSTANCE_COLLECTOR from _pytest.deprecated import NOSE_SUPPORT_METHOD from _pytest.fixtures import FixtureDef from _pytest.fixtures import FixtureRequest @@ -905,20 +904,6 @@ def xunit_setup_method_fixture(self, request) -> Generator[None, None, None]: self.obj.__pytest_setup_method = xunit_setup_method_fixture -class InstanceDummy: - """Instance used to be a node type between Class and Function. It has been - removed in pytest 7.0. Some plugins exist which reference `pytest.Instance` - only to ignore it; this dummy class keeps them working. This will be removed - in pytest 8.""" - - -def __getattr__(name: str) -> object: - if name == "Instance": - warnings.warn(INSTANCE_COLLECTOR, 2) - return InstanceDummy - raise AttributeError(f"module {__name__} has no attribute {name}") - - def hasinit(obj: object) -> bool: init: object = getattr(obj, "__init__", None) if init: diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 4e0c23ddbe7..5fab295c6d7 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -1,7 +1,5 @@ # PYTHON_ARGCOMPLETE_OK """pytest: unit and functional testing with Python.""" -from typing import TYPE_CHECKING - from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo @@ -170,13 +168,3 @@ "xfail", "yield_fixture", ] - -if not TYPE_CHECKING: - - def __getattr__(name: str) -> object: - if name == "Instance": - # The import emits a deprecation warning. - from _pytest.python import Instance - - return Instance - raise AttributeError(f"module {__name__} has no attribute {name}") diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 6fd592aa1b0..0fe0e8a7b9e 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -197,20 +197,6 @@ def collect(self): ) -def test_importing_instance_is_deprecated(pytester: Pytester) -> None: - with pytest.warns( - pytest.PytestDeprecationWarning, - match=re.escape("The pytest.Instance collector type is deprecated"), - ): - pytest.Instance # type:ignore[attr-defined] - - with pytest.warns( - pytest.PytestDeprecationWarning, - match=re.escape("The pytest.Instance collector type is deprecated"), - ): - from _pytest.python import Instance # noqa: F401 - - def test_fixture_disallow_on_marked_functions(): """Test that applying @pytest.fixture to a marked function warns (#3364).""" with pytest.warns( From 0591569b4ba9bfb12e5b5307da621a83c4ceced6 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 13:41:52 +0200 Subject: [PATCH 0332/1271] Remove deprecated pytest.{exit,fail,skip}(msg=...) argument --- doc/en/deprecations.rst | 64 +++++++++++++++++----------------- src/_pytest/deprecated.py | 5 --- src/_pytest/outcomes.py | 70 ++++---------------------------------- testing/deprecated_test.py | 58 ------------------------------- testing/test_skipping.py | 48 -------------------------- 5 files changed, 39 insertions(+), 206 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 436a29e969b..1b661d4d74d 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -255,37 +255,6 @@ Directly constructing the following classes is now deprecated: These constructors have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 8. -Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.0 - -Passing the keyword argument ``msg`` to :func:`pytest.skip`, :func:`pytest.fail` or :func:`pytest.exit` -is now deprecated and ``reason`` should be used instead. This change is to bring consistency between these -functions and the ``@pytest.mark.skip`` and ``@pytest.mark.xfail`` markers which already accept a ``reason`` argument. - -.. code-block:: python - - def test_fail_example(): - # old - pytest.fail(msg="foo") - # new - pytest.fail(reason="bar") - - - def test_skip_example(): - # old - pytest.skip(msg="foo") - # new - pytest.skip(reason="bar") - - - def test_exit_example(): - # old - pytest.exit(msg="foo") - # new - pytest.exit(reason="bar") - .. _diamond-inheritance-deprecated: Diamond inheritance between :class:`pytest.Collector` and :class:`pytest.Item` @@ -414,6 +383,39 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 +.. versionremoved:: 8.0 + +Passing the keyword argument ``msg`` to :func:`pytest.skip`, :func:`pytest.fail` or :func:`pytest.exit` +is now deprecated and ``reason`` should be used instead. This change is to bring consistency between these +functions and the ``@pytest.mark.skip`` and ``@pytest.mark.xfail`` markers which already accept a ``reason`` argument. + +.. code-block:: python + + def test_fail_example(): + # old + pytest.fail(msg="foo") + # new + pytest.fail(reason="bar") + + + def test_skip_example(): + # old + pytest.skip(msg="foo") + # new + pytest.skip(reason="bar") + + + def test_exit_example(): + # old + pytest.exit(msg="foo") + # new + pytest.exit(reason="bar") + + .. _instance-collector-deprecation: The ``pytest.Instance`` collector diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 798cf7d34d6..f728d7a554a 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -65,11 +65,6 @@ "#fspath-argument-for-node-constructors-replaced-with-pathlib-path", ) -KEYWORD_MSG_ARG = UnformattedWarning( - PytestRemovedIn8Warning, - "pytest.{func}(msg=...) is now deprecated, use pytest.{func}(reason=...) instead", -) - HOOK_LEGACY_MARKING = UnformattedWarning( PytestDeprecationWarning, "The hook{type} {fullname} uses old-style configuration options (marks or attributes).\n" diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 0f64f91d9ff..8710ba3e85d 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -1,7 +1,6 @@ """Exception classes and constants handling test outcomes as well as functions creating them.""" import sys -import warnings from typing import Any from typing import Callable from typing import cast @@ -11,8 +10,6 @@ from typing import Type from typing import TypeVar -from _pytest.deprecated import KEYWORD_MSG_ARG - class OutcomeException(BaseException): """OutcomeException and its subclass instances indicate and contain info @@ -103,7 +100,8 @@ def decorate(func: _F) -> _WithException[_F, _ET]: @_with_exception(Exit) def exit( - reason: str = "", returncode: Optional[int] = None, *, msg: Optional[str] = None + reason: str = "", + returncode: Optional[int] = None, ) -> NoReturn: """Exit testing process. @@ -113,28 +111,16 @@ def exit( :param returncode: Return code to be used when exiting pytest. None means the same as ``0`` (no error), same as :func:`sys.exit`. - - :param msg: - Same as ``reason``, but deprecated. Will be removed in a future version, use ``reason`` instead. """ __tracebackhide__ = True - from _pytest.config import UsageError - - if reason and msg: - raise UsageError( - "cannot pass reason and msg to exit(), `msg` is deprecated, use `reason`." - ) - if not reason: - if msg is None: - raise UsageError("exit() requires a reason argument") - warnings.warn(KEYWORD_MSG_ARG.format(func="exit"), stacklevel=2) - reason = msg raise Exit(reason, returncode) @_with_exception(Skipped) def skip( - reason: str = "", *, allow_module_level: bool = False, msg: Optional[str] = None + reason: str = "", + *, + allow_module_level: bool = False, ) -> NoReturn: """Skip an executing test with the given message. @@ -153,9 +139,6 @@ def skip( Defaults to False. - :param msg: - Same as ``reason``, but deprecated. Will be removed in a future version, use ``reason`` instead. - .. note:: It is better to use the :ref:`pytest.mark.skipif ref` marker when possible to declare a test to be skipped under certain conditions @@ -164,12 +147,11 @@ def skip( to skip a doctest statically. """ __tracebackhide__ = True - reason = _resolve_msg_to_reason("skip", reason, msg) raise Skipped(msg=reason, allow_module_level=allow_module_level) @_with_exception(Failed) -def fail(reason: str = "", pytrace: bool = True, msg: Optional[str] = None) -> NoReturn: +def fail(reason: str = "", pytrace: bool = True) -> NoReturn: """Explicitly fail an executing test with the given message. :param reason: @@ -178,51 +160,11 @@ def fail(reason: str = "", pytrace: bool = True, msg: Optional[str] = None) -> N :param pytrace: If False, msg represents the full failure information and no python traceback will be reported. - - :param msg: - Same as ``reason``, but deprecated. Will be removed in a future version, use ``reason`` instead. """ __tracebackhide__ = True - reason = _resolve_msg_to_reason("fail", reason, msg) raise Failed(msg=reason, pytrace=pytrace) -def _resolve_msg_to_reason( - func_name: str, reason: str, msg: Optional[str] = None -) -> str: - """ - Handles converting the deprecated msg parameter if provided into - reason, raising a deprecation warning. This function will be removed - when the optional msg argument is removed from here in future. - - :param str func_name: - The name of the offending function, this is formatted into the deprecation message. - - :param str reason: - The reason= passed into either pytest.fail() or pytest.skip() - - :param str msg: - The msg= passed into either pytest.fail() or pytest.skip(). This will - be converted into reason if it is provided to allow pytest.skip(msg=) or - pytest.fail(msg=) to continue working in the interim period. - - :returns: - The value to use as reason. - - """ - __tracebackhide__ = True - if msg is not None: - if reason: - from pytest import UsageError - - raise UsageError( - f"Passing both ``reason`` and ``msg`` to pytest.{func_name}(...) is not permitted." - ) - warnings.warn(KEYWORD_MSG_ARG.format(func=func_name), stacklevel=3) - reason = msg - return reason - - class XFailed(Failed): """Raised from an explicit call to pytest.xfail().""" diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 0fe0e8a7b9e..284441f7302 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -120,64 +120,6 @@ def test_hookproxy_warnings_for_pathlib(tmp_path, hooktype, request): ) -class TestSkipMsgArgumentDeprecated: - def test_skip_with_msg_is_deprecated(self, pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import pytest - - def test_skipping_msg(): - pytest.skip(msg="skippedmsg") - """ - ) - result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning") - result.stdout.fnmatch_lines( - [ - "*PytestRemovedIn8Warning: pytest.skip(msg=...) is now deprecated, " - "use pytest.skip(reason=...) instead", - '*pytest.skip(msg="skippedmsg")*', - ] - ) - result.assert_outcomes(skipped=1, warnings=1) - - def test_fail_with_msg_is_deprecated(self, pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import pytest - - def test_failing_msg(): - pytest.fail(msg="failedmsg") - """ - ) - result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning") - result.stdout.fnmatch_lines( - [ - "*PytestRemovedIn8Warning: pytest.fail(msg=...) is now deprecated, " - "use pytest.fail(reason=...) instead", - '*pytest.fail(msg="failedmsg")', - ] - ) - result.assert_outcomes(failed=1, warnings=1) - - def test_exit_with_msg_is_deprecated(self, pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import pytest - - def test_exit_msg(): - pytest.exit(msg="exitmsg") - """ - ) - result = pytester.runpytest(p, "-Wdefault::pytest.PytestRemovedIn8Warning") - result.stdout.fnmatch_lines( - [ - "*PytestRemovedIn8Warning: pytest.exit(msg=...) is now deprecated, " - "use pytest.exit(reason=...) instead", - ] - ) - result.assert_outcomes(warnings=1) - - def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: mod = pytester.getmodulecol("") diff --git a/testing/test_skipping.py b/testing/test_skipping.py index b7e448df366..a002ba6e836 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -1494,54 +1494,6 @@ def test_failing_reason(): result.assert_outcomes(failed=1) -def test_fail_fails_with_msg_and_reason(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import pytest - - def test_fail_both_arguments(): - pytest.fail(reason="foo", msg="bar") - """ - ) - result = pytester.runpytest(p) - result.stdout.fnmatch_lines( - "*UsageError: Passing both ``reason`` and ``msg`` to pytest.fail(...) is not permitted.*" - ) - result.assert_outcomes(failed=1) - - -def test_skip_fails_with_msg_and_reason(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import pytest - - def test_skip_both_arguments(): - pytest.skip(reason="foo", msg="bar") - """ - ) - result = pytester.runpytest(p) - result.stdout.fnmatch_lines( - "*UsageError: Passing both ``reason`` and ``msg`` to pytest.skip(...) is not permitted.*" - ) - result.assert_outcomes(failed=1) - - -def test_exit_with_msg_and_reason_fails(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import pytest - - def test_exit_both_arguments(): - pytest.exit(reason="foo", msg="bar") - """ - ) - result = pytester.runpytest(p) - result.stdout.fnmatch_lines( - "*UsageError: cannot pass reason and msg to exit(), `msg` is deprecated, use `reason`.*" - ) - result.assert_outcomes(failed=1) - - def test_exit_with_reason_works_ok(pytester: Pytester) -> None: p = pytester.makepyfile( """ From 0f18a7fe5e8911fe4b329931dcf8f23cb30130bd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 15:20:38 +0200 Subject: [PATCH 0333/1271] Remove deprecated nose support --- README.rst | 4 +- doc/en/adopt.rst | 3 +- doc/en/contents.rst | 1 - doc/en/deprecations.rst | 216 ++++++------ doc/en/example/index.rst | 1 - doc/en/explanation/fixtures.rst | 2 +- doc/en/how-to/existingtestsuite.rst | 4 +- doc/en/how-to/index.rst | 1 - doc/en/how-to/nose.rst | 99 ------ doc/en/index.rst | 2 +- setup.cfg | 1 - src/_pytest/config/__init__.py | 1 - src/_pytest/deprecated.py | 15 - src/_pytest/nose.py | 50 --- src/_pytest/python.py | 37 -- testing/deprecated_test.py | 59 ---- testing/test_nose.py | 529 ---------------------------- 17 files changed, 116 insertions(+), 909 deletions(-) delete mode 100644 doc/en/how-to/nose.rst delete mode 100644 src/_pytest/nose.py delete mode 100644 testing/test_nose.py diff --git a/README.rst b/README.rst index bbf41a18399..6e4772b04ac 100644 --- a/README.rst +++ b/README.rst @@ -97,8 +97,8 @@ Features - `Modular fixtures `_ for managing small or parametrized long-lived test resources -- Can run `unittest `_ (or trial), - `nose `_ test suites out of the box +- Can run `unittest `_ (or trial) + test suites out of the box - Python 3.8+ or PyPy3 diff --git a/doc/en/adopt.rst b/doc/en/adopt.rst index 13d82bf0116..b95a117debb 100644 --- a/doc/en/adopt.rst +++ b/doc/en/adopt.rst @@ -44,7 +44,7 @@ Partner projects, sign up here! (by 22 March) What does it mean to "adopt pytest"? ----------------------------------------- -There can be many different definitions of "success". Pytest can run many nose_ and unittest_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right? +There can be many different definitions of "success". Pytest can run many unittest_ tests by default, so using pytest as your testrunner may be possible from day 1. Job done, right? Progressive success might look like: @@ -62,7 +62,6 @@ Progressive success might look like: It may be after the month is up, the partner project decides that pytest is not right for it. That's okay - hopefully the pytest team will also learn something about its weaknesses or deficiencies. -.. _nose: nose.html .. _unittest: unittest.html .. _assert: assert.html .. _pycmd: https://bitbucket.org/hpk42/pycmd/overview diff --git a/doc/en/contents.rst b/doc/en/contents.rst index ae42884f658..181207203b2 100644 --- a/doc/en/contents.rst +++ b/doc/en/contents.rst @@ -44,7 +44,6 @@ How-to guides how-to/existingtestsuite how-to/unittest - how-to/nose how-to/xunit_setup how-to/bash-completion diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 1b661d4d74d..f1007d97737 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -19,113 +19,6 @@ Below is a complete list of all pytest features which are considered deprecated. :class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `. -.. _nose-deprecation: - -Support for tests written for nose -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.2 - -Support for running tests written for `nose `__ is now deprecated. - -``nose`` has been in maintenance mode-only for years, and maintaining the plugin is not trivial as it spills -over the code base (see :issue:`9886` for more details). - -setup/teardown -^^^^^^^^^^^^^^ - -One thing that might catch users by surprise is that plain ``setup`` and ``teardown`` methods are not pytest native, -they are in fact part of the ``nose`` support. - - -.. code-block:: python - - class Test: - def setup(self): - self.resource = make_resource() - - def teardown(self): - self.resource.close() - - def test_foo(self): - ... - - def test_bar(self): - ... - - - -Native pytest support uses ``setup_method`` and ``teardown_method`` (see :ref:`xunit-method-setup`), so the above should be changed to: - -.. code-block:: python - - class Test: - def setup_method(self): - self.resource = make_resource() - - def teardown_method(self): - self.resource.close() - - def test_foo(self): - ... - - def test_bar(self): - ... - - -This is easy to do in an entire code base by doing a simple find/replace. - -@with_setup -^^^^^^^^^^^ - -Code using `@with_setup `_ such as this: - -.. code-block:: python - - from nose.tools import with_setup - - - def setup_some_resource(): - ... - - - def teardown_some_resource(): - ... - - - @with_setup(setup_some_resource, teardown_some_resource) - def test_foo(): - ... - -Will also need to be ported to a supported pytest style. One way to do it is using a fixture: - -.. code-block:: python - - import pytest - - - def setup_some_resource(): - ... - - - def teardown_some_resource(): - ... - - - @pytest.fixture - def some_resource(): - setup_some_resource() - yield - teardown_some_resource() - - - def test_foo(some_resource): - ... - - -.. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup - - .. _node-ctor-fspath-deprecation: ``fspath`` argument for Node constructors replaced with ``pathlib.Path`` @@ -383,6 +276,115 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +.. _nose-deprecation: + +Support for tests written for nose +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.2 +.. versionremoved:: 8.0 + +Support for running tests written for `nose `__ is now deprecated. + +``nose`` has been in maintenance mode-only for years, and maintaining the plugin is not trivial as it spills +over the code base (see :issue:`9886` for more details). + +setup/teardown +^^^^^^^^^^^^^^ + +One thing that might catch users by surprise is that plain ``setup`` and ``teardown`` methods are not pytest native, +they are in fact part of the ``nose`` support. + + +.. code-block:: python + + class Test: + def setup(self): + self.resource = make_resource() + + def teardown(self): + self.resource.close() + + def test_foo(self): + ... + + def test_bar(self): + ... + + + +Native pytest support uses ``setup_method`` and ``teardown_method`` (see :ref:`xunit-method-setup`), so the above should be changed to: + +.. code-block:: python + + class Test: + def setup_method(self): + self.resource = make_resource() + + def teardown_method(self): + self.resource.close() + + def test_foo(self): + ... + + def test_bar(self): + ... + + +This is easy to do in an entire code base by doing a simple find/replace. + +@with_setup +^^^^^^^^^^^ + +Code using `@with_setup `_ such as this: + +.. code-block:: python + + from nose.tools import with_setup + + + def setup_some_resource(): + ... + + + def teardown_some_resource(): + ... + + + @with_setup(setup_some_resource, teardown_some_resource) + def test_foo(): + ... + +Will also need to be ported to a supported pytest style. One way to do it is using a fixture: + +.. code-block:: python + + import pytest + + + def setup_some_resource(): + ... + + + def teardown_some_resource(): + ... + + + @pytest.fixture + def some_resource(): + setup_some_resource() + yield + teardown_some_resource() + + + def test_foo(some_resource): + ... + + +.. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup + + + Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/en/example/index.rst b/doc/en/example/index.rst index e8835aae9d3..840819002d4 100644 --- a/doc/en/example/index.rst +++ b/doc/en/example/index.rst @@ -18,7 +18,6 @@ For basic examples, see - :ref:`Fixtures ` for basic fixture/setup examples - :ref:`parametrize` for basic test function parametrization - :ref:`unittest` for basic unittest integration -- :ref:`noseintegration` for basic nosetests integration The following examples aim at various use cases you might encounter. diff --git a/doc/en/explanation/fixtures.rst b/doc/en/explanation/fixtures.rst index 322718873e0..0bb3bf49fb0 100644 --- a/doc/en/explanation/fixtures.rst +++ b/doc/en/explanation/fixtures.rst @@ -85,7 +85,7 @@ style of setup/teardown functions: In addition, pytest continues to support :ref:`xunitsetup`. You can mix both styles, moving incrementally from classic to new style, as you prefer. You can also start out from existing :ref:`unittest.TestCase -style ` or :ref:`nose based ` projects. +style `. diff --git a/doc/en/how-to/existingtestsuite.rst b/doc/en/how-to/existingtestsuite.rst index 9909e7d113a..1c37023c72a 100644 --- a/doc/en/how-to/existingtestsuite.rst +++ b/doc/en/how-to/existingtestsuite.rst @@ -4,8 +4,8 @@ How to use pytest with an existing test suite ============================================== Pytest can be used with most existing test suites, but its -behavior differs from other test runners such as :ref:`nose ` or -Python's default unittest framework. +behavior differs from other test runners such as Python's +default unittest framework. Before using this section you will want to :ref:`install pytest `. diff --git a/doc/en/how-to/index.rst b/doc/en/how-to/index.rst index 6f52aaecdc3..225f289651e 100644 --- a/doc/en/how-to/index.rst +++ b/doc/en/how-to/index.rst @@ -52,7 +52,6 @@ pytest and other test systems existingtestsuite unittest - nose xunit_setup pytest development environment diff --git a/doc/en/how-to/nose.rst b/doc/en/how-to/nose.rst deleted file mode 100644 index 45d3357cf39..00000000000 --- a/doc/en/how-to/nose.rst +++ /dev/null @@ -1,99 +0,0 @@ -.. _`noseintegration`: - -How to run tests written for nose -======================================= - -``pytest`` has basic support for running tests written for nose_. - -.. warning:: - This functionality has been deprecated and is likely to be removed in ``pytest 8.x``. - -.. _nosestyle: - -Usage -------------- - -After :ref:`installation` type: - -.. code-block:: bash - - python setup.py develop # make sure tests can import our package - pytest # instead of 'nosetests' - -and you should be able to run your nose style tests and -make use of pytest's capabilities. - -Supported nose Idioms ----------------------- - -* ``setup()`` and ``teardown()`` at module/class/method level: any function or method called ``setup`` will be called during the setup phase for each test, same for ``teardown``. -* ``SkipTest`` exceptions and markers -* setup/teardown decorators -* ``__test__`` attribute on modules/classes/functions -* general usage of nose utilities - -Unsupported idioms / known issues ----------------------------------- - -- unittest-style ``setUp, tearDown, setUpClass, tearDownClass`` - are recognized only on ``unittest.TestCase`` classes but not - on plain classes. ``nose`` supports these methods also on plain - classes but pytest deliberately does not. As nose and pytest already - both support ``setup_class, teardown_class, setup_method, teardown_method`` - it doesn't seem useful to duplicate the unittest-API like nose does. - If you however rather think pytest should support the unittest-spelling on - plain classes please post to :issue:`377`. - -- nose imports test modules with the same import path (e.g. - ``tests.test_mode``) but different file system paths - (e.g. ``tests/test_mode.py`` and ``other/tests/test_mode.py``) - by extending sys.path/import semantics. pytest does not do that. Note that - `nose2 choose to avoid this sys.path/import hackery `_. - - If you place a conftest.py file in the root directory of your project - (as determined by pytest) pytest will run tests "nose style" against - the code below that directory by adding it to your ``sys.path`` instead of - running against your installed code. - - You may find yourself wanting to do this if you ran ``python setup.py install`` - to set up your project, as opposed to ``python setup.py develop`` or any of - the package manager equivalents. Installing with develop in a - virtual environment like tox is recommended over this pattern. - -- nose-style doctests are not collected and executed correctly, - also doctest fixtures don't work. - -- no nose-configuration is recognized. - -- ``yield``-based methods are - fundamentally incompatible with pytest because they don't support fixtures - properly since collection and test execution are separated. - -Here is a table comparing the default supported naming conventions for both -nose and pytest. - -========= ========================== ======= ===== -what default naming convention pytest nose -========= ========================== ======= ===== -module ``test*.py`` ✅ -module ``test_*.py`` ✅ ✅ -module ``*_test.py`` ✅ -module ``*_tests.py`` -class ``*(unittest.TestCase)`` ✅ ✅ -method ``test_*`` ✅ ✅ -class ``Test*`` ✅ -method ``test_*`` ✅ -function ``test_*`` ✅ -========= ========================== ======= ===== - - -Migrating from nose to pytest ------------------------------- - -`nose2pytest `_ is a Python script -and pytest plugin to help convert Nose-based tests into pytest-based tests. -Specifically, the script transforms ``nose.tools.assert_*`` function calls into -raw assert statements, while preserving format of original arguments -as much as possible. - -.. _nose: https://nose.readthedocs.io/en/latest/ diff --git a/doc/en/index.rst b/doc/en/index.rst index 50c84f6ae05..bef42716f48 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -74,7 +74,7 @@ Features - :ref:`Modular fixtures ` for managing small or parametrized long-lived test resources -- Can run :ref:`unittest ` (including trial) and :ref:`nose ` test suites out of the box +- Can run :ref:`unittest ` (including trial) test suites out of the box - Python 3.8+ or PyPy 3 diff --git a/setup.cfg b/setup.cfg index 3b1c627de06..02f6031bdc7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -69,7 +69,6 @@ testing = attrs>=19.2.0 hypothesis>=3.56 mock - nose pygments>=2.7.2 requests setuptools diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 2d5db172412..5d176c7aca3 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -252,7 +252,6 @@ def directory_arg(path: str, optname: str) -> str: "monkeypatch", "recwarn", "pastebin", - "nose", "assertion", "junitxml", "doctest", diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index f728d7a554a..072da3211e9 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -23,21 +23,6 @@ "pytest_faulthandler", } -NOSE_SUPPORT = UnformattedWarning( - PytestRemovedIn8Warning, - "Support for nose tests is deprecated and will be removed in a future release.\n" - "{nodeid} is using nose method: `{method}` ({stage})\n" - "See docs: https://docs.pytest.org/en/stable/deprecations.html#support-for-tests-written-for-nose", -) - -NOSE_SUPPORT_METHOD = UnformattedWarning( - PytestRemovedIn8Warning, - "Support for nose tests is deprecated and will be removed in a future release.\n" - "{nodeid} is using nose-specific method: `{method}(self)`\n" - "To remove this warning, rename it to `{method}_method(self)`\n" - "See docs: https://docs.pytest.org/en/stable/deprecations.html#support-for-tests-written-for-nose", -) - # This can be* removed pytest 8, but it's harmless and common, so no rush to remove. # * If you're in the future: "could have been". diff --git a/src/_pytest/nose.py b/src/_pytest/nose.py deleted file mode 100644 index 273bd045fb6..00000000000 --- a/src/_pytest/nose.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Run testsuites written for nose.""" -import warnings - -from _pytest.config import hookimpl -from _pytest.deprecated import NOSE_SUPPORT -from _pytest.fixtures import getfixturemarker -from _pytest.nodes import Item -from _pytest.python import Function -from _pytest.unittest import TestCaseFunction - - -@hookimpl(trylast=True) -def pytest_runtest_setup(item: Item) -> None: - if not isinstance(item, Function): - return - # Don't do nose style setup/teardown on direct unittest style classes. - if isinstance(item, TestCaseFunction): - return - - # Capture the narrowed type of item for the teardown closure, - # see https://github.com/python/mypy/issues/2608 - func = item - - call_optional(func.obj, "setup", func.nodeid) - func.addfinalizer(lambda: call_optional(func.obj, "teardown", func.nodeid)) - - # NOTE: Module- and class-level fixtures are handled in python.py - # with `pluginmanager.has_plugin("nose")` checks. - # It would have been nicer to implement them outside of core, but - # it's not straightforward. - - -def call_optional(obj: object, name: str, nodeid: str) -> bool: - method = getattr(obj, name, None) - if method is None: - return False - is_fixture = getfixturemarker(method) is not None - if is_fixture: - return False - if not callable(method): - return False - # Warn about deprecation of this plugin. - method_name = getattr(method, "__name__", str(method)) - warnings.warn( - NOSE_SUPPORT.format(nodeid=nodeid, method=method_name, stage=name), stacklevel=2 - ) - # If there are any problems allow the exception to raise rather than - # silently ignoring it. - method() - return True diff --git a/src/_pytest/python.py b/src/_pytest/python.py index f7e0a30b5f2..969bb676514 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -57,7 +57,6 @@ from _pytest.config import hookimpl from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest -from _pytest.deprecated import NOSE_SUPPORT_METHOD from _pytest.fixtures import FixtureDef from _pytest.fixtures import FixtureRequest from _pytest.fixtures import FuncFixtureInfo @@ -596,23 +595,12 @@ def _inject_setup_module_fixture(self) -> None: Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with other fixtures (#517). """ - has_nose = self.config.pluginmanager.has_plugin("nose") setup_module = _get_first_non_fixture_func( self.obj, ("setUpModule", "setup_module") ) - if setup_module is None and has_nose: - # The name "setup" is too common - only treat as fixture if callable. - setup_module = _get_first_non_fixture_func(self.obj, ("setup",)) - if not callable(setup_module): - setup_module = None teardown_module = _get_first_non_fixture_func( self.obj, ("tearDownModule", "teardown_module") ) - if teardown_module is None and has_nose: - teardown_module = _get_first_non_fixture_func(self.obj, ("teardown",)) - # Same as "setup" above - only treat as fixture if callable. - if not callable(teardown_module): - teardown_module = None if setup_module is None and teardown_module is None: return @@ -853,21 +841,10 @@ def _inject_setup_method_fixture(self) -> None: Using a fixture to invoke these methods ensures we play nicely and unsurprisingly with other fixtures (#517). """ - has_nose = self.config.pluginmanager.has_plugin("nose") setup_name = "setup_method" setup_method = _get_first_non_fixture_func(self.obj, (setup_name,)) - emit_nose_setup_warning = False - if setup_method is None and has_nose: - setup_name = "setup" - emit_nose_setup_warning = True - setup_method = _get_first_non_fixture_func(self.obj, (setup_name,)) teardown_name = "teardown_method" teardown_method = _get_first_non_fixture_func(self.obj, (teardown_name,)) - emit_nose_teardown_warning = False - if teardown_method is None and has_nose: - teardown_name = "teardown" - emit_nose_teardown_warning = True - teardown_method = _get_first_non_fixture_func(self.obj, (teardown_name,)) if setup_method is None and teardown_method is None: return @@ -882,24 +859,10 @@ def xunit_setup_method_fixture(self, request) -> Generator[None, None, None]: if setup_method is not None: func = getattr(self, setup_name) _call_with_optional_argument(func, method) - if emit_nose_setup_warning: - warnings.warn( - NOSE_SUPPORT_METHOD.format( - nodeid=request.node.nodeid, method="setup" - ), - stacklevel=2, - ) yield if teardown_method is not None: func = getattr(self, teardown_name) _call_with_optional_argument(func, method) - if emit_nose_teardown_warning: - warnings.warn( - NOSE_SUPPORT_METHOD.format( - nodeid=request.node.nodeid, method="teardown" - ), - stacklevel=2, - ) self.obj.__pytest_setup_method = xunit_setup_method_fixture diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 284441f7302..62314240f6e 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -188,62 +188,3 @@ def foo(): raise NotImplementedError() assert len(record) == 2 # one for each mark decorator - - -@pytest.mark.filterwarnings("default") -def test_nose_deprecated_with_setup(pytester: Pytester) -> None: - pytest.importorskip("nose") - pytester.makepyfile( - """ - from nose.tools import with_setup - - def setup_fn_no_op(): - ... - - def teardown_fn_no_op(): - ... - - @with_setup(setup_fn_no_op, teardown_fn_no_op) - def test_omits_warnings(): - ... - """ - ) - output = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning") - message = [ - "*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.", - "*test_nose_deprecated_with_setup.py::test_omits_warnings is using nose method: `setup_fn_no_op` (setup)", - "*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.", - "*test_nose_deprecated_with_setup.py::test_omits_warnings is using nose method: `teardown_fn_no_op` (teardown)", - ] - output.stdout.fnmatch_lines(message) - output.assert_outcomes(passed=1) - - -@pytest.mark.filterwarnings("default") -def test_nose_deprecated_setup_teardown(pytester: Pytester) -> None: - pytest.importorskip("nose") - pytester.makepyfile( - """ - class Test: - - def setup(self): - ... - - def teardown(self): - ... - - def test(self): - ... - """ - ) - output = pytester.runpytest("-Wdefault::pytest.PytestRemovedIn8Warning") - message = [ - "*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.", - "*test_nose_deprecated_setup_teardown.py::Test::test is using nose-specific method: `setup(self)`", - "*To remove this warning, rename it to `setup_method(self)`", - "*PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.", - "*test_nose_deprecated_setup_teardown.py::Test::test is using nose-specific method: `teardown(self)`", - "*To remove this warning, rename it to `teardown_method(self)`", - ] - output.stdout.fnmatch_lines(message) - output.assert_outcomes(passed=1) diff --git a/testing/test_nose.py b/testing/test_nose.py deleted file mode 100644 index 7ec4026f249..00000000000 --- a/testing/test_nose.py +++ /dev/null @@ -1,529 +0,0 @@ -import pytest -from _pytest.pytester import Pytester - - -def setup_module(mod): - mod.nose = pytest.importorskip("nose") - - -def test_nose_setup(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - values = [] - from nose.tools import with_setup - - @with_setup(lambda: values.append(1), lambda: values.append(2)) - def test_hello(): - assert values == [1] - - def test_world(): - assert values == [1,2] - - test_hello.setup = lambda: values.append(1) - test_hello.teardown = lambda: values.append(2) - """ - ) - result = pytester.runpytest( - p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" - ) - result.assert_outcomes(passed=2) - - -def test_setup_func_with_setup_decorator() -> None: - from _pytest.nose import call_optional - - values = [] - - class A: - @pytest.fixture(autouse=True) - def f(self): - values.append(1) - - call_optional(A(), "f", "A.f") - assert not values - - -def test_setup_func_not_callable() -> None: - from _pytest.nose import call_optional - - class A: - f = 1 - - call_optional(A(), "f", "A.f") - - -def test_nose_setup_func(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - from nose.tools import with_setup - - values = [] - - def my_setup(): - a = 1 - values.append(a) - - def my_teardown(): - b = 2 - values.append(b) - - @with_setup(my_setup, my_teardown) - def test_hello(): - print(values) - assert values == [1] - - def test_world(): - print(values) - assert values == [1,2] - - """ - ) - result = pytester.runpytest( - p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" - ) - result.assert_outcomes(passed=2) - - -def test_nose_setup_func_failure(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - from nose.tools import with_setup - - values = [] - my_setup = lambda x: 1 - my_teardown = lambda x: 2 - - @with_setup(my_setup, my_teardown) - def test_hello(): - print(values) - assert values == [1] - - def test_world(): - print(values) - assert values == [1,2] - - """ - ) - result = pytester.runpytest( - p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" - ) - result.stdout.fnmatch_lines(["*TypeError: ()*"]) - - -def test_nose_setup_func_failure_2(pytester: Pytester) -> None: - pytester.makepyfile( - """ - values = [] - - my_setup = 1 - my_teardown = 2 - - def test_hello(): - assert values == [] - - test_hello.setup = my_setup - test_hello.teardown = my_teardown - """ - ) - reprec = pytester.inline_run() - reprec.assertoutcome(passed=1) - - -def test_nose_setup_partial(pytester: Pytester) -> None: - pytest.importorskip("functools") - p = pytester.makepyfile( - """ - from functools import partial - - values = [] - - def my_setup(x): - a = x - values.append(a) - - def my_teardown(x): - b = x - values.append(b) - - my_setup_partial = partial(my_setup, 1) - my_teardown_partial = partial(my_teardown, 2) - - def test_hello(): - print(values) - assert values == [1] - - def test_world(): - print(values) - assert values == [1,2] - - test_hello.setup = my_setup_partial - test_hello.teardown = my_teardown_partial - """ - ) - result = pytester.runpytest( - p, "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" - ) - result.stdout.fnmatch_lines(["*2 passed*"]) - - -def test_module_level_setup(pytester: Pytester) -> None: - pytester.makepyfile( - """ - from nose.tools import with_setup - items = {} - - def setup(): - items.setdefault("setup", []).append("up") - - def teardown(): - items.setdefault("setup", []).append("down") - - def setup2(): - items.setdefault("setup2", []).append("up") - - def teardown2(): - items.setdefault("setup2", []).append("down") - - def test_setup_module_setup(): - assert items["setup"] == ["up"] - - def test_setup_module_setup_again(): - assert items["setup"] == ["up"] - - @with_setup(setup2, teardown2) - def test_local_setup(): - assert items["setup"] == ["up"] - assert items["setup2"] == ["up"] - - @with_setup(setup2, teardown2) - def test_local_setup_again(): - assert items["setup"] == ["up"] - assert items["setup2"] == ["up", "down", "up"] - """ - ) - result = pytester.runpytest( - "-p", "nose", "-Wignore::pytest.PytestRemovedIn8Warning" - ) - result.stdout.fnmatch_lines(["*4 passed*"]) - - -def test_nose_style_setup_teardown(pytester: Pytester) -> None: - pytester.makepyfile( - """ - values = [] - - def setup_module(): - values.append(1) - - def teardown_module(): - del values[0] - - def test_hello(): - assert values == [1] - - def test_world(): - assert values == [1] - """ - ) - result = pytester.runpytest("-p", "nose") - result.stdout.fnmatch_lines(["*2 passed*"]) - - -def test_fixtures_nose_setup_issue8394(pytester: Pytester) -> None: - pytester.makepyfile( - """ - def setup_module(): - pass - - def teardown_module(): - pass - - def setup_function(func): - pass - - def teardown_function(func): - pass - - def test_world(): - pass - - class Test(object): - def setup_class(cls): - pass - - def teardown_class(cls): - pass - - def setup_method(self, meth): - pass - - def teardown_method(self, meth): - pass - - def test_method(self): pass - """ - ) - match = "*no docstring available*" - result = pytester.runpytest("--fixtures") - assert result.ret == 0 - result.stdout.no_fnmatch_line(match) - - result = pytester.runpytest("--fixtures", "-v") - assert result.ret == 0 - result.stdout.fnmatch_lines([match, match, match, match]) - - -def test_nose_setup_ordering(pytester: Pytester) -> None: - pytester.makepyfile( - """ - def setup_module(mod): - mod.visited = True - - class TestClass(object): - def setup(self): - assert visited - self.visited_cls = True - def test_first(self): - assert visited - assert self.visited_cls - """ - ) - result = pytester.runpytest("-Wignore::pytest.PytestRemovedIn8Warning") - result.stdout.fnmatch_lines(["*1 passed*"]) - - -def test_apiwrapper_problem_issue260(pytester: Pytester) -> None: - # this would end up trying a call an optional teardown on the class - # for plain unittests we don't want nose behaviour - pytester.makepyfile( - """ - import unittest - class TestCase(unittest.TestCase): - def setup(self): - #should not be called in unittest testcases - assert 0, 'setup' - def teardown(self): - #should not be called in unittest testcases - assert 0, 'teardown' - def setUp(self): - print('setup') - def tearDown(self): - print('teardown') - def test_fun(self): - pass - """ - ) - result = pytester.runpytest() - result.assert_outcomes(passed=1) - - -def test_setup_teardown_linking_issue265(pytester: Pytester) -> None: - # we accidentally didn't integrate nose setupstate with normal setupstate - # this test ensures that won't happen again - pytester.makepyfile( - ''' - import pytest - - class TestGeneric(object): - def test_nothing(self): - """Tests the API of the implementation (for generic and specialized).""" - - @pytest.mark.skipif("True", reason= - "Skip tests to check if teardown is skipped as well.") - class TestSkipTeardown(TestGeneric): - - def setup(self): - """Sets up my specialized implementation for $COOL_PLATFORM.""" - raise Exception("should not call setup for skipped tests") - - def teardown(self): - """Undoes the setup.""" - raise Exception("should not call teardown for skipped tests") - ''' - ) - reprec = pytester.runpytest() - reprec.assert_outcomes(passed=1, skipped=1) - - -def test_SkipTest_during_collection(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import nose - raise nose.SkipTest("during collection") - def test_failing(): - assert False - """ - ) - result = pytester.runpytest(p) - result.assert_outcomes(skipped=1, warnings=0) - - -def test_SkipTest_in_test(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import nose - - def test_skipping(): - raise nose.SkipTest("in test") - """ - ) - reprec = pytester.inline_run() - reprec.assertoutcome(skipped=1) - - -def test_istest_function_decorator(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import nose.tools - @nose.tools.istest - def not_test_prefix(): - pass - """ - ) - result = pytester.runpytest(p) - result.assert_outcomes(passed=1) - - -def test_nottest_function_decorator(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import nose.tools - @nose.tools.nottest - def test_prefix(): - pass - """ - ) - reprec = pytester.inline_run() - assert not reprec.getfailedcollections() - calls = reprec.getreports("pytest_runtest_logreport") - assert not calls - - -def test_istest_class_decorator(pytester: Pytester) -> None: - p = pytester.makepyfile( - """ - import nose.tools - @nose.tools.istest - class NotTestPrefix(object): - def test_method(self): - pass - """ - ) - result = pytester.runpytest(p) - result.assert_outcomes(passed=1) - - -def test_nottest_class_decorator(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import nose.tools - @nose.tools.nottest - class TestPrefix(object): - def test_method(self): - pass - """ - ) - reprec = pytester.inline_run() - assert not reprec.getfailedcollections() - calls = reprec.getreports("pytest_runtest_logreport") - assert not calls - - -def test_skip_test_with_unicode(pytester: Pytester) -> None: - pytester.makepyfile( - """\ - import unittest - class TestClass(): - def test_io(self): - raise unittest.SkipTest('😊') - """ - ) - result = pytester.runpytest() - result.stdout.fnmatch_lines(["* 1 skipped *"]) - - -def test_raises(pytester: Pytester) -> None: - pytester.makepyfile( - """ - from nose.tools import raises - - @raises(RuntimeError) - def test_raises_runtimeerror(): - raise RuntimeError - - @raises(Exception) - def test_raises_baseexception_not_caught(): - raise BaseException - - @raises(BaseException) - def test_raises_baseexception_caught(): - raise BaseException - """ - ) - result = pytester.runpytest("-vv") - result.stdout.fnmatch_lines( - [ - "test_raises.py::test_raises_runtimeerror PASSED*", - "test_raises.py::test_raises_baseexception_not_caught FAILED*", - "test_raises.py::test_raises_baseexception_caught PASSED*", - "*= FAILURES =*", - "*_ test_raises_baseexception_not_caught _*", - "", - "arg = (), kw = {}", - "", - " def newfunc(*arg, **kw):", - " try:", - "> func(*arg, **kw)", - "", - "*/nose/*: ", - "_ _ *", - "", - " @raises(Exception)", - " def test_raises_baseexception_not_caught():", - "> raise BaseException", - "E BaseException", - "", - "test_raises.py:9: BaseException", - "* 1 failed, 2 passed *", - ] - ) - - -def test_nose_setup_skipped_if_non_callable(pytester: Pytester) -> None: - """Regression test for #9391.""" - p = pytester.makepyfile( - __init__="", - setup=""" - """, - teardown=""" - """, - test_it=""" - from . import setup, teardown - - def test_it(): - pass - """, - ) - result = pytester.runpytest(p.parent, "-p", "nose") - assert result.ret == 0 - - -@pytest.mark.parametrize("fixture_name", ("teardown", "teardown_class")) -def test_teardown_fixture_not_called_directly(fixture_name, pytester: Pytester) -> None: - """Regression test for #10597.""" - p = pytester.makepyfile( - f""" - import pytest - - class TestHello: - - @pytest.fixture - def {fixture_name}(self): - yield - - def test_hello(self, {fixture_name}): - assert True - """ - ) - result = pytester.runpytest(p, "-p", "nose") - assert result.ret == 0 From cb5a42c836744181229b522611084a70220e4e33 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 2 Jan 2024 19:31:37 +0200 Subject: [PATCH 0334/1271] terminalwriter: fix crash trying to highlight empty source For quick checking I don't know how we can reach here with an empty source, so test just checks the function directly. Fix #11758. --- changelog/11758.bugfix.rst | 2 ++ src/_pytest/_io/terminalwriter.py | 3 ++- testing/io/test_terminalwriter.py | 14 ++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 changelog/11758.bugfix.rst diff --git a/changelog/11758.bugfix.rst b/changelog/11758.bugfix.rst new file mode 100644 index 00000000000..af8a3f3514f --- /dev/null +++ b/changelog/11758.bugfix.rst @@ -0,0 +1,2 @@ +Fixed ``IndexError: string index out of range`` crash in ``if highlighted[-1] == "\n" and source[-1] != "\n"``. +This bug was introduced in pytest 8.0.0rc1. diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index bf9b7665194..56107d56647 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -200,8 +200,9 @@ def _highlight( """Highlight the given source if we have markup support.""" from _pytest.config.exceptions import UsageError - if not self.hasmarkup or not self.code_highlight: + if not source or not self.hasmarkup or not self.code_highlight: return source + try: from pygments.formatters.terminal import TerminalFormatter diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index 96e7366e543..c7e63c67284 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -306,3 +306,17 @@ def test_code_highlight(has_markup, code_highlight, expected, color_mapping): match=re.escape("indents size (2) should have same size as lines (1)"), ): tw._write_source(["assert 0"], [" ", " "]) + + +def test_highlight_empty_source() -> None: + """Don't crash trying to highlight empty source code. + + Issue #11758. + """ + f = io.StringIO() + tw = terminalwriter.TerminalWriter(f) + tw.hasmarkup = True + tw.code_highlight = True + tw._write_source([]) + + assert f.getvalue() == "" From effc2b05294b63e23162327a5704077dda6c60d4 Mon Sep 17 00:00:00 2001 From: Marc Bresson <50196352+MarcBresson@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:20:54 +0100 Subject: [PATCH 0335/1271] Clarified `markers` ini property. Fix #11738 (#11739) --- AUTHORS | 1 + doc/en/reference/reference.rst | 2 +- src/_pytest/mark/__init__.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 42cfd0be249..14a35c3d5c3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -242,6 +242,7 @@ Marc Mueller Marc Schlaich Marcelo Duarte Trevisani Marcin Bachry +Marc Bresson Marco Gorelli Mark Abramowitz Mark Dickinson diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 33aff0f7c5c..2796fa4f5a8 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2100,7 +2100,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: [pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg|pyproject.toml file found: - markers (linelist): Markers for test functions + markers (linelist): Register new markers for test functions empty_parameter_set_mark (string): Default marker for empty parametersets norecursedirs (args): Directory patterns to avoid for recursion diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index 3f97299ea70..bcee802f3b1 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -105,7 +105,7 @@ def pytest_addoption(parser: Parser) -> None: help="show markers (builtin, plugin and per-project ones).", ) - parser.addini("markers", "Markers for test functions", "linelist") + parser.addini("markers", "Register new markers for test functions", "linelist") parser.addini(EMPTY_PARAMETERSET_OPTION, "Default marker for empty parametersets") From a98f02d4238793300f1be01f75bf0fff5609a241 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 16:36:50 +0200 Subject: [PATCH 0336/1271] Remove deprecated py.path hook arguments --- doc/en/deprecations.rst | 52 +++++++++++++------------ src/_pytest/config/__init__.py | 4 +- src/_pytest/config/compat.py | 70 ---------------------------------- src/_pytest/deprecated.py | 7 ---- src/_pytest/hookspec.py | 43 +++++++++++---------- src/_pytest/main.py | 3 +- testing/deprecated_test.py | 33 ---------------- 7 files changed, 51 insertions(+), 161 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index f1007d97737..c623f09ca99 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -104,31 +104,6 @@ Changed ``hookwrapper`` attributes: * ``historic`` -``py.path.local`` arguments for hooks replaced with ``pathlib.Path`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.0 - -In order to support the transition from ``py.path.local`` to :mod:`pathlib`, the following hooks now receive additional arguments: - -* :hook:`pytest_ignore_collect(collection_path: pathlib.Path) ` as equivalent to ``path`` -* :hook:`pytest_collect_file(file_path: pathlib.Path) ` as equivalent to ``path`` -* :hook:`pytest_pycollect_makemodule(module_path: pathlib.Path) ` as equivalent to ``path`` -* :hook:`pytest_report_header(start_path: pathlib.Path) ` as equivalent to ``startdir`` -* :hook:`pytest_report_collectionfinish(start_path: pathlib.Path) ` as equivalent to ``startdir`` - -The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments. - -.. note:: - The name of the :class:`~_pytest.nodes.Node` arguments and attributes, - :ref:`outlined above ` (the new attribute - being ``path``) is **the opposite** of the situation for hooks (the old - argument being ``path``). - - This is an unfortunate artifact due to historical reasons, which should be - resolved in future versions as we slowly get rid of the :pypi:`py` - dependency (see :issue:`9283` for a longer discussion). - Directly constructing internal classes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -276,6 +251,33 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +``py.path.local`` arguments for hooks replaced with ``pathlib.Path`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 +.. versionremoved:: 8.0 + +In order to support the transition from ``py.path.local`` to :mod:`pathlib`, the following hooks now receive additional arguments: + +* :hook:`pytest_ignore_collect(collection_path: pathlib.Path) ` as equivalent to ``path`` +* :hook:`pytest_collect_file(file_path: pathlib.Path) ` as equivalent to ``path`` +* :hook:`pytest_pycollect_makemodule(module_path: pathlib.Path) ` as equivalent to ``path`` +* :hook:`pytest_report_header(start_path: pathlib.Path) ` as equivalent to ``startdir`` +* :hook:`pytest_report_collectionfinish(start_path: pathlib.Path) ` as equivalent to ``startdir`` + +The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments. + +.. note:: + The name of the :class:`~_pytest.nodes.Node` arguments and attributes, + :ref:`outlined above ` (the new attribute + being ``path``) is **the opposite** of the situation for hooks (the old + argument being ``path``). + + This is an unfortunate artifact due to historical reasons, which should be + resolved in future versions as we slowly get rid of the :pypi:`py` + dependency (see :issue:`9283` for a longer discussion). + + .. _nose-deprecation: Support for tests written for nose diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 5d176c7aca3..49d63a357c5 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -38,7 +38,6 @@ from typing import TYPE_CHECKING from typing import Union -import pluggy from pluggy import HookimplMarker from pluggy import HookimplOpts from pluggy import HookspecMarker @@ -48,7 +47,6 @@ import _pytest._code import _pytest.deprecated import _pytest.hookspec -from .compat import PathAwareHookProxy from .exceptions import PrintHelp as PrintHelp from .exceptions import UsageError as UsageError from .findpaths import determine_setup @@ -1008,7 +1006,7 @@ def __init__( self._store = self.stash self.trace = self.pluginmanager.trace.root.get("config") - self.hook: pluggy.HookRelay = PathAwareHookProxy(self.pluginmanager.hook) # type: ignore[assignment] + self.hook = self.pluginmanager.hook # type: ignore[assignment] self._inicache: Dict[str, Any] = {} self._override_ini: Sequence[str] = () self._opt2dest: Dict[str, str] = {} diff --git a/src/_pytest/config/compat.py b/src/_pytest/config/compat.py index afb38bbcc62..9c61b4dac09 100644 --- a/src/_pytest/config/compat.py +++ b/src/_pytest/config/compat.py @@ -1,24 +1,8 @@ from __future__ import annotations -import functools -import warnings from pathlib import Path -from typing import Mapping - -import pluggy from ..compat import LEGACY_PATH -from ..compat import legacy_path -from ..deprecated import HOOK_LEGACY_PATH_ARG - -# hookname: (Path, LEGACY_PATH) -imply_paths_hooks: Mapping[str, tuple[str, str]] = { - "pytest_ignore_collect": ("collection_path", "path"), - "pytest_collect_file": ("file_path", "path"), - "pytest_pycollect_makemodule": ("module_path", "path"), - "pytest_report_header": ("start_path", "startdir"), - "pytest_report_collectionfinish": ("start_path", "startdir"), -} def _check_path(path: Path, fspath: LEGACY_PATH) -> None: @@ -27,57 +11,3 @@ def _check_path(path: Path, fspath: LEGACY_PATH) -> None: f"Path({fspath!r}) != {path!r}\n" "if both path and fspath are given they need to be equal" ) - - -class PathAwareHookProxy: - """ - this helper wraps around hook callers - until pluggy supports fixingcalls, this one will do - - it currently doesn't return full hook caller proxies for fixed hooks, - this may have to be changed later depending on bugs - """ - - def __init__(self, hook_relay: pluggy.HookRelay) -> None: - self._hook_relay = hook_relay - - def __dir__(self) -> list[str]: - return dir(self._hook_relay) - - def __getattr__(self, key: str) -> pluggy.HookCaller: - hook: pluggy.HookCaller = getattr(self._hook_relay, key) - if key not in imply_paths_hooks: - self.__dict__[key] = hook - return hook - else: - path_var, fspath_var = imply_paths_hooks[key] - - @functools.wraps(hook) - def fixed_hook(**kw): - path_value: Path | None = kw.pop(path_var, None) - fspath_value: LEGACY_PATH | None = kw.pop(fspath_var, None) - if fspath_value is not None: - warnings.warn( - HOOK_LEGACY_PATH_ARG.format( - pylib_path_arg=fspath_var, pathlib_path_arg=path_var - ), - stacklevel=2, - ) - if path_value is not None: - if fspath_value is not None: - _check_path(path_value, fspath_value) - else: - fspath_value = legacy_path(path_value) - else: - assert fspath_value is not None - path_value = Path(fspath_value) - - kw[path_var] = path_value - kw[fspath_var] = fspath_value - return hook(**kw) - - fixed_hook.name = hook.name # type: ignore[attr-defined] - fixed_hook.spec = hook.spec # type: ignore[attr-defined] - fixed_hook.__name__ = key - self.__dict__[key] = fixed_hook - return fixed_hook # type: ignore[return-value] diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 072da3211e9..5421f23204c 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -35,13 +35,6 @@ PRIVATE = PytestDeprecationWarning("A private pytest class or function was used.") -HOOK_LEGACY_PATH_ARG = UnformattedWarning( - PytestRemovedIn8Warning, - "The ({pylib_path_arg}: py.path.local) argument is deprecated, please use ({pathlib_path_arg}: pathlib.Path)\n" - "see https://docs.pytest.org/en/latest/deprecations.html" - "#py-path-local-arguments-for-hooks-replaced-with-pathlib-path", -) - NODE_CTOR_FSPATH_ARG = UnformattedWarning( PytestRemovedIn8Warning, "The (fspath: py.path.local) argument to {node_type_name} is deprecated. " diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 14f7f45fa1f..c1963b4d7b2 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -40,7 +40,6 @@ from _pytest.runner import CallInfo from _pytest.terminal import TerminalReporter from _pytest.terminal import TestShortLogReport - from _pytest.compat import LEGACY_PATH hookspec = HookspecMarker("pytest") @@ -246,9 +245,7 @@ def pytest_collection_finish(session: "Session") -> None: @hookspec(firstresult=True) -def pytest_ignore_collect( - collection_path: Path, path: "LEGACY_PATH", config: "Config" -) -> Optional[bool]: +def pytest_ignore_collect(collection_path: Path, config: "Config") -> Optional[bool]: """Return True to prevent considering this path for collection. This hook is consulted for all files and directories prior to calling @@ -262,8 +259,10 @@ def pytest_ignore_collect( .. versionchanged:: 7.0.0 The ``collection_path`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``path`` parameter. The ``path`` parameter - has been deprecated. + equivalent of the ``path`` parameter. + + .. versionchanged:: 8.0.0 + The ``path`` parameter has been removed. """ @@ -288,9 +287,7 @@ def pytest_collect_directory(path: Path, parent: "Collector") -> "Optional[Colle """ -def pytest_collect_file( - file_path: Path, path: "LEGACY_PATH", parent: "Collector" -) -> "Optional[Collector]": +def pytest_collect_file(file_path: Path, parent: "Collector") -> "Optional[Collector]": """Create a :class:`~pytest.Collector` for the given path, or None if not relevant. For best results, the returned collector should be a subclass of @@ -303,8 +300,10 @@ def pytest_collect_file( .. versionchanged:: 7.0.0 The ``file_path`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``path`` parameter. The ``path`` parameter - has been deprecated. + equivalent of the ``path`` parameter. + + .. versionchanged:: 8.0.0 + The ``path`` parameter was removed. """ @@ -363,9 +362,7 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor @hookspec(firstresult=True) -def pytest_pycollect_makemodule( - module_path: Path, path: "LEGACY_PATH", parent -) -> Optional["Module"]: +def pytest_pycollect_makemodule(module_path: Path, parent) -> Optional["Module"]: """Return a :class:`pytest.Module` collector or None for the given path. This hook will be called for each matching test module path. @@ -381,7 +378,8 @@ def pytest_pycollect_makemodule( The ``module_path`` parameter was added as a :class:`pathlib.Path` equivalent of the ``path`` parameter. - The ``path`` parameter has been deprecated in favor of ``fspath``. + .. versionchanged:: 8.0.0 + The ``path`` parameter has been removed in favor of ``module_path``. """ @@ -751,7 +749,7 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No def pytest_report_header( # type:ignore[empty-body] - config: "Config", start_path: Path, startdir: "LEGACY_PATH" + config: "Config", start_path: Path ) -> Union[str, List[str]]: """Return a string or list of strings to be displayed as header info for terminal reporting. @@ -774,15 +772,16 @@ def pytest_report_header( # type:ignore[empty-body] .. versionchanged:: 7.0.0 The ``start_path`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``startdir`` parameter. The ``startdir`` parameter - has been deprecated. + equivalent of the ``startdir`` parameter. + + .. versionchanged:: 8.0.0 + The ``startdir`` parameter has been removed. """ def pytest_report_collectionfinish( # type:ignore[empty-body] config: "Config", start_path: Path, - startdir: "LEGACY_PATH", items: Sequence["Item"], ) -> Union[str, List[str]]: """Return a string or list of strings to be displayed after collection @@ -806,8 +805,10 @@ def pytest_report_collectionfinish( # type:ignore[empty-body] .. versionchanged:: 7.0.0 The ``start_path`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``startdir`` parameter. The ``startdir`` parameter - has been deprecated. + equivalent of the ``startdir`` parameter. + + .. versionchanged:: 8.0.0 + The ``startdir`` parameter has been removed. """ diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 3672df05a01..83952c60c1f 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -33,7 +33,6 @@ from _pytest.config import PytestPluginManager from _pytest.config import UsageError from _pytest.config.argparsing import Parser -from _pytest.config.compat import PathAwareHookProxy from _pytest.fixtures import FixtureManager from _pytest.outcomes import exit from _pytest.pathlib import absolutepath @@ -644,7 +643,7 @@ def gethookproxy(self, fspath: "os.PathLike[str]") -> pluggy.HookRelay: proxy: pluggy.HookRelay if remove_mods: # One or more conftests are not in use at this path. - proxy = PathAwareHookProxy(FSHookProxy(pm, remove_mods)) # type: ignore[arg-type,assignment] + proxy = FSHookProxy(pm, remove_mods) # type: ignore[arg-type,assignment] else: # All plugins are active for this fspath. proxy = self.config.hook diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 62314240f6e..5f7f4a2a6f7 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -1,6 +1,4 @@ import re -import sys -from pathlib import Path import pytest from _pytest import deprecated @@ -89,37 +87,6 @@ def __init__(self, foo: int, *, _ispytest: bool = False) -> None: PrivateInit(10, _ispytest=True) -@pytest.mark.parametrize("hooktype", ["hook", "ihook"]) -def test_hookproxy_warnings_for_pathlib(tmp_path, hooktype, request): - path = legacy_path(tmp_path) - - PATH_WARN_MATCH = r".*path: py\.path\.local\) argument is deprecated, please use \(collection_path: pathlib\.Path.*" - if hooktype == "ihook": - hooks = request.node.ihook - else: - hooks = request.config.hook - - with pytest.warns(PytestDeprecationWarning, match=PATH_WARN_MATCH) as r: - l1 = sys._getframe().f_lineno - hooks.pytest_ignore_collect( - config=request.config, path=path, collection_path=tmp_path - ) - l2 = sys._getframe().f_lineno - - (record,) = r - assert record.filename == __file__ - assert l1 < record.lineno < l2 - - hooks.pytest_ignore_collect(config=request.config, collection_path=tmp_path) - - # Passing entirely *different* paths is an outright error. - with pytest.raises(ValueError, match=r"path.*fspath.*need to be equal"): - with pytest.warns(PytestDeprecationWarning, match=PATH_WARN_MATCH) as r: - hooks.pytest_ignore_collect( - config=request.config, path=path, collection_path=Path("/bla/bla") - ) - - def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: mod = pytester.getmodulecol("") From 6c89f9261c6f5bde93bd116ef56b7ac96fc0ef21 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 16:45:17 +0200 Subject: [PATCH 0337/1271] Remove deprecated py.path (`fspath`) node constructor arguments --- doc/en/conf.py | 1 - doc/en/deprecations.rst | 79 ++++++++++++++++++------------------ src/_pytest/compat.py | 15 ------- src/_pytest/config/compat.py | 13 ------ src/_pytest/deprecated.py | 9 ---- src/_pytest/legacypath.py | 18 +++++++- src/_pytest/main.py | 1 - src/_pytest/nodes.py | 45 +++----------------- src/_pytest/python.py | 3 -- testing/deprecated_test.py | 22 ---------- testing/test_legacypath.py | 4 +- testing/test_nodes.py | 9 ++-- 12 files changed, 66 insertions(+), 153 deletions(-) delete mode 100644 src/_pytest/config/compat.py diff --git a/doc/en/conf.py b/doc/en/conf.py index d3a98015a68..2bc18be5828 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -199,7 +199,6 @@ ("py:class", "_tracing.TagTracerSub"), ("py:class", "warnings.WarningMessage"), # Undocumented type aliases - ("py:class", "LEGACY_PATH"), ("py:class", "_PluggyPlugin"), # TypeVars ("py:class", "_pytest._code.code.E"), diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index c623f09ca99..bcc195c601b 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -19,45 +19,6 @@ Below is a complete list of all pytest features which are considered deprecated. :class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `. -.. _node-ctor-fspath-deprecation: - -``fspath`` argument for Node constructors replaced with ``pathlib.Path`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.0 - -In order to support the transition from ``py.path.local`` to :mod:`pathlib`, -the ``fspath`` argument to :class:`~_pytest.nodes.Node` constructors like -:func:`pytest.Function.from_parent()` and :func:`pytest.Class.from_parent()` -is now deprecated. - -Plugins which construct nodes should pass the ``path`` argument, of type -:class:`pathlib.Path`, instead of the ``fspath`` argument. - -Plugins which implement custom items and collectors are encouraged to replace -``fspath`` parameters (``py.path.local``) with ``path`` parameters -(``pathlib.Path``), and drop any other usage of the ``py`` library if possible. - -If possible, plugins with custom items should use :ref:`cooperative -constructors ` to avoid hardcoding -arguments they only pass on to the superclass. - -.. note:: - The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the - new attribute being ``path``) is **the opposite** of the situation for - hooks, :ref:`outlined below ` (the old - argument being ``path``). - - This is an unfortunate artifact due to historical reasons, which should be - resolved in future versions as we slowly get rid of the :pypi:`py` - dependency (see :issue:`9283` for a longer discussion). - -Due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo` -which still is expected to return a ``py.path.local`` object, nodes still have -both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes, -no matter what argument was used in the constructor. We expect to deprecate the -``fspath`` attribute in a future release. - .. _legacy-path-hooks-deprecated: Configuring hook specs/impls using markers @@ -251,6 +212,46 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +.. _node-ctor-fspath-deprecation: + +``fspath`` argument for Node constructors replaced with ``pathlib.Path`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 + +In order to support the transition from ``py.path.local`` to :mod:`pathlib`, +the ``fspath`` argument to :class:`~_pytest.nodes.Node` constructors like +:func:`pytest.Function.from_parent()` and :func:`pytest.Class.from_parent()` +is now deprecated. + +Plugins which construct nodes should pass the ``path`` argument, of type +:class:`pathlib.Path`, instead of the ``fspath`` argument. + +Plugins which implement custom items and collectors are encouraged to replace +``fspath`` parameters (``py.path.local``) with ``path`` parameters +(``pathlib.Path``), and drop any other usage of the ``py`` library if possible. + +If possible, plugins with custom items should use :ref:`cooperative +constructors ` to avoid hardcoding +arguments they only pass on to the superclass. + +.. note:: + The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the + new attribute being ``path``) is **the opposite** of the situation for + hooks, :ref:`outlined below ` (the old + argument being ``path``). + + This is an unfortunate artifact due to historical reasons, which should be + resolved in future versions as we slowly get rid of the :pypi:`py` + dependency (see :issue:`9283` for a longer discussion). + +Due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo` +which still is expected to return a ``py.path.local`` object, nodes still have +both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes, +no matter what argument was used in the constructor. We expect to deprecate the +``fspath`` attribute in a future release. + + ``py.path.local`` arguments for hooks replaced with ``pathlib.Path`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 73d77f978f7..1e9c38ca8e5 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -16,25 +16,10 @@ from typing import NoReturn from typing import TypeVar -import py - _T = TypeVar("_T") _S = TypeVar("_S") -#: constant to prepare valuing pylib path replacements/lazy proxies later on -# intended for removal in pytest 8.0 or 9.0 - -# fmt: off -# intentional space to create a fake difference for the verification -LEGACY_PATH = py.path. local -# fmt: on - - -def legacy_path(path: str | os.PathLike[str]) -> LEGACY_PATH: - """Internal wrapper to prepare lazy proxies for legacy_path instances""" - return LEGACY_PATH(path) - # fmt: off # Singleton type for NOTSET, as described in: diff --git a/src/_pytest/config/compat.py b/src/_pytest/config/compat.py deleted file mode 100644 index 9c61b4dac09..00000000000 --- a/src/_pytest/config/compat.py +++ /dev/null @@ -1,13 +0,0 @@ -from __future__ import annotations - -from pathlib import Path - -from ..compat import LEGACY_PATH - - -def _check_path(path: Path, fspath: LEGACY_PATH) -> None: - if Path(fspath) != path: - raise ValueError( - f"Path({fspath!r}) != {path!r}\n" - "if both path and fspath are given they need to be equal" - ) diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 5421f23204c..1bc2cf57e80 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -11,7 +11,6 @@ from warnings import warn from _pytest.warning_types import PytestDeprecationWarning -from _pytest.warning_types import PytestRemovedIn8Warning from _pytest.warning_types import PytestRemovedIn9Warning from _pytest.warning_types import UnformattedWarning @@ -35,14 +34,6 @@ PRIVATE = PytestDeprecationWarning("A private pytest class or function was used.") -NODE_CTOR_FSPATH_ARG = UnformattedWarning( - PytestRemovedIn8Warning, - "The (fspath: py.path.local) argument to {node_type_name} is deprecated. " - "Please use the (path: pathlib.Path) argument instead.\n" - "See https://docs.pytest.org/en/latest/deprecations.html" - "#fspath-argument-for-node-constructors-replaced-with-pathlib-path", -) - HOOK_LEGACY_MARKING = UnformattedWarning( PytestDeprecationWarning, "The hook{type} {fullname} uses old-style configuration options (marks or attributes).\n" diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index 4876a083a67..b2dd87436e1 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -1,5 +1,6 @@ """Add backward compatibility support for the legacy py path type.""" import dataclasses +import os import shlex import subprocess from pathlib import Path @@ -12,9 +13,8 @@ from iniconfig import SectionWrapper +import py from _pytest.cacheprovider import Cache -from _pytest.compat import LEGACY_PATH -from _pytest.compat import legacy_path from _pytest.config import Config from _pytest.config import hookimpl from _pytest.config import PytestPluginManager @@ -36,6 +36,20 @@ import pexpect +#: constant to prepare valuing pylib path replacements/lazy proxies later on +# intended for removal in pytest 8.0 or 9.0 + +# fmt: off +# intentional space to create a fake difference for the verification +LEGACY_PATH = py.path. local +# fmt: on + + +def legacy_path(path: Union[str, "os.PathLike[str]"]) -> LEGACY_PATH: + """Internal wrapper to prepare lazy proxies for legacy_path instances""" + return LEGACY_PATH(path) + + @final class Testdir: """ diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 83952c60c1f..9fb96840e5c 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -541,7 +541,6 @@ def __init__(self, config: Config) -> None: super().__init__( name="", path=config.rootpath, - fspath=None, parent=None, config=config, session=self, diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index eefe690de3f..4cf6768e605 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -1,6 +1,5 @@ import abc import os -import pathlib import warnings from functools import cached_property from inspect import signature @@ -28,11 +27,8 @@ from _pytest._code.code import ExceptionInfo from _pytest._code.code import TerminalRepr from _pytest._code.code import Traceback -from _pytest.compat import LEGACY_PATH from _pytest.config import Config from _pytest.config import ConftestImportFailure -from _pytest.config.compat import _check_path -from _pytest.deprecated import NODE_CTOR_FSPATH_ARG from _pytest.mark.structures import Mark from _pytest.mark.structures import MarkDecorator from _pytest.mark.structures import NodeKeywords @@ -98,27 +94,6 @@ def iterparentnodeids(nodeid: str) -> Iterator[str]: yield nodeid -def _imply_path( - node_type: Type["Node"], - path: Optional[Path], - fspath: Optional[LEGACY_PATH], -) -> Path: - if fspath is not None: - warnings.warn( - NODE_CTOR_FSPATH_ARG.format( - node_type_name=node_type.__name__, - ), - stacklevel=6, - ) - if path is not None: - if fspath is not None: - _check_path(path, fspath) - return path - else: - assert fspath is not None - return Path(fspath) - - _NodeType = TypeVar("_NodeType", bound="Node") @@ -173,14 +148,6 @@ class Node(abc.ABC, metaclass=NodeMeta): ``Collector``\'s are the internal nodes of the tree, and ``Item``\'s are the leaf nodes. """ - - # Implemented in the legacypath plugin. - #: A ``LEGACY_PATH`` copy of the :attr:`path` attribute. Intended for usage - #: for methods not migrated to ``pathlib.Path`` yet, such as - #: :meth:`Item.reportinfo `. Will be deprecated in - #: a future release, prefer using :attr:`path` instead. - fspath: LEGACY_PATH - # Use __slots__ to make attribute access faster. # Note that __dict__ is still available. __slots__ = ( @@ -200,7 +167,6 @@ def __init__( parent: "Optional[Node]" = None, config: Optional[Config] = None, session: "Optional[Session]" = None, - fspath: Optional[LEGACY_PATH] = None, path: Optional[Path] = None, nodeid: Optional[str] = None, ) -> None: @@ -226,10 +192,11 @@ def __init__( raise TypeError("session or parent must be provided") self.session = parent.session - if path is None and fspath is None: + if path is None: path = getattr(parent, "path", None) + assert path is not None #: Filesystem path where this node was collected from (can be None). - self.path: pathlib.Path = _imply_path(type(self), path, fspath=fspath) + self.path = path # The explicit annotation is to avoid publicly exposing NodeKeywords. #: Keywords/markers collected from all scopes. @@ -595,7 +562,6 @@ class FSCollector(Collector, abc.ABC): def __init__( self, - fspath: Optional[LEGACY_PATH] = None, path_or_parent: Optional[Union[Path, Node]] = None, path: Optional[Path] = None, name: Optional[str] = None, @@ -611,8 +577,8 @@ def __init__( elif isinstance(path_or_parent, Path): assert path is None path = path_or_parent + assert path is not None - path = _imply_path(type(self), path, fspath=fspath) if name is None: name = path.name if parent is not None and parent.path != path: @@ -652,12 +618,11 @@ def from_parent( cls, parent, *, - fspath: Optional[LEGACY_PATH] = None, path: Optional[Path] = None, **kw, ): """The public constructor.""" - return super().from_parent(parent=parent, fspath=fspath, path=path, **kw) + return super().from_parent(parent=parent, path=path, **kw) class File(FSCollector, abc.ABC): diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 969bb676514..184399080d0 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -47,7 +47,6 @@ from _pytest.compat import getlocation from _pytest.compat import is_async_function from _pytest.compat import is_generator -from _pytest.compat import LEGACY_PATH from _pytest.compat import NOTSET from _pytest.compat import safe_getattr from _pytest.compat import safe_isclass @@ -672,7 +671,6 @@ class Package(nodes.Directory): def __init__( self, - fspath: Optional[LEGACY_PATH], parent: nodes.Collector, # NOTE: following args are unused: config=None, @@ -684,7 +682,6 @@ def __init__( # super().__init__(self, fspath, parent=parent) session = parent.session super().__init__( - fspath=fspath, path=path, parent=parent, config=config, diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 5f7f4a2a6f7..ebff49ce6d9 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -1,8 +1,5 @@ -import re - import pytest from _pytest import deprecated -from _pytest.compat import legacy_path from _pytest.pytester import Pytester from pytest import PytestDeprecationWarning @@ -87,25 +84,6 @@ def __init__(self, foo: int, *, _ispytest: bool = False) -> None: PrivateInit(10, _ispytest=True) -def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: - mod = pytester.getmodulecol("") - - class MyFile(pytest.File): - def collect(self): - raise NotImplementedError() - - with pytest.warns( - pytest.PytestDeprecationWarning, - match=re.escape( - "The (fspath: py.path.local) argument to MyFile is deprecated." - ), - ): - MyFile.from_parent( - parent=mod.parent, - fspath=legacy_path("bla"), - ) - - def test_fixture_disallow_on_marked_functions(): """Test that applying @pytest.fixture to a marked function warns (#3364).""" with pytest.warns( diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index b4fd1bf2c22..700499f24ea 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -1,8 +1,8 @@ from pathlib import Path import pytest -from _pytest.compat import LEGACY_PATH from _pytest.fixtures import TopRequest +from _pytest.legacypath import LEGACY_PATH from _pytest.legacypath import TempdirFactory from _pytest.legacypath import Testdir @@ -15,7 +15,7 @@ def test_item_fspath(pytester: pytest.Pytester) -> None: items2, hookrec = pytester.inline_genitems(item.nodeid) (item2,) = items2 assert item2.name == item.name - assert item2.fspath == item.fspath + assert item2.fspath == item.fspath # type: ignore[attr-defined] assert item2.path == item.path diff --git a/testing/test_nodes.py b/testing/test_nodes.py index 84c377cf990..880e2a44fae 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -7,7 +7,6 @@ import pytest from _pytest import nodes -from _pytest.compat import legacy_path from _pytest.outcomes import OutcomeException from _pytest.pytester import Pytester from _pytest.warning_types import PytestWarning @@ -69,9 +68,9 @@ def test_subclassing_both_item_and_collector_deprecated( warnings.simplefilter("error") class SoWrong(nodes.Item, nodes.File): - def __init__(self, fspath, parent): + def __init__(self, path, parent): """Legacy ctor with legacy call # don't wana see""" - super().__init__(fspath, parent) + super().__init__(parent, path) def collect(self): raise NotImplementedError() @@ -80,9 +79,7 @@ def runtest(self): raise NotImplementedError() with pytest.warns(PytestWarning) as rec: - SoWrong.from_parent( - request.session, fspath=legacy_path(tmp_path / "broken.txt") - ) + SoWrong.from_parent(request.session, path=tmp_path / "broken.txt", wrong=10) messages = [str(x.message) for x in rec] assert any( re.search(".*SoWrong.* not using a cooperative constructor.*", x) From 215f4d1fab4fad11ea57fdd2b497d7cd3b46c7c1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 2 Jan 2024 12:21:08 +0200 Subject: [PATCH 0338/1271] Remove `PytestRemovedIn8Warning` Per our deprecation policy. --- doc/en/changelog.rst | 2 +- doc/en/reference/reference.rst | 3 --- src/_pytest/warning_types.py | 6 ------ src/_pytest/warnings.py | 3 ++- src/pytest/__init__.py | 2 -- testing/test_warnings.py | 9 ++++----- 6 files changed, 7 insertions(+), 18 deletions(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index c097202ef78..755f386c6ca 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -227,7 +227,7 @@ These are breaking changes where deprecation was not possible. Deprecations ------------ -- `#10465 `_: Test functions returning a value other than ``None`` will now issue a :class:`pytest.PytestWarning` instead of :class:`pytest.PytestRemovedIn8Warning`, meaning this will stay a warning instead of becoming an error in the future. +- `#10465 `_: Test functions returning a value other than ``None`` will now issue a :class:`pytest.PytestWarning` instead of ``pytest.PytestRemovedIn8Warning``, meaning this will stay a warning instead of becoming an error in the future. - `#3664 `_: Applying a mark to a fixture function now issues a warning: marks in fixtures never had any effect, but it is a common user error to apply a mark to a fixture (for example ``usefixtures``) and expect it to work. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index bd64bac411c..3e1c5358dba 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1207,9 +1207,6 @@ Custom warnings generated in some situations such as improper usage or deprecate .. autoclass:: pytest.PytestReturnNotNoneWarning :show-inheritance: -.. autoclass:: pytest.PytestRemovedIn8Warning - :show-inheritance: - .. autoclass:: pytest.PytestRemovedIn9Warning :show-inheritance: diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index 4219f1439a2..6c109b03f0a 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -49,12 +49,6 @@ class PytestDeprecationWarning(PytestWarning, DeprecationWarning): __module__ = "pytest" -class PytestRemovedIn8Warning(PytestDeprecationWarning): - """Warning class for features that will be removed in pytest 8.""" - - __module__ = "pytest" - - class PytestRemovedIn9Warning(PytestDeprecationWarning): """Warning class for features that will be removed in pytest 9.""" diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index 6f20a872cca..6ef4fafdce5 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -46,7 +46,8 @@ def catch_warnings_for_item( warnings.filterwarnings("always", category=DeprecationWarning) warnings.filterwarnings("always", category=PendingDeprecationWarning) - warnings.filterwarnings("error", category=pytest.PytestRemovedIn8Warning) + # To be enabled in pytest 9.0.0. + # warnings.filterwarnings("error", category=pytest.PytestRemovedIn9Warning) apply_warning_filters(config_filters, cmdline_filters) diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 5fab295c6d7..449cb39b82d 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -73,7 +73,6 @@ from _pytest.warning_types import PytestConfigWarning from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestExperimentalApiWarning -from _pytest.warning_types import PytestRemovedIn8Warning from _pytest.warning_types import PytestRemovedIn9Warning from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning @@ -137,7 +136,6 @@ "PytestConfigWarning", "PytestDeprecationWarning", "PytestExperimentalApiWarning", - "PytestRemovedIn8Warning", "PytestRemovedIn9Warning", "PytestReturnNotNoneWarning", "Pytester", diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 96ecad6f647..e7834dc4d4d 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -518,8 +518,7 @@ def test_hidden_by_system(self, pytester: Pytester, monkeypatch) -> None: assert WARNINGS_SUMMARY_HEADER not in result.stdout.str() -# In 8.1, uncomment below and change RemovedIn8 -> RemovedIn9. -# @pytest.mark.skip("not relevant until pytest 9.0") +@pytest.mark.skip("not relevant until pytest 9.0") @pytest.mark.parametrize("change_default", [None, "ini", "cmdline"]) def test_removed_in_x_warning_as_error(pytester: Pytester, change_default) -> None: """This ensures that PytestRemovedInXWarnings raised by pytest are turned into errors. @@ -531,7 +530,7 @@ def test_removed_in_x_warning_as_error(pytester: Pytester, change_default) -> No """ import warnings, pytest def test(): - warnings.warn(pytest.PytestRemovedIn8Warning("some warning")) + warnings.warn(pytest.PytestRemovedIn9Warning("some warning")) """ ) if change_default == "ini": @@ -539,12 +538,12 @@ def test(): """ [pytest] filterwarnings = - ignore::pytest.PytestRemovedIn8Warning + ignore::pytest.PytestRemovedIn9Warning """ ) args = ( - ("-Wignore::pytest.PytestRemovedIn8Warning",) + ("-Wignore::pytest.PytestRemovedIn9Warning",) if change_default == "cmdline" else () ) From 1ba07450e427b7e291fd7c33278c0c087529a57d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 18:53:46 +0200 Subject: [PATCH 0339/1271] doc/deprecations: fix incorrect title level --- doc/en/deprecations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index bcc195c601b..f5334ace5b3 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -136,7 +136,7 @@ conflicts (such as :class:`pytest.File` now taking ``path`` instead of deprecation warning is now raised. Applying a mark to a fixture function -------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. deprecated:: 7.4 From 12b9bd580198edf88a795b692cbd6a1a05fe408a Mon Sep 17 00:00:00 2001 From: Ben Brown Date: Wed, 3 Jan 2024 12:39:24 -0500 Subject: [PATCH 0340/1271] Fix teardown error reporting when `--maxfail=1` (#11721) Co-authored-by: Ran Benita --- AUTHORS | 1 + changelog/11706.bugfix.rst | 1 + src/_pytest/main.py | 42 ++++++++++++++++++++++++-- src/_pytest/runner.py | 4 +++ testing/test_runner.py | 50 +++++++++++++++++++++++++++++++ testing/test_session.py | 60 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 changelog/11706.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 14a35c3d5c3..67e794527fb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -54,6 +54,7 @@ Aviral Verma Aviv Palivoda Babak Keyvani Barney Gale +Ben Brown Ben Gartner Ben Webb Benjamin Peterson diff --git a/changelog/11706.bugfix.rst b/changelog/11706.bugfix.rst new file mode 100644 index 00000000000..1b90d8f0b60 --- /dev/null +++ b/changelog/11706.bugfix.rst @@ -0,0 +1 @@ +Fix reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 9fb96840e5c..51be84164b2 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -6,6 +6,7 @@ import importlib import os import sys +import warnings from pathlib import Path from typing import AbstractSet from typing import Callable @@ -44,6 +45,7 @@ from _pytest.reports import TestReport from _pytest.runner import collect_one_node from _pytest.runner import SetupState +from _pytest.warning_types import PytestWarning def pytest_addoption(parser: Parser) -> None: @@ -548,8 +550,8 @@ def __init__(self, config: Config) -> None: ) self.testsfailed = 0 self.testscollected = 0 - self.shouldstop: Union[bool, str] = False - self.shouldfail: Union[bool, str] = False + self._shouldstop: Union[bool, str] = False + self._shouldfail: Union[bool, str] = False self.trace = config.trace.root.get("collection") self._initialpaths: FrozenSet[Path] = frozenset() self._initialpaths_with_parents: FrozenSet[Path] = frozenset() @@ -576,6 +578,42 @@ def __repr__(self) -> str: self.testscollected, ) + @property + def shouldstop(self) -> Union[bool, str]: + return self._shouldstop + + @shouldstop.setter + def shouldstop(self, value: Union[bool, str]) -> None: + # The runner checks shouldfail and assumes that if it is set we are + # definitely stopping, so prevent unsetting it. + if value is False and self._shouldstop: + warnings.warn( + PytestWarning( + "session.shouldstop cannot be unset after it has been set; ignoring." + ), + stacklevel=2, + ) + return + self._shouldstop = value + + @property + def shouldfail(self) -> Union[bool, str]: + return self._shouldfail + + @shouldfail.setter + def shouldfail(self, value: Union[bool, str]) -> None: + # The runner checks shouldfail and assumes that if it is set we are + # definitely stopping, so prevent unsetting it. + if value is False and self._shouldfail: + warnings.warn( + PytestWarning( + "session.shouldfail cannot be unset after it has been set; ignoring." + ), + stacklevel=2, + ) + return + self._shouldfail = value + @property def startpath(self) -> Path: """The path from which pytest was invoked. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index e20338520eb..3e19f0de50c 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -131,6 +131,10 @@ def runtestprotocol( show_test_item(item) if not item.config.getoption("setuponly", False): reports.append(call_and_report(item, "call", log)) + # If the session is about to fail or stop, teardown everything - this is + # necessary to correctly report fixture teardown errors (see #11706) + if item.session.shouldfail or item.session.shouldstop: + nextitem = None reports.append(call_and_report(item, "teardown", log, nextitem=nextitem)) # After all teardown hooks have been called # want funcargs and request info to go away. diff --git a/testing/test_runner.py b/testing/test_runner.py index c8b646857e7..26f5b9a0bc2 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1087,3 +1087,53 @@ def func() -> None: with pytest.raises(TypeError) as excinfo: OutcomeException(func) # type: ignore assert str(excinfo.value) == expected + + +def test_teardown_session_failed(pytester: Pytester) -> None: + """Test that higher-scoped fixture teardowns run in the context of the last + item after the test session bails early due to --maxfail. + + Regression test for #11706. + """ + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="module") + def baz(): + yield + pytest.fail("This is a failing teardown") + + def test_foo(baz): + pytest.fail("This is a failing test") + + def test_bar(): pass + """ + ) + result = pytester.runpytest("--maxfail=1") + result.assert_outcomes(failed=1, errors=1) + + +def test_teardown_session_stopped(pytester: Pytester) -> None: + """Test that higher-scoped fixture teardowns run in the context of the last + item after the test session bails early due to --stepwise. + + Regression test for #11706. + """ + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="module") + def baz(): + yield + pytest.fail("This is a failing teardown") + + def test_foo(baz): + pytest.fail("This is a failing test") + + def test_bar(): pass + """ + ) + result = pytester.runpytest("--stepwise") + result.assert_outcomes(failed=1, errors=1) diff --git a/testing/test_session.py b/testing/test_session.py index 136e85eb640..803bbed5434 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -418,3 +418,63 @@ def test_rootdir_wrong_option_arg(pytester: Pytester) -> None: result.stderr.fnmatch_lines( ["*Directory *wrong_dir* not found. Check your '--rootdir' option.*"] ) + + +def test_shouldfail_is_sticky(pytester: Pytester) -> None: + """Test that session.shouldfail cannot be reset to False after being set. + + Issue #11706. + """ + pytester.makeconftest( + """ + def pytest_sessionfinish(session): + assert session.shouldfail + session.shouldfail = False + assert session.shouldfail + """ + ) + pytester.makepyfile( + """ + import pytest + + def test_foo(): + pytest.fail("This is a failing test") + + def test_bar(): pass + """ + ) + + result = pytester.runpytest("--maxfail=1", "-Wall") + + result.assert_outcomes(failed=1, warnings=1) + result.stdout.fnmatch_lines("*session.shouldfail cannot be unset*") + + +def test_shouldstop_is_sticky(pytester: Pytester) -> None: + """Test that session.shouldstop cannot be reset to False after being set. + + Issue #11706. + """ + pytester.makeconftest( + """ + def pytest_sessionfinish(session): + assert session.shouldstop + session.shouldstop = False + assert session.shouldstop + """ + ) + pytester.makepyfile( + """ + import pytest + + def test_foo(): + pytest.fail("This is a failing test") + + def test_bar(): pass + """ + ) + + result = pytester.runpytest("--stepwise", "-Wall") + + result.assert_outcomes(failed=1, warnings=1) + result.stdout.fnmatch_lines("*session.shouldstop cannot be unset*") From 5aa289e47865ab9c1ca4d1efbffa1fd1024b81f7 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 31 Dec 2023 10:09:33 -0300 Subject: [PATCH 0341/1271] Improve GitHub release workflow This changes the existing script to just generate the release notes and delegate the actual publishing to the `softprops/action-gh-release@v1` action. This allows us to delete the custom code, which failed recently in https://github.com/pytest-dev/pytest/actions/runs/7370258570/job/20056477756. --- .github/workflows/deploy.yml | 13 +++-- scripts/.gitignore | 1 + ...-notes.py => generate-gh-release-notes.py} | 49 +++++-------------- tox.ini | 11 ++--- 4 files changed, 24 insertions(+), 50 deletions(-) create mode 100644 scripts/.gitignore rename scripts/{publish-gh-release-notes.py => generate-gh-release-notes.py} (56%) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ca65662c128..fed725f0ef1 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -82,9 +82,14 @@ jobs: python -m pip install --upgrade pip pip install --upgrade tox - - name: Publish GitHub release notes - env: - GH_RELEASE_NOTES_TOKEN: ${{ github.token }} + - name: Generate release notes run: | sudo apt-get install pandoc - tox -e publish-gh-release-notes + tox -e generate-gh-release-notes -- ${{ github.event.inputs.version }} scripts/latest-release-notes.md + + - name: Publish GitHub Release + uses: softprops/action-gh-release@v1 + with: + body_path: scripts/latest-release-notes.md + files: dist/* + tag_name: ${{ github.event.inputs.version }} diff --git a/scripts/.gitignore b/scripts/.gitignore new file mode 100644 index 00000000000..50a75b62959 --- /dev/null +++ b/scripts/.gitignore @@ -0,0 +1 @@ +latest-release-notes.md diff --git a/scripts/publish-gh-release-notes.py b/scripts/generate-gh-release-notes.py similarity index 56% rename from scripts/publish-gh-release-notes.py rename to scripts/generate-gh-release-notes.py index 68cbd7adffd..d30b8ef3037 100644 --- a/scripts/publish-gh-release-notes.py +++ b/scripts/generate-gh-release-notes.py @@ -1,3 +1,4 @@ +# mypy:disallow-untyped-defs """ Script used to publish GitHub release notes extracted from CHANGELOG.rst. @@ -19,27 +20,18 @@ Requires Python3.6+. """ -import os import re import sys from pathlib import Path -import github3 import pypandoc -def publish_github_release(slug, token, tag_name, body): - github = github3.login(token=token) - owner, repo = slug.split("/") - repo = github.repository(owner, repo) - return repo.create_release(tag_name=tag_name, body=body) - - def parse_changelog(tag_name): p = Path(__file__).parent.parent / "doc/en/changelog.rst" changelog_lines = p.read_text(encoding="UTF-8").splitlines() - title_regex = re.compile(r"pytest (\d\.\d+\.\d+) \(\d{4}-\d{2}-\d{2}\)") + title_regex = re.compile(r"pytest (\d\.\d+\.\d+\w*) \(\d{4}-\d{2}-\d{2}\)") consuming_version = False version_lines = [] for line in changelog_lines: @@ -64,36 +56,17 @@ def convert_rst_to_md(text): def main(argv): - if len(argv) > 1: - tag_name = argv[1] - else: - tag_name = os.environ.get("GITHUB_REF") - if not tag_name: - print("tag_name not given and $GITHUB_REF not set", file=sys.stderr) - return 1 - if tag_name.startswith("refs/tags/"): - tag_name = tag_name[len("refs/tags/") :] - - token = os.environ.get("GH_RELEASE_NOTES_TOKEN") - if not token: - print("GH_RELEASE_NOTES_TOKEN not set", file=sys.stderr) - return 1 - - slug = os.environ.get("GITHUB_REPOSITORY") - if not slug: - print("GITHUB_REPOSITORY not set", file=sys.stderr) - return 1 - - rst_body = parse_changelog(tag_name) - md_body = convert_rst_to_md(rst_body) - if not publish_github_release(slug, token, tag_name, md_body): - print("Could not publish release notes:", file=sys.stderr) - print(md_body, file=sys.stderr) - return 5 + if len(argv) != 3: + print("Usage: generate-gh-release-notes VERSION FILE") + return 2 + version, filename = argv[1:3] + print(f"Generating GitHub release notes for version {version}") + rst_body = parse_changelog(version) + md_body = convert_rst_to_md(rst_body) + Path(filename).write_text(md_body, encoding="UTF-8") print() - print(f"Release notes for {tag_name} published successfully:") - print(f"https://github.com/{slug}/releases/tag/{tag_name}") + print(f"Done: {filename}") print() return 0 diff --git a/tox.ini b/tox.ini index c52a43fd7a7..e92f6c98b73 100644 --- a/tox.ini +++ b/tox.ini @@ -177,18 +177,13 @@ passenv = {[testenv:release]passenv} deps = {[testenv:release]deps} commands = python scripts/prepare-release-pr.py {posargs} -[testenv:publish-gh-release-notes] -description = create GitHub release after deployment +[testenv:generate-gh-release-notes] +description = generate release notes that can be published as GitHub Release basepython = python3 usedevelop = True -passenv = - GH_RELEASE_NOTES_TOKEN - GITHUB_REF - GITHUB_REPOSITORY deps = - github3.py pypandoc -commands = python scripts/publish-gh-release-notes.py {posargs} +commands = python scripts/generate-gh-release-notes.py {posargs} [flake8] max-line-length = 120 From 6321b74faefef7c5dc267862eccc6a56f9a0ec61 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 31 Dec 2023 10:25:13 -0300 Subject: [PATCH 0342/1271] Enable type-checking in scripts/ --- .pre-commit-config.yaml | 3 ++- scripts/generate-gh-release-notes.py | 13 ++++++++----- scripts/prepare-release-pr.py | 1 + scripts/release.py | 25 ++++++++++++++----------- scripts/towncrier-draft-to-file.py | 7 ++++--- scripts/update-plugin-list.py | 27 +++++++++++++++++++++------ 6 files changed, 50 insertions(+), 26 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7c328ad48b6..ce1cce6e089 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,7 +59,7 @@ repos: rev: v1.8.0 hooks: - id: mypy - files: ^(src/|testing/) + files: ^(src/|testing/|scripts/) args: [] additional_dependencies: - iniconfig>=1.1.0 @@ -67,6 +67,7 @@ repos: - packaging - tomli - types-pkg_resources + - types-tabulate # for mypy running on python>=3.11 since exceptiongroup is only a dependency # on <3.11 - exceptiongroup>=1.0.0rc8 diff --git a/scripts/generate-gh-release-notes.py b/scripts/generate-gh-release-notes.py index d30b8ef3037..8eddb80552f 100644 --- a/scripts/generate-gh-release-notes.py +++ b/scripts/generate-gh-release-notes.py @@ -1,4 +1,4 @@ -# mypy:disallow-untyped-defs +# mypy: disallow-untyped-defs """ Script used to publish GitHub release notes extracted from CHANGELOG.rst. @@ -23,11 +23,12 @@ import re import sys from pathlib import Path +from typing import Sequence import pypandoc -def parse_changelog(tag_name): +def parse_changelog(tag_name: str) -> str: p = Path(__file__).parent.parent / "doc/en/changelog.rst" changelog_lines = p.read_text(encoding="UTF-8").splitlines() @@ -49,13 +50,15 @@ def parse_changelog(tag_name): return "\n".join(version_lines) -def convert_rst_to_md(text): - return pypandoc.convert_text( +def convert_rst_to_md(text: str) -> str: + result = pypandoc.convert_text( text, "md", format="rst", extra_args=["--wrap=preserve"] ) + assert isinstance(result, str), repr(result) + return result -def main(argv): +def main(argv: Sequence[str]) -> int: if len(argv) != 3: print("Usage: generate-gh-release-notes VERSION FILE") return 2 diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index 8ffa6696466..ce8242a74a3 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -1,3 +1,4 @@ +# mypy: disallow-untyped-defs """ This script is part of the pytest release process which is triggered manually in the Actions tab of the repository. diff --git a/scripts/release.py b/scripts/release.py index 19fef428428..66617feb5a9 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -1,3 +1,4 @@ +# mypy: disallow-untyped-defs """Invoke development tasks.""" import argparse import os @@ -10,15 +11,15 @@ from colorama import init -def announce(version, template_name, doc_version): +def announce(version: str, template_name: str, doc_version: str) -> None: """Generates a new release announcement entry in the docs.""" # Get our list of authors - stdout = check_output(["git", "describe", "--abbrev=0", "--tags"]) - stdout = stdout.decode("utf-8") + stdout = check_output(["git", "describe", "--abbrev=0", "--tags"], encoding="UTF-8") last_version = stdout.strip() - stdout = check_output(["git", "log", f"{last_version}..HEAD", "--format=%aN"]) - stdout = stdout.decode("utf-8") + stdout = check_output( + ["git", "log", f"{last_version}..HEAD", "--format=%aN"], encoding="UTF-8" + ) contributors = { name @@ -61,7 +62,7 @@ def announce(version, template_name, doc_version): check_call(["git", "add", str(target)]) -def regen(version): +def regen(version: str) -> None: """Call regendoc tool to update examples and pytest output in the docs.""" print(f"{Fore.CYAN}[generate.regen] {Fore.RESET}Updating docs") check_call( @@ -70,7 +71,7 @@ def regen(version): ) -def fix_formatting(): +def fix_formatting() -> None: """Runs pre-commit in all files to ensure they are formatted correctly""" print( f"{Fore.CYAN}[generate.fix linting] {Fore.RESET}Fixing formatting using pre-commit" @@ -78,13 +79,15 @@ def fix_formatting(): call(["pre-commit", "run", "--all-files"]) -def check_links(): +def check_links() -> None: """Runs sphinx-build to check links""" print(f"{Fore.CYAN}[generate.check_links] {Fore.RESET}Checking links") check_call(["tox", "-e", "docs-checklinks"]) -def pre_release(version, template_name, doc_version, *, skip_check_links): +def pre_release( + version: str, template_name: str, doc_version: str, *, skip_check_links: bool +) -> None: """Generates new docs, release announcements and creates a local tag.""" announce(version, template_name, doc_version) regen(version) @@ -102,12 +105,12 @@ def pre_release(version, template_name, doc_version, *, skip_check_links): print("Please push your branch and open a PR.") -def changelog(version, write_out=False): +def changelog(version: str, write_out: bool = False) -> None: addopts = [] if write_out else ["--draft"] check_call(["towncrier", "--yes", "--version", version] + addopts) -def main(): +def main() -> None: init(autoreset=True) parser = argparse.ArgumentParser() parser.add_argument("version", help="Release version") diff --git a/scripts/towncrier-draft-to-file.py b/scripts/towncrier-draft-to-file.py index 1f1068689a8..7b2748aa840 100644 --- a/scripts/towncrier-draft-to-file.py +++ b/scripts/towncrier-draft-to-file.py @@ -1,11 +1,12 @@ +# mypy: disallow-untyped-defs import sys from subprocess import call -def main(): +def main() -> int: """ - Platform agnostic wrapper script for towncrier. - Fixes the issue (#7251) where windows users are unable to natively run tox -e docs to build pytest docs. + Platform-agnostic wrapper script for towncrier. + Fixes the issue (#7251) where Windows users are unable to natively run tox -e docs to build pytest docs. """ with open( "doc/en/_changelog_towncrier_draft.rst", "w", encoding="utf-8" diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 46f22ad1e08..0f811b778ed 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -1,8 +1,13 @@ +# mypy: disallow-untyped-defs import datetime import pathlib import re from textwrap import dedent from textwrap import indent +from typing import Any +from typing import Iterable +from typing import Iterator +from typing import TypedDict import packaging.version import platformdirs @@ -109,7 +114,17 @@ def pytest_plugin_projects_from_pypi(session: CachedSession) -> dict[str, int]: } -def iter_plugins(): +class PluginInfo(TypedDict): + """Relevant information about a plugin to generate the summary.""" + + name: str + summary: str + last_release: str + status: str + requires: str + + +def iter_plugins() -> Iterator[PluginInfo]: session = get_session() name_2_serial = pytest_plugin_projects_from_pypi(session) @@ -136,7 +151,7 @@ def iter_plugins(): requires = requirement break - def version_sort_key(version_string): + def version_sort_key(version_string: str) -> Any: """ Return the sort key for the given version string returned by the API. @@ -162,20 +177,20 @@ def version_sort_key(version_string): yield { "name": name, "summary": summary.strip(), - "last release": last_release, + "last_release": last_release, "status": status, "requires": requires, } -def plugin_definitions(plugins): +def plugin_definitions(plugins: Iterable[PluginInfo]) -> Iterator[str]: """Return RST for the plugin list that fits better on a vertical page.""" for plugin in plugins: yield dedent( f""" {plugin['name']} - *last release*: {plugin["last release"]}, + *last release*: {plugin["last_release"]}, *status*: {plugin["status"]}, *requires*: {plugin["requires"]} @@ -184,7 +199,7 @@ def plugin_definitions(plugins): ) -def main(): +def main() -> None: plugins = [*iter_plugins()] reference_dir = pathlib.Path("doc", "en", "reference") From d38193646d872db966731234dcfc06ca995d07e4 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 4 Jan 2024 07:29:20 -0300 Subject: [PATCH 0343/1271] Update docstring of scripts/generate-gh-release-notes.py (#11767) Follow up to #11754. --- scripts/generate-gh-release-notes.py | 30 +++++++++------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/scripts/generate-gh-release-notes.py b/scripts/generate-gh-release-notes.py index 8eddb80552f..d22a5cf4c44 100644 --- a/scripts/generate-gh-release-notes.py +++ b/scripts/generate-gh-release-notes.py @@ -1,22 +1,10 @@ # mypy: disallow-untyped-defs """ -Script used to publish GitHub release notes extracted from CHANGELOG.rst. +Script used to generate a Markdown file containing only the changelog entries of a specific pytest release, which +is then published as a GitHub Release during deploy (see workflows/deploy.yml). -This script is meant to be executed after a successful deployment in GitHub actions. - -Uses the following environment variables: - -* GIT_TAG: the name of the tag of the current commit. -* GH_RELEASE_NOTES_TOKEN: a personal access token with 'repo' permissions. - - Create one at: - - https://github.com/settings/tokens - - This token should be set in a secret in the repository, which is exposed as an - environment variable in the main.yml workflow file. - -The script also requires ``pandoc`` to be previously installed in the system. +The script requires ``pandoc`` to be previously installed in the system -- we need to convert from RST (the format of +our CHANGELOG) into Markdown (which is required by GitHub Releases). Requires Python3.6+. """ @@ -28,7 +16,7 @@ import pypandoc -def parse_changelog(tag_name: str) -> str: +def extract_changelog_entries_for(version: str) -> str: p = Path(__file__).parent.parent / "doc/en/changelog.rst" changelog_lines = p.read_text(encoding="UTF-8").splitlines() @@ -38,10 +26,10 @@ def parse_changelog(tag_name: str) -> str: for line in changelog_lines: m = title_regex.match(line) if m: - # found the version we want: start to consume lines until we find the next version title - if m.group(1) == tag_name: + # Found the version we want: start to consume lines until we find the next version title. + if m.group(1) == version: consuming_version = True - # found a new version title while parsing the version we want: break out + # Found a new version title while parsing the version we want: break out. elif consuming_version: break if consuming_version: @@ -65,7 +53,7 @@ def main(argv: Sequence[str]) -> int: version, filename = argv[1:3] print(f"Generating GitHub release notes for version {version}") - rst_body = parse_changelog(version) + rst_body = extract_changelog_entries_for(version) md_body = convert_rst_to_md(rst_body) Path(filename).write_text(md_body, encoding="UTF-8") print() From ac96256272b6b806f1b036ed4476910b16dd7ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Thu, 4 Jan 2024 11:51:12 +0100 Subject: [PATCH 0344/1271] Fix a mistake in pytest.warns' docstring (expect_warning accepts tuples, not any sequence) --- src/_pytest/recwarn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 175d545b9b9..b3279dd314f 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -113,7 +113,7 @@ def warns( # noqa: F811 ) -> Union["WarningsChecker", Any]: r"""Assert that code raises a particular class of warning. - Specifically, the parameter ``expected_warning`` can be a warning class or sequence + Specifically, the parameter ``expected_warning`` can be a warning class or tuple of warning classes, and the code inside the ``with`` block must issue at least one warning of that class or classes. From 7b4ab8134ead2bd11d3e670b281d960c547e50f0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 23:03:24 +0200 Subject: [PATCH 0345/1271] fixtures: remove unnecessary `fspath` workaround --- src/_pytest/fixtures.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 89046ddd0bd..c5e46655008 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1674,11 +1674,6 @@ def parsefactories( # noqa: F811 self._holderobjseen.add(holderobj) autousenames = [] for name in dir(holderobj): - # ugly workaround for one of the fspath deprecated property of node - # todo: safely generalize - if isinstance(holderobj, nodes.Node) and name == "fspath": - continue - # The attribute can be an arbitrary descriptor, so the attribute # access below can raise. safe_getatt() ignores such exceptions. obj = safe_getattr(holderobj, name, None) From 685e52ec30f87cd968fea28addf985925631b703 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 1 Jan 2024 23:09:33 +0200 Subject: [PATCH 0346/1271] nodes: fix attribute name `fspath` -> `path` in `get_fslocation_from_item` --- src/_pytest/nodes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 4cf6768e605..112f9a149d3 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -488,7 +488,7 @@ def get_fslocation_from_item(node: "Node") -> Tuple[Union[str, Path], Optional[i * "location": a pair (path, lineno) * "obj": a Python object that the node wraps. - * "fspath": just a path + * "path": just a path :rtype: A tuple of (str|Path, int) with filename and 0-based line number. """ @@ -499,7 +499,7 @@ def get_fslocation_from_item(node: "Node") -> Tuple[Union[str, Path], Optional[i obj = getattr(node, "obj", None) if obj is not None: return getfslineno(obj) - return getattr(node, "fspath", "unknown location"), -1 + return getattr(node, "path", "unknown location"), -1 class Collector(Node, abc.ABC): From a616adf3aef6057203994852a8e0ae3cef54e0e3 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 5 Jan 2024 13:18:10 +0200 Subject: [PATCH 0347/1271] unittest: inline `_make_xunit_fixture` The indirection makes things harder to follow in this case IMO. --- src/_pytest/unittest.py | 138 +++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 81 deletions(-) diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 34845cec1c7..dee0c3e4407 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -29,7 +29,6 @@ from _pytest.python import Function from _pytest.python import Module from _pytest.runner import CallInfo -from _pytest.scope import Scope if TYPE_CHECKING: import unittest @@ -71,7 +70,8 @@ def collect(self) -> Iterable[Union[Item, Collector]]: skipped = _is_skipped(cls) if not skipped: - self._inject_setup_teardown_fixtures(cls) + self._inject_unittest_setup_method_fixture(cls) + self._inject_unittest_setup_class_fixture(cls) self._inject_setup_class_fixture() self.session._fixturemanager.parsefactories(self, unittest=True) @@ -93,91 +93,67 @@ def collect(self) -> Iterable[Union[Item, Collector]]: if ut is None or runtest != ut.TestCase.runTest: # type: ignore yield TestCaseFunction.from_parent(self, name="runTest") - def _inject_setup_teardown_fixtures(self, cls: type) -> None: - """Injects a hidden auto-use fixture to invoke setUpClass/setup_method and corresponding - teardown functions (#517).""" - class_fixture = _make_xunit_fixture( - cls, - "setUpClass", - "tearDownClass", - "doClassCleanups", - scope=Scope.Class, - pass_self=False, - ) - if class_fixture: - cls.__pytest_class_setup = class_fixture # type: ignore[attr-defined] - - method_fixture = _make_xunit_fixture( - cls, - "setup_method", - "teardown_method", - None, - scope=Scope.Function, - pass_self=True, - ) - if method_fixture: - cls.__pytest_method_setup = method_fixture # type: ignore[attr-defined] - - -def _make_xunit_fixture( - obj: type, - setup_name: str, - teardown_name: str, - cleanup_name: Optional[str], - scope: Scope, - pass_self: bool, -): - setup = getattr(obj, setup_name, None) - teardown = getattr(obj, teardown_name, None) - if setup is None and teardown is None: - return None - - if cleanup_name: - cleanup = getattr(obj, cleanup_name, lambda *args: None) - else: - - def cleanup(*args): - pass + def _inject_unittest_setup_class_fixture(self, cls: type) -> None: + """Injects a hidden auto-use fixture to invoke setUpClass and + tearDownClass (#517).""" + setup = getattr(cls, "setUpClass", None) + teardown = getattr(cls, "tearDownClass", None) + if setup is None and teardown is None: + return None + cleanup = getattr(cls, "doClassCleanups", lambda: None) - @pytest.fixture( - scope=scope.value, - autouse=True, - # Use a unique name to speed up lookup. - name=f"_unittest_{setup_name}_fixture_{obj.__qualname__}", - ) - def fixture(self, request: FixtureRequest) -> Generator[None, None, None]: - if _is_skipped(self): - reason = self.__unittest_skip_why__ - raise pytest.skip.Exception(reason, _use_item_location=True) - if setup is not None: - try: - if pass_self: - setup(self, request.function) - else: + @pytest.fixture( + scope="class", + autouse=True, + # Use a unique name to speed up lookup. + name=f"_unittest_setUpClass_fixture_{cls.__qualname__}", + ) + def fixture(self) -> Generator[None, None, None]: + if _is_skipped(self): + reason = self.__unittest_skip_why__ + raise pytest.skip.Exception(reason, _use_item_location=True) + if setup is not None: + try: setup() - # unittest does not call the cleanup function for every BaseException, so we - # follow this here. - except Exception: - if pass_self: - cleanup(self) - else: + # unittest does not call the cleanup function for every BaseException, so we + # follow this here. + except Exception: cleanup() - - raise - yield - try: - if teardown is not None: - if pass_self: - teardown(self, request.function) - else: + raise + yield + try: + if teardown is not None: teardown() - finally: - if pass_self: - cleanup(self) - else: + finally: cleanup() - return fixture + cls.__pytest_class_setup = fixture # type: ignore[attr-defined] + + def _inject_unittest_setup_method_fixture(self, cls: type) -> None: + """Injects a hidden auto-use fixture to invoke setup_method and + teardown_method (#517).""" + setup = getattr(cls, "setup_method", None) + teardown = getattr(cls, "teardown_method", None) + if setup is None and teardown is None: + return None + + @pytest.fixture( + scope="function", + autouse=True, + # Use a unique name to speed up lookup. + name=f"_unittest_setup_method_fixture_{cls.__qualname__}", + ) + def fixture(self, request: FixtureRequest) -> Generator[None, None, None]: + if _is_skipped(self): + reason = self.__unittest_skip_why__ + raise pytest.skip.Exception(reason, _use_item_location=True) + if setup is not None: + setup(self, request.function) + yield + if teardown is not None: + teardown(self, request.function) + + cls.__pytest_method_setup = fixture # type: ignore[attr-defined] class TestCaseFunction(Function): From 13eacdad8ac434b4336cf1e6496869815a6457c7 Mon Sep 17 00:00:00 2001 From: Fabian Sturm Date: Fri, 5 Jan 2024 13:59:19 +0100 Subject: [PATCH 0348/1271] Add summary for xfails with -rxX option (#11574) Co-authored-by: Brian Okken <1568356+okken@users.noreply.github.com> --- AUTHORS | 1 + changelog/11233.feature.rst | 5 ++ src/_pytest/terminal.py | 58 ++++++++++++------ testing/test_skipping.py | 2 +- testing/test_terminal.py | 119 ++++++++++++++++++++++++++++++++++++ 5 files changed, 166 insertions(+), 19 deletions(-) create mode 100644 changelog/11233.feature.rst diff --git a/AUTHORS b/AUTHORS index 67e794527fb..353489b6cd2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -138,6 +138,7 @@ Erik Hasse Erik M. Bray Evan Kepner Evgeny Seliverstov +Fabian Sturm Fabien Zarifian Fabio Zadrozny Felix Hofstätter diff --git a/changelog/11233.feature.rst b/changelog/11233.feature.rst new file mode 100644 index 00000000000..c465def84ec --- /dev/null +++ b/changelog/11233.feature.rst @@ -0,0 +1,5 @@ +Improvements to how ``-r`` for xfailures and xpasses: + +* Report tracebacks for xfailures when ``-rx`` is set. +* Report captured output for xpasses when ``-rX`` is set. +* For xpasses, add ``-`` in summary between test name and reason, to match how xfail is displayed. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index ea26d9368dc..b91a97221cd 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -878,8 +878,10 @@ def pytest_sessionfinish( def pytest_terminal_summary(self) -> Generator[None, None, None]: self.summary_errors() self.summary_failures() + self.summary_xfailures() self.summary_warnings() self.summary_passes() + self.summary_xpasses() try: return (yield) finally: @@ -1009,12 +1011,20 @@ def collapsed_location_report(reports: List[WarningReport]) -> str: ) def summary_passes(self) -> None: + self.summary_passes_combined("passed", "PASSES", "P") + + def summary_xpasses(self) -> None: + self.summary_passes_combined("xpassed", "XPASSES", "X") + + def summary_passes_combined( + self, which_reports: str, sep_title: str, needed_opt: str + ) -> None: if self.config.option.tbstyle != "no": - if self.hasopt("P"): - reports: List[TestReport] = self.getreports("passed") + if self.hasopt(needed_opt): + reports: List[TestReport] = self.getreports(which_reports) if not reports: return - self.write_sep("=", "PASSES") + self.write_sep("=", sep_title) for rep in reports: if rep.sections: msg = self._getfailureheadline(rep) @@ -1048,21 +1058,30 @@ def print_teardown_sections(self, rep: TestReport) -> None: self._tw.line(content) def summary_failures(self) -> None: + self.summary_failures_combined("failed", "FAILURES") + + def summary_xfailures(self) -> None: + self.summary_failures_combined("xfailed", "XFAILURES", "x") + + def summary_failures_combined( + self, which_reports: str, sep_title: str, needed_opt: Optional[str] = None + ) -> None: if self.config.option.tbstyle != "no": - reports: List[BaseReport] = self.getreports("failed") - if not reports: - return - self.write_sep("=", "FAILURES") - if self.config.option.tbstyle == "line": - for rep in reports: - line = self._getcrashline(rep) - self.write_line(line) - else: - for rep in reports: - msg = self._getfailureheadline(rep) - self.write_sep("_", msg, red=True, bold=True) - self._outrep_summary(rep) - self._handle_teardown_sections(rep.nodeid) + if not needed_opt or self.hasopt(needed_opt): + reports: List[BaseReport] = self.getreports(which_reports) + if not reports: + return + self.write_sep("=", sep_title) + if self.config.option.tbstyle == "line": + for rep in reports: + line = self._getcrashline(rep) + self.write_line(line) + else: + for rep in reports: + msg = self._getfailureheadline(rep) + self.write_sep("_", msg, red=True, bold=True) + self._outrep_summary(rep) + self._handle_teardown_sections(rep.nodeid) def summary_errors(self) -> None: if self.config.option.tbstyle != "no": @@ -1168,8 +1187,11 @@ def show_xpassed(lines: List[str]) -> None: verbose_word, **{_color_for_type["warnings"]: True} ) nodeid = _get_node_id_with_markup(self._tw, self.config, rep) + line = f"{markup_word} {nodeid}" reason = rep.wasxfail - lines.append(f"{markup_word} {nodeid} {reason}") + if reason: + line += " - " + str(reason) + lines.append(line) def show_skipped(lines: List[str]) -> None: skipped: List[CollectReport] = self.stats.get("skipped", []) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index a002ba6e836..86940baa6fd 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -649,7 +649,7 @@ def test_foo(): result.stdout.fnmatch_lines( [ "*test_strict_xfail*", - "XPASS test_strict_xfail.py::test_foo unsupported feature", + "XPASS test_strict_xfail.py::test_foo - unsupported feature", ] ) assert result.ret == (1 if strict else 0) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 20392096e40..b521deea7d1 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2619,3 +2619,122 @@ def test_format_trimmed() -> None: assert _format_trimmed(" ({}) ", msg, len(msg) + 4) == " (unconditional skip) " assert _format_trimmed(" ({}) ", msg, len(msg) + 3) == " (unconditional ...) " + + +def test_summary_xfail_reason(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_xfail(): + assert False + + @pytest.mark.xfail(reason="foo") + def test_xfail_reason(): + assert False + """ + ) + result = pytester.runpytest("-rx") + expect1 = "XFAIL test_summary_xfail_reason.py::test_xfail" + expect2 = "XFAIL test_summary_xfail_reason.py::test_xfail_reason - foo" + result.stdout.fnmatch_lines([expect1, expect2]) + assert result.stdout.lines.count(expect1) == 1 + assert result.stdout.lines.count(expect2) == 1 + + +def test_summary_xfail_tb(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_xfail(): + a, b = 1, 2 + assert a == b + """ + ) + result = pytester.runpytest("-rx") + result.stdout.fnmatch_lines( + [ + "*= XFAILURES =*", + "*_ test_xfail _*", + "* @pytest.mark.xfail*", + "* def test_xfail():*", + "* a, b = 1, 2*", + "> *assert a == b*", + "E *assert 1 == 2*", + "test_summary_xfail_tb.py:6: AssertionError*", + "*= short test summary info =*", + "XFAIL test_summary_xfail_tb.py::test_xfail", + "*= 1 xfailed in * =*", + ] + ) + + +def test_xfail_tb_line(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_xfail(): + a, b = 1, 2 + assert a == b + """ + ) + result = pytester.runpytest("-rx", "--tb=line") + result.stdout.fnmatch_lines( + [ + "*= XFAILURES =*", + "*test_xfail_tb_line.py:6: assert 1 == 2", + "*= short test summary info =*", + "XFAIL test_xfail_tb_line.py::test_xfail", + "*= 1 xfailed in * =*", + ] + ) + + +def test_summary_xpass_reason(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_pass(): + ... + + @pytest.mark.xfail(reason="foo") + def test_reason(): + ... + """ + ) + result = pytester.runpytest("-rX") + expect1 = "XPASS test_summary_xpass_reason.py::test_pass" + expect2 = "XPASS test_summary_xpass_reason.py::test_reason - foo" + result.stdout.fnmatch_lines([expect1, expect2]) + assert result.stdout.lines.count(expect1) == 1 + assert result.stdout.lines.count(expect2) == 1 + + +def test_xpass_output(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.xfail + def test_pass(): + print('hi there') + """ + ) + result = pytester.runpytest("-rX") + result.stdout.fnmatch_lines( + [ + "*= XPASSES =*", + "*_ test_pass _*", + "*- Captured stdout call -*", + "*= short test summary info =*", + "XPASS test_xpass_output.py::test_pass*", + "*= 1 xpassed in * =*", + ] + ) From 5747a6c06ebc4823a48a2b66d0644f36dda3eee6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 7 Jan 2024 10:20:38 -0300 Subject: [PATCH 0349/1271] [automated] Update plugin list (#11784) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 160 +++++++++++++++++-------------- 1 file changed, 88 insertions(+), 72 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index a967a33bda4..f1b672ecd6e 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,12 +27,12 @@ please refer to `the update script =7.3.0,<8.0.0) @@ -105,7 +105,7 @@ This list contains 1357 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 Dec 09, 2023 4 - Beta pytest >=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Jan 01, 2024 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) @@ -134,7 +134,7 @@ This list contains 1357 plugins. :pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) :pypi:`pytest-bdd` BDD for pytest Dec 02, 2023 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) - :pypi:`pytest-bdd-ng` BDD for pytest Jul 01, 2023 4 - Beta pytest (>=5.0) + :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 15, 2023 N/A pytest >=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) @@ -190,7 +190,7 @@ This list contains 1357 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Dec 28, 2023 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 03, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A @@ -198,7 +198,7 @@ This list contains 1357 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Sep 22, 2023 N/A pytest + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Dec 31, 2023 N/A pytest :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -306,6 +306,7 @@ This list contains 1357 plugins. :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-dbt-core` Pytest extension for dbt. Aug 25, 2023 N/A pytest >=6.2.5 ; extra == 'test' + :pypi:`pytest-dbt-postgres` Pytest tooling to unittest DBT & Postgres models Jan 02, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-dc` Manages Docker containers during your integration tests Aug 16, 2023 5 - Production/Stable pytest >=3.3 @@ -314,7 +315,7 @@ This list contains 1357 plugins. :pypi:`pytest-deepcov` deepcov Mar 30, 2021 N/A N/A :pypi:`pytest-defer` Aug 24, 2021 N/A N/A :pypi:`pytest-demo-plugin` pytest示例插件 May 15, 2021 N/A N/A - :pypi:`pytest-dependency` Manage dependencies of tests Feb 14, 2020 4 - Beta N/A + :pypi:`pytest-dependency` Manage dependencies of tests Dec 31, 2023 4 - Beta N/A :pypi:`pytest-depends` Tests that depend on other tests Apr 05, 2020 5 - Production/Stable pytest (>=3) :pypi:`pytest-deprecate` Mark tests as testing a deprecated feature with a warning note. Jul 01, 2019 N/A N/A :pypi:`pytest-describe` Describe-style plugin for pytest Apr 09, 2023 5 - Production/Stable pytest (<8,>=4.6) @@ -338,6 +339,7 @@ This list contains 1357 plugins. :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A :pypi:`pytest-django-class` A pytest plugin for running django in class-scoped fixtures Aug 08, 2023 4 - Beta N/A + :pypi:`pytest-django-docker-pg` Jan 05, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) :pypi:`pytest-django-factories` Factories for your Django models that can be used as Pytest fixtures. Nov 12, 2020 4 - Beta N/A :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 @@ -369,7 +371,7 @@ This list contains 1357 plugins. :pypi:`pytest-docker-postgresql` A simple plugin to use with pytest Sep 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-docker-py` Easy to use, simple to extend, pytest plugin that minimally leverages docker-py. Nov 27, 2018 N/A pytest (==4.0.0) :pypi:`pytest-docker-registry-fixtures` Pytest fixtures for testing with docker registries. Apr 08, 2022 4 - Beta pytest - :pypi:`pytest-docker-service` pytest plugin to start docker container Feb 22, 2023 3 - Alpha pytest (>=7.1.3) + :pypi:`pytest-docker-service` pytest plugin to start docker container Jan 03, 2024 3 - Alpha pytest (>=7.1.3) :pypi:`pytest-docker-squid-fixtures` Pytest fixtures for testing with squid. Feb 09, 2022 4 - Beta pytest :pypi:`pytest-docker-tools` Docker integration tests for pytest Feb 17, 2022 4 - Beta pytest (>=6.0.1) :pypi:`pytest-docs` Documentation tool for pytest Nov 11, 2018 4 - Beta pytest (>=3.5.0) @@ -410,14 +412,14 @@ This list contains 1357 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. Dec 29, 2023 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Dec 29, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Dec 29, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Dec 29, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Dec 29, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Dec 29, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Dec 29, 2023 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Dec 29, 2023 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jan 04, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 04, 2024 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) @@ -546,7 +548,7 @@ This list contains 1357 plugins. :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A - :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Sep 15, 2023 4 - Beta pytest >=2.6.0 + :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest :pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest @@ -577,7 +579,7 @@ This list contains 1357 plugins. :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Dec 15, 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` Dec 27, 2023 N/A N/A + :pypi:`pytest-hot-reloading` Jan 06, 2024 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. Dec 25, 2023 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) @@ -587,7 +589,7 @@ This list contains 1357 plugins. :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Nov 11, 2023 N/A N/A - :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Mar 04, 2022 5 - Production/Stable N/A + :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Jan 05, 2024 5 - Production/Stable N/A :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A :pypi:`pytest-html-report-merger` Oct 23, 2023 N/A N/A @@ -601,6 +603,7 @@ This list contains 1357 plugins. :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Dec 21, 2023 5 - Production/Stable pytest ==7.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) + :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A @@ -623,7 +626,7 @@ This list contains 1357 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 19, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Dec 13, 2023 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Dec 11, 2023 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package Jan 04, 2024 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 @@ -634,14 +637,13 @@ This list contains 1357 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. Dec 05, 2023 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Jan 03, 2024 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 :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Oct 31, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-is-running` pytest plugin providing a function to check if pytest is running. Jul 10, 2023 5 - Production/Stable N/A :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 22, 2020 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A @@ -753,7 +755,7 @@ This list contains 1357 plugins. :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Dec 24, 2023 N/A pytest >=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Jan 04, 2024 N/A pytest >=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) @@ -930,7 +932,7 @@ This list contains 1357 plugins. :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest :pypi:`pytest-prosper` Test helpers for Prosper projects Sep 24, 2018 N/A N/A - :pypi:`pytest-prysk` Pytest plugin for prysk Jul 18, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-prysk` Pytest plugin for prysk Dec 30, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) @@ -954,8 +956,8 @@ This list contains 1357 plugins. :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Nov 03, 2023 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Aug 20, 2023 4 - Beta pytest >=7.0.0 - :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Mar 12, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) - :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. May 07, 2023 N/A pytest (>=3.5.0) + :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Jan 02, 2024 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest @@ -1041,7 +1043,7 @@ This list contains 1357 plugins. :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Oct 04, 2023 N/A pytest >=7.0.0 + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Jan 04, 2024 N/A pytest >=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest @@ -1075,7 +1077,7 @@ This list contains 1357 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 04, 2024 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) @@ -1084,7 +1086,7 @@ This list contains 1357 plugins. :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 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. Dec 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jan 04, 2024 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 @@ -1112,7 +1114,7 @@ This list contains 1357 plugins. :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest :pypi:`pytest-single-file-logging` Allow for multiple processes to log to a single file May 05, 2016 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-skip-markers` Pytest Salt Plugin Oct 20, 2023 5 - Production/Stable pytest >=7.1.0 + :pypi:`pytest-skip-markers` Pytest Salt Plugin Jan 04, 2024 5 - Production/Stable pytest >=7.1.0 :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 @@ -1149,7 +1151,7 @@ This list contains 1357 plugins. :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 + :pypi:`pytest-spiratest` Exports unit tests as test runs in Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Jun 11, 2022 6 - Mature pytest (<8.0,>=7.1.2) :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Apr 12, 2023 4 - Beta pytest (>=5,<8) @@ -1263,7 +1265,7 @@ This list contains 1357 plugins. :pypi:`pytest-timer` A timer plugin for pytest Dec 26, 2023 N/A pytest :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) - :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Dec 28, 2023 5 - Production/Stable pytest + :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) :pypi:`pytest-tipsi-django` Nov 17, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Nov 04, 2020 4 - Beta pytest (>=3.3.0) @@ -1894,7 +1896,7 @@ This list contains 1357 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Dec 09, 2023, + *last release*: Jan 01, 2024, *status*: 4 - Beta, *requires*: pytest >=7.0.0 @@ -2097,9 +2099,9 @@ This list contains 1357 plugins. pytest plugin to display BDD info in HTML test report :pypi:`pytest-bdd-ng` - *last release*: Jul 01, 2023, + *last release*: Dec 31, 2023, *status*: 4 - Beta, - *requires*: pytest (>=5.0) + *requires*: pytest >=5.0 BDD for pytest @@ -2489,7 +2491,7 @@ This list contains 1357 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Dec 28, 2023, + *last release*: Jan 03, 2024, *status*: N/A, *requires*: N/A @@ -2545,7 +2547,7 @@ This list contains 1357 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Sep 22, 2023, + *last release*: Dec 31, 2023, *status*: N/A, *requires*: pytest @@ -3300,6 +3302,13 @@ This list contains 1357 plugins. Pytest extension for dbt. + :pypi:`pytest-dbt-postgres` + *last release*: Jan 02, 2024, + *status*: N/A, + *requires*: pytest (>=7.4.3,<8.0.0) + + Pytest tooling to unittest DBT & Postgres models + :pypi:`pytest-dbus-notification` *last release*: Mar 05, 2014, *status*: 5 - Production/Stable, @@ -3357,7 +3366,7 @@ This list contains 1357 plugins. pytest示例插件 :pypi:`pytest-dependency` - *last release*: Feb 14, 2020, + *last release*: Dec 31, 2023, *status*: 4 - Beta, *requires*: N/A @@ -3524,6 +3533,13 @@ This list contains 1357 plugins. A pytest plugin for running django in class-scoped fixtures + :pypi:`pytest-django-docker-pg` + *last release*: Jan 05, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest >=7.0.0 + + + :pypi:`pytest-django-dotenv` *last release*: Nov 26, 2019, *status*: 4 - Beta, @@ -3742,7 +3758,7 @@ This list contains 1357 plugins. Pytest fixtures for testing with docker registries. :pypi:`pytest-docker-service` - *last release*: Feb 22, 2023, + *last release*: Jan 03, 2024, *status*: 3 - Alpha, *requires*: pytest (>=7.1.3) @@ -4029,56 +4045,56 @@ This list contains 1357 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Dec 29, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Dec 29, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Dec 29, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Dec 29, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Dec 29, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Dec 29, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Dec 29, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Dec 29, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4981,7 +4997,7 @@ This list contains 1357 plugins. Parallelize pytest across GitLab CI workers. :pypi:`pytest-gitlab-fold` - *last release*: Sep 15, 2023, + *last release*: Dec 31, 2023, *status*: 4 - Beta, *requires*: pytest >=2.6.0 @@ -5198,7 +5214,7 @@ This list contains 1357 plugins. Report on tests that honor constraints, and guard against regressions :pypi:`pytest-hot-reloading` - *last release*: Dec 27, 2023, + *last release*: Jan 06, 2024, *status*: N/A, *requires*: N/A @@ -5268,7 +5284,7 @@ This list contains 1357 plugins. Pytest HTML reports merging utility :pypi:`pytest-html-object-storage` - *last release*: Mar 04, 2022, + *last release*: Jan 05, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5365,6 +5381,13 @@ This list contains 1357 plugins. Disable httpx requests during a test run + :pypi:`pytest-httpx-recorder` + *last release*: Jan 04, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest + + Recorder feature based on pytest_httpx, like recorder feature in responses. + :pypi:`pytest-hue` *last release*: May 09, 2019, *status*: N/A, @@ -5520,7 +5543,7 @@ This list contains 1357 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Dec 11, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5597,7 +5620,7 @@ This list contains 1357 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Dec 05, 2023, + *last release*: Jan 03, 2024, *status*: 4 - Beta, *requires*: pytest @@ -5645,13 +5668,6 @@ This list contains 1357 plugins. py.test plugin to check import ordering using isort - :pypi:`pytest-is-running` - *last release*: Jul 10, 2023, - *status*: 5 - Production/Stable, - *requires*: N/A - - pytest plugin providing a function to check if pytest is running. - :pypi:`pytest-it` *last release*: Jan 22, 2020, *status*: 4 - Beta, @@ -6430,7 +6446,7 @@ This list contains 1357 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: Dec 24, 2023, + *last release*: Jan 04, 2024, *status*: N/A, *requires*: pytest >=5.0.0 @@ -7669,7 +7685,7 @@ This list contains 1357 plugins. Test helpers for Prosper projects :pypi:`pytest-prysk` - *last release*: Jul 18, 2023, + *last release*: Dec 30, 2023, *status*: 4 - Beta, *requires*: pytest (>=7.3.2,<8.0.0) @@ -7837,16 +7853,16 @@ This list contains 1357 plugins. Pytest plugin for type checking code with Pyright :pypi:`pytest-pyspec` - *last release*: Mar 12, 2023, - *status*: 5 - Production/Stable, + *last release*: Jan 02, 2024, + *status*: N/A, *requires*: pytest (>=7.2.1,<8.0.0) A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". :pypi:`pytest-pystack` - *last release*: May 07, 2023, + *last release*: Jan 04, 2024, *status*: N/A, - *requires*: pytest (>=3.5.0) + *requires*: pytest >=3.5.0 Plugin to run pystack after a timeout for a test suite. @@ -8446,7 +8462,7 @@ This list contains 1357 plugins. A RethinkDB plugin for pytest. :pypi:`pytest-retry` - *last release*: Oct 04, 2023, + *last release*: Jan 04, 2024, *status*: N/A, *requires*: pytest >=7.0.0 @@ -8684,7 +8700,7 @@ This list contains 1357 plugins. :pypi:`pytest-sbase` - *last release*: Dec 23, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8747,7 +8763,7 @@ This list contains 1357 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Dec 23, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8943,7 +8959,7 @@ This list contains 1357 plugins. Allow for multiple processes to log to a single file :pypi:`pytest-skip-markers` - *last release*: Oct 20, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=7.1.0 @@ -9202,11 +9218,11 @@ This list contains 1357 plugins. Doctest plugin for pytest with support for Sphinx-specific doctest-directives :pypi:`pytest-spiratest` - *last release*: Feb 08, 2022, + *last release*: Jan 01, 2024, *status*: N/A, *requires*: N/A - Exports unit tests as test runs in SpiraTest/Team/Plan + Exports unit tests as test runs in Spira (SpiraTest/Team/Plan) :pypi:`pytest-splinter` *last release*: Sep 09, 2022, @@ -10000,7 +10016,7 @@ This list contains 1357 plugins. A simple plugin to view timestamps for each test :pypi:`pytest-tiny-api-client` - *last release*: Dec 28, 2023, + *last release*: Jan 04, 2024, *status*: 5 - Production/Stable, *requires*: pytest From 3234c79ee57feb7ec481811af1925bb0f81acdea Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 4 Jan 2024 23:48:03 +0200 Subject: [PATCH 0350/1271] fixtures: add an internal API for registering a fixture Add a function on the `FixtureManager` to register a fixture with pytest. Currently this can only be done through `parsefactories`. My aim is to eventually make something like this available to plugins, as it's a pretty common need. --- src/_pytest/fixtures.py | 93 ++++++++++++++++++++++++++++++----------- 1 file changed, 69 insertions(+), 24 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index c5e46655008..d4b780caf1f 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1621,6 +1621,69 @@ def pytest_collection_modifyitems(self, items: List[nodes.Item]) -> None: # Separate parametrized setups. items[:] = reorder_items(items) + def _register_fixture( + self, + *, + name: str, + func: "_FixtureFunc[object]", + nodeid: Optional[str], + scope: Union[ + Scope, _ScopeName, Callable[[str, Config], _ScopeName], None + ] = "function", + params: Optional[Sequence[object]] = None, + ids: Optional[ + Union[Tuple[Optional[object], ...], Callable[[Any], Optional[object]]] + ] = None, + autouse: bool = False, + unittest: bool = False, + ) -> None: + """Register a fixture + + :param name: + The fixture's name. + :param func: + The fixture's implementation function. + :param nodeid: + The visibility of the fixture. The fixture will be available to the + node with this nodeid and its children in the collection tree. + None means that the fixture is visible to the entire collection tree, + e.g. a fixture defined for general use in a plugin. + :param scope: + The fixture's scope. + :param params: + The fixture's parametrization params. + :param ids: + The fixture's IDs. + :param autouse: + Whether this is an autouse fixture. + :param unittest: + Set this if this is a unittest fixture. + """ + fixture_def = FixtureDef( + fixturemanager=self, + baseid=nodeid, + argname=name, + func=func, + scope=scope, + params=params, + unittest=unittest, + ids=ids, + _ispytest=True, + ) + + faclist = self._arg2fixturedefs.setdefault(name, []) + if fixture_def.has_location: + faclist.append(fixture_def) + else: + # fixturedefs with no location are at the front + # so this inserts the current fixturedef after the + # existing fixturedefs from external plugins but + # before the fixturedefs provided in conftests. + i = len([f for f in faclist if not f.has_location]) + faclist.insert(i, fixture_def) + if autouse: + self._nodeid_autousenames.setdefault(nodeid or "", []).append(name) + @overload def parsefactories( self, @@ -1672,7 +1735,6 @@ def parsefactories( # noqa: F811 return self._holderobjseen.add(holderobj) - autousenames = [] for name in dir(holderobj): # The attribute can be an arbitrary descriptor, so the attribute # access below can raise. safe_getatt() ignores such exceptions. @@ -1690,36 +1752,19 @@ def parsefactories( # noqa: F811 # to issue a warning if called directly, so here we unwrap it in # order to not emit the warning when pytest itself calls the # fixture function. - obj = get_real_method(obj, holderobj) + func = get_real_method(obj, holderobj) - fixture_def = FixtureDef( - fixturemanager=self, - baseid=nodeid, - argname=name, - func=obj, + self._register_fixture( + name=name, + nodeid=nodeid, + func=func, scope=marker.scope, params=marker.params, unittest=unittest, ids=marker.ids, - _ispytest=True, + autouse=marker.autouse, ) - faclist = self._arg2fixturedefs.setdefault(name, []) - if fixture_def.has_location: - faclist.append(fixture_def) - else: - # fixturedefs with no location are at the front - # so this inserts the current fixturedef after the - # existing fixturedefs from external plugins but - # before the fixturedefs provided in conftests. - i = len([f for f in faclist if not f.has_location]) - faclist.insert(i, fixture_def) - if marker.autouse: - autousenames.append(name) - - if autousenames: - self._nodeid_autousenames.setdefault(nodeid or "", []).extend(autousenames) - def getfixturedefs( self, argname: str, nodeid: str ) -> Optional[Sequence[FixtureDef[Any]]]: From c8792bd0800b8ffc536a6ce251f9eb3075b5f5fa Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 4 Jan 2024 23:51:58 +0200 Subject: [PATCH 0351/1271] python,unittest: replace obj fixture patching with `FixtureManager._register_fixture` Instead of modifying user objects like modules and classes that we really shouldn't be touching, use the new `_register_fixture` internal API to do it directly. --- src/_pytest/python.py | 108 +++++++++++++++++++++------------------- src/_pytest/unittest.py | 58 +++++++++++---------- 2 files changed, 91 insertions(+), 75 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 184399080d0..aa134020fe3 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -582,13 +582,13 @@ def _getobj(self): return importtestmodule(self.path, self.config) def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: - self._inject_setup_module_fixture() - self._inject_setup_function_fixture() + self._register_setup_module_fixture() + self._register_setup_function_fixture() self.session._fixturemanager.parsefactories(self) return super().collect() - def _inject_setup_module_fixture(self) -> None: - """Inject a hidden autouse, module scoped fixture into the collected module object + def _register_setup_module_fixture(self) -> None: + """Register an autouse, module-scoped fixture for the collected module object that invokes setUpModule/tearDownModule if either or both are available. Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with @@ -604,23 +604,25 @@ def _inject_setup_module_fixture(self) -> None: if setup_module is None and teardown_module is None: return - @fixtures.fixture( - autouse=True, - scope="module", - # Use a unique name to speed up lookup. - name=f"_xunit_setup_module_fixture_{self.obj.__name__}", - ) def xunit_setup_module_fixture(request) -> Generator[None, None, None]: + module = request.module if setup_module is not None: - _call_with_optional_argument(setup_module, request.module) + _call_with_optional_argument(setup_module, module) yield if teardown_module is not None: - _call_with_optional_argument(teardown_module, request.module) + _call_with_optional_argument(teardown_module, module) - self.obj.__pytest_setup_module = xunit_setup_module_fixture + self.session._fixturemanager._register_fixture( + # Use a unique name to speed up lookup. + name=f"_xunit_setup_module_fixture_{self.obj.__name__}", + func=xunit_setup_module_fixture, + nodeid=self.nodeid, + scope="module", + autouse=True, + ) - def _inject_setup_function_fixture(self) -> None: - """Inject a hidden autouse, function scoped fixture into the collected module object + def _register_setup_function_fixture(self) -> None: + """Register an autouse, function-scoped fixture for the collected module object that invokes setup_function/teardown_function if either or both are available. Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with @@ -633,25 +635,27 @@ def _inject_setup_function_fixture(self) -> None: if setup_function is None and teardown_function is None: return - @fixtures.fixture( - autouse=True, - scope="function", - # Use a unique name to speed up lookup. - name=f"_xunit_setup_function_fixture_{self.obj.__name__}", - ) def xunit_setup_function_fixture(request) -> Generator[None, None, None]: if request.instance is not None: # in this case we are bound to an instance, so we need to let # setup_method handle this yield return + function = request.function if setup_function is not None: - _call_with_optional_argument(setup_function, request.function) + _call_with_optional_argument(setup_function, function) yield if teardown_function is not None: - _call_with_optional_argument(teardown_function, request.function) + _call_with_optional_argument(teardown_function, function) - self.obj.__pytest_setup_function = xunit_setup_function_fixture + self.session._fixturemanager._register_fixture( + # Use a unique name to speed up lookup. + name=f"_xunit_setup_function_fixture_{self.obj.__name__}", + func=xunit_setup_function_fixture, + nodeid=self.nodeid, + scope="function", + autouse=True, + ) class Package(nodes.Directory): @@ -795,15 +799,15 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: ) return [] - self._inject_setup_class_fixture() - self._inject_setup_method_fixture() + self._register_setup_class_fixture() + self._register_setup_method_fixture() self.session._fixturemanager.parsefactories(self.newinstance(), self.nodeid) return super().collect() - def _inject_setup_class_fixture(self) -> None: - """Inject a hidden autouse, class scoped fixture into the collected class object + def _register_setup_class_fixture(self) -> None: + """Register an autouse, class scoped fixture into the collected class object that invokes setup_class/teardown_class if either or both are available. Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with @@ -814,25 +818,27 @@ def _inject_setup_class_fixture(self) -> None: if setup_class is None and teardown_class is None: return - @fixtures.fixture( - autouse=True, - scope="class", - # Use a unique name to speed up lookup. - name=f"_xunit_setup_class_fixture_{self.obj.__qualname__}", - ) - def xunit_setup_class_fixture(cls) -> Generator[None, None, None]: + def xunit_setup_class_fixture(request) -> Generator[None, None, None]: + cls = request.cls if setup_class is not None: func = getimfunc(setup_class) - _call_with_optional_argument(func, self.obj) + _call_with_optional_argument(func, cls) yield if teardown_class is not None: func = getimfunc(teardown_class) - _call_with_optional_argument(func, self.obj) + _call_with_optional_argument(func, cls) - self.obj.__pytest_setup_class = xunit_setup_class_fixture + self.session._fixturemanager._register_fixture( + # Use a unique name to speed up lookup. + name=f"_xunit_setup_class_fixture_{self.obj.__qualname__}", + func=xunit_setup_class_fixture, + nodeid=self.nodeid, + scope="class", + autouse=True, + ) - def _inject_setup_method_fixture(self) -> None: - """Inject a hidden autouse, function scoped fixture into the collected class object + def _register_setup_method_fixture(self) -> None: + """Register an autouse, function scoped fixture into the collected class object that invokes setup_method/teardown_method if either or both are available. Using a fixture to invoke these methods ensures we play nicely and unsurprisingly with @@ -845,23 +851,25 @@ def _inject_setup_method_fixture(self) -> None: if setup_method is None and teardown_method is None: return - @fixtures.fixture( - autouse=True, - scope="function", - # Use a unique name to speed up lookup. - name=f"_xunit_setup_method_fixture_{self.obj.__qualname__}", - ) - def xunit_setup_method_fixture(self, request) -> Generator[None, None, None]: + def xunit_setup_method_fixture(request) -> Generator[None, None, None]: + instance = request.instance method = request.function if setup_method is not None: - func = getattr(self, setup_name) + func = getattr(instance, setup_name) _call_with_optional_argument(func, method) yield if teardown_method is not None: - func = getattr(self, teardown_name) + func = getattr(instance, teardown_name) _call_with_optional_argument(func, method) - self.obj.__pytest_setup_method = xunit_setup_method_fixture + self.session._fixturemanager._register_fixture( + # Use a unique name to speed up lookup. + name=f"_xunit_setup_method_fixture_{self.obj.__qualname__}", + func=xunit_setup_method_fixture, + nodeid=self.nodeid, + scope="function", + autouse=True, + ) def hasinit(obj: object) -> bool: diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index dee0c3e4407..6bf8f4f2f5b 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -70,9 +70,9 @@ def collect(self) -> Iterable[Union[Item, Collector]]: skipped = _is_skipped(cls) if not skipped: - self._inject_unittest_setup_method_fixture(cls) - self._inject_unittest_setup_class_fixture(cls) - self._inject_setup_class_fixture() + self._register_unittest_setup_method_fixture(cls) + self._register_unittest_setup_class_fixture(cls) + self._register_setup_class_fixture() self.session._fixturemanager.parsefactories(self, unittest=True) loader = TestLoader() @@ -93,8 +93,8 @@ def collect(self) -> Iterable[Union[Item, Collector]]: if ut is None or runtest != ut.TestCase.runTest: # type: ignore yield TestCaseFunction.from_parent(self, name="runTest") - def _inject_unittest_setup_class_fixture(self, cls: type) -> None: - """Injects a hidden auto-use fixture to invoke setUpClass and + def _register_unittest_setup_class_fixture(self, cls: type) -> None: + """Register an auto-use fixture to invoke setUpClass and tearDownClass (#517).""" setup = getattr(cls, "setUpClass", None) teardown = getattr(cls, "tearDownClass", None) @@ -102,15 +102,12 @@ def _inject_unittest_setup_class_fixture(self, cls: type) -> None: return None cleanup = getattr(cls, "doClassCleanups", lambda: None) - @pytest.fixture( - scope="class", - autouse=True, - # Use a unique name to speed up lookup. - name=f"_unittest_setUpClass_fixture_{cls.__qualname__}", - ) - def fixture(self) -> Generator[None, None, None]: - if _is_skipped(self): - reason = self.__unittest_skip_why__ + def unittest_setup_class_fixture( + request: FixtureRequest, + ) -> Generator[None, None, None]: + cls = request.cls + if _is_skipped(cls): + reason = cls.__unittest_skip_why__ raise pytest.skip.Exception(reason, _use_item_location=True) if setup is not None: try: @@ -127,23 +124,27 @@ def fixture(self) -> Generator[None, None, None]: finally: cleanup() - cls.__pytest_class_setup = fixture # type: ignore[attr-defined] + self.session._fixturemanager._register_fixture( + # Use a unique name to speed up lookup. + name=f"_unittest_setUpClass_fixture_{cls.__qualname__}", + func=unittest_setup_class_fixture, + nodeid=self.nodeid, + scope="class", + autouse=True, + ) - def _inject_unittest_setup_method_fixture(self, cls: type) -> None: - """Injects a hidden auto-use fixture to invoke setup_method and + def _register_unittest_setup_method_fixture(self, cls: type) -> None: + """Register an auto-use fixture to invoke setup_method and teardown_method (#517).""" setup = getattr(cls, "setup_method", None) teardown = getattr(cls, "teardown_method", None) if setup is None and teardown is None: return None - @pytest.fixture( - scope="function", - autouse=True, - # Use a unique name to speed up lookup. - name=f"_unittest_setup_method_fixture_{cls.__qualname__}", - ) - def fixture(self, request: FixtureRequest) -> Generator[None, None, None]: + def unittest_setup_method_fixture( + request: FixtureRequest, + ) -> Generator[None, None, None]: + self = request.instance if _is_skipped(self): reason = self.__unittest_skip_why__ raise pytest.skip.Exception(reason, _use_item_location=True) @@ -153,7 +154,14 @@ def fixture(self, request: FixtureRequest) -> Generator[None, None, None]: if teardown is not None: teardown(self, request.function) - cls.__pytest_method_setup = fixture # type: ignore[attr-defined] + self.session._fixturemanager._register_fixture( + # Use a unique name to speed up lookup. + name=f"_unittest_setup_method_fixture_{cls.__qualname__}", + func=unittest_setup_method_fixture, + nodeid=self.nodeid, + scope="function", + autouse=True, + ) class TestCaseFunction(Function): From 992d0f082f43c06f6a50bf9c863eba2d221d2272 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 6 Jan 2024 13:12:02 +0200 Subject: [PATCH 0352/1271] fixtures: match fixtures based on actual node hierarchy, not textual nodeids Refs #11662. --- Problem Each fixture definition has a "visibility", the `FixtureDef.baseid` attribute. This is nodeid-like string. When a certain `node` requests a certain fixture name, we match node's nodeid against the fixture definitions with this name. The matching currently happens on the *textual* representation of the nodeid - we split `node.nodeid` to its "parent nodeids" and then check if the fixture's `baseid` is in there. While this has worked so far, we really should try to avoid textual manipulation of nodeids as much as possible. It has also caused problem in an odd case of a `Package` in the root directory: the `Package` gets nodeid `.`, while a `Module` in it gets nodeid `test_module.py`. And textually, `.` is not a parent of `test_module.py`. --- Solution Avoid this entirely by just checking the node hierarchy itself. This is made possible by the fact that we now have proper `Directory` nodes (`Dir` or `Package`) for the entire hierarchy. Also do the same for `_getautousenames` which is a similar deal. The `iterparentnodeids` function is no longer used and is removed. --- changelog/11785.trivial.rst | 7 +++ src/_pytest/fixtures.py | 37 +++++++-------- src/_pytest/nodes.py | 50 +++----------------- testing/plugins_integration/requirements.txt | 4 +- testing/python/fixtures.py | 6 +-- testing/test_nodes.py | 24 ---------- tox.ini | 4 +- 7 files changed, 40 insertions(+), 92 deletions(-) create mode 100644 changelog/11785.trivial.rst diff --git a/changelog/11785.trivial.rst b/changelog/11785.trivial.rst new file mode 100644 index 00000000000..b6b74d0dad2 --- /dev/null +++ b/changelog/11785.trivial.rst @@ -0,0 +1,7 @@ +Some changes were made to private functions which may affect plugins which access them: + +- ``FixtureManager._getautousenames()`` now takes a ``Node`` itself instead of the nodeid. +- ``FixtureManager.getfixturedefs()`` now takes the ``Node`` itself instead of the nodeid. +- The ``_pytest.nodes.iterparentnodeids()`` function is removed without replacement. + Prefer to traverse the node hierarchy itself instead. + If you really need to, copy the function from the previous pytest release. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 89046ddd0bd..a693867cbf7 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -424,9 +424,9 @@ def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": # We arrive here because of a dynamic call to # getfixturevalue(argname) usage which was naturally # not known at parsing/collection time. - assert self._pyfuncitem.parent is not None - parentid = self._pyfuncitem.parent.nodeid - fixturedefs = self._fixturemanager.getfixturedefs(argname, parentid) + parent = self._pyfuncitem.parent + assert parent is not None + fixturedefs = self._fixturemanager.getfixturedefs(argname, parent) if fixturedefs is not None: self._arg2fixturedefs[argname] = fixturedefs # No fixtures defined with this name. @@ -846,9 +846,8 @@ def formatrepr(self) -> "FixtureLookupErrorRepr": available = set() parent = self.request._pyfuncitem.parent assert parent is not None - parentid = parent.nodeid for name, fixturedefs in fm._arg2fixturedefs.items(): - faclist = list(fm._matchfactories(fixturedefs, parentid)) + faclist = list(fm._matchfactories(fixturedefs, parent)) if faclist: available.add(name) if self.argname in available: @@ -989,9 +988,8 @@ def __init__( # The "base" node ID for the fixture. # # This is a node ID prefix. A fixture is only available to a node (e.g. - # a `Function` item) if the fixture's baseid is a parent of the node's - # nodeid (see the `iterparentnodeids` function for what constitutes a - # "parent" and a "prefix" in this context). + # a `Function` item) if the fixture's baseid is a nodeid of a parent of + # node. # # For a fixture found in a Collector's object (e.g. a `Module`s module, # a `Class`'s class), the baseid is the Collector's nodeid. @@ -1482,7 +1480,7 @@ def getfixtureinfo( else: argnames = () usefixturesnames = self._getusefixturesnames(node) - autousenames = self._getautousenames(node.nodeid) + autousenames = self._getautousenames(node) initialnames = deduplicate_names(autousenames, usefixturesnames, argnames) direct_parametrize_args = _get_direct_parametrize_args(node) @@ -1517,10 +1515,10 @@ def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None: self.parsefactories(plugin, nodeid) - def _getautousenames(self, nodeid: str) -> Iterator[str]: - """Return the names of autouse fixtures applicable to nodeid.""" - for parentnodeid in nodes.iterparentnodeids(nodeid): - basenames = self._nodeid_autousenames.get(parentnodeid) + def _getautousenames(self, node: nodes.Node) -> Iterator[str]: + """Return the names of autouse fixtures applicable to node.""" + for parentnode in reversed(list(nodes.iterparentnodes(node))): + basenames = self._nodeid_autousenames.get(parentnode.nodeid) if basenames: yield from basenames @@ -1542,7 +1540,6 @@ def getfixtureclosure( # to re-discover fixturedefs again for each fixturename # (discovering matching fixtures for a given name/node is expensive). - parentid = parentnode.nodeid fixturenames_closure = list(initialnames) arg2fixturedefs: Dict[str, Sequence[FixtureDef[Any]]] = {} @@ -1554,7 +1551,7 @@ def getfixtureclosure( continue if argname in arg2fixturedefs: continue - fixturedefs = self.getfixturedefs(argname, parentid) + fixturedefs = self.getfixturedefs(argname, parentnode) if fixturedefs: arg2fixturedefs[argname] = fixturedefs for arg in fixturedefs[-1].argnames: @@ -1726,7 +1723,7 @@ def parsefactories( # noqa: F811 self._nodeid_autousenames.setdefault(nodeid or "", []).extend(autousenames) def getfixturedefs( - self, argname: str, nodeid: str + self, argname: str, node: nodes.Node ) -> Optional[Sequence[FixtureDef[Any]]]: """Get FixtureDefs for a fixture name which are applicable to a given node. @@ -1737,18 +1734,18 @@ def getfixturedefs( an empty result is returned). :param argname: Name of the fixture to search for. - :param nodeid: Full node id of the requesting test. + :param node: The requesting Node. """ try: fixturedefs = self._arg2fixturedefs[argname] except KeyError: return None - return tuple(self._matchfactories(fixturedefs, nodeid)) + return tuple(self._matchfactories(fixturedefs, node)) def _matchfactories( - self, fixturedefs: Iterable[FixtureDef[Any]], nodeid: str + self, fixturedefs: Iterable[FixtureDef[Any]], node: nodes.Node ) -> Iterator[FixtureDef[Any]]: - parentnodeids = set(nodes.iterparentnodeids(nodeid)) + parentnodeids = {n.nodeid for n in nodes.iterparentnodes(node)} for fixturedef in fixturedefs: if fixturedef.baseid in parentnodeids: yield fixturedef diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 4cf6768e605..da220918c22 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -49,49 +49,13 @@ tracebackcutdir = Path(_pytest.__file__).parent -def iterparentnodeids(nodeid: str) -> Iterator[str]: - """Return the parent node IDs of a given node ID, inclusive. - - For the node ID - - "testing/code/test_excinfo.py::TestFormattedExcinfo::test_repr_source" - - the result would be - - "" - "testing" - "testing/code" - "testing/code/test_excinfo.py" - "testing/code/test_excinfo.py::TestFormattedExcinfo" - "testing/code/test_excinfo.py::TestFormattedExcinfo::test_repr_source" - - Note that / components are only considered until the first ::. - """ - pos = 0 - first_colons: Optional[int] = nodeid.find("::") - if first_colons == -1: - first_colons = None - # The root Session node - always present. - yield "" - # Eagerly consume SEP parts until first colons. - while True: - at = nodeid.find(SEP, pos, first_colons) - if at == -1: - break - if at > 0: - yield nodeid[:at] - pos = at + len(SEP) - # Eagerly consume :: parts. - while True: - at = nodeid.find("::", pos) - if at == -1: - break - if at > 0: - yield nodeid[:at] - pos = at + len("::") - # The node ID itself. - if nodeid: - yield nodeid +def iterparentnodes(node: "Node") -> Iterator["Node"]: + """Return the parent nodes, including the node itself, from the node + upwards.""" + parent: Optional[Node] = node + while parent is not None: + yield parent + parent = parent.parent _NodeType = TypeVar("_NodeType", bound="Node") diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index dfdeeb7a8fc..40abcfccdf8 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,7 +1,9 @@ anyio[curio,trio]==4.2.0 django==5.0 pytest-asyncio==0.23.2 -pytest-bdd==7.0.1 +# Temporarily not installed until pytest-bdd is fixed: +# https://github.com/pytest-dev/pytest/pull/11785 +# pytest-bdd==7.0.1 pytest-cov==4.1.0 pytest-django==4.7.0 pytest-flakes==4.0.5 diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 775056a8e98..81aa2bcc782 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1574,7 +1574,7 @@ def test_parsefactories_conftest(self, pytester: Pytester) -> None: """ def test_hello(item, fm): for name in ("fm", "hello", "item"): - faclist = fm.getfixturedefs(name, item.nodeid) + faclist = fm.getfixturedefs(name, item) assert len(faclist) == 1 fac = faclist[0] assert fac.func.__name__ == name @@ -1598,7 +1598,7 @@ class TestClass(object): def hello(self, request): return "class" def test_hello(self, item, fm): - faclist = fm.getfixturedefs("hello", item.nodeid) + faclist = fm.getfixturedefs("hello", item) print(faclist) assert len(faclist) == 3 @@ -1804,7 +1804,7 @@ def test_parsefactories_conftest(self, pytester: Pytester) -> None: """ from _pytest.pytester import get_public_names def test_check_setup(item, fm): - autousenames = list(fm._getautousenames(item.nodeid)) + autousenames = list(fm._getautousenames(item)) assert len(get_public_names(autousenames)) == 2 assert "perfunction2" in autousenames assert "perfunction" in autousenames diff --git a/testing/test_nodes.py b/testing/test_nodes.py index 880e2a44fae..1de0f995e8a 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -2,7 +2,6 @@ import warnings from pathlib import Path from typing import cast -from typing import List from typing import Type import pytest @@ -12,29 +11,6 @@ from _pytest.warning_types import PytestWarning -@pytest.mark.parametrize( - ("nodeid", "expected"), - ( - ("", [""]), - ("a", ["", "a"]), - ("aa/b", ["", "aa", "aa/b"]), - ("a/b/c", ["", "a", "a/b", "a/b/c"]), - ("a/bbb/c::D", ["", "a", "a/bbb", "a/bbb/c", "a/bbb/c::D"]), - ("a/b/c::D::eee", ["", "a", "a/b", "a/b/c", "a/b/c::D", "a/b/c::D::eee"]), - ("::xx", ["", "::xx"]), - # / only considered until first :: - ("a/b/c::D/d::e", ["", "a", "a/b", "a/b/c", "a/b/c::D/d", "a/b/c::D/d::e"]), - # : alone is not a separator. - ("a/b::D:e:f::g", ["", "a", "a/b", "a/b::D:e:f", "a/b::D:e:f::g"]), - # / not considered if a part of a test name - ("a/b::c/d::e[/test]", ["", "a", "a/b", "a/b::c/d", "a/b::c/d::e[/test]"]), - ), -) -def test_iterparentnodeids(nodeid: str, expected: List[str]) -> None: - result = list(nodes.iterparentnodeids(nodeid)) - assert result == expected - - def test_node_from_parent_disallowed_arguments() -> None: with pytest.raises(TypeError, match="session is"): nodes.Node.from_parent(None, session=None) # type: ignore[arg-type] diff --git a/tox.ini b/tox.ini index e92f6c98b73..e4ad300a932 100644 --- a/tox.ini +++ b/tox.ini @@ -134,9 +134,11 @@ changedir = testing/plugins_integration deps = -rtesting/plugins_integration/requirements.txt setenv = PYTHONPATH=. +# Command temporarily removed until pytest-bdd is fixed: +# https://github.com/pytest-dev/pytest/pull/11785 +# pytest bdd_wallet.py commands = pip check - pytest bdd_wallet.py pytest --cov=. simple_integration.py pytest --ds=django_settings simple_integration.py pytest --html=simple.html simple_integration.py From 913d93debb75a2614bae742e6dd568731c5f29c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 20:24:22 +0000 Subject: [PATCH 0353/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.2 to 0.23.3. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.2...v0.23.3) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 40abcfccdf8..0839b18c9fa 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.2.0 django==5.0 -pytest-asyncio==0.23.2 +pytest-asyncio==0.23.3 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 # pytest-bdd==7.0.1 From 7bc8385924f3688b4c425c52e45ac780b6858cd2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 21:19:35 +0000 Subject: [PATCH 0354/1271] [pre-commit.ci] pre-commit autoupdate (#11792) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/PyCQA/flake8: 6.1.0 → 7.0.0](https://github.com/PyCQA/flake8/compare/6.1.0...7.0.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ce1cce6e089..be0b4315b7f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,7 +29,7 @@ repos: language: python files: \.py$ - repo: https://github.com/PyCQA/flake8 - rev: 6.1.0 + rev: 7.0.0 hooks: - id: flake8 language_version: python3 From 956d0e5e9d9a10c7e7faa90909452890f6081e62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 03:29:54 +0000 Subject: [PATCH 0355/1271] build(deps): Bump hynek/build-and-inspect-python-package Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 1.5.4 to 2.0.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v1.5.4...v2.0.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index fed725f0ef1..f8b9f5f8403 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v1.5.4 + uses: hynek/build-and-inspect-python-package@v2.0.0 deploy: if: github.repository == 'pytest-dev/pytest' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9fbd273bcfa..79f806c6c74 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v1.5.4 + uses: hynek/build-and-inspect-python-package@v2.0.0 build: needs: [package] From 2270cab1c2dfb34dcc60c0e458be33ecb653e92d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 03:29:58 +0000 Subject: [PATCH 0356/1271] build(deps): Bump actions/download-artifact from 3 to 4 Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f8b9f5f8403..585398ba315 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@v4 - name: Download Package - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: Packages path: dist diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 79f806c6c74..3d6f00bb747 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -173,7 +173,7 @@ jobs: persist-credentials: false - name: Download Package - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: Packages path: dist From 372c17e22899e8e676e105dae714e897426bef86 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 9 Jan 2024 23:01:50 +0200 Subject: [PATCH 0357/1271] fixtures: avoid FixtureDef <-> FixtureManager reference cycle There is no need to store the FixtureManager on each FixtureDef. --- src/_pytest/fixtures.py | 7 +++---- src/_pytest/python.py | 2 +- src/_pytest/setuponly.py | 15 +++++++++------ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index c184d2f3c50..1c94583e87e 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -970,7 +970,7 @@ class FixtureDef(Generic[FixtureValue]): def __init__( self, - fixturemanager: "FixtureManager", + config: Config, baseid: Optional[str], argname: str, func: "_FixtureFunc[FixtureValue]", @@ -984,7 +984,6 @@ def __init__( _ispytest: bool = False, ) -> None: check_ispytest(_ispytest) - self._fixturemanager = fixturemanager # The "base" node ID for the fixture. # # This is a node ID prefix. A fixture is only available to a node (e.g. @@ -1010,7 +1009,7 @@ def __init__( if scope is None: scope = Scope.Function elif callable(scope): - scope = _eval_scope_callable(scope, argname, fixturemanager.config) + scope = _eval_scope_callable(scope, argname, config) if isinstance(scope, str): scope = Scope.from_user( scope, descr=f"Fixture '{func.__name__}'", where=baseid @@ -1657,7 +1656,7 @@ def _register_fixture( Set this if this is a unittest fixture. """ fixture_def = FixtureDef( - fixturemanager=self, + config=self.config, baseid=nodeid, argname=name, func=func, diff --git a/src/_pytest/python.py b/src/_pytest/python.py index aa134020fe3..36d2eba0323 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1323,7 +1323,7 @@ def parametrize( fixturedef = name2pseudofixturedef[argname] else: fixturedef = FixtureDef( - fixturemanager=self.definition.session._fixturemanager, + config=self.config, baseid="", argname=argname, func=get_direct_param_fixture_func, diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index 0f8be899af2..0f104580693 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -47,20 +47,23 @@ def pytest_fixture_setup( else: param = request.param fixturedef.cached_param = param # type: ignore[attr-defined] - _show_fixture_action(fixturedef, "SETUP") + _show_fixture_action(fixturedef, request.config, "SETUP") -def pytest_fixture_post_finalizer(fixturedef: FixtureDef[object]) -> None: +def pytest_fixture_post_finalizer( + fixturedef: FixtureDef[object], request: SubRequest +) -> None: if fixturedef.cached_result is not None: - config = fixturedef._fixturemanager.config + config = request.config if config.option.setupshow: - _show_fixture_action(fixturedef, "TEARDOWN") + _show_fixture_action(fixturedef, request.config, "TEARDOWN") if hasattr(fixturedef, "cached_param"): del fixturedef.cached_param # type: ignore[attr-defined] -def _show_fixture_action(fixturedef: FixtureDef[object], msg: str) -> None: - config = fixturedef._fixturemanager.config +def _show_fixture_action( + fixturedef: FixtureDef[object], config: Config, msg: str +) -> None: capman = config.pluginmanager.getplugin("capturemanager") if capman: capman.suspend_global_capture() From 368fa2c03e5be3eb00cfea45e168886d9a24a286 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 9 Jan 2024 23:31:35 +0200 Subject: [PATCH 0358/1271] fixtures: remove unhelpful FixtureManager.{FixtureLookupError,FixtureLookupErrorRepr} Couldn't find any reason for this indirection, nor any plugins which rely on it. Seems like historically it was done to avoid some imports... --- src/_pytest/fixtures.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 1c94583e87e..13c1790bea1 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -525,7 +525,7 @@ def raiseerror(self, msg: Optional[str]) -> NoReturn: :param msg: An optional custom error message. """ - raise self._fixturemanager.FixtureLookupError(None, self, msg) + raise FixtureLookupError(None, self, msg) def getfixturevalue(self, argname: str) -> Any: """Dynamically run a named fixture function. @@ -1438,9 +1438,6 @@ class FixtureManager: by a lookup of their FuncFixtureInfo. """ - FixtureLookupError = FixtureLookupError - FixtureLookupErrorRepr = FixtureLookupErrorRepr - def __init__(self, session: "Session") -> None: self.session = session self.config: Config = session.config From 35a3863b151aa97b52b4b612b4959090cab307d9 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 25 Dec 2023 19:40:40 +0200 Subject: [PATCH 0359/1271] config: clarify a bit of code in `_importconftest` --- src/_pytest/config/__init__.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 49d63a357c5..1fd82f49d8f 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -638,9 +638,16 @@ def _importconftest( if existing is not None: return cast(types.ModuleType, existing) + # conftest.py files there are not in a Python package all have module + # name "conftest", and thus conflict with each other. Clear the existing + # before loading the new one, otherwise the existing one will be + # returned from the module cache. pkgpath = resolve_package_path(conftestpath) if pkgpath is None: - _ensure_removed_sysmodule(conftestpath.stem) + try: + del sys.modules[conftestpath.stem] + except KeyError: + pass try: mod = import_path(conftestpath, mode=importmode, root=rootpath) @@ -818,13 +825,6 @@ def _get_plugin_specs_as_list( ) -def _ensure_removed_sysmodule(modname: str) -> None: - try: - del sys.modules[modname] - except KeyError: - pass - - class Notset: def __repr__(self): return "" From c7d85c5dc668e4a9eb2867e7432d599cdde799bd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 10 Jan 2024 18:56:36 +0200 Subject: [PATCH 0360/1271] python: remove support for nose's `compat_co_firstlineno` Since we're removing nose support, let's also drop support for this attribute. From doing a code search on github, this seems completely unused outside of nose, except for some projects which used to use it, but no longer do. --- doc/en/deprecations.rst | 7 +++++++ src/_pytest/python.py | 15 +-------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index f5334ace5b3..76cc3482ad3 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -387,6 +387,13 @@ Will also need to be ported to a supported pytest style. One way to do it is usi .. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup +The ``compat_co_firstlineno`` attribute +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Nose inspects this attribute on function objects to allow overriding the function's inferred line number. +Pytest no longer respects this attribute. + + Passing ``msg=`` to ``pytest.skip``, ``pytest.fail`` or ``pytest.exit`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 184399080d0..c4a840be13d 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -6,7 +6,6 @@ import inspect import itertools import os -import sys import types import warnings from collections import Counter @@ -350,20 +349,8 @@ def getmodpath(self, stopatmodule: bool = True, includemodule: bool = False) -> def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: # XXX caching? - obj = self.obj - compat_co_firstlineno = getattr(obj, "compat_co_firstlineno", None) - if isinstance(compat_co_firstlineno, int): - # nose compatibility - file_path = sys.modules[obj.__module__].__file__ - assert file_path is not None - if file_path.endswith(".pyc"): - file_path = file_path[:-1] - path: Union["os.PathLike[str]", str] = file_path - lineno = compat_co_firstlineno - else: - path, lineno = getfslineno(obj) + path, lineno = getfslineno(self.obj) modpath = self.getmodpath() - assert isinstance(lineno, int) return path, lineno, modpath From 996e45d66a8e4ec16562e2937a532e9a3afe9876 Mon Sep 17 00:00:00 2001 From: Faisal Fawad <76597599+faisal-fawad@users.noreply.github.com> Date: Thu, 11 Jan 2024 06:01:07 -0500 Subject: [PATCH 0361/1271] Slight change to tmp_path documentation to more clearly illustrate its behavior (#11800) --- doc/en/how-to/tmp_path.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index b75fb59641f..3e680dcac76 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -9,7 +9,7 @@ The ``tmp_path`` fixture ------------------------ You can use the ``tmp_path`` fixture which will -provide a temporary directory unique to the test invocation, +provide a temporary directory unique to the current test, created in the `base temporary directory`_. ``tmp_path`` is a :class:`pathlib.Path` object. Here is an example test usage: From 5bd5b80afdec77349a50d3c95b0d85d50f1ec0a9 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 11 Jan 2024 11:30:22 +0200 Subject: [PATCH 0362/1271] nodes: add `Node.iterparents()` function This is a useful addition to the existing `listchain`. While `listchain` returns top-to-bottom, `iterparents` is bottom-to-top and doesn't require an internal full iteration + `reverse`. --- changelog/11801.improvement.rst | 2 ++ src/_pytest/fixtures.py | 24 ++++++++------------- src/_pytest/nodes.py | 38 ++++++++++++++++----------------- src/_pytest/python.py | 4 +--- 4 files changed, 30 insertions(+), 38 deletions(-) create mode 100644 changelog/11801.improvement.rst diff --git a/changelog/11801.improvement.rst b/changelog/11801.improvement.rst new file mode 100644 index 00000000000..3046edca0c2 --- /dev/null +++ b/changelog/11801.improvement.rst @@ -0,0 +1,2 @@ +Added the :func:`iterparents() <_pytest.nodes.Node.iterparents>` helper method on nodes. +It is similar to :func:`listchain <_pytest.nodes.Node.listchain>`, but goes from bottom to top, and returns an iterator, not a list. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 13c1790bea1..dd37f8ec3e3 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -116,22 +116,16 @@ def pytest_sessionstart(session: "Session") -> None: def get_scope_package( node: nodes.Item, fixturedef: "FixtureDef[object]", -) -> Optional[Union[nodes.Item, nodes.Collector]]: +) -> Optional[nodes.Node]: from _pytest.python import Package - current: Optional[Union[nodes.Item, nodes.Collector]] = node - while current and ( - not isinstance(current, Package) or current.nodeid != fixturedef.baseid - ): - current = current.parent # type: ignore[assignment] - if current is None: - return node.session - return current + for parent in node.iterparents(): + if isinstance(parent, Package) and parent.nodeid == fixturedef.baseid: + return parent + return node.session -def get_scope_node( - node: nodes.Node, scope: Scope -) -> Optional[Union[nodes.Item, nodes.Collector]]: +def get_scope_node(node: nodes.Node, scope: Scope) -> Optional[nodes.Node]: import _pytest.python if scope is Scope.Function: @@ -738,7 +732,7 @@ def node(self): scope = self._scope if scope is Scope.Function: # This might also be a non-function Item despite its attribute name. - node: Optional[Union[nodes.Item, nodes.Collector]] = self._pyfuncitem + node: Optional[nodes.Node] = self._pyfuncitem elif scope is Scope.Package: node = get_scope_package(self._pyfuncitem, self._fixturedef) else: @@ -1513,7 +1507,7 @@ def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None: def _getautousenames(self, node: nodes.Node) -> Iterator[str]: """Return the names of autouse fixtures applicable to node.""" - for parentnode in reversed(list(nodes.iterparentnodes(node))): + for parentnode in node.listchain(): basenames = self._nodeid_autousenames.get(parentnode.nodeid) if basenames: yield from basenames @@ -1781,7 +1775,7 @@ def getfixturedefs( def _matchfactories( self, fixturedefs: Iterable[FixtureDef[Any]], node: nodes.Node ) -> Iterator[FixtureDef[Any]]: - parentnodeids = {n.nodeid for n in nodes.iterparentnodes(node)} + parentnodeids = {n.nodeid for n in node.iterparents()} for fixturedef in fixturedefs: if fixturedef.baseid in parentnodeids: yield fixturedef diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index bc6d6f4dd50..e45a515b0ae 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -49,15 +49,6 @@ tracebackcutdir = Path(_pytest.__file__).parent -def iterparentnodes(node: "Node") -> Iterator["Node"]: - """Return the parent nodes, including the node itself, from the node - upwards.""" - parent: Optional[Node] = node - while parent is not None: - yield parent - parent = parent.parent - - _NodeType = TypeVar("_NodeType", bound="Node") @@ -265,12 +256,20 @@ def setup(self) -> None: def teardown(self) -> None: pass - def listchain(self) -> List["Node"]: - """Return list of all parent collectors up to self, starting from - the root of collection tree. + def iterparents(self) -> Iterator["Node"]: + """Iterate over all parent collectors starting from and including self + up to the root of the collection tree. - :returns: The nodes. + .. versionadded:: 8.1 """ + parent: Optional[Node] = self + while parent is not None: + yield parent + parent = parent.parent + + def listchain(self) -> List["Node"]: + """Return a list of all parent collectors starting from the root of the + collection tree down to and including self.""" chain = [] item: Optional[Node] = self while item is not None: @@ -319,7 +318,7 @@ def iter_markers_with_node( :param name: If given, filter the results by the name attribute. :returns: An iterator of (node, mark) tuples. """ - for node in reversed(self.listchain()): + for node in self.iterparents(): for mark in node.own_markers: if name is None or getattr(mark, "name", None) == name: yield node, mark @@ -363,17 +362,16 @@ def addfinalizer(self, fin: Callable[[], object]) -> None: self.session._setupstate.addfinalizer(fin, self) def getparent(self, cls: Type[_NodeType]) -> Optional[_NodeType]: - """Get the next parent node (including self) which is an instance of + """Get the closest parent node (including self) which is an instance of the given class. :param cls: The node class to search for. :returns: The node, if found. """ - current: Optional[Node] = self - while current and not isinstance(current, cls): - current = current.parent - assert current is None or isinstance(current, cls) - return current + for node in self.iterparents(): + if isinstance(node, cls): + return node + return None def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: return excinfo.traceback diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 36d2eba0323..7623a97489c 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -333,10 +333,8 @@ def _getobj(self): def getmodpath(self, stopatmodule: bool = True, includemodule: bool = False) -> str: """Return Python path relative to the containing module.""" - chain = self.listchain() - chain.reverse() parts = [] - for node in chain: + for node in self.iterparents(): name = node.name if isinstance(node, Module): name = os.path.splitext(name)[0] From 82fda31e99b8302c0a242ed33afa2557adb30d5b Mon Sep 17 00:00:00 2001 From: mrbean-bremen Date: Thu, 11 Jan 2024 19:02:26 +0100 Subject: [PATCH 0363/1271] Clarify package scope The behavior of package scope is surprising to some (as seen by related questions on SO), this should clarify it a bit. --- doc/en/how-to/fixtures.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index a8fea574a33..95c376fd307 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -494,7 +494,7 @@ Fixtures are created when first requested by a test, and are destroyed based on * ``function``: the default scope, the fixture is destroyed at the end of the test. * ``class``: the fixture is destroyed during teardown of the last test in the class. * ``module``: the fixture is destroyed during teardown of the last test in the module. -* ``package``: the fixture is destroyed during teardown of the last test in the package. +* ``package``: the fixture is destroyed during teardown of the last test in the package where the fixture is defined, including sub-packages and sub-directories within it. * ``session``: the fixture is destroyed at the end of the test session. .. note:: From 06dbd3c21ccdf1ac76e8fa264048133cb4660842 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 13 Jan 2024 11:15:05 +0200 Subject: [PATCH 0364/1271] doctest: remove special conftest handling (Diff better viewed ignoring whitespace) Since e1c66ab0ad8eda13e5552dfc939e07d7290ecd39, conftest loading is handled at the directory level before sub-nodes are collected, so there is no need for the doctest plugin to handle it specially. This was probably the case even before e1c66ab0ad8eda13e5552dfc939e07d7290ecd39, but I haven't verified this. --- src/_pytest/doctest.py | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index a0125e93c2d..4ce32a298e8 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -558,24 +558,18 @@ def _from_module(self, module, object): else: # pragma: no cover pass - if self.path.name == "conftest.py": - module = self.config.pluginmanager._importconftest( + try: + module = import_path( self.path, - self.config.getoption("importmode"), - rootpath=self.config.rootpath, + root=self.config.rootpath, + mode=self.config.getoption("importmode"), ) - else: - try: - module = import_path( - self.path, - root=self.config.rootpath, - mode=self.config.getoption("importmode"), - ) - except ImportError: - if self.config.getvalue("doctest_ignore_import_errors"): - skip("unable to import module %r" % self.path) - else: - raise + except ImportError: + if self.config.getvalue("doctest_ignore_import_errors"): + skip("unable to import module %r" % self.path) + else: + raise + # Uses internal doctest module parsing mechanism. finder = MockAwareDocTestFinder() optionflags = get_optionflags(self.config) From a7c2549321ea30b778653a00c5307df625407687 Mon Sep 17 00:00:00 2001 From: Franck Charras <29153872+fcharras@users.noreply.github.com> Date: Fri, 15 Dec 2023 16:54:07 +0100 Subject: [PATCH 0365/1271] Fix `assert mod not in mods` crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #27806. Co-authored-by: Loïc Estève Co-authored-by: Ran Benita Co-authored-by: Bruno Oliveira --- changelog/9765.bugfix.rst | 3 ++ src/_pytest/config/__init__.py | 11 ++++--- testing/acceptance_test.py | 59 ++++++++++++++++++++++++++++++++++ testing/test_pluginmanager.py | 34 +++++++++++++++++++- 4 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 changelog/9765.bugfix.rst diff --git a/changelog/9765.bugfix.rst b/changelog/9765.bugfix.rst new file mode 100644 index 00000000000..c726cbf8d56 --- /dev/null +++ b/changelog/9765.bugfix.rst @@ -0,0 +1,3 @@ +Fixed a frustrating bug that afflicted some users with the only error being ``assert mod not in mods``. The issue was caused by the fact that ``str(Path(mod))`` and ``mod.__file__`` don't necessarily produce the same string, and was being erroneously used interchangably in some places in the code. + +This fix also broke the internal API of ``PytestPluginManager.consider_conftest`` by introducing a new parameter -- we mention this in case it is being used by external code, even if marked as *private*. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 1fd82f49d8f..85ae6dddfeb 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -634,7 +634,8 @@ def _rget_with_confmod( def _importconftest( self, conftestpath: Path, importmode: Union[str, ImportMode], rootpath: Path ) -> types.ModuleType: - existing = self.get_plugin(str(conftestpath)) + conftestpath_plugin_name = str(conftestpath) + existing = self.get_plugin(conftestpath_plugin_name) if existing is not None: return cast(types.ModuleType, existing) @@ -666,7 +667,7 @@ def _importconftest( assert mod not in mods mods.append(mod) self.trace(f"loading conftestmodule {mod!r}") - self.consider_conftest(mod) + self.consider_conftest(mod, registration_name=conftestpath_plugin_name) return mod def _check_non_top_pytest_plugins( @@ -746,9 +747,11 @@ def consider_pluginarg(self, arg: str) -> None: del self._name2plugin["pytest_" + name] self.import_plugin(arg, consider_entry_points=True) - def consider_conftest(self, conftestmodule: types.ModuleType) -> None: + def consider_conftest( + self, conftestmodule: types.ModuleType, registration_name: str + ) -> None: """:meta private:""" - self.register(conftestmodule, name=conftestmodule.__file__) + self.register(conftestmodule, name=registration_name) def consider_env(self) -> None: """:meta private:""" diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 43390ab83ae..b875b8f6631 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1,6 +1,7 @@ import dataclasses import importlib.metadata import os +import subprocess import sys import types @@ -1390,3 +1391,61 @@ def test_boo(self): ) result = pytester.runpytest_subprocess() result.stdout.fnmatch_lines("*1 passed*") + + +@pytest.mark.skip(reason="Test is not isolated") +def test_issue_9765(pytester: Pytester) -> None: + """Reproducer for issue #9765 on Windows + + https://github.com/pytest-dev/pytest/issues/9765 + """ + pytester.makepyprojecttoml( + """ + [tool.pytest.ini_options] + addopts = "-p my_package.plugin.my_plugin" + """ + ) + pytester.makepyfile( + **{ + "setup.py": ( + """ + from setuptools import setup + + if __name__ == '__main__': + setup(name='my_package', packages=['my_package', 'my_package.plugin']) + """ + ), + "my_package/__init__.py": "", + "my_package/conftest.py": "", + "my_package/test_foo.py": "def test(): pass", + "my_package/plugin/__init__.py": "", + "my_package/plugin/my_plugin.py": ( + """ + import pytest + + def pytest_configure(config): + + class SimplePlugin: + @pytest.fixture(params=[1, 2, 3]) + def my_fixture(self, request): + yield request.param + + config.pluginmanager.register(SimplePlugin()) + """ + ), + } + ) + + subprocess.run([sys.executable, "setup.py", "develop"], check=True) + try: + # We are using subprocess.run rather than pytester.run on purpose. + # pytester.run is adding the current directory to PYTHONPATH which avoids + # the bug. We also use pytest rather than python -m pytest for the same + # PYTHONPATH reason. + subprocess.run( + ["pytest", "my_package"], capture_output=True, check=True, text=True + ) + except subprocess.CalledProcessError as exc: + raise AssertionError( + f"pytest command failed:\n{exc.stdout=!s}\n{exc.stderr=!s}" + ) from exc diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index e5773412fbf..8bafde33846 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -98,6 +98,38 @@ def pytest_configure(self): config.pluginmanager.register(A()) assert len(values) == 2 + @pytest.mark.skipif( + not sys.platform.startswith("win"), + reason="requires a case-insensitive file system", + ) + def test_conftestpath_case_sensitivity(self, pytester: Pytester) -> None: + """Unit test for issue #9765.""" + config = pytester.parseconfig() + pytester.makepyfile(**{"tests/conftest.py": ""}) + + conftest = pytester.path.joinpath("tests/conftest.py") + conftest_upper_case = pytester.path.joinpath("TESTS/conftest.py") + + mod = config.pluginmanager._importconftest( + conftest, + importmode="prepend", + rootpath=pytester.path, + ) + plugin = config.pluginmanager.get_plugin(str(conftest)) + assert plugin is mod + + mod_uppercase = config.pluginmanager._importconftest( + conftest_upper_case, + importmode="prepend", + rootpath=pytester.path, + ) + plugin_uppercase = config.pluginmanager.get_plugin(str(conftest_upper_case)) + assert plugin_uppercase is mod_uppercase + + # No str(conftestpath) normalization so conftest should be imported + # twice and modules should be different objects + assert mod is not mod_uppercase + def test_hook_tracing(self, _config_for_test: Config) -> None: pytestpm = _config_for_test.pluginmanager # fully initialized with plugins saveindent = [] @@ -368,7 +400,7 @@ def test_consider_conftest_deps( pytester.makepyfile("pytest_plugins='xyz'"), root=pytester.path ) with pytest.raises(ImportError): - pytestpm.consider_conftest(mod) + pytestpm.consider_conftest(mod, registration_name="unused") class TestPytestPluginManagerBootstrapming: From c6ed86453fbfd4a1f9ef6814a7a4679b3ced778f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 14 Jan 2024 01:04:53 -0300 Subject: [PATCH 0366/1271] [automated] Update plugin list (#11811) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 102 +++++++++++++++---------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index f1b672ecd6e..dceb3cf155e 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -71,7 +71,7 @@ This list contains 1359 plugins. :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Oct 11, 2023 5 - Production/Stable pytest <8.0.0,>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jan 10, 2024 5 - Production/Stable pytest >=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -105,7 +105,7 @@ This list contains 1359 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 Jan 01, 2024 4 - Beta pytest >=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Jan 10, 2024 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) @@ -186,11 +186,11 @@ This list contains 1359 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-cases` Separate test code from test cases in pytest. Nov 10, 2023 5 - Production/Stable N/A + :pypi:`pytest-cases` Separate test code from test cases in pytest. Jan 12, 2024 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 03, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 08, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A @@ -198,7 +198,7 @@ This list contains 1359 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Dec 31, 2023 N/A pytest + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 08, 2024 N/A pytest>=7.0.0 :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -576,7 +576,7 @@ This list contains 1359 plugins. :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 Dec 15, 2023 3 - Alpha pytest ==7.4.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jan 13, 2024 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` Jan 06, 2024 N/A N/A @@ -596,7 +596,7 @@ This list contains 1359 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Dec 09, 2023 3 - Alpha pytest >=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A @@ -730,7 +730,7 @@ This list contains 1359 plugins. :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A - :pypi:`pytest-matcher` Match test output against patterns stored in files Dec 10, 2021 5 - Production/Stable N/A + :pypi:`pytest-matcher` Keep a ChangeLog Jan 11, 2024 5 - Production/Stable pytest :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -810,7 +810,7 @@ This list contains 1359 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Sep 18, 2023 N/A pytest (==6.2.5) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jan 11, 2024 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A @@ -903,7 +903,7 @@ This list contains 1359 plugins. :pypi:`pytest-plone` Pytest plugin to test Plone addons Jan 05, 2023 3 - Alpha pytest :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Aug 17, 2020 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Oct 18, 2023 5 - Production/Stable pytest >=7.4.2 + :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Jan 10, 2024 5 - Production/Stable pytest >=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A :pypi:`pytest-pokie` Pokie plugin for pytest Oct 19, 2023 5 - Production/Stable N/A @@ -915,7 +915,7 @@ This list contains 1359 plugins. :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pook` Pytest plugin for pook Dec 23, 2023 4 - Beta pytest :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-porringer` Oct 03, 2023 N/A pytest>=7.4.0 + :pypi:`pytest-porringer` Jan 12, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) @@ -998,7 +998,7 @@ This list contains 1359 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 - :pypi:`pytest-regtest` pytest plugin for regression tests Aug 17, 2023 N/A N/A + :pypi:`pytest-regtest` "pytest plugin for snapshot regression testing" Jan 06, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A @@ -1007,7 +1007,7 @@ This list contains 1359 plugins. :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jun 09, 2021 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jan 11, 2024 5 - Production/Stable pytest :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Jul 22, 2021 4 - Beta pytest @@ -1031,7 +1031,7 @@ This list contains 1359 plugins. :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 Dec 11, 2023 N/A pytest ~=4.6 ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jan 10, 2024 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 @@ -1039,7 +1039,7 @@ This list contains 1359 plugins. :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jul 10, 2023 5 - Production/Stable pytest - :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Oct 15, 2023 N/A pytest>=7.2.0 + :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A @@ -1141,7 +1141,7 @@ This list contains 1359 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Dec 22, 2023 N/A pytest >=7.4.0 + :pypi:`pytest-sort` Tools for sorting test cases Jan 07, 2024 N/A pytest >=7.4.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest @@ -1159,7 +1159,7 @@ This list contains 1359 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 Dec 21, 2023 N/A pytest (>5.4.0,<8) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jan 12, 2024 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 @@ -1197,7 +1197,7 @@ This list contains 1359 plugins. :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A - :pypi:`pytest-synodic` Synodic Pytest utilities Aug 26, 2023 N/A pytest>=7.4.0 + :pypi:`pytest-synodic` Synodic Pytest utilities Jan 12, 2024 N/A pytest>=7.4.4 :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A :pypi:`pytest-tagging` a pytest plugin to tag tests Apr 01, 2023 N/A pytest (>=7.1.3,<8.0.0) @@ -1385,11 +1385,11 @@ This list contains 1359 plugins. :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A - :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Nov 03, 2023 N/A pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Jan 11, 2024 N/A pytest (>=7.2.2,<8.0.0) :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A - :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Oct 27, 2023 5 - Production/Stable pytest (>=4.5.0) + :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jan 08, 2024 5 - Production/Stable pytest (>=4.5.0) :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest @@ -1658,9 +1658,9 @@ This list contains 1359 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Oct 11, 2023, + *last release*: Jan 10, 2024, *status*: 5 - Production/Stable, - *requires*: pytest <8.0.0,>=6 + *requires*: pytest >=6 Plugin for pytest to simplify calling ansible modules from tests or fixtures @@ -1896,7 +1896,7 @@ This list contains 1359 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jan 01, 2024, + *last release*: Jan 10, 2024, *status*: 4 - Beta, *requires*: pytest >=7.0.0 @@ -2463,7 +2463,7 @@ This list contains 1359 plugins. pytest plugin to capture all warnings and put them in one file of your choice :pypi:`pytest-cases` - *last release*: Nov 10, 2023, + *last release*: Jan 12, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -2491,7 +2491,7 @@ This list contains 1359 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Jan 03, 2024, + *last release*: Jan 08, 2024, *status*: N/A, *requires*: N/A @@ -2547,9 +2547,9 @@ This list contains 1359 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Dec 31, 2023, + *last release*: Jan 08, 2024, *status*: N/A, - *requires*: pytest + *requires*: pytest>=7.0.0 A pytest plugin that allows multiple failures per test. @@ -5193,7 +5193,7 @@ This list contains 1359 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Dec 15, 2023, + *last release*: Jan 13, 2024, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5333,7 +5333,7 @@ This list contains 1359 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Dec 09, 2023, + *last release*: Jan 10, 2024, *status*: 3 - Alpha, *requires*: pytest >=7.0.0 @@ -6271,11 +6271,11 @@ This list contains 1359 plugins. UNKNOWN :pypi:`pytest-matcher` - *last release*: Dec 10, 2021, + *last release*: Jan 11, 2024, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest - Match test output against patterns stored in files + Keep a ChangeLog :pypi:`pytest-match-skip` *last release*: May 15, 2019, @@ -6831,9 +6831,9 @@ This list contains 1359 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Sep 18, 2023, + *last release*: Jan 11, 2024, *status*: N/A, - *requires*: pytest (==6.2.5) + *requires*: pytest (>=6.2.5,<7.0.0) Pytest plugin accessing NHSDigital's APIM proxies @@ -7482,7 +7482,7 @@ This list contains 1359 plugins. A plugin to help developing and testing other plugins :pypi:`pytest-plus` - *last release*: Oct 18, 2023, + *last release*: Jan 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=7.4.2 @@ -7566,9 +7566,9 @@ This list contains 1359 plugins. A pytest plugin to help with testing pop projects :pypi:`pytest-porringer` - *last release*: Oct 03, 2023, + *last release*: Jan 12, 2024, *status*: N/A, - *requires*: pytest>=7.4.0 + *requires*: pytest>=7.4.4 @@ -8147,11 +8147,11 @@ This list contains 1359 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Aug 17, 2023, + *last release*: Jan 06, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest>7.2 - pytest plugin for regression tests + "pytest plugin for snapshot regression testing" :pypi:`pytest-relative-order` *last release*: May 17, 2021, @@ -8210,9 +8210,9 @@ This list contains 1359 plugins. pytest plugin for repeating tests :pypi:`pytest-replay` - *last release*: Jun 09, 2021, - *status*: 4 - Beta, - *requires*: pytest (>=3.0.0) + *last release*: Jan 11, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests @@ -8378,7 +8378,7 @@ This list contains 1359 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Dec 11, 2023, + *last release*: Jan 10, 2024, *status*: N/A, *requires*: pytest ~=4.6 ; python_version == "2.7" @@ -8434,7 +8434,7 @@ This list contains 1359 plugins. Pytest plugin to restrict the test types allowed :pypi:`pytest-result-log` - *last release*: Oct 15, 2023, + *last release*: Jan 10, 2024, *status*: N/A, *requires*: pytest>=7.2.0 @@ -9148,7 +9148,7 @@ This list contains 1359 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Dec 22, 2023, + *last release*: Jan 07, 2024, *status*: N/A, *requires*: pytest >=7.4.0 @@ -9274,7 +9274,7 @@ This list contains 1359 plugins. :pypi:`pytest-splunk-addon` - *last release*: Dec 21, 2023, + *last release*: Jan 12, 2024, *status*: N/A, *requires*: pytest (>5.4.0,<8) @@ -9540,9 +9540,9 @@ This list contains 1359 plugins. pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. :pypi:`pytest-synodic` - *last release*: Aug 26, 2023, + *last release*: Jan 12, 2024, *status*: N/A, - *requires*: pytest>=7.4.0 + *requires*: pytest>=7.4.4 Synodic Pytest utilities @@ -10856,7 +10856,7 @@ This list contains 1359 plugins. PyTest plugin to run tests concurrently, each \`yield\` switch context to other one :pypi:`pytest-yls` - *last release*: Nov 03, 2023, + *last release*: Jan 11, 2024, *status*: N/A, *requires*: pytest (>=7.2.2,<8.0.0) @@ -10884,7 +10884,7 @@ This list contains 1359 plugins. OWASP ZAP plugin for py.test. :pypi:`pytest-zebrunner` - *last release*: Oct 27, 2023, + *last release*: Jan 08, 2024, *status*: 5 - Production/Stable, *requires*: pytest (>=4.5.0) From 1c9d6834fdd7343397993703f3eb82e1460c56fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Est=C3=A8ve?= Date: Wed, 10 Jan 2024 06:35:13 +0100 Subject: [PATCH 0367/1271] Improve assert mod not in mods error message [ran: tweaked message, made the formatting lazy] --- src/_pytest/config/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 85ae6dddfeb..dc018ce2a4f 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -664,7 +664,12 @@ def _importconftest( if dirpath in self._dirpath2confmods: for path, mods in self._dirpath2confmods.items(): if dirpath in path.parents or path == dirpath: - assert mod not in mods + if mod in mods: + raise AssertionError( + f"While trying to load conftest path {str(conftestpath)}, " + f"found that the module {mod} is already loaded with path {mod.__file__}. " + "This is not supposed to happen. Please report this issue to pytest." + ) mods.append(mod) self.trace(f"loading conftestmodule {mod!r}") self.consider_conftest(mod, registration_name=conftestpath_plugin_name) From 2413d1b214dd2f58d301043dada54ff153ac373a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 14 Jan 2024 15:05:15 +0200 Subject: [PATCH 0368/1271] main,python: move `__pycache__` ignore to `pytest_ignore_collect` This removes one thing that directory collectors need to worry about. This adds one hook dispatch per `__pycache__` file, but I think it's worth it for consistency. --- src/_pytest/main.py | 5 +++-- src/_pytest/python.py | 2 -- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 51be84164b2..f7e47cece1e 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -376,6 +376,9 @@ def _in_venv(path: Path) -> bool: def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[bool]: + if collection_path.name == "__pycache__": + return True + ignore_paths = config._getconftest_pathlist( "collect_ignore", path=collection_path.parent ) @@ -505,8 +508,6 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: ihook = self.ihook for direntry in scandir(self.path): if direntry.is_dir(): - if direntry.name == "__pycache__": - continue path = Path(direntry.path) if not self.session.isinitpath(path, with_parents=True): if ihook.pytest_ignore_collect(collection_path=path, config=config): diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 4ca77fbfab9..1d7f0fd6f43 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -707,8 +707,6 @@ def sort_key(entry: "os.DirEntry[str]") -> object: ihook = self.ihook for direntry in scandir(self.path, sort_key): if direntry.is_dir(): - if direntry.name == "__pycache__": - continue path = Path(direntry.path) if not self.session.isinitpath(path, with_parents=True): if ihook.pytest_ignore_collect(collection_path=path, config=config): From 707642ad357d6fa1cc394991c2f4770c20aa6ccf Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 14 Jan 2024 15:17:41 +0200 Subject: [PATCH 0369/1271] nodes: rename `iterparents()` -> `iter_parents()` After the fact I remembered there is `node.iter_markers()` so let's be consistent with that rather than with `listchain()`. --- changelog/11801.improvement.rst | 2 +- src/_pytest/fixtures.py | 4 ++-- src/_pytest/nodes.py | 6 +++--- src/_pytest/python.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/changelog/11801.improvement.rst b/changelog/11801.improvement.rst index 3046edca0c2..d9e5f848328 100644 --- a/changelog/11801.improvement.rst +++ b/changelog/11801.improvement.rst @@ -1,2 +1,2 @@ -Added the :func:`iterparents() <_pytest.nodes.Node.iterparents>` helper method on nodes. +Added the :func:`iter_parents() <_pytest.nodes.Node.iter_parents>` helper method on nodes. It is similar to :func:`listchain <_pytest.nodes.Node.listchain>`, but goes from bottom to top, and returns an iterator, not a list. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index dd37f8ec3e3..c294ec586b5 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -119,7 +119,7 @@ def get_scope_package( ) -> Optional[nodes.Node]: from _pytest.python import Package - for parent in node.iterparents(): + for parent in node.iter_parents(): if isinstance(parent, Package) and parent.nodeid == fixturedef.baseid: return parent return node.session @@ -1775,7 +1775,7 @@ def getfixturedefs( def _matchfactories( self, fixturedefs: Iterable[FixtureDef[Any]], node: nodes.Node ) -> Iterator[FixtureDef[Any]]: - parentnodeids = {n.nodeid for n in node.iterparents()} + parentnodeids = {n.nodeid for n in node.iter_parents()} for fixturedef in fixturedefs: if fixturedef.baseid in parentnodeids: yield fixturedef diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index e45a515b0ae..3f22b58714b 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -256,7 +256,7 @@ def setup(self) -> None: def teardown(self) -> None: pass - def iterparents(self) -> Iterator["Node"]: + def iter_parents(self) -> Iterator["Node"]: """Iterate over all parent collectors starting from and including self up to the root of the collection tree. @@ -318,7 +318,7 @@ def iter_markers_with_node( :param name: If given, filter the results by the name attribute. :returns: An iterator of (node, mark) tuples. """ - for node in self.iterparents(): + for node in self.iter_parents(): for mark in node.own_markers: if name is None or getattr(mark, "name", None) == name: yield node, mark @@ -368,7 +368,7 @@ def getparent(self, cls: Type[_NodeType]) -> Optional[_NodeType]: :param cls: The node class to search for. :returns: The node, if found. """ - for node in self.iterparents(): + for node in self.iter_parents(): if isinstance(node, cls): return node return None diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 4ca77fbfab9..10934705b5c 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -333,7 +333,7 @@ def _getobj(self): def getmodpath(self, stopatmodule: bool = True, includemodule: bool = False) -> str: """Return Python path relative to the containing module.""" parts = [] - for node in self.iterparents(): + for node in self.iter_parents(): name = node.name if isinstance(node, Module): name = os.path.splitext(name)[0] From e1074f9c3df36bac760552447eb20a2bc16dbe0e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 13 Jan 2024 23:35:16 +0200 Subject: [PATCH 0370/1271] config: stop using exception triplets in `ConftestImportError` In recent python versions all of the info is on the exception object itself so no reason to deal with the annoying tuple. --- src/_pytest/config/__init__.py | 16 ++++++---------- src/_pytest/debugging.py | 3 ++- src/_pytest/nodes.py | 2 +- testing/test_config.py | 4 +--- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index dc018ce2a4f..6986166649c 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -17,7 +17,6 @@ from pathlib import Path from textwrap import dedent from types import FunctionType -from types import TracebackType from typing import Any from typing import Callable from typing import cast @@ -112,16 +111,14 @@ class ConftestImportFailure(Exception): def __init__( self, path: Path, - excinfo: Tuple[Type[Exception], Exception, TracebackType], + *, + cause: Exception, ) -> None: - super().__init__(path, excinfo) self.path = path - self.excinfo = excinfo + self.cause = cause def __str__(self) -> str: - return "{}: {} (from {})".format( - self.excinfo[0].__name__, self.excinfo[1], self.path - ) + return f"{type(self.cause).__name__}: {self.cause} (from {self.path})" def filter_traceback_for_conftest_import_failure( @@ -152,7 +149,7 @@ def main( try: config = _prepareconfig(args, plugins) except ConftestImportFailure as e: - exc_info = ExceptionInfo.from_exc_info(e.excinfo) + exc_info = ExceptionInfo.from_exception(e.cause) tw = TerminalWriter(sys.stderr) tw.line(f"ImportError while loading conftest '{e.path}'.", red=True) exc_info.traceback = exc_info.traceback.filter( @@ -654,8 +651,7 @@ def _importconftest( mod = import_path(conftestpath, mode=importmode, root=rootpath) except Exception as e: assert e.__traceback__ is not None - exc_info = (type(e), e, e.__traceback__) - raise ConftestImportFailure(conftestpath, exc_info) from e + raise ConftestImportFailure(conftestpath, cause=e) from e self._check_non_top_pytest_plugins(mod, conftestpath) diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 69ec58c5b8c..57f26d219b3 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -377,7 +377,8 @@ def _postmortem_traceback(excinfo: ExceptionInfo[BaseException]) -> types.Traceb elif isinstance(excinfo.value, ConftestImportFailure): # A config.ConftestImportFailure is not useful for post_mortem. # Use the underlying exception instead: - return excinfo.value.excinfo[2] + assert excinfo.value.cause.__traceback__ is not None + return excinfo.value.cause.__traceback__ else: assert excinfo._excinfo is not None return excinfo._excinfo[2] diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 3f22b58714b..45bbb4b5788 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -384,7 +384,7 @@ def _repr_failure_py( from _pytest.fixtures import FixtureLookupError if isinstance(excinfo.value, ConftestImportFailure): - excinfo = ExceptionInfo.from_exc_info(excinfo.value.excinfo) + excinfo = ExceptionInfo.from_exception(excinfo.value.cause) if isinstance(excinfo.value, fail.Exception): if not excinfo.value.pytrace: style = "value" diff --git a/testing/test_config.py b/testing/test_config.py index 2d95fb4cc82..0f586c04388 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2108,9 +2108,7 @@ def test_conftest_import_error_repr(tmp_path: Path) -> None: try: raise RuntimeError("some error") except Exception as exc: - assert exc.__traceback__ is not None - exc_info = (type(exc), exc, exc.__traceback__) - raise ConftestImportFailure(path, exc_info) from exc + raise ConftestImportFailure(path, cause=exc) from exc def test_strtobool() -> None: From 348e6de102c5a5ccdaab88c860d57b1f49f7b1d2 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 15 Jan 2024 21:04:08 +0100 Subject: [PATCH 0371/1271] doc: Update training dates and add pytest sprint (#11819) --- doc/en/index.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index bef42716f48..3fb095a34d4 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -1,8 +1,12 @@ :orphan: -.. sidebar:: Next Open Trainings +.. sidebar:: Next Open Trainings and Events - - `Professional Testing with Python `_, via `Python Academy `_, **March 5th to 7th 2024** (3 day in-depth training), **Leipzig, Germany / Remote** + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training): + * **March 5th to 7th 2024**, Leipzig, Germany / Remote + * **June 11th to 13th 2024**, Remote + * **March 4th to 6th 2025**, Leipzig, Germany / Remote + - `pytest development sprint `_, June 2024 (`date poll `_) Also see :doc:`previous talks and blogposts `. From 9ad8b9fc36f4f62e085b1ad9a8b8bdf041cd8fa9 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 9 Jan 2022 23:17:48 +0200 Subject: [PATCH 0372/1271] hookspec: remove explicit `:param` types Duplicates info in the type annotations which sphinx understands. --- src/_pytest/hookspec.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index c1963b4d7b2..a5c9aff7013 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -54,7 +54,7 @@ def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: """Called at plugin registration time to allow adding new hooks via a call to :func:`pluginmanager.add_hookspecs(module_or_class, prefix) `. - :param pytest.PytestPluginManager pluginmanager: The pytest plugin manager. + :param pluginmanager: The pytest plugin manager. .. note:: This hook is incompatible with hook wrappers. @@ -68,7 +68,7 @@ def pytest_plugin_registered( """A new pytest plugin got registered. :param plugin: The plugin module or instance. - :param pytest.PytestPluginManager manager: pytest plugin manager. + :param manager: pytest plugin manager. .. note:: This hook is incompatible with hook wrappers. @@ -86,13 +86,13 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> files situated at the tests root directory due to how pytest :ref:`discovers plugins during startup `. - :param pytest.Parser parser: + :param parser: To add command line options, call :py:func:`parser.addoption(...) `. To add ini-file values call :py:func:`parser.addini(...) `. - :param pytest.PytestPluginManager pluginmanager: + :param pluginmanager: The pytest plugin manager, which can be used to install :py:func:`~pytest.hookspec`'s or :py:func:`~pytest.hookimpl`'s and allow one plugin to call another plugin's hooks to change how command line options are added. @@ -127,7 +127,7 @@ def pytest_configure(config: "Config") -> None: .. note:: This hook is incompatible with hook wrappers. - :param pytest.Config config: The pytest config object. + :param config: The pytest config object. """ @@ -435,7 +435,7 @@ def pytest_make_parametrize_id( :param config: The pytest config object. :param val: The parametrized value. - :param str argname: The automatic parameter name produced by pytest. + :param argname: The automatic parameter name produced by pytest. """ From dd1447cfe509fac989258e078a73609e0d122a73 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Jan 2022 00:04:20 +0200 Subject: [PATCH 0373/1271] hookspec: move pytest_load_initial_conftests up Reflect the order in which the plugins are called. --- src/_pytest/hookspec.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index a5c9aff7013..f0c579c7bc5 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -156,18 +156,6 @@ def pytest_cmdline_parse( """ -@hookspec(firstresult=True) -def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]: - """Called for performing the main command line action. The default - implementation will invoke the configure hooks and runtest_mainloop. - - Stops at first non-None result, see :ref:`firstresult`. - - :param config: The pytest config object. - :returns: The exit code. - """ - - def pytest_load_initial_conftests( early_config: "Config", parser: "Parser", args: List[str] ) -> None: @@ -183,6 +171,18 @@ def pytest_load_initial_conftests( """ +@hookspec(firstresult=True) +def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]: + """Called for performing the main command line action. The default + implementation will invoke the configure hooks and runtest_mainloop. + + Stops at first non-None result, see :ref:`firstresult`. + + :param config: The pytest config object. + :returns: The exit code. + """ + + # ------------------------------------------------------------------------- # collection hooks # ------------------------------------------------------------------------- From c973ccb622da11181bbb820fa5861e825982f271 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 15 Jan 2024 23:46:59 +0200 Subject: [PATCH 0374/1271] hookspec: modernize a reference --- src/_pytest/hookspec.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index f0c579c7bc5..404eb4e96f4 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -173,8 +173,10 @@ def pytest_load_initial_conftests( @hookspec(firstresult=True) def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]: - """Called for performing the main command line action. The default - implementation will invoke the configure hooks and runtest_mainloop. + """Called for performing the main command line action. + + The default implementation will invoke the configure hooks and + :hook:`pytest_runtestloop`. Stops at first non-None result, see :ref:`firstresult`. From e895c9d38cf4e66912c60c9c8307efcb9f82df4c Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 16 Jan 2024 14:53:10 +0100 Subject: [PATCH 0375/1271] doc: Remove sold out training (#11823) --- doc/en/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 3fb095a34d4..bc0bd56bf45 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -3,7 +3,6 @@ .. sidebar:: Next Open Trainings and Events - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training): - * **March 5th to 7th 2024**, Leipzig, Germany / Remote * **June 11th to 13th 2024**, Remote * **March 4th to 6th 2025**, Leipzig, Germany / Remote - `pytest development sprint `_, June 2024 (`date poll `_) From 6e9f566d7919b52be266c365ea65cbab79108469 Mon Sep 17 00:00:00 2001 From: woutdenolf Date: Tue, 16 Jan 2024 15:41:01 +0100 Subject: [PATCH 0376/1271] avoid using __file__ in pytest_plugin_registered as can be wrong on Windows --- src/_pytest/fixtures.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index c294ec586b5..46b201184c2 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1485,23 +1485,25 @@ def getfixtureinfo( def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None: nodeid = None - try: - p = absolutepath(plugin.__file__) # type: ignore[attr-defined] - except AttributeError: - pass - else: - # Construct the base nodeid which is later used to check - # what fixtures are visible for particular tests (as denoted - # by their test id). - if p.name == "conftest.py": - try: - nodeid = str(p.parent.relative_to(self.config.rootpath)) - except ValueError: - nodeid = "" - if nodeid == ".": - nodeid = "" - if os.sep != nodes.SEP: - nodeid = nodeid.replace(os.sep, nodes.SEP) + plugin_name = self.config.pluginmanager.get_name(plugin) + + # Construct the base nodeid which is later used to check + # what fixtures are visible for particular tests (as denoted + # by their test id). + if plugin_name and plugin_name.endswith("conftest.py"): + # The plugin name is assumed to be equal to plugin.__file__ + # for conftest plugins. The difference is that plugin_name + # has the correct capitalization on capital-insensitive + # systems (Windows). + p = absolutepath(plugin_name) + try: + nodeid = str(p.parent.relative_to(self.config.rootpath)) + except ValueError: + nodeid = "" + if nodeid == ".": + nodeid = "" + if os.sep != nodes.SEP: + nodeid = nodeid.replace(os.sep, nodes.SEP) self.parsefactories(plugin, nodeid) From 6b9bba2edb12a1b6679476aefe20c85dfb652ea0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 17 Jan 2024 15:00:09 +0200 Subject: [PATCH 0377/1271] pre-commit: add pluggy to mypy deps Otherwise mypy doesn't fully recognize pluggy's typing for some reason or another. --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index be0b4315b7f..fe6ed99ae1d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -64,6 +64,7 @@ repos: additional_dependencies: - iniconfig>=1.1.0 - attrs>=19.2.0 + - pluggy - packaging - tomli - types-pkg_resources From 0f5ecd83c432bc56e39549fe7353d06a92455a2a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 17 Jan 2024 14:47:07 +0200 Subject: [PATCH 0378/1271] hookspecs: add `plugin_name` parameter to the `pytest_plugin_registered` hook We have a use case for this in the next commit. The name can be obtained by using `manager.get_name(plugin)`, however this is currently O(num plugins) in pluggy, which would be good to avoid. Besides, it seems generally useful. --- changelog/11825.improvement.rst | 1 + src/_pytest/config/__init__.py | 12 ++++++++---- src/_pytest/hookspec.py | 7 +++++-- 3 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 changelog/11825.improvement.rst diff --git a/changelog/11825.improvement.rst b/changelog/11825.improvement.rst new file mode 100644 index 00000000000..afd85a0416d --- /dev/null +++ b/changelog/11825.improvement.rst @@ -0,0 +1 @@ +The :hook:`pytest_plugin_registered` hook has a new ``plugin_name`` parameter containing the name by which ``plugin`` is registered. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 6986166649c..157c364900d 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -490,15 +490,19 @@ def register( ) ) return None - ret: Optional[str] = super().register(plugin, name) - if ret: + plugin_name = super().register(plugin, name) + if plugin_name is not None: self.hook.pytest_plugin_registered.call_historic( - kwargs=dict(plugin=plugin, manager=self) + kwargs=dict( + plugin=plugin, + plugin_name=plugin_name, + manager=self, + ) ) if isinstance(plugin, types.ModuleType): self.consider_module(plugin) - return ret + return plugin_name def getplugin(self, name: str): # Support deprecated naming because plugins (xdist e.g.) use it. diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 404eb4e96f4..c4cce2d838d 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -63,12 +63,15 @@ def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: @hookspec(historic=True) def pytest_plugin_registered( - plugin: "_PluggyPlugin", manager: "PytestPluginManager" + plugin: "_PluggyPlugin", + plugin_name: str, + manager: "PytestPluginManager", ) -> None: """A new pytest plugin got registered. :param plugin: The plugin module or instance. - :param manager: pytest plugin manager. + :param plugin_name: The name by which the plugin is registered. + :param manager: The pytest plugin manager. .. note:: This hook is incompatible with hook wrappers. From 9ea2e0a79f8d45b801b4bff8e4ad0aefd09fab21 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 17 Jan 2024 14:49:17 +0200 Subject: [PATCH 0379/1271] fixtures: avoid slow `pm.get_name(plugin)` call by using the new `plugin_name` hook parameter --- src/_pytest/fixtures.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 46b201184c2..51c573575ef 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1483,27 +1483,27 @@ def getfixtureinfo( return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs) - def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None: - nodeid = None - plugin_name = self.config.pluginmanager.get_name(plugin) - - # Construct the base nodeid which is later used to check - # what fixtures are visible for particular tests (as denoted - # by their test id). + def pytest_plugin_registered(self, plugin: _PluggyPlugin, plugin_name: str) -> None: + # Fixtures defined in conftest plugins are only visible to within the + # conftest's directory. This is unlike fixtures in non-conftest plugins + # which have global visibility. So for conftests, construct the base + # nodeid from the plugin name (which is the conftest path). if plugin_name and plugin_name.endswith("conftest.py"): - # The plugin name is assumed to be equal to plugin.__file__ - # for conftest plugins. The difference is that plugin_name - # has the correct capitalization on capital-insensitive - # systems (Windows). - p = absolutepath(plugin_name) + # Note: we explicitly do *not* use `plugin.__file__` here -- The + # difference is that plugin_name has the correct capitalization on + # case-insensitive systems (Windows) and other normalization issues + # (issue #11816). + conftestpath = absolutepath(plugin_name) try: - nodeid = str(p.parent.relative_to(self.config.rootpath)) + nodeid = str(conftestpath.parent.relative_to(self.config.rootpath)) except ValueError: nodeid = "" if nodeid == ".": nodeid = "" if os.sep != nodes.SEP: nodeid = nodeid.replace(os.sep, nodes.SEP) + else: + nodeid = None self.parsefactories(plugin, nodeid) From 5cd0535395541d8940035418b368331318002199 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 17 Jan 2024 22:53:04 +0200 Subject: [PATCH 0380/1271] testing: temporarily disable test due to hypothesis issue (#11836) Ref: https://github.com/pytest-dev/pytest/pull/11825#issuecomment-1894094641 --- testing/python/metafunc.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 9768c82ffa7..9393c972746 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -13,9 +13,6 @@ from typing import Tuple from typing import Union -import hypothesis -from hypothesis import strategies - import pytest from _pytest import fixtures from _pytest import python @@ -27,6 +24,9 @@ from _pytest.python import IdMaker from _pytest.scope import Scope +# import hypothesis +# from hypothesis import strategies + class TestMetafunc: def Metafunc(self, func, config=None) -> python.Metafunc: @@ -292,14 +292,15 @@ class A: assert metafunc._calls[2].id == "x1-a" assert metafunc._calls[3].id == "x1-b" - @hypothesis.given(strategies.text() | strategies.binary()) - @hypothesis.settings( - deadline=400.0 - ) # very close to std deadline and CI boxes are not reliable in CPU power - def test_idval_hypothesis(self, value) -> None: - escaped = IdMaker([], [], None, None, None, None, None)._idval(value, "a", 6) - assert isinstance(escaped, str) - escaped.encode("ascii") + # TODO: Uncomment - https://github.com/HypothesisWorks/hypothesis/pull/3849 + # @hypothesis.given(strategies.text() | strategies.binary()) + # @hypothesis.settings( + # deadline=400.0 + # ) # very close to std deadline and CI boxes are not reliable in CPU power + # def test_idval_hypothesis(self, value) -> None: + # escaped = IdMaker([], [], None, None, None, None, None)._idval(value, "a", 6) + # assert isinstance(escaped, str) + # escaped.encode("ascii") def test_unicode_idval(self) -> None: """Test that Unicode strings outside the ASCII character set get From ca5bbd0a9f56c8f9b3f5a43c47ff11c360f33d0b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 17 Jan 2024 23:44:01 +0200 Subject: [PATCH 0381/1271] Merge pull request #11835 from pytest-dev/release-8.0.0rc2 Prepare release version 8.0.0rc2 (cherry picked from commit 97960bdd148972b2f26bd9b336163e590bbc4c6b) --- changelog/11233.feature.rst | 5 ----- changelog/11706.bugfix.rst | 1 - changelog/11758.bugfix.rst | 2 -- changelog/11825.improvement.rst | 1 - changelog/9765.bugfix.rst | 3 --- doc/en/announce/index.rst | 1 + doc/en/announce/release-8.0.0rc2.rst | 32 ++++++++++++++++++++++++++++ doc/en/changelog.rst | 31 +++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 10 ++++----- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/example/simple.rst | 25 ++++++++++++++++++++++ doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/output.rst | 11 +++++++++- 14 files changed, 108 insertions(+), 22 deletions(-) delete mode 100644 changelog/11233.feature.rst delete mode 100644 changelog/11706.bugfix.rst delete mode 100644 changelog/11758.bugfix.rst delete mode 100644 changelog/11825.improvement.rst delete mode 100644 changelog/9765.bugfix.rst create mode 100644 doc/en/announce/release-8.0.0rc2.rst diff --git a/changelog/11233.feature.rst b/changelog/11233.feature.rst deleted file mode 100644 index c465def84ec..00000000000 --- a/changelog/11233.feature.rst +++ /dev/null @@ -1,5 +0,0 @@ -Improvements to how ``-r`` for xfailures and xpasses: - -* Report tracebacks for xfailures when ``-rx`` is set. -* Report captured output for xpasses when ``-rX`` is set. -* For xpasses, add ``-`` in summary between test name and reason, to match how xfail is displayed. diff --git a/changelog/11706.bugfix.rst b/changelog/11706.bugfix.rst deleted file mode 100644 index 1b90d8f0b60..00000000000 --- a/changelog/11706.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`. diff --git a/changelog/11758.bugfix.rst b/changelog/11758.bugfix.rst deleted file mode 100644 index af8a3f3514f..00000000000 --- a/changelog/11758.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed ``IndexError: string index out of range`` crash in ``if highlighted[-1] == "\n" and source[-1] != "\n"``. -This bug was introduced in pytest 8.0.0rc1. diff --git a/changelog/11825.improvement.rst b/changelog/11825.improvement.rst deleted file mode 100644 index afd85a0416d..00000000000 --- a/changelog/11825.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -The :hook:`pytest_plugin_registered` hook has a new ``plugin_name`` parameter containing the name by which ``plugin`` is registered. diff --git a/changelog/9765.bugfix.rst b/changelog/9765.bugfix.rst deleted file mode 100644 index c726cbf8d56..00000000000 --- a/changelog/9765.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a frustrating bug that afflicted some users with the only error being ``assert mod not in mods``. The issue was caused by the fact that ``str(Path(mod))`` and ``mod.__file__`` don't necessarily produce the same string, and was being erroneously used interchangably in some places in the code. - -This fix also broke the internal API of ``PytestPluginManager.consider_conftest`` by introducing a new parameter -- we mention this in case it is being used by external code, even if marked as *private*. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 740767c017e..1c413de7a44 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.0.0rc2 release-8.0.0rc1 release-7.4.4 release-7.4.3 diff --git a/doc/en/announce/release-8.0.0rc2.rst b/doc/en/announce/release-8.0.0rc2.rst new file mode 100644 index 00000000000..1a6444c5214 --- /dev/null +++ b/doc/en/announce/release-8.0.0rc2.rst @@ -0,0 +1,32 @@ +pytest-8.0.0rc2 +======================================= + +The pytest team is proud to announce the 8.0.0rc2 prerelease! + +This is a prerelease, not intended for production use, but to test the upcoming features and improvements +in order to catch any major problems before the final version is released to the major public. + +We appreciate your help testing this out before the final release, making sure to report any +regressions to our issue tracker: + +https://github.com/pytest-dev/pytest/issues + +When doing so, please include the string ``[prerelease]`` in the title. + +You can upgrade from PyPI via: + + pip install pytest==8.0.0rc2 + +Users are encouraged to take a look at the CHANGELOG carefully: + + https://docs.pytest.org/en/release-8.0.0rc2/changelog.html + +Thanks to all the contributors to this release: + +* Ben Brown +* Bruno Oliveira +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 755f386c6ca..da275b622c4 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,37 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.0.0rc2 (2024-01-17) +============================ + + +Improvements +------------ + +- `#11233 `_: Improvements to ``-r`` for xfailures and xpasses: + + * Report tracebacks for xfailures when ``-rx`` is set. + * Report captured output for xpasses when ``-rX`` is set. + * For xpasses, add ``-`` in summary between test name and reason, to match how xfail is displayed. + +- `#11825 `_: The :hook:`pytest_plugin_registered` hook has a new ``plugin_name`` parameter containing the name by which ``plugin`` is registered. + + +Bug Fixes +--------- + +- `#11706 `_: Fix reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`. + + +- `#11758 `_: Fixed ``IndexError: string index out of range`` crash in ``if highlighted[-1] == "\n" and source[-1] != "\n"``. + This bug was introduced in pytest 8.0.0rc1. + + +- `#9765 `_, `#11816 `_: Fixed a frustrating bug that afflicted some users with the only error being ``assert mod not in mods``. The issue was caused by the fact that ``str(Path(mod))`` and ``mod.__file__`` don't necessarily produce the same string, and was being erroneously used interchangably in some places in the code. + + This fix also broke the internal API of ``PytestPluginManager.consider_conftest`` by introducing a new parameter -- we mention this in case it is being used by external code, even if marked as *private*. + + pytest 8.0.0rc1 (2023-12-30) ============================ diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 0426266e581..9d78fc40323 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + @@ -503,10 +503,10 @@ Running it results in some skips if we don't have all the python interpreters in .. code-block:: pytest . $ pytest -rs -q multipython.py - ssssssssssss...ssssssssssss [100%] + ssssssssssssssssssssssss... [100%] ========================= short test summary info ========================== SKIPPED [12] multipython.py:68: 'python3.9' not found - SKIPPED [12] multipython.py:68: 'python3.11' not found + SKIPPED [12] multipython.py:68: 'python3.10' not found 3 passed, 24 skipped in 0.12s Parametrization of optional implementations/imports diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index dbc2c239fdd..e98f1a75245 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 21e5f4a09a5..7064f61f0e2 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -660,6 +660,31 @@ If we run this: E assert 0 test_step.py:11: AssertionError + ================================ XFAILURES ================================= + ______________________ TestUserHandling.test_deletion ______________________ + + item = + + def pytest_runtest_setup(item): + if "incremental" in item.keywords: + # retrieve the class name of the test + cls_name = str(item.cls) + # check if a previous test has failed for this class + if cls_name in _test_failed_incremental: + # retrieve the index of the test (if parametrize is used in combination with incremental) + parametrize_index = ( + tuple(item.callspec.indices.values()) + if hasattr(item, "callspec") + else () + ) + # retrieve the name of the first test function to fail for this class name and index + test_name = _test_failed_incremental[cls_name].get(parametrize_index, None) + # if name found, test has failed for the combination of class name & test name + if test_name is not None: + > pytest.xfail(f"previous test failed ({test_name})") + E _pytest.outcomes.XFailed: previous test failed (test_modification) + + conftest.py:47: XFailed ========================= short test summary info ========================== XFAIL test_step.py::TestUserHandling::test_deletion - reason: previous test failed (test_modification) ================== 1 failed, 2 passed, 1 xfailed in 0.12s ================== diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 0f74a8ecf0b..90765df6099 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.0.0rc1 + pytest 8.0.0rc2 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 95c376fd307..e3209c77717 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index 95c3a89b5a2..76b2a53dd18 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -404,10 +404,19 @@ Example: E assert 0 test_example.py:14: AssertionError + ================================ XFAILURES ================================= + ________________________________ test_xfail ________________________________ + + def test_xfail(): + > pytest.xfail("xfailing this test") + E _pytest.outcomes.XFailed: xfailing this test + + test_example.py:26: XFailed + ================================= XPASSES ================================== ========================= short test summary info ========================== SKIPPED [1] test_example.py:22: skipping this test XFAIL test_example.py::test_xfail - reason: xfailing this test - XPASS test_example.py::test_xpass always xfail + XPASS test_example.py::test_xpass - always xfail ERROR test_example.py::test_error - assert 0 FAILED test_example.py::test_fail - assert 0 == 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s === From 7fd561e4ba5dd5ae7a04c7b92b83cef8492a358d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 17 Jan 2024 19:11:10 -0300 Subject: [PATCH 0382/1271] Properly attach packages to the GH release notes (#11839) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow up to https://github.com/pytest-dev/pytest/pull/11754, noticed that the latest GitHub release does not contain the attached files. Output log from the action: ``` 🤔 Pattern 'dist/*' does not match any files. ``` --- .github/workflows/deploy.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 585398ba315..5d5015f187e 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -72,6 +72,12 @@ jobs: fetch-depth: 0 persist-credentials: false + - name: Download Package + uses: actions/download-artifact@v4 + with: + name: Packages + path: dist + - name: Set up Python uses: actions/setup-python@v5 with: From eefc9d47fc40a9d5971a6207689c50efb1555a95 Mon Sep 17 00:00:00 2001 From: faph Date: Thu, 18 Jan 2024 10:21:49 +0000 Subject: [PATCH 0383/1271] [DOCS] Clarify tmp_path directory location and retention (#11830) Fixes #11789 and #11790 --- AUTHORS | 1 + changelog/11790.doc.rst | 1 + doc/en/how-to/tmp_path.rst | 22 +++++++++++++--------- src/_pytest/legacypath.py | 4 ++-- src/_pytest/tmpdir.py | 4 ++-- 5 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 changelog/11790.doc.rst diff --git a/AUTHORS b/AUTHORS index 353489b6cd2..803bb2b183f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -141,6 +141,7 @@ Evgeny Seliverstov Fabian Sturm Fabien Zarifian Fabio Zadrozny +faph Felix Hofstätter Felix Nieuwenhuizen Feng Ma diff --git a/changelog/11790.doc.rst b/changelog/11790.doc.rst new file mode 100644 index 00000000000..648b20b96af --- /dev/null +++ b/changelog/11790.doc.rst @@ -0,0 +1 @@ +Documented the retention of temporary directories created using the ``tmp_path`` fixture in more detail. diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index 3e680dcac76..3cc5152e992 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -8,9 +8,8 @@ How to use temporary directories and files in tests The ``tmp_path`` fixture ------------------------ -You can use the ``tmp_path`` fixture which will -provide a temporary directory unique to the current test, -created in the `base temporary directory`_. +You can use the ``tmp_path`` fixture which will provide a temporary directory +unique to each test function. ``tmp_path`` is a :class:`pathlib.Path` object. Here is an example test usage: @@ -62,6 +61,11 @@ Running this would result in a passed test except for the last FAILED test_tmp_path.py::test_create_file - assert 0 ============================ 1 failed in 0.12s ============================= +By default, ``pytest`` retains the temporary directory for the last 3 ``pytest`` +invocations. Concurrent invocations of the same test function are supported by +configuring the base temporary directory to be unique for each concurrent +run. See `temporary directory location and retention`_ for details. + .. _`tmp_path_factory example`: The ``tmp_path_factory`` fixture @@ -100,7 +104,7 @@ See :ref:`tmp_path_factory API ` for details. .. _tmpdir: The ``tmpdir`` and ``tmpdir_factory`` fixtures ---------------------------------------------------- +---------------------------------------------- The ``tmpdir`` and ``tmpdir_factory`` fixtures are similar to ``tmp_path`` and ``tmp_path_factory``, but use/return legacy `py.path.local`_ objects @@ -124,10 +128,10 @@ See :fixture:`tmpdir ` :fixture:`tmpdir_factory ` API for details. -.. _`base temporary directory`: +.. _`temporary directory location and retention`: -The default base temporary directory ------------------------------------------------ +Temporary directory location and retention +------------------------------------------ Temporary directories are by default created as sub-directories of the system temporary directory. The base name will be ``pytest-NUM`` where @@ -152,7 +156,7 @@ You can override the default temporary directory setting like this: for that purpose only. When distributing tests on the local machine using ``pytest-xdist``, care is taken to -automatically configure a basetemp directory for the sub processes such that all temporary -data lands below a single per-test run basetemp directory. +automatically configure a `basetemp` directory for the sub processes such that all temporary +data lands below a single per-test run temporary directory. .. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index b2dd87436e1..f69315b5fed 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -326,8 +326,8 @@ def tmpdir(tmp_path: Path) -> LEGACY_PATH: By default, a new base temporary directory is created each test session, and old bases are removed after 3 sessions, to aid in debugging. If - ``--basetemp`` is used then it is cleared each session. See :ref:`base - temporary directory`. + ``--basetemp`` is used then it is cleared each session. See + :ref:`temporary directory location and retention`. The returned object is a `legacy_path`_ object. diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 6fa227760a8..21e5366a354 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -262,8 +262,8 @@ def tmp_path( and old bases are removed after 3 sessions, to aid in debugging. This behavior can be configured with :confval:`tmp_path_retention_count` and :confval:`tmp_path_retention_policy`. - If ``--basetemp`` is used then it is cleared each session. See :ref:`base - temporary directory`. + If ``--basetemp`` is used then it is cleared each session. See + :ref:`temporary directory location and retention`. The returned object is a :class:`pathlib.Path` object. """ From 34fafe4c6b9f03107b5b925d310e875799376679 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 16 Jan 2024 20:42:09 +0200 Subject: [PATCH 0384/1271] config: avoid Path.cwd() call in `_set_initial_conftests` We should aim to remove all `cwd()` calls except one, otherwise things will go bad if the working directory changes. Use the invocation dir instead. --- src/_pytest/config/__init__.py | 13 +++++++++---- testing/test_conftest.py | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 157c364900d..70fceef7bda 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -541,6 +541,7 @@ def _set_initial_conftests( noconftest: bool, rootpath: Path, confcutdir: Optional[Path], + invocation_dir: Path, importmode: Union[ImportMode, str], ) -> None: """Load initial conftest files given a preparsed "namespace". @@ -550,8 +551,9 @@ def _set_initial_conftests( All builtin and 3rd party plugins will have been loaded, however, so common options will not confuse our logic here. """ - current = Path.cwd() - self._confcutdir = absolutepath(current / confcutdir) if confcutdir else None + self._confcutdir = ( + absolutepath(invocation_dir / confcutdir) if confcutdir else None + ) self._noconftest = noconftest self._using_pyargs = pyargs foundanchor = False @@ -561,7 +563,7 @@ def _set_initial_conftests( i = path.find("::") if i != -1: path = path[:i] - anchor = absolutepath(current / path) + anchor = absolutepath(invocation_dir / path) # Ensure we do not break if what appears to be an anchor # is in fact a very long option (#10169, #11394). @@ -569,7 +571,7 @@ def _set_initial_conftests( self._try_load_conftest(anchor, importmode, rootpath) foundanchor = True if not foundanchor: - self._try_load_conftest(current, importmode, rootpath) + self._try_load_conftest(invocation_dir, importmode, rootpath) def _is_in_confcutdir(self, path: Path) -> bool: """Whether a path is within the confcutdir. @@ -1168,6 +1170,7 @@ def pytest_load_initial_conftests(self, early_config: "Config") -> None: noconftest=early_config.known_args_namespace.noconftest, rootpath=early_config.rootpath, confcutdir=early_config.known_args_namespace.confcutdir, + invocation_dir=early_config.invocation_params.dir, importmode=early_config.known_args_namespace.importmode, ) @@ -1261,6 +1264,8 @@ def _decide_args( """Decide the args (initial paths/nodeids) to use given the relevant inputs. :param warn: Whether can issue warnings. + + :returns: The args and the args source. Guaranteed to be non-empty. """ if args: source = Config.ArgsSource.ARGS diff --git a/testing/test_conftest.py b/testing/test_conftest.py index cfc2d577b53..e741907273d 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -35,6 +35,7 @@ def conftest_setinitial( noconftest=False, rootpath=Path(args[0]), confcutdir=confcutdir, + invocation_dir=Path.cwd(), importmode="prepend", ) From 212c55218b1b7406643ba4fe7002702ff6cf2c04 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 16 Jan 2024 20:47:36 +0200 Subject: [PATCH 0385/1271] helpconfig: add invocation dir to debug output The current WD is not supposed to matter, the invocation dir is what should be relevant. But keep them both for debugging. --- src/_pytest/helpconfig.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 364bf4c4276..91ea7699708 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -109,10 +109,11 @@ def pytest_cmdline_parse() -> Generator[None, Config, Config]: debugfile = open(path, "w", encoding="utf-8") debugfile.write( "versions pytest-%s, " - "python-%s\ncwd=%s\nargs=%s\n\n" + "python-%s\ninvocation_dir=%s\ncwd=%s\nargs=%s\n\n" % ( pytest.__version__, ".".join(map(str, sys.version_info)), + config.invocation_params.dir, os.getcwd(), config.invocation_params.args, ) From 676f38d04aa7fc96ecf06235d855820aba05b83a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 16 Jan 2024 20:56:32 +0200 Subject: [PATCH 0386/1271] findpaths: rely on invocation_dir instead of cwd We should aim to remove all `cwd()` calls except one, otherwise things will go bad if the working directory changes. Use the invocation dir instead. --- src/_pytest/config/__init__.py | 4 +- src/_pytest/config/findpaths.py | 32 +++++----- testing/test_config.py | 105 ++++++++++++++++++++++++++------ testing/test_findpaths.py | 13 ++-- 4 files changed, 111 insertions(+), 43 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 70fceef7bda..e4e8f700ab9 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1179,8 +1179,8 @@ def _initini(self, args: Sequence[str]) -> None: args, namespace=copy.copy(self.option) ) rootpath, inipath, inicfg = determine_setup( - ns.inifilename, - ns.file_or_dir + unknown_args, + inifile=ns.inifilename, + args=ns.file_or_dir + unknown_args, rootdir_cmd_arg=ns.rootdir or None, invocation_dir=self.invocation_params.dir, ) diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index fc30533b6e4..8e69a46fd6f 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -87,6 +87,7 @@ def make_scalar(v: object) -> Union[str, List[str]]: def locate_config( + invocation_dir: Path, args: Iterable[Path], ) -> Tuple[Optional[Path], Optional[Path], Dict[str, Union[str, List[str]]]]: """Search in the list of arguments for a valid ini-file for pytest, @@ -100,7 +101,7 @@ def locate_config( ] args = [x for x in args if not str(x).startswith("-")] if not args: - args = [Path.cwd()] + args = [invocation_dir] for arg in args: argpath = absolutepath(arg) for base in (argpath, *argpath.parents): @@ -113,7 +114,10 @@ def locate_config( return None, None, {} -def get_common_ancestor(paths: Iterable[Path]) -> Path: +def get_common_ancestor( + invocation_dir: Path, + paths: Iterable[Path], +) -> Path: common_ancestor: Optional[Path] = None for path in paths: if not path.exists(): @@ -130,7 +134,7 @@ def get_common_ancestor(paths: Iterable[Path]) -> Path: if shared is not None: common_ancestor = shared if common_ancestor is None: - common_ancestor = Path.cwd() + common_ancestor = invocation_dir elif common_ancestor.is_file(): common_ancestor = common_ancestor.parent return common_ancestor @@ -162,10 +166,11 @@ def get_dir_from_path(path: Path) -> Path: def determine_setup( + *, inifile: Optional[str], args: Sequence[str], - rootdir_cmd_arg: Optional[str] = None, - invocation_dir: Optional[Path] = None, + rootdir_cmd_arg: Optional[str], + invocation_dir: Path, ) -> Tuple[Path, Optional[Path], Dict[str, Union[str, List[str]]]]: """Determine the rootdir, inifile and ini configuration values from the command line arguments. @@ -177,8 +182,7 @@ def determine_setup( :param rootdir_cmd_arg: The `--rootdir` command line argument, if given. :param invocation_dir: - The working directory when pytest was invoked, if known. - If not known, the current working directory is used. + The working directory when pytest was invoked. """ rootdir = None dirs = get_dirs_from_args(args) @@ -189,8 +193,8 @@ def determine_setup( if rootdir_cmd_arg is None: rootdir = inipath_.parent else: - ancestor = get_common_ancestor(dirs) - rootdir, inipath, inicfg = locate_config([ancestor]) + ancestor = get_common_ancestor(invocation_dir, dirs) + rootdir, inipath, inicfg = locate_config(invocation_dir, [ancestor]) if rootdir is None and rootdir_cmd_arg is None: for possible_rootdir in (ancestor, *ancestor.parents): if (possible_rootdir / "setup.py").is_file(): @@ -198,13 +202,11 @@ def determine_setup( break else: if dirs != [ancestor]: - rootdir, inipath, inicfg = locate_config(dirs) + rootdir, inipath, inicfg = locate_config(invocation_dir, dirs) if rootdir is None: - if invocation_dir is not None: - cwd = invocation_dir - else: - cwd = Path.cwd() - rootdir = get_common_ancestor([cwd, ancestor]) + rootdir = get_common_ancestor( + invocation_dir, [invocation_dir, ancestor] + ) if is_fs_root(rootdir): rootdir = ancestor if rootdir_cmd_arg: diff --git a/testing/test_config.py b/testing/test_config.py index 0f586c04388..1eb530aceb6 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -59,7 +59,7 @@ def test_getcfg_and_config( ), encoding="utf-8", ) - _, _, cfg = locate_config([sub]) + _, _, cfg = locate_config(Path.cwd(), [sub]) assert cfg["name"] == "value" config = pytester.parseconfigure(str(sub)) assert config.inicfg["name"] == "value" @@ -1436,16 +1436,16 @@ class pytest_something: class TestRootdir: def test_simple_noini(self, tmp_path: Path, monkeypatch: MonkeyPatch) -> None: - assert get_common_ancestor([tmp_path]) == tmp_path + assert get_common_ancestor(Path.cwd(), [tmp_path]) == tmp_path a = tmp_path / "a" a.mkdir() - assert get_common_ancestor([a, tmp_path]) == tmp_path - assert get_common_ancestor([tmp_path, a]) == tmp_path + assert get_common_ancestor(Path.cwd(), [a, tmp_path]) == tmp_path + assert get_common_ancestor(Path.cwd(), [tmp_path, a]) == tmp_path monkeypatch.chdir(tmp_path) - assert get_common_ancestor([]) == tmp_path + assert get_common_ancestor(Path.cwd(), []) == tmp_path no_path = tmp_path / "does-not-exist" - assert get_common_ancestor([no_path]) == tmp_path - assert get_common_ancestor([no_path / "a"]) == tmp_path + assert get_common_ancestor(Path.cwd(), [no_path]) == tmp_path + assert get_common_ancestor(Path.cwd(), [no_path / "a"]) == tmp_path @pytest.mark.parametrize( "name, contents", @@ -1467,10 +1467,20 @@ def test_with_ini(self, tmp_path: Path, name: str, contents: str) -> None: b = a / "b" b.mkdir() for args in ([str(tmp_path)], [str(a)], [str(b)]): - rootpath, parsed_inipath, _ = determine_setup(None, args) + rootpath, parsed_inipath, _ = determine_setup( + inifile=None, + args=args, + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert parsed_inipath == inipath - rootpath, parsed_inipath, ini_config = determine_setup(None, [str(b), str(a)]) + rootpath, parsed_inipath, ini_config = determine_setup( + inifile=None, + args=[str(b), str(a)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert parsed_inipath == inipath assert ini_config == {"x": "10"} @@ -1482,7 +1492,12 @@ def test_pytestini_overrides_empty_other(self, tmp_path: Path, name: str) -> Non a = tmp_path / "a" a.mkdir() (a / name).touch() - rootpath, parsed_inipath, _ = determine_setup(None, [str(a)]) + rootpath, parsed_inipath, _ = determine_setup( + inifile=None, + args=[str(a)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert parsed_inipath == inipath @@ -1491,14 +1506,24 @@ def test_setuppy_fallback(self, tmp_path: Path) -> None: a.mkdir() (a / "setup.cfg").touch() (tmp_path / "setup.py").touch() - rootpath, inipath, inicfg = determine_setup(None, [str(a)]) + rootpath, inipath, inicfg = determine_setup( + inifile=None, + args=[str(a)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert inipath is None assert inicfg == {} def test_nothing(self, tmp_path: Path, monkeypatch: MonkeyPatch) -> None: monkeypatch.chdir(tmp_path) - rootpath, inipath, inicfg = determine_setup(None, [str(tmp_path)]) + rootpath, inipath, inicfg = determine_setup( + inifile=None, + args=[str(tmp_path)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert inipath is None assert inicfg == {} @@ -1520,7 +1545,12 @@ def test_with_specific_inifile( p = tmp_path / name p.touch() p.write_text(contents, encoding="utf-8") - rootpath, inipath, ini_config = determine_setup(str(p), [str(tmp_path)]) + rootpath, inipath, ini_config = determine_setup( + inifile=str(p), + args=[str(tmp_path)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert inipath == p assert ini_config == {"x": "10"} @@ -1534,14 +1564,24 @@ def test_explicit_config_file_sets_rootdir( monkeypatch.chdir(tmp_path) # No config file is explicitly given: rootdir is determined to be cwd. - rootpath, found_inipath, *_ = determine_setup(None, [str(tests_dir)]) + rootpath, found_inipath, *_ = determine_setup( + inifile=None, + args=[str(tests_dir)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert found_inipath is None # Config file is explicitly given: rootdir is determined to be inifile's directory. inipath = tmp_path / "pytest.ini" inipath.touch() - rootpath, found_inipath, *_ = determine_setup(str(inipath), [str(tests_dir)]) + rootpath, found_inipath, *_ = determine_setup( + inifile=str(inipath), + args=[str(tests_dir)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert found_inipath == inipath @@ -1553,7 +1593,12 @@ def test_with_arg_outside_cwd_without_inifile( a.mkdir() b = tmp_path / "b" b.mkdir() - rootpath, inifile, _ = determine_setup(None, [str(a), str(b)]) + rootpath, inifile, _ = determine_setup( + inifile=None, + args=[str(a), str(b)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert inifile is None @@ -1564,7 +1609,12 @@ def test_with_arg_outside_cwd_with_inifile(self, tmp_path: Path) -> None: b.mkdir() inipath = a / "pytest.ini" inipath.touch() - rootpath, parsed_inipath, _ = determine_setup(None, [str(a), str(b)]) + rootpath, parsed_inipath, _ = determine_setup( + inifile=None, + args=[str(a), str(b)], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == a assert inipath == parsed_inipath @@ -1573,7 +1623,12 @@ def test_with_non_dir_arg( self, dirs: Sequence[str], tmp_path: Path, monkeypatch: MonkeyPatch ) -> None: monkeypatch.chdir(tmp_path) - rootpath, inipath, _ = determine_setup(None, dirs) + rootpath, inipath, _ = determine_setup( + inifile=None, + args=dirs, + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert inipath is None @@ -1584,7 +1639,12 @@ def test_with_existing_file_in_subdir( a.mkdir() (a / "exists").touch() monkeypatch.chdir(tmp_path) - rootpath, inipath, _ = determine_setup(None, ["a/exist"]) + rootpath, inipath, _ = determine_setup( + inifile=None, + args=["a/exist"], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path assert inipath is None @@ -1598,7 +1658,12 @@ def test_with_config_also_in_parent_directory( (tmp_path / "myproject" / "tests").mkdir() monkeypatch.chdir(tmp_path / "myproject") - rootpath, inipath, _ = determine_setup(None, ["tests/"]) + rootpath, inipath, _ = determine_setup( + inifile=None, + args=["tests/"], + rootdir_cmd_arg=None, + invocation_dir=Path.cwd(), + ) assert rootpath == tmp_path / "myproject" assert inipath == tmp_path / "myproject" / "setup.cfg" diff --git a/testing/test_findpaths.py b/testing/test_findpaths.py index 8287de603ed..65370a0ba3a 100644 --- a/testing/test_findpaths.py +++ b/testing/test_findpaths.py @@ -109,18 +109,19 @@ def test_has_ancestor(self, tmp_path: Path) -> None: fn2 = tmp_path / "foo" / "zaz" / "test_2.py" fn2.parent.mkdir(parents=True) fn2.touch() - assert get_common_ancestor([fn1, fn2]) == tmp_path / "foo" - assert get_common_ancestor([fn1.parent, fn2]) == tmp_path / "foo" - assert get_common_ancestor([fn1.parent, fn2.parent]) == tmp_path / "foo" - assert get_common_ancestor([fn1, fn2.parent]) == tmp_path / "foo" + cwd = Path.cwd() + assert get_common_ancestor(cwd, [fn1, fn2]) == tmp_path / "foo" + assert get_common_ancestor(cwd, [fn1.parent, fn2]) == tmp_path / "foo" + assert get_common_ancestor(cwd, [fn1.parent, fn2.parent]) == tmp_path / "foo" + assert get_common_ancestor(cwd, [fn1, fn2.parent]) == tmp_path / "foo" def test_single_dir(self, tmp_path: Path) -> None: - assert get_common_ancestor([tmp_path]) == tmp_path + assert get_common_ancestor(Path.cwd(), [tmp_path]) == tmp_path def test_single_file(self, tmp_path: Path) -> None: fn = tmp_path / "foo.py" fn.touch() - assert get_common_ancestor([fn]) == tmp_path + assert get_common_ancestor(Path.cwd(), [fn]) == tmp_path def test_get_dirs_from_args(tmp_path): From a6dd90a41414173110ea143c301d3da9853449ea Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 16 Jan 2024 21:52:23 +0200 Subject: [PATCH 0387/1271] python: use invocation dir instead of cwd in fixture-printing code We should aim to remove all `cwd()` calls except one, otherwise things will go bad if the working directory changes. Use the invocation dir instead. --- src/_pytest/python.py | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index e55772d5ece..64480c97149 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1525,14 +1525,13 @@ def _ascii_escaped_by_config(val: Union[str, bytes], config: Optional[Config]) - return val if escape_option else ascii_escaped(val) # type: ignore -def _pretty_fixture_path(func) -> str: - cwd = Path.cwd() - loc = Path(getlocation(func, str(cwd))) +def _pretty_fixture_path(invocation_dir: Path, func) -> str: + loc = Path(getlocation(func, invocation_dir)) prefix = Path("...", "_pytest") try: return str(prefix / loc.relative_to(_PYTEST_DIR)) except ValueError: - return bestrelpath(cwd, loc) + return bestrelpath(invocation_dir, loc) def show_fixtures_per_test(config): @@ -1545,19 +1544,19 @@ def _show_fixtures_per_test(config: Config, session: Session) -> None: import _pytest.config session.perform_collect() - curdir = Path.cwd() + invocation_dir = config.invocation_params.dir tw = _pytest.config.create_terminal_writer(config) verbose = config.getvalue("verbose") def get_best_relpath(func) -> str: - loc = getlocation(func, str(curdir)) - return bestrelpath(curdir, Path(loc)) + loc = getlocation(func, invocation_dir) + return bestrelpath(invocation_dir, Path(loc)) def write_fixture(fixture_def: fixtures.FixtureDef[object]) -> None: argname = fixture_def.argname if verbose <= 0 and argname.startswith("_"): return - prettypath = _pretty_fixture_path(fixture_def.func) + prettypath = _pretty_fixture_path(invocation_dir, fixture_def.func) tw.write(f"{argname}", green=True) tw.write(f" -- {prettypath}", yellow=True) tw.write("\n") @@ -1601,7 +1600,7 @@ def _showfixtures_main(config: Config, session: Session) -> None: import _pytest.config session.perform_collect() - curdir = Path.cwd() + invocation_dir = config.invocation_params.dir tw = _pytest.config.create_terminal_writer(config) verbose = config.getvalue("verbose") @@ -1615,7 +1614,7 @@ def _showfixtures_main(config: Config, session: Session) -> None: if not fixturedefs: continue for fixturedef in fixturedefs: - loc = getlocation(fixturedef.func, str(curdir)) + loc = getlocation(fixturedef.func, invocation_dir) if (fixturedef.argname, loc) in seen: continue seen.add((fixturedef.argname, loc)) @@ -1623,7 +1622,7 @@ def _showfixtures_main(config: Config, session: Session) -> None: ( len(fixturedef.baseid), fixturedef.func.__module__, - _pretty_fixture_path(fixturedef.func), + _pretty_fixture_path(invocation_dir, fixturedef.func), fixturedef.argname, fixturedef, ) From 111ad26f714b05166b473a01823be9f7a21d306d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 18 Jan 2024 21:37:42 +0200 Subject: [PATCH 0388/1271] doc/writing_plugins: correct inaccuracies re. initial conftest loading --- doc/en/how-to/writing_plugins.rst | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/doc/en/how-to/writing_plugins.rst b/doc/en/how-to/writing_plugins.rst index d907ae398b4..4bb6d183333 100644 --- a/doc/en/how-to/writing_plugins.rst +++ b/doc/en/how-to/writing_plugins.rst @@ -46,24 +46,18 @@ Plugin discovery order at tool startup 5. by loading all plugins specified through the :envvar:`PYTEST_PLUGINS` environment variable. -6. by loading all :file:`conftest.py` files as inferred by the command line - invocation: +6. by loading all "initial ":file:`conftest.py` files: - - if no test paths are specified, use the current dir as a test path - - if exists, load ``conftest.py`` and ``test*/conftest.py`` relative - to the directory part of the first test path. After the ``conftest.py`` - file is loaded, load all plugins specified in its - :globalvar:`pytest_plugins` variable if present. + - determine the test paths: specified on the command line, otherwise in + :confval:`testpaths` if defined and running from the rootdir, otherwise the + current dir + - for each test path, load ``conftest.py`` and ``test*/conftest.py`` relative + to the directory part of the test path, if exist. Before a ``conftest.py`` + file is loaded, load ``conftest.py`` files in all of its parent directories. + After a ``conftest.py`` file is loaded, recursively load all plugins specified + in its :globalvar:`pytest_plugins` variable if present. - Note that pytest does not find ``conftest.py`` files in deeper nested - sub directories at tool startup. It is usually a good idea to keep - your ``conftest.py`` file in the top level test or project root directory. -7. by recursively loading all plugins specified by the - :globalvar:`pytest_plugins` variable in ``conftest.py`` files. - - -.. _`pytest/plugin`: http://bitbucket.org/pytest-dev/pytest/src/tip/pytest/plugin/ .. _`conftest.py plugins`: .. _`localplugin`: .. _`local conftest plugins`: @@ -108,9 +102,9 @@ Here is how you might run it:: See also: :ref:`pythonpath`. .. note:: - Some hooks should be implemented only in plugins or conftest.py files situated at the - tests root directory due to how pytest discovers plugins during startup, - see the documentation of each hook for details. + Some hooks cannot be implemented in conftest.py files which are not + :ref:`initial ` due to how pytest discovers plugins during + startup. See the documentation of each hook for details. Writing your own plugin ----------------------- From d71ef04f117faf97eab2d83ddba935e6ac77c3c2 Mon Sep 17 00:00:00 2001 From: clee2000 <44682903+clee2000@users.noreply.github.com> Date: Thu, 18 Jan 2024 17:08:26 -0800 Subject: [PATCH 0389/1271] Escape skip reason in junitxml (#11842) Co-authored-by: Bruno Oliveira --- changelog/11842.bugfix.rst | 1 + src/_pytest/junitxml.py | 4 +++- testing/test_junitxml.py | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 changelog/11842.bugfix.rst diff --git a/changelog/11842.bugfix.rst b/changelog/11842.bugfix.rst new file mode 100644 index 00000000000..3a11b110f44 --- /dev/null +++ b/changelog/11842.bugfix.rst @@ -0,0 +1 @@ +Properly escape the ``reason`` of a :ref:`skip ` mark when writing JUnit XML files. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 9ee35b84e84..c8032e158da 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -248,7 +248,9 @@ def append_skipped(self, report: TestReport) -> None: skipreason = skipreason[9:] details = f"{filename}:{lineno}: {skipreason}" - skipped = ET.Element("skipped", type="pytest.skip", message=skipreason) + skipped = ET.Element( + "skipped", type="pytest.skip", message=bin_xml_escape(skipreason) + ) skipped.text = bin_xml_escape(details) self.append(skipped) self.write_captured_output(report) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 3f88c21e2b7..b0c2d1c6d4e 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1653,6 +1653,23 @@ def test_skip(): snode.assert_attr(message="1 <> 2") +def test_bin_escaped_skipreason(pytester: Pytester, run_and_parse: RunAndParse) -> None: + """Escape special characters from mark.skip reason (#11842).""" + pytester.makepyfile( + """ + import pytest + @pytest.mark.skip("\33[31;1mred\33[0m") + def test_skip(): + pass + """ + ) + _, dom = run_and_parse() + node = dom.find_first_by_tag("testcase") + snode = node.find_first_by_tag("skipped") + assert "#x1B[31;1mred#x1B[0m" in snode.text + snode.assert_attr(message="#x1B[31;1mred#x1B[0m") + + def test_escaped_setup_teardown_error( pytester: Pytester, run_and_parse: RunAndParse ) -> None: From 79ae9681315fc847db36aa53ea8d5088dd61eb63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:11:09 -0300 Subject: [PATCH 0390/1271] build(deps): Bump actions/cache from 3 to 4 (#11852) Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 349d5f52977..214d734c974 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -30,7 +30,7 @@ jobs: python-version: "3.11" cache: pip - name: requests-cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/.cache/pytest-plugin-list/ key: plugins-http-cache-${{ github.run_id }} # Can use time based key as well From 21440521fac9d8702d43ef63ccdf8e035ae46bc3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:14:58 -0300 Subject: [PATCH 0391/1271] [automated] Update plugin list (#11848) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 124 +++++++++++++++---------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index dceb3cf155e..9321ca852ea 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -71,13 +71,13 @@ This list contains 1359 plugins. :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jan 10, 2024 5 - Production/Stable pytest >=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jan 18, 2024 5 - Production/Stable pytest >=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A :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-anything` Pytest fixtures to assert anything and something Jan 18, 2024 N/A pytest :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) @@ -105,7 +105,7 @@ This list contains 1359 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 Jan 10, 2024 4 - Beta pytest >=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Jan 16, 2024 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) @@ -190,7 +190,7 @@ This list contains 1359 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 08, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 14, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A @@ -198,7 +198,7 @@ This list contains 1359 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 08, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 18, 2024 N/A pytest>=7.0.0 :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -412,14 +412,14 @@ This list contains 1359 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. Jan 04, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 04, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 04, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 04, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 04, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 04, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 04, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jan 18, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 18, 2024 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) @@ -573,10 +573,10 @@ This list contains 1359 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-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jan 13, 2024 3 - Alpha pytest ==7.4.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jan 20, 2024 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` Jan 06, 2024 N/A N/A @@ -589,7 +589,7 @@ This list contains 1359 plugins. :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Nov 11, 2023 N/A N/A - :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Jan 05, 2024 5 - Production/Stable N/A + :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Jan 17, 2024 5 - Production/Stable N/A :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A :pypi:`pytest-html-report-merger` Oct 23, 2023 N/A N/A @@ -730,7 +730,7 @@ This list contains 1359 plugins. :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A - :pypi:`pytest-matcher` Keep a ChangeLog Jan 11, 2024 5 - Production/Stable pytest + :pypi:`pytest-matcher` Keep a ChangeLog Jan 15, 2024 5 - Production/Stable pytest :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -740,7 +740,7 @@ This list contains 1359 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Oct 08, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 - :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Dec 07, 2023 N/A pytest (>=7.4.3) + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Jan 19, 2024 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 @@ -751,7 +751,7 @@ This list contains 1359 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 Dec 07, 2023 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Jan 16, 2024 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) @@ -901,7 +901,7 @@ This list contains 1359 plugins. :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A :pypi:`pytest-plone` Pytest plugin to test Plone addons Jan 05, 2023 3 - Alpha pytest - :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Aug 17, 2020 5 - Production/Stable pytest + :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Jan 10, 2024 5 - Production/Stable pytest >=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A @@ -915,7 +915,7 @@ This list contains 1359 plugins. :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pook` Pytest plugin for pook Dec 23, 2023 4 - Beta pytest :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-porringer` Jan 12, 2024 N/A pytest>=7.4.4 + :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) @@ -984,7 +984,7 @@ This list contains 1359 plugins. :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Aug 15, 2023 5 - Production/Stable pytest :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A - :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Dec 03, 2022 5 - Production/Stable pytest (>=3.0.0) + :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 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. 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 @@ -998,7 +998,7 @@ This list contains 1359 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 - :pypi:`pytest-regtest` "pytest plugin for snapshot regression testing" Jan 06, 2024 N/A pytest>7.2 + :pypi:`pytest-regtest` "pytest plugin for snapshot regression testing" Jan 15, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A @@ -1077,7 +1077,7 @@ This list contains 1359 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 19, 2024 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) @@ -1086,7 +1086,7 @@ This list contains 1359 plugins. :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 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. Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jan 19, 2024 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 @@ -1173,7 +1173,7 @@ This list contains 1359 plugins. :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A - :pypi:`pytest-static` pytest-static Sep 03, 2023 1 - Planning N/A + :pypi:`pytest-static` pytest-static Jan 15, 2024 1 - Planning pytest (>=7.4.3,<8.0.0) :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A @@ -1200,7 +1200,6 @@ This list contains 1359 plugins. :pypi:`pytest-synodic` Synodic Pytest utilities Jan 12, 2024 N/A pytest>=7.4.4 :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A - :pypi:`pytest-tagging` a pytest plugin to tag tests Apr 01, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) @@ -1390,6 +1389,7 @@ This list contains 1359 plugins. :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jan 08, 2024 5 - Production/Stable pytest (>=4.5.0) + :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Jan 16, 2024 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest @@ -1658,7 +1658,7 @@ This list contains 1359 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Jan 10, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=6 @@ -1700,7 +1700,7 @@ This list contains 1359 plugins. The pytest anyio plugin is built into anyio. You don't need this package. :pypi:`pytest-anything` - *last release*: Oct 13, 2022, + *last release*: Jan 18, 2024, *status*: N/A, *requires*: pytest @@ -1896,7 +1896,7 @@ This list contains 1359 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jan 10, 2024, + *last release*: Jan 16, 2024, *status*: 4 - Beta, *requires*: pytest >=7.0.0 @@ -2491,7 +2491,7 @@ This list contains 1359 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Jan 08, 2024, + *last release*: Jan 14, 2024, *status*: N/A, *requires*: N/A @@ -2547,7 +2547,7 @@ This list contains 1359 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Jan 08, 2024, + *last release*: Jan 18, 2024, *status*: N/A, *requires*: pytest>=7.0.0 @@ -4045,56 +4045,56 @@ This list contains 1359 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jan 04, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jan 04, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jan 04, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jan 04, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jan 04, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jan 04, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jan 04, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Jan 04, 2024, + *last release*: Jan 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5172,7 +5172,7 @@ This list contains 1359 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, + *last release*: Jan 14, 2024, *status*: N/A, *requires*: pytest (>=7.4.3,<8.0.0) @@ -5193,7 +5193,7 @@ This list contains 1359 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jan 13, 2024, + *last release*: Jan 20, 2024, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5284,7 +5284,7 @@ This list contains 1359 plugins. Pytest HTML reports merging utility :pypi:`pytest-html-object-storage` - *last release*: Jan 05, 2024, + *last release*: Jan 17, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6271,7 +6271,7 @@ This list contains 1359 plugins. UNKNOWN :pypi:`pytest-matcher` - *last release*: Jan 11, 2024, + *last release*: Jan 15, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -6341,7 +6341,7 @@ This list contains 1359 plugins. A pytest plugin to make a test results report with Markdown table format. :pypi:`pytest-meilisearch` - *last release*: Dec 07, 2023, + *last release*: Jan 19, 2024, *status*: N/A, *requires*: pytest (>=7.4.3) @@ -6418,7 +6418,7 @@ This list contains 1359 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Dec 07, 2023, + *last release*: Jan 16, 2024, *status*: N/A, *requires*: pytest @@ -7468,7 +7468,7 @@ This list contains 1359 plugins. Pytest plugin to test Plone addons :pypi:`pytest-plt` - *last release*: Aug 17, 2020, + *last release*: Jan 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -7566,7 +7566,7 @@ This list contains 1359 plugins. A pytest plugin to help with testing pop projects :pypi:`pytest-porringer` - *last release*: Jan 12, 2024, + *last release*: Jan 18, 2024, *status*: N/A, *requires*: pytest>=7.4.4 @@ -8049,9 +8049,9 @@ This list contains 1359 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-random-order` - *last release*: Dec 03, 2022, + *last release*: Jan 20, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.0.0) + *requires*: pytest >=3.0.0 Randomise the order in which pytest tests are run with some control over the randomness @@ -8147,7 +8147,7 @@ This list contains 1359 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Jan 06, 2024, + *last release*: Jan 15, 2024, *status*: N/A, *requires*: pytest>7.2 @@ -8700,7 +8700,7 @@ This list contains 1359 plugins. :pypi:`pytest-sbase` - *last release*: Jan 04, 2024, + *last release*: Jan 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8763,7 +8763,7 @@ This list contains 1359 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jan 04, 2024, + *last release*: Jan 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9372,9 +9372,9 @@ This list contains 1359 plugins. A package to prevent Dependency Confusion attacks against Yandex. :pypi:`pytest-static` - *last release*: Sep 03, 2023, + *last release*: Jan 15, 2024, *status*: 1 - Planning, - *requires*: N/A + *requires*: pytest (>=7.4.3,<8.0.0) pytest-static @@ -9560,13 +9560,6 @@ This list contains 1359 plugins. Pyst - Pytest System-Test Plugin - :pypi:`pytest-tagging` - *last release*: Apr 01, 2023, - *status*: N/A, - *requires*: pytest (>=7.1.3,<8.0.0) - - a pytest plugin to tag tests - :pypi:`pytest-takeltest` *last release*: Feb 15, 2023, *status*: N/A, @@ -10890,6 +10883,13 @@ This list contains 1359 plugins. Pytest connector for Zebrunner reporting + :pypi:`pytest-zeebe` + *last release*: Jan 16, 2024, + *status*: N/A, + *requires*: pytest (>=7.4.2,<8.0.0) + + Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. + :pypi:`pytest-zest` *last release*: Nov 17, 2022, *status*: N/A, From 5ab8972bb5607bced7c9198296a7dd9fb35e8723 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 22 Jan 2024 16:26:55 +0200 Subject: [PATCH 0392/1271] runner: inline `call_runtest_hook` - Reduce the common stacktrace by an entry - this is mostly for benefit of devs looking at crash logs. - Reduce 6 slow `ihook` calls per test to 3. --- src/_pytest/runner.py | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 3e19f0de50c..01de439903b 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -223,13 +223,26 @@ def pytest_report_teststatus(report: BaseReport) -> Optional[Tuple[str, str, str def call_and_report( item: Item, when: Literal["setup", "call", "teardown"], log: bool = True, **kwds ) -> TestReport: - call = call_runtest_hook(item, when, **kwds) - hook = item.ihook - report: TestReport = hook.pytest_runtest_makereport(item=item, call=call) + ihook = item.ihook + if when == "setup": + runtest_hook: Callable[..., None] = ihook.pytest_runtest_setup + elif when == "call": + runtest_hook = ihook.pytest_runtest_call + elif when == "teardown": + runtest_hook = ihook.pytest_runtest_teardown + else: + assert False, f"Unhandled runtest hook case: {when}" + reraise: Tuple[Type[BaseException], ...] = (Exit,) + if not item.config.getoption("usepdb", False): + reraise += (KeyboardInterrupt,) + call = CallInfo.from_call( + lambda: runtest_hook(item=item, **kwds), when=when, reraise=reraise + ) + report: TestReport = ihook.pytest_runtest_makereport(item=item, call=call) if log: - hook.pytest_runtest_logreport(report=report) + ihook.pytest_runtest_logreport(report=report) if check_interactive_exception(call, report): - hook.pytest_exception_interact(node=item, call=call, report=report) + ihook.pytest_exception_interact(node=item, call=call, report=report) return report @@ -248,25 +261,6 @@ def check_interactive_exception(call: "CallInfo[object]", report: BaseReport) -> return True -def call_runtest_hook( - item: Item, when: Literal["setup", "call", "teardown"], **kwds -) -> "CallInfo[None]": - if when == "setup": - ihook: Callable[..., None] = item.ihook.pytest_runtest_setup - elif when == "call": - ihook = item.ihook.pytest_runtest_call - elif when == "teardown": - ihook = item.ihook.pytest_runtest_teardown - else: - assert False, f"Unhandled runtest hook case: {when}" - reraise: Tuple[Type[BaseException], ...] = (Exit,) - if not item.config.getoption("usepdb", False): - reraise += (KeyboardInterrupt,) - return CallInfo.from_call( - lambda: ihook(item=item, **kwds), when=when, reraise=reraise - ) - - TResult = TypeVar("TResult", covariant=True) From 44bf7a2ec0b52b60089ebd8439f64487df079214 Mon Sep 17 00:00:00 2001 From: Joachim B Haga Date: Mon, 22 Jan 2024 22:29:14 +0100 Subject: [PATCH 0393/1271] Mark some xfails from #10042 as non-strict (#11832) Related to #10042, some tests in `test_debugging.py` are actually flaky and should not be considered strict xfailures. --- testing/test_debugging.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/testing/test_debugging.py b/testing/test_debugging.py index eecc1e39fd3..ea3367e5791 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -372,7 +372,7 @@ def test_pdb_prevent_ConftestImportFailure_hiding_exception( result = pytester.runpytest_subprocess("--pdb", ".") result.stdout.fnmatch_lines(["-> import unknown"]) - @pytest.mark.xfail(reason="#10042") + @pytest.mark.xfail(reason="#10042", strict=False) def test_pdb_interaction_capturing_simple(self, pytester: Pytester) -> None: p1 = pytester.makepyfile( """ @@ -541,7 +541,7 @@ def function_1(): assert "BdbQuit" not in rest assert "UNEXPECTED EXCEPTION" not in rest - @pytest.mark.xfail(reason="#10042") + @pytest.mark.xfail(reason="#10042", strict=False) def test_pdb_interaction_capturing_twice(self, pytester: Pytester) -> None: p1 = pytester.makepyfile( """ @@ -577,7 +577,7 @@ def test_1(): assert "1 failed" in rest self.flush(child) - @pytest.mark.xfail(reason="#10042") + @pytest.mark.xfail(reason="#10042", strict=False) def test_pdb_with_injected_do_debug(self, pytester: Pytester) -> None: """Simulates pdbpp, which injects Pdb into do_debug, and uses self.__class__ in do_continue. @@ -1022,7 +1022,7 @@ def test_1(): assert "reading from stdin while output" not in rest TestPDB.flush(child) - @pytest.mark.xfail(reason="#10042") + @pytest.mark.xfail(reason="#10042", strict=False) def test_pdb_not_altered(self, pytester: Pytester) -> None: p1 = pytester.makepyfile( """ @@ -1182,7 +1182,7 @@ def test_2(): @pytest.mark.parametrize("fixture", ("capfd", "capsys")) -@pytest.mark.xfail(reason="#10042") +@pytest.mark.xfail(reason="#10042", strict=False) def test_pdb_suspends_fixture_capturing(pytester: Pytester, fixture: str) -> None: """Using "-s" with pytest should suspend/resume fixture capturing.""" p1 = pytester.makepyfile( From d97295730330f7686a155dd6482405ad4a823b1d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 23 Jan 2024 16:08:16 +0200 Subject: [PATCH 0394/1271] hookspec: document conftest behavior for all hooks (#9496) Have each hook explain how implementing it in conftests works. This is part of the functional specification of a hook. --- src/_pytest/hookspec.py | 340 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 315 insertions(+), 25 deletions(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index c4cce2d838d..83c9be3ef6b 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -58,6 +58,12 @@ def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: .. note:: This hook is incompatible with hook wrappers. + + Use in conftest plugins + ======================= + + If a conftest plugin implements this hook, it will be called immediately + when the conftest is registered. """ @@ -75,6 +81,14 @@ def pytest_plugin_registered( .. note:: This hook is incompatible with hook wrappers. + + Use in conftest plugins + ======================= + + If a conftest plugin implements this hook, it will be called immediately + when the conftest is registered, once for each plugin registered thus far + (including itself!), and for all plugins thereafter when they are + registered. """ @@ -83,12 +97,6 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> """Register argparse-style options and ini-style config values, called once at the beginning of a test run. - .. note:: - - This function should be implemented only in plugins or ``conftest.py`` - files situated at the tests root directory due to how pytest - :ref:`discovers plugins during startup `. - :param parser: To add command line options, call :py:func:`parser.addoption(...) `. @@ -114,6 +122,14 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> .. note:: This hook is incompatible with hook wrappers. + + Use in conftest plugins + ======================= + + If a conftest plugin implements this hook, it will be called immediately + when the conftest is registered. + + This hook is only called for :ref:`initial conftests `. """ @@ -121,16 +137,17 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> def pytest_configure(config: "Config") -> None: """Allow plugins and conftest files to perform initial configuration. - This hook is called for every plugin and initial conftest file - after command line options have been parsed. - - After that, the hook is called for other conftest files as they are - imported. - .. note:: This hook is incompatible with hook wrappers. :param config: The pytest config object. + + Use in conftest plugins + ======================= + + This hook is called for every :ref:`initial conftest ` file + after command line options have been parsed. After that, the hook is called + for other conftest files as they are registered. """ @@ -149,28 +166,35 @@ def pytest_cmdline_parse( Stops at first non-None result, see :ref:`firstresult`. .. note:: - This hook will only be called for plugin classes passed to the + This hook is only called for plugin classes passed to the ``plugins`` arg when using `pytest.main`_ to perform an in-process test run. :param pluginmanager: The pytest plugin manager. :param args: List of arguments passed on the command line. :returns: A pytest config object. + + Use in conftest plugins + ======================= + + This hook is not called for conftest files. """ def pytest_load_initial_conftests( early_config: "Config", parser: "Parser", args: List[str] ) -> None: - """Called to implement the loading of initial conftest files ahead - of command line option parsing. - - .. note:: - This hook will not be called for ``conftest.py`` files, only for setuptools plugins. + """Called to implement the loading of :ref:`initial conftest files + ` ahead of command line option parsing. :param early_config: The pytest config object. :param args: Arguments passed on the command line. :param parser: To add command line options. + + Use in conftest plugins + ======================= + + This hook is not called for conftest files. """ @@ -185,6 +209,11 @@ def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]: :param config: The pytest config object. :returns: The exit code. + + Use in conftest plugins + ======================= + + This hook is only called for :ref:`initial conftests `. """ @@ -227,6 +256,11 @@ def pytest_collection(session: "Session") -> Optional[object]: counter (and returns `None`). :param session: The pytest session object. + + Use in conftest plugins + ======================= + + This hook is only called for :ref:`initial conftests `. """ @@ -239,6 +273,11 @@ def pytest_collection_modifyitems( :param session: The pytest session object. :param config: The pytest config object. :param items: List of item objects. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -246,6 +285,11 @@ def pytest_collection_finish(session: "Session") -> None: """Called after collection has been performed and modified. :param session: The pytest session object. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -268,6 +312,14 @@ def pytest_ignore_collect(collection_path: Path, config: "Config") -> Optional[b .. versionchanged:: 8.0.0 The ``path`` parameter has been removed. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collection path, only + conftest files in parent directories of the collection path are consulted + (if the path is a directory, its own conftest file is *not* consulted - a + directory cannot ignore itself!). """ @@ -289,6 +341,14 @@ def pytest_collect_directory(path: Path, parent: "Collector") -> "Optional[Colle See :ref:`custom directory collectors` for a simple example of use of this hook. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collection path, only + conftest files in parent directories of the collection path are consulted + (if the path is a directory, its own conftest file is *not* consulted - a + directory cannot collect itself!). """ @@ -309,6 +369,12 @@ def pytest_collect_file(file_path: Path, parent: "Collector") -> "Optional[Colle .. versionchanged:: 8.0.0 The ``path`` parameter was removed. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given file path, only + conftest files in parent directories of the file path are consulted. """ @@ -320,6 +386,13 @@ def pytest_collectstart(collector: "Collector") -> None: :param collector: The collector. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collector, only + conftest files in the collector's directory and its parent directories are + consulted. """ @@ -328,6 +401,12 @@ def pytest_itemcollected(item: "Item") -> None: :param item: The item. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -336,6 +415,13 @@ def pytest_collectreport(report: "CollectReport") -> None: :param report: The collect report. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collector, only + conftest files in the collector's directory and its parent directories are + consulted. """ @@ -346,6 +432,11 @@ def pytest_deselected(items: Sequence["Item"]) -> None: :param items: The items. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -358,6 +449,13 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor :param collector: The collector. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collector, only + conftest files in the collector's directory and its parent directories are + consulted. """ @@ -385,6 +483,13 @@ def pytest_pycollect_makemodule(module_path: Path, parent) -> Optional["Module"] .. versionchanged:: 8.0.0 The ``path`` parameter has been removed in favor of ``module_path``. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given parent collector, + only conftest files in the collector's directory and its parent directories + are consulted. """ @@ -404,6 +509,13 @@ def pytest_pycollect_makeitem( The object. :returns: The created items/collectors. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given collector, only + conftest files in the collector's directory and its parent directories + are consulted. """ @@ -415,6 +527,13 @@ def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]: :param pyfuncitem: The function item. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only + conftest files in the item's directory and its parent directories + are consulted. """ @@ -423,6 +542,13 @@ def pytest_generate_tests(metafunc: "Metafunc") -> None: :param metafunc: The :class:`~pytest.Metafunc` helper for the test function. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given function definition, + only conftest files in the functions's directory and its parent directories + are consulted. """ @@ -441,6 +567,11 @@ def pytest_make_parametrize_id( :param config: The pytest config object. :param val: The parametrized value. :param argname: The automatic parameter name produced by pytest. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -467,6 +598,11 @@ def pytest_runtestloop(session: "Session") -> Optional[object]: Stops at first non-None result, see :ref:`firstresult`. The return value is not used, but only stops further processing. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -505,6 +641,11 @@ def pytest_runtest_protocol( Stops at first non-None result, see :ref:`firstresult`. The return value is not used, but only stops further processing. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -519,6 +660,12 @@ def pytest_runtest_logstart( :param location: A tuple of ``(filename, lineno, testname)`` where ``filename`` is a file path relative to ``config.rootpath`` and ``lineno`` is 0-based. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -533,6 +680,12 @@ def pytest_runtest_logfinish( :param location: A tuple of ``(filename, lineno, testname)`` where ``filename`` is a file path relative to ``config.rootpath`` and ``lineno`` is 0-based. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -546,6 +699,12 @@ def pytest_runtest_setup(item: "Item") -> None: :param item: The item. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -556,6 +715,12 @@ def pytest_runtest_call(item: "Item") -> None: :param item: The item. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -574,6 +739,12 @@ def pytest_runtest_teardown(item: "Item", nextitem: Optional["Item"]) -> None: scheduled). This argument is used to perform exact teardowns, i.e. calling just enough finalizers so that nextitem only needs to call setup functions. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -590,6 +761,12 @@ def pytest_runtest_makereport( :param call: The :class:`~pytest.CallInfo` for the phase. Stops at first non-None result, see :ref:`firstresult`. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -598,6 +775,12 @@ def pytest_runtest_logreport(report: "TestReport") -> None: of the setup, call and teardown runtest phases of an item. See :hook:`pytest_runtest_protocol` for a description of the runtest protocol. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -611,6 +794,12 @@ def pytest_report_to_serializable( :param config: The pytest config object. :param report: The report. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. The exact details may depend + on the plugin which calls the hook. """ @@ -623,6 +812,12 @@ def pytest_report_from_serializable( :hook:`pytest_report_to_serializable`. :param config: The pytest config object. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. The exact details may depend + on the plugin which calls the hook. """ @@ -650,6 +845,13 @@ def pytest_fixture_setup( If the fixture function returns None, other implementations of this hook function will continue to be called, according to the behavior of the :ref:`firstresult` option. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given fixture, only + conftest files in the fixture scope's directory and its parent directories + are consulted. """ @@ -664,6 +866,13 @@ def pytest_fixture_post_finalizer( The fixture definition object. :param request: The fixture request object. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given fixture, only + conftest files in the fixture scope's directory and its parent directories + are consulted. """ @@ -677,6 +886,11 @@ def pytest_sessionstart(session: "Session") -> None: and entering the run test loop. :param session: The pytest session object. + + Use in conftest plugins + ======================= + + This hook is only called for :ref:`initial conftests `. """ @@ -688,6 +902,11 @@ def pytest_sessionfinish( :param session: The pytest session object. :param exitstatus: The status which pytest will return to the system. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -695,6 +914,11 @@ def pytest_unconfigure(config: "Config") -> None: """Called before test process is exited. :param config: The pytest config object. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. """ @@ -717,6 +941,12 @@ def pytest_assertrepr_compare( :param op: The operator, e.g. `"=="`, `"!="`, `"not in"`. :param left: The left operand. :param right: The right operand. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -745,6 +975,12 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No :param lineno: Line number of the assert statement. :param orig: String with the original assertion. :param expl: String with the assert explanation. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in the item's directory and its parent directories are consulted. """ @@ -769,18 +1005,17 @@ def pytest_report_header( # type:ignore[empty-body] If you want to have your line(s) displayed first, use :ref:`trylast=True `. - .. note:: - - This function should be implemented only in plugins or ``conftest.py`` - files situated at the tests root directory due to how pytest - :ref:`discovers plugins during startup `. - .. versionchanged:: 7.0.0 The ``start_path`` parameter was added as a :class:`pathlib.Path` equivalent of the ``startdir`` parameter. .. versionchanged:: 8.0.0 The ``startdir`` parameter has been removed. + + Use in conftest plugins + ======================= + + This hook is only called for :ref:`initial conftests `. """ @@ -814,6 +1049,11 @@ def pytest_report_collectionfinish( # type:ignore[empty-body] .. versionchanged:: 8.0.0 The ``startdir`` parameter has been removed. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -842,6 +1082,11 @@ def pytest_report_teststatus( # type:ignore[empty-body] :returns: The test status. Stops at first non-None result, see :ref:`firstresult`. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -858,6 +1103,11 @@ def pytest_terminal_summary( .. versionadded:: 4.2 The ``config`` parameter. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -882,7 +1132,8 @@ def pytest_warning_recorded( * ``"runtest"``: during test execution. :param nodeid: - Full id of the item. + Full id of the item. Empty string for warnings that are not specific to + a particular node. :param location: When available, holds information about the execution context of the captured @@ -890,6 +1141,13 @@ def pytest_warning_recorded( when the execution context is at the module level. .. versionadded:: 6.0 + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. If the warning is specific to a + particular node, only conftest files in parent directories of the node are + consulted. """ @@ -913,6 +1171,12 @@ def pytest_markeval_namespace( # type:ignore[empty-body] :param config: The pytest config object. :returns: A dictionary of additional globals to add. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given item, only conftest + files in parent directories of the item are consulted. """ @@ -932,6 +1196,11 @@ def pytest_internalerror( :param excrepr: The exception repr object. :param excinfo: The exception info. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -941,6 +1210,11 @@ def pytest_keyboard_interrupt( """Called for keyboard interrupt. :param excinfo: The exception info. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -967,6 +1241,12 @@ def pytest_exception_interact( The call information. Contains the exception. :param report: The collection or test report. + + Use in conftest plugins + ======================= + + Any conftest file can implement this hook. For a given node, only conftest + files in parent directories of the node are consulted. """ @@ -978,6 +1258,11 @@ def pytest_enter_pdb(config: "Config", pdb: "pdb.Pdb") -> None: :param config: The pytest config object. :param pdb: The Pdb instance. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ @@ -989,4 +1274,9 @@ def pytest_leave_pdb(config: "Config", pdb: "pdb.Pdb") -> None: :param config: The pytest config object. :param pdb: The Pdb instance. + + Use in conftest plugins + ======================= + + Any conftest plugin can implement this hook. """ From bca4bb0738f23f79cbf21f8c36e076d12ef62468 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 24 Jan 2024 13:22:36 +0200 Subject: [PATCH 0395/1271] config: use `pluginmanager.unblock` instead of accessing pluggy's internals The function was added in pluggy 1.4.0. --- .pre-commit-config.yaml | 2 +- setup.cfg | 2 +- src/_pytest/config/__init__.py | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fe6ed99ae1d..26ca339b961 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -64,7 +64,7 @@ repos: additional_dependencies: - iniconfig>=1.1.0 - attrs>=19.2.0 - - pluggy + - pluggy>=1.4.0 - packaging - tomli - types-pkg_resources diff --git a/setup.cfg b/setup.cfg index 02f6031bdc7..9ee64a4e835 100644 --- a/setup.cfg +++ b/setup.cfg @@ -46,7 +46,7 @@ py_modules = py install_requires = iniconfig packaging - pluggy>=1.3.0,<2.0 + pluggy>=1.4.0,<2.0 colorama;sys_platform=="win32" exceptiongroup>=1.0.0rc8;python_version<"3.11" tomli>=1.0.0;python_version<"3.11" diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index e4e8f700ab9..6c16ad0b240 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -745,13 +745,10 @@ def consider_pluginarg(self, arg: str) -> None: self.set_blocked("pytest_" + name) else: name = arg - # Unblock the plugin. None indicates that it has been blocked. - # There is no interface with pluggy for this. - if self._name2plugin.get(name, -1) is None: - del self._name2plugin[name] + # Unblock the plugin. + self.unblock(name) if not name.startswith("pytest_"): - if self._name2plugin.get("pytest_" + name, -1) is None: - del self._name2plugin["pytest_" + name] + self.unblock("pytest_" + name) self.import_plugin(arg, consider_entry_points=True) def consider_conftest( From eb9013d42c97c61e234aadff9651d4cedb83eae3 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 25 Jan 2024 17:33:23 +0200 Subject: [PATCH 0396/1271] pathlib: speed up `make_numbered_dir` given a large tmp root The function currently uses `find_suffixes` which iterates the entire directory searching for files with the given suffix. In some cases though, like in pytest's selftest, the directory can get big: $ ls /tmp/pytest-of-ran/pytest-0/ 7686 and iterating it many times can get slow. This doesn't fix the underlying issue (iterating the directory) but at least speeds it up a bit by using `os.scandir` instead of `path.iterdir`. So `make_numbered_dir` is still slow for pytest's selftests, but reduces ~10s for me. --- src/_pytest/pathlib.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 4cd635ed7e1..ce5156b06eb 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -171,23 +171,23 @@ def rm_rf(path: Path) -> None: shutil.rmtree(str(path), onerror=onerror) -def find_prefixed(root: Path, prefix: str) -> Iterator[Path]: +def find_prefixed(root: Path, prefix: str) -> Iterator["os.DirEntry[str]"]: """Find all elements in root that begin with the prefix, case insensitive.""" l_prefix = prefix.lower() - for x in root.iterdir(): + for x in os.scandir(root): if x.name.lower().startswith(l_prefix): yield x -def extract_suffixes(iter: Iterable[PurePath], prefix: str) -> Iterator[str]: +def extract_suffixes(iter: Iterable["os.DirEntry[str]"], prefix: str) -> Iterator[str]: """Return the parts of the paths following the prefix. :param iter: Iterator over path names. :param prefix: Expected prefix of the path names. """ p_len = len(prefix) - for p in iter: - yield p.name[p_len:] + for entry in iter: + yield entry.name[p_len:] def find_suffixes(root: Path, prefix: str) -> Iterator[str]: @@ -346,12 +346,12 @@ def cleanup_candidates(root: Path, prefix: str, keep: int) -> Iterator[Path]: """List candidates for numbered directories to be removed - follows py.path.""" max_existing = max(map(parse_num, find_suffixes(root, prefix)), default=-1) max_delete = max_existing - keep - paths = find_prefixed(root, prefix) - paths, paths2 = itertools.tee(paths) - numbers = map(parse_num, extract_suffixes(paths2, prefix)) - for path, number in zip(paths, numbers): + entries = find_prefixed(root, prefix) + entries, entries2 = itertools.tee(entries) + numbers = map(parse_num, extract_suffixes(entries2, prefix)) + for entry, number in zip(entries, numbers): if number <= max_delete: - yield path + yield Path(entry) def cleanup_dead_symlinks(root: Path): From a164ed6400b675118ba499304ba94a65b8cf9bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C6=B0=C6=A1ng=20Qu=E1=BB=91c=20Kh=C3=A1nh?= Date: Sat, 27 Jan 2024 22:40:31 +0900 Subject: [PATCH 0397/1271] logging: avoid rounding microsecond to `1_000_000` (#11861) Rounding microsecond might cause it to reach `1_000_000`, which raises a TypeError. --- changelog/11861.bugfix.rst | 1 + src/_pytest/logging.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/11861.bugfix.rst diff --git a/changelog/11861.bugfix.rst b/changelog/11861.bugfix.rst new file mode 100644 index 00000000000..a2734d79924 --- /dev/null +++ b/changelog/11861.bugfix.rst @@ -0,0 +1 @@ +Avoid microsecond exceeds ``1_000_000`` when using ``log-date-format`` with ``%f`` specifier, which might cause the test suite to crash. diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 5426c35131f..d7e498d5563 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -71,7 +71,8 @@ def formatTime(self, record: LogRecord, datefmt: Optional[str] = None) -> str: tz = timezone(timedelta(seconds=ct.tm_gmtoff), ct.tm_zone) # Construct `datetime.datetime` object from `struct_time` # and msecs information from `record` - dt = datetime(*ct[0:6], microsecond=round(record.msecs * 1000), tzinfo=tz) + # Using int() instead of round() to avoid it exceeding 1_000_000 and causing a ValueError (#11861). + dt = datetime(*ct[0:6], microsecond=int(record.msecs * 1000), tzinfo=tz) return dt.strftime(datefmt) # Use `logging.Formatter` for non-microsecond formats return super().formatTime(record, datefmt) From c6da0d20d2d1ebc1b69a013d9ff2555c93d890f3 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 27 Jan 2024 23:55:26 +0200 Subject: [PATCH 0398/1271] Merge pull request #11864 from bluetech/release-8.0.0 Prepare release version 8.0.0 (cherry picked from commit 24c681d4eeaad22ba26c5bcf6958e0476ae37a89) --- changelog/11842.bugfix.rst | 1 - changelog/11861.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.0.0.rst | 26 ++++++++++++++++++++++++++ doc/en/builtin.rst | 8 ++++---- doc/en/changelog.rst | 12 ++++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 10 files changed, 50 insertions(+), 13 deletions(-) delete mode 100644 changelog/11842.bugfix.rst delete mode 100644 changelog/11861.bugfix.rst create mode 100644 doc/en/announce/release-8.0.0.rst diff --git a/changelog/11842.bugfix.rst b/changelog/11842.bugfix.rst deleted file mode 100644 index 3a11b110f44..00000000000 --- a/changelog/11842.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Properly escape the ``reason`` of a :ref:`skip ` mark when writing JUnit XML files. diff --git a/changelog/11861.bugfix.rst b/changelog/11861.bugfix.rst deleted file mode 100644 index a2734d79924..00000000000 --- a/changelog/11861.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Avoid microsecond exceeds ``1_000_000`` when using ``log-date-format`` with ``%f`` specifier, which might cause the test suite to crash. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 1c413de7a44..120aae6626e 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.0.0 release-8.0.0rc2 release-8.0.0rc1 release-7.4.4 diff --git a/doc/en/announce/release-8.0.0.rst b/doc/en/announce/release-8.0.0.rst new file mode 100644 index 00000000000..00f54fd8225 --- /dev/null +++ b/doc/en/announce/release-8.0.0.rst @@ -0,0 +1,26 @@ +pytest-8.0.0 +======================================= + +The pytest team is proud to announce the 8.0.0 release! + +This release contains new features, improvements, bug fixes, and breaking changes, so users +are encouraged to take a look at the CHANGELOG carefully: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 2acbce96606..c565a87c469 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -129,7 +129,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a if pytestconfig.getoption("verbose") > 0: ... - record_property -- .../_pytest/junitxml.py:282 + record_property -- .../_pytest/junitxml.py:284 Add extra properties to the calling test. User properties become part of the test report and are available to the @@ -143,13 +143,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a def test_function(record_property): record_property("example_key", 1) - record_xml_attribute -- .../_pytest/junitxml.py:305 + record_xml_attribute -- .../_pytest/junitxml.py:307 Add extra xml attributes to the tag for the calling test. The fixture is callable with ``name, value``. The value is automatically XML-encoded. - record_testsuite_property [session scope] -- .../_pytest/junitxml.py:343 + record_testsuite_property [session scope] -- .../_pytest/junitxml.py:345 Record a new ```` tag as child of the root ````. This is suitable to writing global information regarding the entire test @@ -196,7 +196,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:593 + caplog -- .../_pytest/logging.py:594 Access and control log capturing. Captured logs are available through the following properties/methods:: diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index da275b622c4..fc36a5dcf0d 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,18 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.0.0 (2024-01-27) +========================= + +Bug Fixes +--------- + +- `#11842 `_: Properly escape the ``reason`` of a :ref:`skip ` mark when writing JUnit XML files. + + +- `#11861 `_: Avoid microsecond exceeds ``1_000_000`` when using ``log-date-format`` with ``%f`` specifier, which might cause the test suite to crash. + + pytest 8.0.0rc2 (2024-01-17) ============================ diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 9d78fc40323..207aa145bc6 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index e98f1a75245..89acb7d3b65 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 90765df6099..48af9d9754e 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.0.0rc2 + pytest 8.0.0 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index e3209c77717..ade0d809e38 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From 878af85aefc5a2a255395d66a38a2136aeaeb086 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 28 Jan 2024 10:12:42 -0300 Subject: [PATCH 0399/1271] mypy: disallow untyped defs by default (#11862) Change our mypy configuration to disallow untyped defs by default, which ensures *new* files added to the code base are fully typed. To avoid having to type-annotate everything now, add `# mypy: allow-untyped-defs` to files which are not fully type annotated yet. As we fully type annotate those modules, we can then just remove that directive from the top. --- setup.cfg | 1 + src/_pytest/_code/code.py | 1 + src/_pytest/_code/source.py | 1 + src/_pytest/_io/pprint.py | 1 + src/_pytest/_py/path.py | 1 + src/_pytest/assertion/__init__.py | 1 + src/_pytest/assertion/util.py | 1 + src/_pytest/cacheprovider.py | 1 + src/_pytest/capture.py | 1 + src/_pytest/compat.py | 1 + src/_pytest/config/__init__.py | 1 + src/_pytest/config/argparsing.py | 1 + src/_pytest/debugging.py | 1 + src/_pytest/doctest.py | 1 + src/_pytest/fixtures.py | 1 + src/_pytest/helpconfig.py | 1 + src/_pytest/hookspec.py | 1 + src/_pytest/junitxml.py | 1 + src/_pytest/legacypath.py | 1 + src/_pytest/logging.py | 1 + src/_pytest/mark/structures.py | 1 + src/_pytest/monkeypatch.py | 1 + src/_pytest/nodes.py | 1 + src/_pytest/pastebin.py | 1 + src/_pytest/pathlib.py | 1 + src/_pytest/pytester.py | 1 + src/_pytest/python.py | 1 + src/_pytest/python_api.py | 1 + src/_pytest/recwarn.py | 1 + src/_pytest/reports.py | 1 + src/_pytest/runner.py | 1 + src/_pytest/skipping.py | 1 + src/_pytest/terminal.py | 1 + src/_pytest/tmpdir.py | 1 + src/_pytest/unittest.py | 1 + src/_pytest/warnings.py | 1 + testing/_py/test_local.py | 1 + testing/acceptance_test.py | 1 + testing/code/test_code.py | 1 + testing/code/test_excinfo.py | 1 + testing/code/test_source.py | 1 + testing/conftest.py | 1 + testing/deprecated_test.py | 1 + .../example_scripts/acceptance/fixture_mock_integration.py | 1 + .../collect/collect_init_tests/tests/__init__.py | 1 + .../collect/collect_init_tests/tests/test_foo.py | 1 + .../collect/package_infinite_recursion/conftest.py | 1 + .../collect/package_infinite_recursion/tests/test_basic.py | 1 + .../collect/package_init_given_as_arg/pkg/__init__.py | 1 + .../collect/package_init_given_as_arg/pkg/test_foo.py | 1 + .../example_scripts/config/collect_pytest_prefix/test_foo.py | 1 + testing/example_scripts/conftest_usageerror/conftest.py | 1 + testing/example_scripts/customdirectory/conftest.py | 1 + testing/example_scripts/customdirectory/tests/test_first.py | 1 + testing/example_scripts/customdirectory/tests/test_second.py | 1 + testing/example_scripts/customdirectory/tests/test_third.py | 1 + testing/example_scripts/dataclasses/test_compare_initvar.py | 1 + .../dataclasses/test_compare_recursive_dataclasses.py | 1 + testing/example_scripts/doctest/main_py/__main__.py | 1 + .../example_scripts/doctest/main_py/test_normal_module.py | 1 + testing/example_scripts/fixtures/custom_item/conftest.py | 1 + testing/example_scripts/fixtures/custom_item/foo/test_foo.py | 1 + .../sub1/conftest.py | 1 + .../sub1/test_in_sub1.py | 1 + .../sub2/conftest.py | 1 + .../sub2/test_in_sub2.py | 1 + .../fill_fixtures/test_detect_recursive_dependency_error.py | 1 + .../test_extend_fixture_conftest_conftest/conftest.py | 1 + .../test_extend_fixture_conftest_conftest/pkg/conftest.py | 1 + .../test_extend_fixture_conftest_conftest/pkg/test_spam.py | 1 + .../test_extend_fixture_conftest_module/conftest.py | 1 + .../test_extend_fixture_conftest_module.py | 1 + .../fill_fixtures/test_extend_fixture_module_class.py | 1 + .../fixtures/fill_fixtures/test_funcarg_basic.py | 1 + .../fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py | 1 + .../fill_fixtures/test_funcarg_lookup_modulelevel.py | 1 + .../fixtures/fill_fixtures/test_funcarg_lookupfails.py | 1 + .../example_scripts/fixtures/test_fixture_named_request.py | 1 + .../example_scripts/fixtures/test_getfixturevalue_dynamic.py | 1 + .../issue88_initial_file_multinodes/conftest.py | 1 + .../issue88_initial_file_multinodes/test_hello.py | 1 + testing/example_scripts/issue_519.py | 1 + .../marks_considered_keywords/test_marks_as_keywords.py | 1 + .../perf_examples/collect_stats/generate_folders.py | 1 + .../perf_examples/collect_stats/template_test.py | 1 + testing/example_scripts/tmpdir/tmp_path_fixture.py | 1 + .../unittest/test_parametrized_fixture_error_message.py | 1 + testing/example_scripts/unittest/test_setup_skip.py | 1 + testing/example_scripts/unittest/test_setup_skip_class.py | 1 + testing/example_scripts/unittest/test_setup_skip_module.py | 1 + testing/example_scripts/unittest/test_unittest_asyncio.py | 1 + testing/example_scripts/unittest/test_unittest_asynctest.py | 1 + .../example_scripts/unittest/test_unittest_plain_async.py | 1 + .../warnings/test_group_warnings_by_message.py | 1 + .../test_group_warnings_by_message_summary/test_1.py | 1 + .../test_group_warnings_by_message_summary/test_2.py | 1 + testing/freeze/tests/test_trivial.py | 1 + testing/io/test_saferepr.py | 1 + testing/io/test_terminalwriter.py | 1 + testing/logging/test_reporting.py | 1 + testing/plugins_integration/bdd_wallet.py | 1 + testing/plugins_integration/pytest_anyio_integration.py | 1 + testing/plugins_integration/pytest_asyncio_integration.py | 1 + testing/plugins_integration/pytest_mock_integration.py | 1 + testing/plugins_integration/pytest_trio_integration.py | 1 + testing/plugins_integration/pytest_twisted_integration.py | 1 + testing/plugins_integration/simple_integration.py | 1 + testing/python/approx.py | 1 + testing/python/collect.py | 1 + testing/python/fixtures.py | 3 ++- testing/python/integration.py | 1 + testing/python/metafunc.py | 1 + testing/python/raises.py | 1 + testing/test_argcomplete.py | 1 + testing/test_assertion.py | 1 + testing/test_assertrewrite.py | 1 + testing/test_cacheprovider.py | 1 + testing/test_capture.py | 1 + testing/test_collection.py | 1 + testing/test_compat.py | 1 + testing/test_config.py | 1 + testing/test_conftest.py | 1 + testing/test_debugging.py | 1 + testing/test_doctest.py | 1 + testing/test_entry_points.py | 1 + testing/test_faulthandler.py | 1 + testing/test_findpaths.py | 1 + testing/test_helpconfig.py | 1 + testing/test_junitxml.py | 1 + testing/test_legacypath.py | 1 + testing/test_link_resolve.py | 1 + testing/test_main.py | 1 + testing/test_mark.py | 1 + testing/test_monkeypatch.py | 1 + testing/test_nodes.py | 1 + testing/test_parseopt.py | 1 + testing/test_pastebin.py | 1 + testing/test_pathlib.py | 1 + testing/test_pluginmanager.py | 1 + testing/test_pytester.py | 1 + testing/test_python_path.py | 1 + testing/test_recwarn.py | 1 + testing/test_reports.py | 1 + testing/test_runner.py | 1 + testing/test_runner_xunit.py | 1 + testing/test_session.py | 1 + testing/test_setuponly.py | 1 + testing/test_skipping.py | 1 + testing/test_stepwise.py | 1 + testing/test_terminal.py | 1 + testing/test_tmpdir.py | 1 + testing/test_unittest.py | 1 + testing/test_warning_types.py | 1 + testing/test_warnings.py | 5 +++-- testing/typing_checks.py | 1 + 155 files changed, 158 insertions(+), 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index 9ee64a4e835..eebce8c7cfd 100644 --- a/setup.cfg +++ b/setup.cfg @@ -94,6 +94,7 @@ formats = sdist.tgz,bdist_wheel mypy_path = src check_untyped_defs = True disallow_any_generics = True +disallow_untyped_defs = True ignore_missing_imports = True show_error_codes = True strict_equality = True diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 0288d7a54f5..d99b5236661 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import ast import dataclasses import inspect diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index cc7ac407e52..efee1fad3bf 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import ast import inspect import textwrap diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 7559c6778df..6ec5d540107 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs # This module was imported from the cpython standard library # (https://github.com/python/cpython/) at commit # c5140945c723ae6c4b7ee81ff720ac8ea4b52cfd (python3.12). diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 24348525a3e..04b1695f174 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """local path implementation.""" from __future__ import annotations diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index e1e7a5e6663..93365697890 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Support for presenting detailed information in failing assertions.""" import sys from typing import Any diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 6f97101a932..d2f67994c30 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Utilities for assertion debugging.""" import collections.abc import os diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 793e796de69..ee68cc38c79 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Implementation of the cache provider.""" # This plugin was not named "cache" to avoid conflicts with the external # pytest-cache version. diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index ebdcaedcea1..c89763344a6 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Per-test stdout/stderr capturing mechanism.""" import abc import collections diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 1e9c38ca8e5..ad8558b1f51 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Python version compatibility code.""" from __future__ import annotations diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 6c16ad0b240..c0e1e195f0d 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Command line options, ini-file and conftest.py processing.""" import argparse import collections.abc diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 39e41760518..a31278f32a0 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import argparse import os import sys diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 57f26d219b3..aaac3e1b9c3 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Interactive debugging with PDB, the Python Debugger.""" import argparse import functools diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 4ce32a298e8..6a5bc75774e 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Discover and run doctests in modules and test files.""" import bdb import functools diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 51c573575ef..d7d8a720bc5 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import abc import dataclasses import functools diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 91ea7699708..4f7d351729d 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Version info, help messages, tracing configuration.""" import os import sys diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 83c9be3ef6b..3c27dcf911a 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Hook specifications for pytest plugins which are invoked by pytest itself and by builtin plugins.""" from pathlib import Path diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index c8032e158da..f01afd91578 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Report test results in JUnit-XML format, for use with Jenkins and build integration servers. diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index f69315b5fed..cb9a3624392 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Add backward compatibility support for the legacy py path type.""" import dataclasses import os diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index d7e498d5563..5565a6b3f9f 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Access and control log capturing.""" import io import logging diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 55ec67700b6..e3580cf6fca 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import collections.abc import dataclasses import inspect diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index 834700b1b4c..01c74d6eb43 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Monkeypatching and mocking functionality.""" import os import re diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 45bbb4b5788..2d6ad7b8fff 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import abc import os import warnings diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 22c7a622373..48470337468 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Submit failure or test session information to a pastebin service.""" import tempfile from io import StringIO diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index ce5156b06eb..929d8c88ea3 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import atexit import contextlib import fnmatch diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index d388758a2d0..69a24c7c90b 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """(Disabled by default) support for testing pytest and pytest plugins. PYTEST_DONT_REWRITE diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 64480c97149..5fa32260b78 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Python test discovery, setup and run of test functions.""" import abc import dataclasses diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index f914d70e83f..c32d75b44b7 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import math import pprint from collections.abc import Collection diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index b3279dd314f..57d4bb47ccc 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Record warnings during test function execution.""" import re import warnings diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 18f1c948afc..ddf7f298321 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import dataclasses import os from io import StringIO diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 01de439903b..44fded69bb1 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Basic collect and runtest protocol implementations.""" import bdb import dataclasses diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 0c5c38f5f1a..617f7bb853c 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Support for skip/xfail functions and markers.""" import dataclasses import os diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index b91a97221cd..42b85b56dbc 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Terminal reporting of the full testing process. This is a good source for looking at the various reporting hooks. diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 21e5366a354..937b1687ab8 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Support for providing temporary directories to test functions.""" import dataclasses import os diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 6bf8f4f2f5b..ce06b7d9bc4 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Discover and run std-library "unittest" style tests.""" import sys import traceback diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index 6ef4fafdce5..de4b0830f98 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import sys import warnings from contextlib import contextmanager diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 77a9838cf11..ba19aef38ae 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import contextlib import multiprocessing import os diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index b875b8f6631..64e65f313f2 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import dataclasses import importlib.metadata import os diff --git a/testing/code/test_code.py b/testing/code/test_code.py index 33809528a06..a59af4a49e6 100644 --- a/testing/code/test_code.py +++ b/testing/code/test_code.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import re import sys from types import FrameType diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 22be51d407e..a9982b4f323 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from __future__ import annotations import importlib diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 260c80299b4..9d0565380e4 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs # flake8: noqa # disable flake check on this file because some constructs are strange # or redundant on purpose and can't be disable on a line-by-line basis diff --git a/testing/conftest.py b/testing/conftest.py index bcb05339b62..0912285d845 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import dataclasses import re import sys diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index ebff49ce6d9..752ccc91be0 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest from _pytest import deprecated from _pytest.pytester import Pytester diff --git a/testing/example_scripts/acceptance/fixture_mock_integration.py b/testing/example_scripts/acceptance/fixture_mock_integration.py index 5b00ac90e1b..d607e959dcd 100644 --- a/testing/example_scripts/acceptance/fixture_mock_integration.py +++ b/testing/example_scripts/acceptance/fixture_mock_integration.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Reproduces issue #3774""" from unittest import mock diff --git a/testing/example_scripts/collect/collect_init_tests/tests/__init__.py b/testing/example_scripts/collect/collect_init_tests/tests/__init__.py index 9cd366295e7..58c41942d1c 100644 --- a/testing/example_scripts/collect/collect_init_tests/tests/__init__.py +++ b/testing/example_scripts/collect/collect_init_tests/tests/__init__.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_init(): pass diff --git a/testing/example_scripts/collect/collect_init_tests/tests/test_foo.py b/testing/example_scripts/collect/collect_init_tests/tests/test_foo.py index 8f2d73cfa4f..d88c001c2cc 100644 --- a/testing/example_scripts/collect/collect_init_tests/tests/test_foo.py +++ b/testing/example_scripts/collect/collect_init_tests/tests/test_foo.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_foo(): pass diff --git a/testing/example_scripts/collect/package_infinite_recursion/conftest.py b/testing/example_scripts/collect/package_infinite_recursion/conftest.py index 973ccc0c030..bba5db8b2fd 100644 --- a/testing/example_scripts/collect/package_infinite_recursion/conftest.py +++ b/testing/example_scripts/collect/package_infinite_recursion/conftest.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def pytest_ignore_collect(collection_path): return False diff --git a/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py b/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py index f174823854e..2809d0cc689 100644 --- a/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py +++ b/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test(): pass diff --git a/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py b/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py index 9cd366295e7..58c41942d1c 100644 --- a/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py +++ b/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_init(): pass diff --git a/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py b/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py index 8f2d73cfa4f..d88c001c2cc 100644 --- a/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py +++ b/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_foo(): pass diff --git a/testing/example_scripts/config/collect_pytest_prefix/test_foo.py b/testing/example_scripts/config/collect_pytest_prefix/test_foo.py index 8f2d73cfa4f..d88c001c2cc 100644 --- a/testing/example_scripts/config/collect_pytest_prefix/test_foo.py +++ b/testing/example_scripts/config/collect_pytest_prefix/test_foo.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_foo(): pass diff --git a/testing/example_scripts/conftest_usageerror/conftest.py b/testing/example_scripts/conftest_usageerror/conftest.py index 8973e4252d3..64bbeefac1d 100644 --- a/testing/example_scripts/conftest_usageerror/conftest.py +++ b/testing/example_scripts/conftest_usageerror/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs def pytest_configure(config): import pytest diff --git a/testing/example_scripts/customdirectory/conftest.py b/testing/example_scripts/customdirectory/conftest.py index 5357014d7ab..fe1c743a686 100644 --- a/testing/example_scripts/customdirectory/conftest.py +++ b/testing/example_scripts/customdirectory/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs # content of conftest.py import json diff --git a/testing/example_scripts/customdirectory/tests/test_first.py b/testing/example_scripts/customdirectory/tests/test_first.py index 0a78de59945..890ca3dea38 100644 --- a/testing/example_scripts/customdirectory/tests/test_first.py +++ b/testing/example_scripts/customdirectory/tests/test_first.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs # content of test_first.py def test_1(): pass diff --git a/testing/example_scripts/customdirectory/tests/test_second.py b/testing/example_scripts/customdirectory/tests/test_second.py index eed724a7d96..42108d5da84 100644 --- a/testing/example_scripts/customdirectory/tests/test_second.py +++ b/testing/example_scripts/customdirectory/tests/test_second.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs # content of test_second.py def test_2(): pass diff --git a/testing/example_scripts/customdirectory/tests/test_third.py b/testing/example_scripts/customdirectory/tests/test_third.py index 61cf59dc16c..ede0f3e6025 100644 --- a/testing/example_scripts/customdirectory/tests/test_third.py +++ b/testing/example_scripts/customdirectory/tests/test_third.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs # content of test_third.py def test_3(): pass diff --git a/testing/example_scripts/dataclasses/test_compare_initvar.py b/testing/example_scripts/dataclasses/test_compare_initvar.py index d859634ddd5..d687fc22530 100644 --- a/testing/example_scripts/dataclasses/test_compare_initvar.py +++ b/testing/example_scripts/dataclasses/test_compare_initvar.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from dataclasses import dataclass from dataclasses import InitVar diff --git a/testing/example_scripts/dataclasses/test_compare_recursive_dataclasses.py b/testing/example_scripts/dataclasses/test_compare_recursive_dataclasses.py index 0945790f004..801aa0a732e 100644 --- a/testing/example_scripts/dataclasses/test_compare_recursive_dataclasses.py +++ b/testing/example_scripts/dataclasses/test_compare_recursive_dataclasses.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from dataclasses import dataclass diff --git a/testing/example_scripts/doctest/main_py/__main__.py b/testing/example_scripts/doctest/main_py/__main__.py index e471d06d643..c8a124f5416 100644 --- a/testing/example_scripts/doctest/main_py/__main__.py +++ b/testing/example_scripts/doctest/main_py/__main__.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_this_is_ignored(): assert True diff --git a/testing/example_scripts/doctest/main_py/test_normal_module.py b/testing/example_scripts/doctest/main_py/test_normal_module.py index 700cc9750cf..26a4d90bc89 100644 --- a/testing/example_scripts/doctest/main_py/test_normal_module.py +++ b/testing/example_scripts/doctest/main_py/test_normal_module.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs def test_doc(): """ >>> 10 > 5 diff --git a/testing/example_scripts/fixtures/custom_item/conftest.py b/testing/example_scripts/fixtures/custom_item/conftest.py index a7a5e9db80a..fe1ae620aa6 100644 --- a/testing/example_scripts/fixtures/custom_item/conftest.py +++ b/testing/example_scripts/fixtures/custom_item/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/custom_item/foo/test_foo.py b/testing/example_scripts/fixtures/custom_item/foo/test_foo.py index f174823854e..2809d0cc689 100644 --- a/testing/example_scripts/fixtures/custom_item/foo/test_foo.py +++ b/testing/example_scripts/fixtures/custom_item/foo/test_foo.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test(): pass diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/conftest.py index be5adbeb6e5..3a5d3ac33fe 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/test_in_sub1.py b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/test_in_sub1.py index df36da1369b..d0c4bdbdfd9 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/test_in_sub1.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/test_in_sub1.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_1(arg1): pass diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/conftest.py index 00981c5dc12..a1f3b2d58b9 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/test_in_sub2.py b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/test_in_sub2.py index 1c34f94acc4..45e9744786a 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/test_in_sub2.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/test_in_sub2.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_2(arg2): pass diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_detect_recursive_dependency_error.py b/testing/example_scripts/fixtures/fill_fixtures/test_detect_recursive_dependency_error.py index d1efcbb338c..84e5256f070 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_detect_recursive_dependency_error.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_detect_recursive_dependency_error.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/conftest.py index 5dfd2f77957..7f1769beb9b 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/conftest.py index 4e22ce5a137..ad26fdd8cdc 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/test_spam.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/test_spam.py index 0d891fbb503..9ee74a47186 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/test_spam.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/test_spam.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_spam(spam): assert spam == "spamspam" diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/conftest.py index 5dfd2f77957..7f1769beb9b 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/test_extend_fixture_conftest_module.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/test_extend_fixture_conftest_module.py index 46d1446f470..fa688f0a844 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/test_extend_fixture_conftest_module.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/test_extend_fixture_conftest_module.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_module_class.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_module_class.py index 87a0c894111..f78a57c322b 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_module_class.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_module_class.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_basic.py b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_basic.py index 0661cb301fc..12e0e3e91d4 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_basic.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_basic.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py index 256b92a17dd..8b6e8697e06 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_modulelevel.py b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_modulelevel.py index e15dbd2ca45..40587cf2bd1 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_modulelevel.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_modulelevel.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookupfails.py b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookupfails.py index b775203231f..0cc8446d8ee 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookupfails.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookupfails.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/test_fixture_named_request.py b/testing/example_scripts/fixtures/test_fixture_named_request.py index 75514bf8b8c..a2ab7ee330d 100644 --- a/testing/example_scripts/fixtures/test_fixture_named_request.py +++ b/testing/example_scripts/fixtures/test_fixture_named_request.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/fixtures/test_getfixturevalue_dynamic.py b/testing/example_scripts/fixtures/test_getfixturevalue_dynamic.py index 055a1220b1c..0f316f0e449 100644 --- a/testing/example_scripts/fixtures/test_getfixturevalue_dynamic.py +++ b/testing/example_scripts/fixtures/test_getfixturevalue_dynamic.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/issue88_initial_file_multinodes/conftest.py b/testing/example_scripts/issue88_initial_file_multinodes/conftest.py index 0598eb841a4..bde5c0711ac 100644 --- a/testing/example_scripts/issue88_initial_file_multinodes/conftest.py +++ b/testing/example_scripts/issue88_initial_file_multinodes/conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/issue88_initial_file_multinodes/test_hello.py b/testing/example_scripts/issue88_initial_file_multinodes/test_hello.py index 56444d14748..dd18e1741f0 100644 --- a/testing/example_scripts/issue88_initial_file_multinodes/test_hello.py +++ b/testing/example_scripts/issue88_initial_file_multinodes/test_hello.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_hello(): pass diff --git a/testing/example_scripts/issue_519.py b/testing/example_scripts/issue_519.py index 73437ef7bdb..39766164490 100644 --- a/testing/example_scripts/issue_519.py +++ b/testing/example_scripts/issue_519.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pprint from typing import List from typing import Tuple diff --git a/testing/example_scripts/marks/marks_considered_keywords/test_marks_as_keywords.py b/testing/example_scripts/marks/marks_considered_keywords/test_marks_as_keywords.py index 35a2c7b7628..d95ad0a83d9 100644 --- a/testing/example_scripts/marks/marks_considered_keywords/test_marks_as_keywords.py +++ b/testing/example_scripts/marks/marks_considered_keywords/test_marks_as_keywords.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/perf_examples/collect_stats/generate_folders.py b/testing/example_scripts/perf_examples/collect_stats/generate_folders.py index ff1eaf7d6bb..3d8e77e88bf 100644 --- a/testing/example_scripts/perf_examples/collect_stats/generate_folders.py +++ b/testing/example_scripts/perf_examples/collect_stats/generate_folders.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import argparse import pathlib diff --git a/testing/example_scripts/perf_examples/collect_stats/template_test.py b/testing/example_scripts/perf_examples/collect_stats/template_test.py index 064ade190a1..f50eb65525c 100644 --- a/testing/example_scripts/perf_examples/collect_stats/template_test.py +++ b/testing/example_scripts/perf_examples/collect_stats/template_test.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_x(): pass diff --git a/testing/example_scripts/tmpdir/tmp_path_fixture.py b/testing/example_scripts/tmpdir/tmp_path_fixture.py index 8675eb2fa62..4aa35faa0b6 100644 --- a/testing/example_scripts/tmpdir/tmp_path_fixture.py +++ b/testing/example_scripts/tmpdir/tmp_path_fixture.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/example_scripts/unittest/test_parametrized_fixture_error_message.py b/testing/example_scripts/unittest/test_parametrized_fixture_error_message.py index d421ce927c9..d66b66df5b7 100644 --- a/testing/example_scripts/unittest/test_parametrized_fixture_error_message.py +++ b/testing/example_scripts/unittest/test_parametrized_fixture_error_message.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import unittest import pytest diff --git a/testing/example_scripts/unittest/test_setup_skip.py b/testing/example_scripts/unittest/test_setup_skip.py index 93f79bb3b2e..4681cda0352 100644 --- a/testing/example_scripts/unittest/test_setup_skip.py +++ b/testing/example_scripts/unittest/test_setup_skip.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Skipping an entire subclass with unittest.skip() should *not* call setUp from a base class.""" import unittest diff --git a/testing/example_scripts/unittest/test_setup_skip_class.py b/testing/example_scripts/unittest/test_setup_skip_class.py index 4f251dcba17..eae98287f91 100644 --- a/testing/example_scripts/unittest/test_setup_skip_class.py +++ b/testing/example_scripts/unittest/test_setup_skip_class.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Skipping an entire subclass with unittest.skip() should *not* call setUpClass from a base class.""" import unittest diff --git a/testing/example_scripts/unittest/test_setup_skip_module.py b/testing/example_scripts/unittest/test_setup_skip_module.py index 98befbe510f..43c24136edf 100644 --- a/testing/example_scripts/unittest/test_setup_skip_module.py +++ b/testing/example_scripts/unittest/test_setup_skip_module.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """setUpModule is always called, even if all tests in the module are skipped""" import unittest diff --git a/testing/example_scripts/unittest/test_unittest_asyncio.py b/testing/example_scripts/unittest/test_unittest_asyncio.py index 1cd2168604c..a82ddaebcc3 100644 --- a/testing/example_scripts/unittest/test_unittest_asyncio.py +++ b/testing/example_scripts/unittest/test_unittest_asyncio.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from typing import List from unittest import IsolatedAsyncioTestCase diff --git a/testing/example_scripts/unittest/test_unittest_asynctest.py b/testing/example_scripts/unittest/test_unittest_asynctest.py index fb26617067c..b3f03e3256b 100644 --- a/testing/example_scripts/unittest/test_unittest_asynctest.py +++ b/testing/example_scripts/unittest/test_unittest_asynctest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Issue #7110""" import asyncio from typing import List diff --git a/testing/example_scripts/unittest/test_unittest_plain_async.py b/testing/example_scripts/unittest/test_unittest_plain_async.py index 78dfece684e..2a4a66509a4 100644 --- a/testing/example_scripts/unittest/test_unittest_plain_async.py +++ b/testing/example_scripts/unittest/test_unittest_plain_async.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import unittest diff --git a/testing/example_scripts/warnings/test_group_warnings_by_message.py b/testing/example_scripts/warnings/test_group_warnings_by_message.py index 6985caa4407..be64a1ff2c8 100644 --- a/testing/example_scripts/warnings/test_group_warnings_by_message.py +++ b/testing/example_scripts/warnings/test_group_warnings_by_message.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import warnings import pytest diff --git a/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_1.py b/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_1.py index b8c11cb71c9..95fa795efe0 100644 --- a/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_1.py +++ b/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_1.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import warnings import pytest diff --git a/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_2.py b/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_2.py index 636d04a5505..5204fde8a85 100644 --- a/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_2.py +++ b/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_2.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from test_1 import func diff --git a/testing/freeze/tests/test_trivial.py b/testing/freeze/tests/test_trivial.py index 08a55552abb..425f29a649c 100644 --- a/testing/freeze/tests/test_trivial.py +++ b/testing/freeze/tests/test_trivial.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs def test_upper(): assert "foo".upper() == "FOO" diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index d94faa4f194..4091747d50a 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import saferepr diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index c7e63c67284..a13f9a4bcd9 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import io import os import re diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 5d10688a00e..92fd72300f4 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import io import os import re diff --git a/testing/plugins_integration/bdd_wallet.py b/testing/plugins_integration/bdd_wallet.py index 35927ea5875..2bdb1545424 100644 --- a/testing/plugins_integration/bdd_wallet.py +++ b/testing/plugins_integration/bdd_wallet.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from pytest_bdd import given from pytest_bdd import scenario from pytest_bdd import then diff --git a/testing/plugins_integration/pytest_anyio_integration.py b/testing/plugins_integration/pytest_anyio_integration.py index 65c2f593663..383d7a0b5db 100644 --- a/testing/plugins_integration/pytest_anyio_integration.py +++ b/testing/plugins_integration/pytest_anyio_integration.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import anyio import pytest diff --git a/testing/plugins_integration/pytest_asyncio_integration.py b/testing/plugins_integration/pytest_asyncio_integration.py index 5d2a3faccfc..b216c4beecd 100644 --- a/testing/plugins_integration/pytest_asyncio_integration.py +++ b/testing/plugins_integration/pytest_asyncio_integration.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import asyncio import pytest diff --git a/testing/plugins_integration/pytest_mock_integration.py b/testing/plugins_integration/pytest_mock_integration.py index 740469d00fb..5494c44270a 100644 --- a/testing/plugins_integration/pytest_mock_integration.py +++ b/testing/plugins_integration/pytest_mock_integration.py @@ -1,2 +1,3 @@ +# mypy: allow-untyped-defs def test_mocker(mocker): mocker.MagicMock() diff --git a/testing/plugins_integration/pytest_trio_integration.py b/testing/plugins_integration/pytest_trio_integration.py index 199f7850bc4..60f48ec609b 100644 --- a/testing/plugins_integration/pytest_trio_integration.py +++ b/testing/plugins_integration/pytest_trio_integration.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import trio import pytest diff --git a/testing/plugins_integration/pytest_twisted_integration.py b/testing/plugins_integration/pytest_twisted_integration.py index 94748d036e5..0dbf5faeb8a 100644 --- a/testing/plugins_integration/pytest_twisted_integration.py +++ b/testing/plugins_integration/pytest_twisted_integration.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest_twisted from twisted.internet.task import deferLater diff --git a/testing/plugins_integration/simple_integration.py b/testing/plugins_integration/simple_integration.py index 20b2fc4b5bb..48089afcc7e 100644 --- a/testing/plugins_integration/simple_integration.py +++ b/testing/plugins_integration/simple_integration.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest diff --git a/testing/python/approx.py b/testing/python/approx.py index 3b87e58f91a..132855b0440 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import operator from contextlib import contextmanager from decimal import Decimal diff --git a/testing/python/collect.py b/testing/python/collect.py index da11dd34a9a..683b6281252 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import sys import textwrap diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 81aa2bcc782..d232742ea2b 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import sys import textwrap @@ -4403,7 +4404,7 @@ def test_fixture_named_request(pytester: Pytester) -> None: result.stdout.fnmatch_lines( [ "*'request' is a reserved word for fixtures, use another name:", - " *test_fixture_named_request.py:5", + " *test_fixture_named_request.py:6", ] ) diff --git a/testing/python/integration.py b/testing/python/integration.py index 054c14a39e4..dbe1b1a00f5 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest from _pytest._code import getfslineno from _pytest.fixtures import getfixturemarker diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 9393c972746..8f41975f3e7 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import dataclasses import itertools import re diff --git a/testing/python/raises.py b/testing/python/raises.py index 3dcec31eb1f..47b22f28a92 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import re import sys diff --git a/testing/test_argcomplete.py b/testing/test_argcomplete.py index 8c10e230b0c..6813d8f13c8 100644 --- a/testing/test_argcomplete.py +++ b/testing/test_argcomplete.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import subprocess import sys from pathlib import Path diff --git a/testing/test_assertion.py b/testing/test_assertion.py index e55ec38e145..640890e9a11 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import collections import sys import textwrap diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index a4d48b6feeb..a4386b3a8fa 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import ast import errno import glob diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 21c1957cfeb..73f5687d387 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import shutil from pathlib import Path diff --git a/testing/test_capture.py b/testing/test_capture.py index b6ea8161356..c49eeb67314 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import contextlib import io import os diff --git a/testing/test_collection.py b/testing/test_collection.py index be65169f75c..f1552b6aea9 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import pprint import shutil diff --git a/testing/test_compat.py b/testing/test_compat.py index 27c6db95bbf..53d3df14a5e 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import enum import sys from functools import cached_property diff --git a/testing/test_config.py b/testing/test_config.py index 1eb530aceb6..45bcce4ea7f 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import dataclasses import importlib.metadata import os diff --git a/testing/test_conftest.py b/testing/test_conftest.py index e741907273d..33d2e38dcd0 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import textwrap from pathlib import Path diff --git a/testing/test_debugging.py b/testing/test_debugging.py index ea3367e5791..1cd46ae487a 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import sys from typing import List diff --git a/testing/test_doctest.py b/testing/test_doctest.py index f4d3155c435..110e0557cab 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import inspect import sys import textwrap diff --git a/testing/test_entry_points.py b/testing/test_entry_points.py index dfb3d57d2d8..68e3a8a92e4 100644 --- a/testing/test_entry_points.py +++ b/testing/test_entry_points.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import importlib.metadata diff --git a/testing/test_faulthandler.py b/testing/test_faulthandler.py index 5b7911f21f8..22545ea214c 100644 --- a/testing/test_faulthandler.py +++ b/testing/test_faulthandler.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import io import sys diff --git a/testing/test_findpaths.py b/testing/test_findpaths.py index 65370a0ba3a..0759ba55158 100644 --- a/testing/test_findpaths.py +++ b/testing/test_findpaths.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os from pathlib import Path from textwrap import dedent diff --git a/testing/test_helpconfig.py b/testing/test_helpconfig.py index ba89d0c4acf..272d4d29065 100644 --- a/testing/test_helpconfig.py +++ b/testing/test_helpconfig.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest from _pytest.config import ExitCode from _pytest.pytester import Pytester diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index b0c2d1c6d4e..88749c0c851 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import platform from datetime import datetime diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index 700499f24ea..72899b60df8 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from pathlib import Path import pytest diff --git a/testing/test_link_resolve.py b/testing/test_link_resolve.py index 1ac3afd09e8..c9d307f8802 100644 --- a/testing/test_link_resolve.py +++ b/testing/test_link_resolve.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os.path import subprocess import sys diff --git a/testing/test_main.py b/testing/test_main.py index 3c8998c1a35..b1abf2c7178 100644 --- a/testing/test_main.py +++ b/testing/test_main.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import argparse import os import re diff --git a/testing/test_mark.py b/testing/test_mark.py index 609f73d68eb..45acf050486 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import sys from typing import List diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 8175b5f0fad..3a1045d6708 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import re import sys diff --git a/testing/test_nodes.py b/testing/test_nodes.py index 1de0f995e8a..4efb39e036b 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import re import warnings from pathlib import Path diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 2a629198438..b2d5479311c 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import argparse import locale import os diff --git a/testing/test_pastebin.py b/testing/test_pastebin.py index 86b231f8b5e..277454f9b18 100644 --- a/testing/test_pastebin.py +++ b/testing/test_pastebin.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import email.message import io from typing import List diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 3e1d2265bb7..99cd48503b8 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import errno import os.path import pickle diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 8bafde33846..ea44d8748b4 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import shutil import sys diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 6fc6bd24519..e35fb529427 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import subprocess import sys diff --git a/testing/test_python_path.py b/testing/test_python_path.py index dfef0f3fecf..4054134b480 100644 --- a/testing/test_python_path.py +++ b/testing/test_python_path.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import sys from textwrap import dedent from typing import Generator diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 2508e22a2db..9d46c1fc870 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import warnings from typing import List from typing import Optional diff --git a/testing/test_reports.py b/testing/test_reports.py index 627ea1ed24f..ae2b68cdb7e 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from typing import Sequence from typing import Union diff --git a/testing/test_runner.py b/testing/test_runner.py index 26f5b9a0bc2..d2007647eee 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import inspect import os import sys diff --git a/testing/test_runner_xunit.py b/testing/test_runner_xunit.py index e077ac41e2c..dbdb51d2470 100644 --- a/testing/test_runner_xunit.py +++ b/testing/test_runner_xunit.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Test correct setup/teardowns at module, class, and instance level.""" from typing import List diff --git a/testing/test_session.py b/testing/test_session.py index 803bbed5434..232e9c834a5 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import pytest from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch diff --git a/testing/test_setuponly.py b/testing/test_setuponly.py index fe4bdc514eb..0f70383a63e 100644 --- a/testing/test_setuponly.py +++ b/testing/test_setuponly.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import sys import pytest diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 86940baa6fd..346dfa44e89 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import sys import textwrap diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index 85e38c7d568..4aa72d02496 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs from pathlib import Path import pytest diff --git a/testing/test_terminal.py b/testing/test_terminal.py index b521deea7d1..283722887ae 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """Terminal reporting of the full testing process.""" import collections import os diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 2215e978a60..42df6608811 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import dataclasses import os import stat diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 24f954051d6..fc967d99262 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import gc import sys from typing import List diff --git a/testing/test_warning_types.py b/testing/test_warning_types.py index 5f69439ef3e..0ea3f2976f8 100644 --- a/testing/test_warning_types.py +++ b/testing/test_warning_types.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import inspect import pytest diff --git a/testing/test_warnings.py b/testing/test_warnings.py index e7834dc4d4d..2f0ab9b54bd 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs import os import sys import warnings @@ -623,11 +624,11 @@ def test_group_warnings_by_message_summary(pytester: Pytester) -> None: "*== %s ==*" % WARNINGS_SUMMARY_HEADER, "test_1.py: 21 warnings", "test_2.py: 1 warning", - " */test_1.py:7: UserWarning: foo", + " */test_1.py:8: UserWarning: foo", " warnings.warn(UserWarning(msg))", "", "test_1.py: 20 warnings", - " */test_1.py:7: UserWarning: bar", + " */test_1.py:8: UserWarning: bar", " warnings.warn(UserWarning(msg))", "", "-- Docs: *", diff --git a/testing/typing_checks.py b/testing/typing_checks.py index 57f2bae475f..a2ceabcbd67 100644 --- a/testing/typing_checks.py +++ b/testing/typing_checks.py @@ -1,3 +1,4 @@ +# mypy: allow-untyped-defs """File for checking typing issues. This file is not executed, it is only checked by mypy to ensure that From 8853a57532899b124578af7baa217acc26061070 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 28 Jan 2024 13:28:28 +0000 Subject: [PATCH 0400/1271] [automated] Update plugin list (#11867) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 2822 +++++++++++++++--------------- 1 file changed, 1427 insertions(+), 1395 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 9321ca852ea..45f4de9110e 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,1373 +27,1377 @@ please refer to `the update script =7.3.0,<8.0.0) - :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A - :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A - :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) - :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) - :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Nov 08, 2023 N/A pytest >=5.4.0 - :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-adf` Pytest plugin for writing Azure Data Factory integration tests May 10, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-ads-testplan` Azure DevOps Test Case reporting for pytest tests Sep 15, 2022 N/A N/A - :pypi:`pytest-affected` Nov 06, 2023 N/A N/A - :pypi:`pytest-agent` Service that exposes a REST API that can be used to interract remotely with Pytest. It is shipped with a dashboard that enables running tests in a more convenient way. Nov 25, 2021 N/A N/A - :pypi:`pytest-aggreport` pytest plugin for pytest-repeat that generate aggregate report of the same test cases with additional statistics details. Mar 07, 2021 4 - Beta pytest (>=6.2.2) - :pypi:`pytest-aio` Pytest plugin for testing async python code Feb 03, 2023 4 - Beta pytest - :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A - :pypi:`pytest-aiogram` May 06, 2023 N/A N/A - :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Sep 06, 2023 4 - Beta pytest >=6.1.0 - :pypi:`pytest-aiohttp-client` Pytest \`client\` fixture for the Aiohttp Jan 10, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-aiomoto` pytest-aiomoto Jun 24, 2023 N/A pytest (>=7.0,<8.0) - :pypi:`pytest-aioresponses` py.test integration for aioresponses Jul 29, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 - :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) - :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 06, 2023 N/A pytest (>=6.0) - :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest - :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) - :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) - :pypi:`pytest-allure-collection` pytest plugin to collect allure markers without running any tests Apr 13, 2023 N/A pytest - :pypi:`pytest-allure-dsl` pytest plugin to test case doc string dls instructions Oct 25, 2020 4 - Beta pytest - :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) - :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest - :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Dec 06, 2023 N/A pytest >=7.3.1 - :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest - :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jan 18, 2024 5 - Production/Stable pytest >=6 - :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A - :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) - :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A - :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 Jan 18, 2024 N/A pytest - :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 - :pypi:`pytest-apistellar` apistellar plugin for pytest. Jun 18, 2019 N/A N/A - :pypi:`pytest-appengine` AppEngine integration that works well with pytest-django Feb 27, 2017 N/A N/A - :pypi:`pytest-appium` Pytest plugin for appium Dec 05, 2019 N/A N/A - :pypi:`pytest-approvaltests` A plugin to use approvaltests with pytest May 08, 2022 4 - Beta pytest (>=7.0.1) - :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Dec 12, 2023 5 - Production/Stable pytest - :pypi:`pytest-archon` Rule your architecture like a real developer Dec 18, 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 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 Dec 20, 2023 4 - Beta N/A - :pypi:`pytest-asptest` test Answer Set Programming programs Apr 28, 2018 4 - Beta N/A - :pypi:`pytest-assertcount` Plugin to count actual number of asserts in pytest Oct 23, 2022 N/A pytest (>=5.0.0) - :pypi:`pytest-assertions` Pytest Assertions Apr 27, 2022 N/A N/A - :pypi:`pytest-assertutil` pytest-assertutil May 10, 2019 N/A N/A - :pypi:`pytest-assert-utils` Useful assertion utilities for use with pytest Apr 14, 2022 3 - Alpha N/A - :pypi:`pytest-assume` A pytest plugin that allows multiple failures per test Jun 24, 2021 N/A pytest (>=2.7) - :pypi:`pytest-assurka` A pytest plugin for Assurka Studio Aug 04, 2022 N/A N/A - :pypi:`pytest-ast-back-to-python` A plugin for pytest devs to view how assertion rewriting recodes the AST Sep 29, 2019 4 - Beta N/A - :pypi:`pytest-asteroid` PyTest plugin for docker-based testing on database images Aug 15, 2022 N/A pytest (>=6.2.5,<8.0.0) - :pypi:`pytest-astropy` Meta-package containing dependencies for testing Sep 26, 2023 5 - Production/Stable pytest >=4.6 - :pypi:`pytest-astropy-header` pytest plugin to add diagnostic information to the header of the test output Sep 06, 2022 3 - Alpha pytest (>=4.6) - :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest - :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Jan 16, 2024 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进行自定义 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 - :pypi:`pytest-autocap` automatically capture test & fixture stdout/stderr to files May 15, 2022 N/A pytest (<7.2,>=7.1.2) - :pypi:`pytest-autochecklog` automatically check condition and log all the checks Apr 25, 2015 4 - Beta N/A - :pypi:`pytest-automation` pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. May 20, 2022 N/A pytest (>=7.0.0) - :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' - :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A - :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest - :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest - :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A - :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A - :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) - :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest - :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest - :pypi:`pytest-azure-devops` Simplifies using azure devops parallel strategy (https://docs.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner) with pytest. Jun 20, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-azurepipelines` Formatting PyTest output for Azure Pipelines UI Oct 06, 2023 5 - Production/Stable pytest (>=5.0.0) - :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) - :pypi:`pytest-bdd` BDD for pytest Dec 02, 2023 6 - Mature pytest (>=6.2.0) - :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) - :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 - :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 15, 2023 N/A pytest >=7.1.3 - :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) - :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A - :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest - :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A - :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A - :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A - :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) - :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A - :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A - :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) - :pypi:`pytest-black` A pytest plugin to enable format checking with black Oct 05, 2020 4 - Beta N/A - :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' - :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-blame` A pytest plugin helps developers to debug by providing useful commits history. May 04, 2019 N/A pytest (>=4.4.0) - :pypi:`pytest-blender` Blender Pytest plugin. Aug 10, 2023 N/A pytest ; extra == 'dev' - :pypi:`pytest-blink1` Pytest plugin to emit notifications via the Blink(1) RGB LED Jan 07, 2018 4 - Beta N/A - :pypi:`pytest-blockage` Disable network requests during a test run. Dec 21, 2021 N/A pytest - :pypi:`pytest-blocker` pytest plugin to mark a test as blocker and skip all other tests Sep 07, 2015 4 - Beta N/A - :pypi:`pytest-blue` A pytest plugin that adds a \`blue\` fixture for printing stuff in blue. Sep 05, 2022 N/A N/A - :pypi:`pytest-board` Local continuous test runner with pytest and watchdog. Jan 20, 2019 N/A N/A - :pypi:`pytest-boost-xml` Plugin for pytest to generate boost xml reports Nov 30, 2022 4 - Beta N/A - :pypi:`pytest-bootstrap` Mar 04, 2022 N/A N/A - :pypi:`pytest-bpdb` A py.test plug-in to enable drop to bpdb debugger on test failure. Jan 19, 2015 2 - Pre-Alpha N/A - :pypi:`pytest-bravado` Pytest-bravado automatically generates from OpenAPI specification client fixtures. Feb 15, 2022 N/A N/A - :pypi:`pytest-breakword` Use breakword with pytest Aug 04, 2021 N/A pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-breed-adapter` A simple plugin to connect with breed-server Nov 07, 2018 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-briefcase` A pytest plugin for running tests on a Briefcase project. Jun 14, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-browser` A pytest plugin for console based browser test selection just after the collection phase Dec 10, 2016 3 - Alpha N/A - :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A - :pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A - :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest - :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Sep 23, 2023 5 - Production/Stable pytest >=7.1.0 - :pypi:`pytest-bugtong-tag` pytest-bugtong-tag is a plugin for pytest Jan 16, 2022 N/A N/A - :pypi:`pytest-bugzilla` py.test bugzilla integration plugin May 05, 2010 4 - Beta N/A - :pypi:`pytest-bugzilla-notifier` A plugin that allows you to execute create, update, and read information from BugZilla bugs Jun 15, 2018 4 - Beta pytest (>=2.9.2) - :pypi:`pytest-buildkite` Plugin for pytest that automatically publishes coverage and pytest report annotations to Buildkite. Jul 13, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-builtin-types` Nov 17, 2021 N/A pytest - :pypi:`pytest-bwrap` Run your tests in Bubblewrap sandboxes Oct 26, 2018 3 - Alpha N/A - :pypi:`pytest-cache` pytest plugin with mechanisms for caching across test runs Jun 04, 2013 3 - Alpha N/A - :pypi:`pytest-cache-assert` Cache assertion data to simplify regression testing of complex serializable data Aug 14, 2023 5 - Production/Stable pytest (>=6.0.0) - :pypi:`pytest-cagoule` Pytest plugin to only run tests affected by changes Jan 01, 2020 3 - Alpha N/A - :pypi:`pytest-cairo` Pytest support for cairo-lang and starknet Apr 17, 2022 N/A pytest - :pypi:`pytest-call-checker` Small pytest utility to easily create test doubles Oct 16, 2022 4 - Beta pytest (>=7.1.3,<8.0.0) - :pypi:`pytest-camel-collect` Enable CamelCase-aware pytest class collection Aug 02, 2020 N/A pytest (>=2.9) - :pypi:`pytest-canonical-data` A plugin which allows to compare results with canonical results, based on previous runs May 08, 2020 2 - Pre-Alpha pytest (>=3.5.0) - :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A - :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A - :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-cases` Separate test code from test cases in pytest. Jan 12, 2024 5 - Production/Stable N/A - :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A - :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) - :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 14, 2024 N/A N/A - :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A - :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A - :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A - :pypi:`pytest-change-demo` turn . into √,turn F into x Mar 02, 2022 N/A pytest - :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest - :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest - :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 18, 2024 N/A pytest>=7.0.0 - :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' - :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 - :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A - :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A - :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest>=7.0 - :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 Dec 26, 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 - :pypi:`pytest-circleci-parallelized-rjp` Parallelize pytest across CircleCI workers. Jun 21, 2022 N/A pytest - :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest - :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A - :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) - :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 25, 2023 4 - Beta N/A - :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) - :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) - :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A - :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) - :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Jul 19, 2023 N/A pytest<8,>=4 - :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) - :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest - :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A - :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Nov 29, 2022 4 - Beta pytest (>=4.6.0) - :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A - :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) - :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Sep 01, 2023 5 - Production/Stable pytest>=3.8 - :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest - :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A - :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A - :pypi:`pytest-collect-interface-info-plugin` Get executed interface information in pytest interface automation framework Sep 25, 2023 4 - Beta N/A - :pypi:`pytest-collector` Python package for collecting pytest. Aug 02, 2022 N/A pytest (>=7.0,<8.0) - :pypi:`pytest-collect-pytest-interinfo` A simple plugin to use with pytest Sep 26, 2023 4 - Beta N/A - :pypi:`pytest-colordots` Colorizes the progress indicators Oct 06, 2017 5 - Production/Stable N/A - :pypi:`pytest-commander` An interactive GUI test runner for PyTest Aug 17, 2021 N/A pytest (<7.0.0,>=6.2.4) - :pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method May 15, 2022 N/A pytest (>=3.6,<8) - :pypi:`pytest-compare` pytest plugin for comparing call arguments. Jun 22, 2023 5 - Production/Stable N/A - :pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1) - :pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A - :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A - :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) - :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest - :pypi:`pytest-container` Pytest fixtures for writing container based tests Sep 26, 2023 4 - Beta pytest (>=3.10) - :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A - :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A - :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) - :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Nov 14, 2023 3 - Alpha pytest - :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 - :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A - :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A - :pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6) - :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A - :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A - :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' - :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 26, 2023 N/A N/A - :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A - :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) - :pypi:`pytest-crayons` A pytest plugin for colorful print statements Oct 08, 2023 N/A pytest - :pypi:`pytest-create` pytest-create Feb 15, 2023 1 - Planning N/A - :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest - :pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A - :pypi:`pytest-csv` CSV output for pytest. Apr 22, 2021 N/A pytest (>=6.0) - :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Jul 01, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) - :pypi:`pytest-curio` Pytest support for curio. Oct 07, 2020 N/A N/A - :pypi:`pytest-curl-report` pytest plugin to generate curl command line report Dec 11, 2016 4 - Beta N/A - :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A - :pypi:`pytest-custom-exit-code` Exit pytest test session with custom exit code in different scenarios Aug 07, 2019 4 - Beta pytest (>=4.0.2) - :pypi:`pytest-custom-nodeid` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 07, 2021 N/A N/A - :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest - :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A - :pypi:`pytest-cython` A plugin for testing Cython extension modules Feb 16, 2023 5 - Production/Stable pytest (>=4.6.0) - :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest - :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Aug 16, 2020 N/A pytest (>=6.0.1) ; extra == 'test' - :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A - :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest - :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 - :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) - :pypi:`pytest-datadir-ng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Dec 25, 2019 5 - Production/Stable pytest - :pypi:`pytest-datadir-nng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Nov 09, 2022 5 - Production/Stable pytest (>=7.0.0,<8.0.0) - :pypi:`pytest-data-extractor` A pytest plugin to extract relevant metadata about tests into an external file (currently only json support) Jul 19, 2022 N/A pytest (>=7.0.1) - :pypi:`pytest-data-file` Fixture "data" and "case_data" for test from yaml file Dec 04, 2019 N/A N/A - :pypi:`pytest-datafiles` py.test plugin to create a 'tmp_path' containing predefined files/directories. Feb 24, 2023 5 - Production/Stable pytest (>=3.6) - :pypi:`pytest-datafixtures` Data fixtures for pytest made simple Dec 05, 2020 5 - Production/Stable N/A - :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest - :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A - :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jan 08, 2023 5 - Production/Stable pytest - :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A - :pypi:`pytest-data-suites` Class-based pytest parametrization Jul 24, 2022 N/A pytest (>=6.0,<8.0) - :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) - :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Dec 04, 2019 N/A N/A - :pypi:`pytest-dbfixtures` Databases fixtures plugin for py.test. Dec 07, 2016 4 - Beta N/A - :pypi:`pytest-db-plugin` Nov 27, 2021 N/A pytest (>=5.0) - :pypi:`pytest-dbt` Unit test dbt models with standard python tooling Jun 08, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) - :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) - :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-dbt-core` Pytest extension for dbt. Aug 25, 2023 N/A pytest >=6.2.5 ; extra == 'test' - :pypi:`pytest-dbt-postgres` Pytest tooling to unittest DBT & Postgres models Jan 02, 2024 N/A pytest (>=7.4.3,<8.0.0) - :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A - :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) - :pypi:`pytest-dc` Manages Docker containers during your integration tests Aug 16, 2023 5 - Production/Stable pytest >=3.3 - :pypi:`pytest-deadfixtures` A simple plugin to list unused fixtures in pytest Jul 23, 2020 5 - Production/Stable N/A - :pypi:`pytest-deduplicate` Identifies duplicate unit tests Aug 12, 2023 4 - Beta pytest - :pypi:`pytest-deepcov` deepcov Mar 30, 2021 N/A N/A - :pypi:`pytest-defer` Aug 24, 2021 N/A N/A - :pypi:`pytest-demo-plugin` pytest示例插件 May 15, 2021 N/A N/A - :pypi:`pytest-dependency` Manage dependencies of tests Dec 31, 2023 4 - Beta N/A - :pypi:`pytest-depends` Tests that depend on other tests Apr 05, 2020 5 - Production/Stable pytest (>=3) - :pypi:`pytest-deprecate` Mark tests as testing a deprecated feature with a warning note. Jul 01, 2019 N/A N/A - :pypi:`pytest-describe` Describe-style plugin for pytest Apr 09, 2023 5 - Production/Stable pytest (<8,>=4.6) - :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest - :pypi:`pytest-devpi-server` DevPI server fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-dhos` Common fixtures for pytest in DHOS services and libraries Sep 07, 2022 N/A N/A - :pypi:`pytest-diamond` pytest plugin for diamond Aug 31, 2015 4 - Beta N/A - :pypi:`pytest-dicom` pytest plugin to provide DICOM fixtures Dec 19, 2018 3 - Alpha pytest - :pypi:`pytest-dictsdiff` Jul 26, 2019 N/A N/A - :pypi:`pytest-diff` A simple plugin to use with pytest Mar 30, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A - :pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all' - :pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0) - :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 11, 2023 4 - Beta pytest>=7.3.2 - :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A - :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 - :pypi:`pytest-django` A Django plugin for pytest. Nov 08, 2023 5 - Production/Stable pytest >=7.0.0 - :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) - :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest - :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A - :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A - :pypi:`pytest-django-class` A pytest plugin for running django in class-scoped fixtures Aug 08, 2023 4 - Beta N/A - :pypi:`pytest-django-docker-pg` Jan 05, 2024 5 - Production/Stable pytest >=7.0.0 - :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) - :pypi:`pytest-django-factories` Factories for your Django models that can be used as Pytest fixtures. Nov 12, 2020 4 - Beta N/A - :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 - :pypi:`pytest-django-gcir` A Django plugin for pytest. Mar 06, 2018 5 - Production/Stable N/A - :pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4) - :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Aug 27, 2023 5 - Production/Stable N/A - :pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A - :pypi:`pytest-django-liveserver-ssl` Jan 20, 2022 3 - Alpha N/A - :pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A - :pypi:`pytest-django-ordering` A pytest plugin for preserving the order in which Django runs tests. Jul 25, 2019 5 - Production/Stable pytest (>=2.3.0) - :pypi:`pytest-django-queries` Generate performance reports from your django database performance tests. Mar 01, 2021 N/A N/A - :pypi:`pytest-djangorestframework` A djangorestframework plugin for pytest Aug 11, 2019 4 - Beta N/A - :pypi:`pytest-django-rq` A pytest plugin to help writing unit test for django-rq Apr 13, 2020 4 - Beta N/A - :pypi:`pytest-django-sqlcounts` py.test plugin for reporting the number of SQLs executed per django testcase. Jun 16, 2015 4 - Beta N/A - :pypi:`pytest-django-testing-postgresql` Use a temporary PostgreSQL database with pytest-django Jan 31, 2022 4 - Beta N/A - :pypi:`pytest-doc` A documentation plugin for py.test. Jun 28, 2015 5 - Production/Stable N/A - :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) - :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A - :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Sep 01, 2023 N/A pytest <8.0,>=4.0 - :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Feb 16, 2022 4 - Beta pytest - :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A - :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) - :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) - :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) - :pypi:`pytest-docker-fixtures` pytest docker fixtures Nov 17, 2023 3 - Alpha N/A - :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Feb 09, 2022 4 - Beta pytest - :pypi:`pytest-docker-haproxy-fixtures` Pytest fixtures for testing with haproxy. Feb 09, 2022 4 - Beta pytest - :pypi:`pytest-docker-pexpect` pytest plugin for writing functional tests with pexpect and docker Jan 14, 2019 N/A pytest - :pypi:`pytest-docker-postgresql` A simple plugin to use with pytest Sep 24, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-docker-py` Easy to use, simple to extend, pytest plugin that minimally leverages docker-py. Nov 27, 2018 N/A pytest (==4.0.0) - :pypi:`pytest-docker-registry-fixtures` Pytest fixtures for testing with docker registries. Apr 08, 2022 4 - Beta pytest - :pypi:`pytest-docker-service` pytest plugin to start docker container Jan 03, 2024 3 - Alpha pytest (>=7.1.3) - :pypi:`pytest-docker-squid-fixtures` Pytest fixtures for testing with squid. Feb 09, 2022 4 - Beta pytest - :pypi:`pytest-docker-tools` Docker integration tests for pytest Feb 17, 2022 4 - Beta pytest (>=6.0.1) - :pypi:`pytest-docs` Documentation tool for pytest Nov 11, 2018 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-docstyle` pytest plugin to run pydocstyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A - :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A - :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Dec 13, 2023 5 - Production/Stable 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 Dec 14, 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) - :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) - :pypi:`pytest-dot-only-pkcopley` A Pytest marker for only running a single test Oct 27, 2023 N/A N/A - :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest - :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) - :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A - :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection May 23, 2020 4 - Beta pytest (>=2.7) - :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 18, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) - :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest - :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A - :pypi:`pytest-duration-insights` Jun 25, 2021 N/A N/A - :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Apr 22, 2022 5 - Production/Stable pytest (>=4.6) - :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A - :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Jun 12, 2023 5 - Production/Stable pytest - :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A - :pypi:`pytest-easy-api` Simple API testing with pytest Mar 26, 2018 N/A N/A - :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A - :pypi:`pytest-easyread` pytest plugin that makes terminal printouts of the reports easier to read Nov 17, 2017 N/A N/A - :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" - :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A - :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A - :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 - :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest - :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Sep 13, 2023 5 - Production/Stable pytest >=7.0 - :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) - :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) - :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest - :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jan 18, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 18, 2024 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) - :pypi:`pytest-enabler` Enable installed pytest plugins Dec 23, 2023 5 - Production/Stable pytest >=6 ; extra == 'testing' - :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A - :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest - :pypi:`pytest-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. 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) - :pypi:`pytest-envvars` Pytest plugin to validate use of envvars on your tests Jun 13, 2020 5 - Production/Stable pytest (>=3.0.0) - :pypi:`pytest-env-yaml` Apr 02, 2019 N/A N/A - :pypi:`pytest-eradicate` pytest plugin to check for commented out code Sep 08, 2020 N/A pytest (>=2.4.2) - :pypi:`pytest-error-for-skips` Pytest plugin to treat skipped tests a test failure Dec 19, 2019 4 - Beta pytest (>=4.6) - :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A - :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' - :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) - :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 - :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A - :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A - :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest - :pypi:`pytest-executable` pytest plugin for testing executables Oct 07, 2023 N/A pytest <8,>=5 - :pypi:`pytest-execution-timer` A timer for the phases of Pytest's execution. Dec 24, 2021 4 - Beta N/A - :pypi:`pytest-expect` py.test plugin to store test expectations and mark tests based on them Apr 21, 2016 4 - Beta N/A - :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-expecter` Better testing with expecter and pytest. Sep 18, 2022 5 - Production/Stable N/A - :pypi:`pytest-expectr` This plugin is used to expect multiple assert using pytest framework. Oct 05, 2018 N/A pytest (>=2.4.2) - :pypi:`pytest-expect-test` A fixture to support expect tests in pytest Apr 10, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-experiments` A pytest plugin to help developers of research-oriented software projects keep track of the results of their numerical experiments. Dec 13, 2021 4 - Beta pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-explicit` A Pytest plugin to ignore certain marked tests by default Jun 15, 2021 5 - Production/Stable pytest - :pypi:`pytest-exploratory` Interactive console for pytest. Aug 18, 2023 N/A pytest (>=6.2) - :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A - :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' - :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest - :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest - :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A - :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A - :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) - :pypi:`pytest-factoryboy` Factory Boy support for pytest. Oct 10, 2023 6 - Mature pytest (>=6.2) - :pypi:`pytest-factoryboy-fixtures` Generates pytest fixtures that allow the use of type hinting Jun 25, 2020 N/A N/A - :pypi:`pytest-factoryboy-state` Simple factoryboy random state management Mar 22, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-failed-screen-record` Create a video of the screen when pytest fails Jan 05, 2023 4 - Beta pytest (>=7.1.2d,<8.0.0) - :pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A - :pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0) - :pypi:`pytest-fail-slow` Fail tests that take too long to run Oct 21, 2023 N/A pytest >=6.0 - :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A - :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A - :pypi:`pytest-falcon-client` Pytest \`client\` fixture for the Falcon Framework Mar 19, 2019 N/A N/A - :pypi:`pytest-fantasy` Pytest plugin for Flask Fantasy Framework Mar 14, 2019 N/A N/A - :pypi:`pytest-fastapi` Dec 27, 2020 N/A N/A - :pypi:`pytest-fastapi-deps` A fixture which allows easy replacement of fastapi dependencies for testing Jul 20, 2022 5 - Production/Stable pytest - :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) - :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest - :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) - :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) - :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A - :pypi:`pytest-filecov` A pytest plugin to detect unused files Jun 27, 2021 4 - Beta pytest - :pypi:`pytest-filedata` easily load data from files Jan 17, 2019 4 - Beta N/A - :pypi:`pytest-filemarker` A pytest plugin that runs marked tests when files change. Dec 01, 2020 N/A pytest - :pypi:`pytest-file-watcher` Pytest-File-Watcher is a CLI tool that watches for changes in your code and runs pytest on the changed files. Mar 23, 2023 N/A pytest - :pypi:`pytest-filter-case` run test cases filter by mark Nov 05, 2020 N/A N/A - :pypi:`pytest-filter-subpackage` Pytest plugin for filtering based on sub-packages Dec 12, 2022 3 - Alpha pytest (>=3.0) - :pypi:`pytest-find-dependencies` A pytest plugin to find dependencies between tests Apr 09, 2022 4 - Beta pytest (>=4.3.0) - :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) - :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) - :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest - :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Nov 09, 2023 4 - Beta pytest >=3.5.0 - :pypi:`pytest-fixture-config` Fixture configuration utils for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-fixture-maker` Pytest plugin to load fixtures from YAML files Sep 21, 2021 N/A N/A - :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A - :pypi:`pytest-fixture-order` pytest plugin to control fixture evaluation order May 16, 2022 5 - Production/Stable pytest (>=3.0) - :pypi:`pytest-fixture-ref` Lets users reference fixtures without name matching magic. Nov 17, 2022 4 - Beta N/A - :pypi:`pytest-fixture-rtttg` Warn or fail on fixture name clash Feb 23, 2022 N/A pytest (>=7.0.1,<8.0.0) - :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A - :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest - :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest - :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Mar 18, 2022 4 - Beta pytest (>=7.0) - :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jul 10, 2023 5 - Production/Stable pytest - :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) - :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) - :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) - :pypi:`pytest-flaptastic` Flaptastic py.test plugin Mar 17, 2019 N/A N/A - :pypi:`pytest-flask` A set of py.test fixtures to test Flask applications. Oct 23, 2023 5 - Production/Stable pytest >=5.2 - :pypi:`pytest-flask-ligand` Pytest fixtures and helper functions to use for testing flask-ligand microservices. Apr 25, 2023 4 - Beta pytest (~=7.3) - :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) - :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) - :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest - :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jun 26, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest - :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest - :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) - :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A - :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A - :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A - :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Oct 29, 2023 4 - Beta pytest>=7.0.0 - :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 - :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A - :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) - :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) - :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 Dec 15, 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. Dec 18, 2023 3 - Alpha pytest - :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest - :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) - :pypi:`pytest-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. Dec 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 - :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest - :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A - :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) - :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A - :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A - :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A - :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 - :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A - :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest - :pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest - :pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2) - :pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest - :pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A - :pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A - :pypi:`pytest-group-by-class` A Pytest plugin for running a subset of your tests by splitting them in to groups of classes. Jun 27, 2023 5 - Production/Stable pytest (>=2.5) - :pypi:`pytest-growl` Growl notifications for pytest results. Jan 13, 2014 5 - Production/Stable N/A - :pypi:`pytest-grpc` pytest plugin for grpc May 01, 2020 N/A pytest (>=3.6.0) - :pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Feb 05, 2023 N/A N/A - :pypi:`pytest-hammertime` Display "🔨 " instead of "." for passed pytest tests. Jul 28, 2018 N/A pytest - :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) - :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Jun 10, 2022 5 - Production/Stable N/A - :pypi:`pytest-helm-chart` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Jun 15, 2020 4 - Beta pytest (>=5.4.2,<6.0.0) - :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Sep 13, 2023 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A - :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest - :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) - :pypi:`pytest-henry` Aug 29, 2023 N/A N/A - :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 Jan 14, 2024 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 Jan 20, 2024 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` Jan 06, 2024 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. Dec 25, 2023 N/A pytest - :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) - :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) - :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-html` pytest plugin for generating HTML reports Nov 07, 2023 5 - Production/Stable pytest>=7.0.0 - :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A - :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-html-merger` Pytest HTML reports merging utility Nov 11, 2023 N/A N/A - :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Jan 17, 2024 5 - Production/Stable N/A - :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) - :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A - :pypi:`pytest-html-report-merger` Oct 23, 2023 N/A N/A - :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A - :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A - :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 - :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A - :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Dec 21, 2023 5 - Production/Stable pytest ==7.* - :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) - :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest - :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A - :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest - :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Dec 22, 2023 3 - Alpha pytest (>=7.0.0,<8.0.0) - :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 - :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest - :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A - :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Dec 13, 2023 5 - Production/Stable N/A - :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A - :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. 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 - :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A - :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A - :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A - :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A - :pypi:`pytest-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. Dec 13, 2023 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Jan 04, 2024 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) - :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) - :pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0) - :pypi:`pytest-integration` Organizing pytests by integration or not Nov 17, 2022 N/A N/A - :pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest 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. Jan 03, 2024 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 - :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest - :pypi:`pytest-isort` py.test plugin to check import ordering using isort Oct 31, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 22, 2020 4 - Beta N/A - :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A - :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A - :pypi:`pytest-jasmine` Run jasmine tests from your pytest test suite Nov 04, 2017 1 - Planning N/A - :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) - :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Jun 12, 2023 3 - Alpha N/A - :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Sep 08, 2023 4 - Beta pytest >=6.2.4 - :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest - :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) - :pypi:`pytest-json` Generate JSON test reports Jan 18, 2016 4 - Beta N/A - :pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Mar 14, 2023 4 - Beta N/A - :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A - :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) - :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 - :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Dec 05, 2023 4 - Beta pytest - :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest - :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest - :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest - :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) - :pypi:`pytest-keep-together` Pytest plugin to customize test ordering by running all 'related' tests together Dec 07, 2022 5 - Production/Stable pytest - :pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Oct 01, 2023 N/A pytest (>=7.1) - :pypi:`pytest-kind` Kubernetes test support with KIND for pytest Nov 30, 2022 5 - Production/Stable N/A - :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) - :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A - :pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A - :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A - :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) - :pypi:`pytest-kwparametrize` Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks Jan 22, 2021 N/A pytest (>=6) - :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. Aug 20, 2022 3 - Alpha pytest (>=3.6,<8) - :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A - :pypi:`pytest-langchain` Pytest-style test runner for langchain agents Feb 26, 2023 N/A pytest - :pypi:`pytest-lark` Create fancy and clear HTML test reports. Nov 05, 2023 N/A N/A - :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) - :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A - :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. May 28, 2023 N/A pytest (>=7.2.1,<8.0.0) - :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest - :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A - :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest - :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A - :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest - :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A - :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest - :pypi:`pytest-line-profiler` Profile code executed by pytest Aug 10, 2023 4 - Beta pytest >=3.5.0 - :pypi:`pytest-line-profiler-apn` Profile code executed by pytest Dec 05, 2022 N/A pytest (>=3.5.0) - :pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-listener` A simple network listener May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-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. 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 - :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A - :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-lockable` lockable resource plugin for pytest Nov 06, 2023 5 - Production/Stable pytest - :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) - :pypi:`pytest-log` print log Aug 15, 2021 N/A pytest (>=3.8) - :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) - :pypi:`pytest-logdog` Pytest plugin to test logging Jun 15, 2021 1 - Planning pytest (>=6.2.0) - :pypi:`pytest-logfest` Pytest plugin providing three logger fixtures with basic or full writing to log files Jul 21, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) - :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A - :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Jul 17, 2023 5 - Production/Stable pytest (==7.4.0) - :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A - :pypi:`pytest-loguru` Pytest Loguru Oct 04, 2023 5 - Production/Stable pytest - :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) - :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 13, 2023 3 - Alpha pytest - :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 - :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) - :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 09, 2023 N/A N/A - :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A - :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) - :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A - :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest - :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A - :pypi:`pytest-matcher` Keep a ChangeLog Jan 15, 2024 5 - Production/Stable pytest - :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) - :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A - :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) - :pypi:`pytest-maxcov` Compute the maximum coverage available through pytest with the minimum execution time cost Sep 24, 2023 N/A pytest (>=7.4.0,<8.0.0) - :pypi:`pytest-maybe-context` Simplify tests with warning and exception cases. Apr 16, 2023 N/A pytest (>=7,<8) - :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' - :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) - :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Oct 08, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 - :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Jan 19, 2024 N/A pytest (>=7.4.3) - :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) - :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A - :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 - :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) - :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) - :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A - :pypi:`pytest-metadata` pytest plugin for test session metadata 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 Jan 16, 2024 N/A pytest - :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) - :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) - :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Jan 04, 2024 N/A pytest >=5.0.0 - :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A - :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) - :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Oct 19, 2023 5 - Production/Stable pytest >=5.0 - :pypi:`pytest-mock-api` A mock API server with configurable routes and responses available as a fixture. Feb 13, 2019 1 - Planning pytest (>=4.0.0) - :pypi:`pytest-mock-generator` A pytest fixture wrapper for https://pypi.org/project/mock-generator May 16, 2022 5 - Production/Stable N/A - :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest - :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A - :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Sep 25, 2023 N/A pytest (>=1.0) - :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) - :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest - :pypi:`pytest-modified-env` Pytest plugin to fail a test if it leaves modified \`os.environ\` afterwards. Jan 29, 2022 4 - Beta N/A - :pypi:`pytest-modifyjunit` Utility for adding additional properties to junit xml for IDM QE Jan 10, 2019 N/A N/A - :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest - :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jul 20, 2023 5 - Production/Stable pytest (>=6.2) - :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A - :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest - :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A - :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A - :pypi:`pytest-moto` Fixtures for integration tests of AWS services,uses moto mocking library. Aug 28, 2015 1 - Planning N/A - :pypi:`pytest-motor` A pytest plugin for motor, the non-blocking MongoDB driver. Jul 21, 2021 3 - Alpha pytest - :pypi:`pytest-mp` A test batcher for multiprocessed Pytest runs May 23, 2018 4 - Beta pytest - :pypi:`pytest-mpi` pytest plugin to collect information from tests Jan 08, 2022 3 - Alpha pytest - :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest - :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Jul 23, 2022 4 - Beta pytest - :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Aug 03, 2023 4 - Beta pytest (<8) ; extra == 'test' - :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A - :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest - :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A - :pypi:`pytest-multithreading-allure` pytest_multithreading_allure Nov 25, 2022 N/A N/A - :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) - :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) - :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" - :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jul 25, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 - :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 - :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 - :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest - :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) - :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Oct 26, 2023 N/A pytest <7.3,>=3.5.0 - :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A - :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest - :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) - :pypi:`pytest-nginx` nginx fixture for pytest Aug 12, 2017 5 - Production/Stable N/A - :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A - :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest - :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jan 11, 2024 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest - :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A - :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A - :pypi:`pytest-nocustom` Run all tests without custom markers Jul 07, 2021 5 - Production/Stable N/A - :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) - :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A - :pypi:`pytest-notice` Send pytest execution result email Nov 05, 2020 N/A N/A - :pypi:`pytest-notification` A pytest plugin for sending a desktop notification and playing a sound upon completion of tests Jun 19, 2020 N/A pytest (>=4) - :pypi:`pytest-notifier` A pytest plugin to notify test result Jun 12, 2020 3 - Alpha pytest - :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) - :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A - :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Oct 11, 2023 5 - Production/Stable N/A - :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 - :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest - :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A - :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-odoo` py.test plugin to run Odoo tests Jul 06, 2023 4 - Beta pytest (>=7.2.0) - :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A - :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A - :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) - :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 May 16, 2023 N/A N/A - :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A - :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" - :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 11, 2023 4 - Beta N/A - :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A - :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) - :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Oct 01, 2023 N/A pytest - :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Jun 02, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest - :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 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 - :pypi:`pytest-otel` pytest-otel report OpenTelemetry traces about test executed Jan 18, 2023 N/A N/A - :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A - :pypi:`pytest-owner` Add owner mark for tests Apr 25, 2022 N/A N/A - :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A - :pypi:`pytest-pahrametahrize` Parametrize your tests with a Boston accent. Nov 24, 2021 4 - Beta pytest (>=6.0,<7.0) - :pypi:`pytest-parallel` a pytest plugin for parallel and concurrent testing Oct 10, 2021 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-parallel-39` a pytest plugin for parallel and concurrent testing Jul 12, 2021 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-parallelize-tests` pytest plugin that parallelizes test execution across multiple hosts Jan 27, 2023 4 - Beta N/A - :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) - :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) - :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A - :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) - :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest - :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest - :pypi:`pytest-param-scope` pytest parametrize scope fixture workaround Oct 18, 2023 N/A pytest - :pypi:`pytest-parawtf` Finally spell paramete?ri[sz]e correctly Dec 03, 2018 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-pass` Check out https://github.com/elilutsky/pytest-pass Dec 04, 2019 N/A N/A - :pypi:`pytest-passrunner` Pytest plugin providing the 'run_on_pass' marker Feb 10, 2021 5 - Production/Stable pytest (>=4.6.0) - :pypi:`pytest-paste-config` Allow setting the path to a paste config file Sep 18, 2013 3 - Alpha N/A - :pypi:`pytest-patch` An automagic \`patch\` fixture that can patch objects directly or by name. Apr 29, 2023 3 - Alpha pytest (>=7.0.0) - :pypi:`pytest-patches` A contextmanager pytest fixture for handling multiple mock patches Aug 30, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-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 - :pypi:`pytest-pep8` pytest plugin to check PEP8 requirements Apr 27, 2014 N/A N/A - :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) - :pypi:`pytest-perf` Run performance tests against the mainline code. Jun 02, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' - :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) - :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A - :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) - :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) - :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) - :pypi:`pytest-picked` Run the tests related to the changed files Jul 27, 2023 N/A pytest (>=3.7.0) - :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) - :pypi:`pytest-pikachu` Show surprise when tests are passing Aug 05, 2021 5 - Production/Stable pytest - :pypi:`pytest-pilot` Slice in your test base thanks to powerful markers. Oct 09, 2020 5 - Production/Stable N/A - :pypi:`pytest-pingguo-pytest-plugin` pingguo test Oct 26, 2022 4 - Beta N/A - :pypi:`pytest-pings` 🦊 The pytest plugin for Firefox Telemetry 📊 Jun 29, 2019 3 - Alpha pytest (>=5.0.0) - :pypi:`pytest-pinned` A simple pytest plugin for pinning tests Sep 17, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-pinpoint` A pytest plugin which runs SBFL algorithms to detect faults. Sep 25, 2020 N/A pytest (>=4.4.0) - :pypi:`pytest-pipeline` Pytest plugin for functional testing of data analysispipelines Jan 24, 2017 3 - Alpha N/A - :pypi:`pytest-pitch` runs tests in an order such that coverage increases as fast as possible Nov 02, 2023 4 - Beta pytest >=7.3.1 - :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Oct 09, 2023 N/A pytest (<8.0.0,>=6.2.4) - :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A - :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A - :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A - :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A - :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A - :pypi:`pytest-plone` Pytest plugin to test Plone addons Jan 05, 2023 3 - Alpha pytest - :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest - :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Jan 10, 2024 5 - Production/Stable pytest >=7.4.2 - :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A - :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A - :pypi:`pytest-pokie` Pokie plugin for pytest Oct 19, 2023 5 - Production/Stable N/A - :pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A - :pypi:`pytest-polarion-collect` pytest plugin for collecting polarion test cases data Jun 18, 2020 3 - Alpha pytest - :pypi:`pytest-polecat` Provides Polecat pytest fixtures Aug 12, 2019 4 - Beta N/A - :pypi:`pytest-ponyorm` PonyORM in Pytest Oct 31, 2018 N/A pytest (>=3.1.1) - :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) - :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A - :pypi:`pytest-pook` Pytest plugin for pook Dec 23, 2023 4 - Beta pytest - :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 - :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) - :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) - :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) - :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 - :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) - :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A - :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Aug 25, 2023 5 - Production/Stable pytest>=7.4 - :pypi:`pytest-priority` pytest plugin for add priority for tests Jul 23, 2023 N/A N/A - :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) - :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A - :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A - :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest - :pypi:`pytest-prosper` Test helpers for Prosper projects Sep 24, 2018 N/A N/A - :pypi:`pytest-prysk` Pytest plugin for prysk Dec 30, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) - :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) - :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-pudb` Pytest PuDB debugger integration Oct 25, 2018 3 - Alpha pytest (>=2.0) - :pypi:`pytest-pumpkin-spice` A pytest plugin that makes your test reporting pumpkin-spiced Sep 18, 2022 4 - Beta N/A - :pypi:`pytest-purkinje` py.test plugin for purkinje test runner Oct 28, 2017 2 - Pre-Alpha N/A - :pypi:`pytest-pusher` pytest plugin for push report to minio Jan 06, 2023 5 - Production/Stable pytest (>=3.6) - :pypi:`pytest-py125` Dec 03, 2022 N/A N/A - :pypi:`pytest-pycharm` Plugin for py.test to enter PyCharm debugger on uncaught exceptions Aug 13, 2020 5 - Production/Stable pytest (>=2.3) - :pypi:`pytest-pycodestyle` pytest plugin to run pycodestyle Oct 28, 2022 3 - Alpha N/A - :pypi:`pytest-pydev` py.test plugin to connect to a remote debug server with PyDev or PyCharm. Nov 15, 2017 3 - Alpha N/A - :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A - :pypi:`pytest-pylint` pytest plugin to check source code with pylint Oct 06, 2023 5 - Production/Stable pytest >=7.0 - :pypi:`pytest-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 Dec 09, 2023 N/A pytest - :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A - :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) - :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A - :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest - :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Nov 03, 2023 N/A pytest - :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Aug 20, 2023 4 - Beta pytest >=7.0.0 - :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Jan 02, 2024 N/A pytest (>=7.2.1,<8.0.0) - :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 - :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) - :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) - :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest - :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) - :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) - :pypi:`pytest-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 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 Dec 22, 2023 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A - :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) - :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) - :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Jul 05, 2023 5 - Production/Stable pytest (>=6.2) - :pypi:`pytest-race` Race conditions tester for pytest Jun 07, 2022 4 - Beta N/A - :pypi:`pytest-rage` pytest plugin to implement PEP712 Oct 21, 2011 3 - Alpha N/A - :pypi:`pytest-rail` pytest plugin for creating TestRail runs and adding results May 02, 2022 N/A pytest (>=3.6) - :pypi:`pytest-railflow-testrail-reporter` Generate json reports along with specified metadata defined in test markers. Jun 29, 2022 5 - Production/Stable pytest - :pypi:`pytest-raises` An implementation of pytest.raises as a pytest.mark fixture Apr 23, 2020 N/A pytest (>=3.2.2) - :pypi:`pytest-raisesregexp` Simple pytest plugin to look for regex in Exceptions Dec 18, 2015 N/A N/A - :pypi:`pytest-raisin` Plugin enabling the use of exception instances with pytest.raises Feb 06, 2022 N/A pytest - :pypi:`pytest-random` py.test plugin to randomize tests Apr 28, 2013 3 - Alpha N/A - :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Aug 15, 2023 5 - Production/Stable pytest - :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A - :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A - :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 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. 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 Dec 06, 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) - :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest - :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A - :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A - :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest - :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 - :pypi:`pytest-regtest` "pytest plugin for snapshot regression testing" Jan 15, 2024 N/A pytest>7.2 - :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A - :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) - :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A - :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Sep 26, 2023 5 - Production/Stable pytest >=4.6 - :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) - :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest - :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest - :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jan 11, 2024 5 - Production/Stable pytest - :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest - :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A - :pypi:`pytest-reporter` Generate Pytest reports with templates Jul 22, 2021 4 - Beta pytest - :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Jun 05, 2023 4 - Beta N/A - :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A - :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest - :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest - :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Dec 06, 2023 N/A pytest >=3.8.0 - :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A - :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) - :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A - :pypi:`pytest-requests-futures` Pytest Plugin to Mock Requests Futures Jul 06, 2022 5 - Production/Stable pytest - :pypi:`pytest-requires` A pytest plugin to elegantly skip tests with optional requirements Dec 21, 2021 4 - Beta pytest (>=3.5.0) - :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 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 Jan 10, 2024 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 - :pypi:`pytest-responsemock` Simplified requests calls mocking for pytest Mar 10, 2022 5 - Production/Stable N/A - :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) - :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jul 10, 2023 5 - Production/Stable pytest - :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 - :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 - :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) - :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Jan 04, 2024 N/A pytest >=7.0.0 - :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) - :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A - :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest - :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) - :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest - :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) - :pypi:`pytest-richtrace` A pytest plugin that displays the names and information of the pytest hook functions as they are executed. Jun 20, 2023 N/A N/A - :pypi:`pytest-ringo` pytest plugin to test webapplications using the Ringo webframework Sep 27, 2017 3 - Alpha N/A - :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) - :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest - :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A - :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) - :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) - :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A - :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A - :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Oct 31, 2023 4 - Beta N/A - :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest - :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A - :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest - :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest - :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 - :pypi:`pytest-runtime-yoyo` run case mark timeout Jun 12, 2023 N/A pytest (>=7.2.0) - :pypi:`pytest-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 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. Jan 19, 2024 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 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. Jan 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A - :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A - :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A - :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A - :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest - :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Dec 19, 2023 3 - Alpha pytest >=6.2 - :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A - :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest - :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A - :pypi:`pytest-session_to_file` pytest-session_to_file is a py.test plugin for capturing and saving to file the stdout of py.test. Oct 01, 2015 3 - Alpha N/A - :pypi:`pytest-setupinfo` Displaying setup info during pytest command run Jan 23, 2023 N/A N/A - :pypi:`pytest-sftpserver` py.test plugin to locally test sftp server connections. Sep 16, 2019 4 - Beta N/A - :pypi:`pytest-shard` Dec 11, 2020 4 - Beta pytest - :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) - :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A - :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Jul 02, 2023 5 - Production/Stable pytest (>=7.1.0) - :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest - :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 - :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-simplehttpserver` Simple pytest fixture to spin up an HTTP server Jun 24, 2021 4 - Beta N/A - :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A - :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest - :pypi:`pytest-single-file-logging` Allow for multiple processes to log to a single file May 05, 2016 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-skip-markers` Pytest Salt Plugin Jan 04, 2024 5 - Production/Stable pytest >=7.1.0 - :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 - :pypi:`pytest-slow-last` Run tests in order of execution time (faster tests first) Dec 10, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) - :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A - :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A - :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest - :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A - :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest - :pypi:`pytest-smtp-test-server` pytest plugin for using \`smtp-test-server\` as a fixture Dec 03, 2023 2 - Pre-Alpha pytest (>=7.4.3,<8.0.0) - :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) - :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A - :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-snapshot-with-message-generator` A plugin for snapshot testing with pytest. Jul 25, 2023 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-snmpserver` May 12, 2021 N/A N/A - :pypi:`pytest-snowflake-bdd` Setup test data and run tests on snowflake in BDD style! Jan 05, 2022 4 - Beta pytest (>=6.2.0) - :pypi:`pytest-socket` Pytest Plugin to disable socket calls during tests Feb 03, 2023 4 - Beta pytest (>=3.6.3) - :pypi:`pytest-sofaepione` Test the installation of SOFA and the SofaEpione plugin. Aug 17, 2022 N/A N/A - :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest - :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' - :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Jan 07, 2024 N/A pytest >=7.4.0 - :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) - :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest - :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest - :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest - :pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A - :pypi:`pytest-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. 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 Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A - :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) - :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Jun 11, 2022 6 - Mature pytest (<8.0,>=7.1.2) - :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Apr 12, 2023 4 - Beta pytest (>=5,<8) - :pypi:`pytest-split-ext` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Sep 23, 2023 4 - Beta pytest (>=5,<8) - :pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) - :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) - :pypi:`pytest-split-tests-tresorit` Feb 22, 2021 1 - Planning N/A - :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jan 12, 2024 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 - :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Mar 15, 2023 3 - Alpha pytest (>=2.0) - :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 19, 2023 4 - Beta pytest (>=7.0) - :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest - :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest - :pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A pytest>=6.2.0 - :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest - :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A - :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A - :pypi:`pytest-static` pytest-static Jan 15, 2024 1 - Planning pytest (>=7.4.3,<8.0.0) - :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) - :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest - :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A - :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A - :pypi:`pytest-stf` pytest plugin for openSTF Oct 10, 2023 N/A pytest >=5.0 - :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A - :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) - :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-structlog` Structured logging assertions Dec 18, 2022 N/A pytest - :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A - :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A - :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) - :pypi:`pytest-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) - :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) - :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Apr 10, 2023 4 - Beta pytest (>=6.2.0) - :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A - :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A - :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A - :pypi:`pytest-synodic` Synodic Pytest utilities Jan 12, 2024 N/A pytest>=7.4.4 - :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) - :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A - :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A - :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A - :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) - :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Jul 15, 2023 5 - Production/Stable pytest (>=3.0) - :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A - :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) - :pypi:`pytest-tcp` A Pytest plugin for test prioritization Dec 10, 2023 4 - Beta pytest >=7.4.3 - :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) - :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A - :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A - :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Dec 10, 2020 5 - Production/Stable N/A - :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A - :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-terra-fixt` Terraform and Terragrunt fixtures for pytest Sep 15, 2022 N/A pytest (==6.2.5) - :pypi:`pytest-terraform` A pytest plugin for using terraform fixtures Jun 20, 2023 N/A pytest (>=6.0) - :pypi:`pytest-terraform-fixture` generate terraform resources to use with pytest Nov 14, 2018 4 - Beta N/A - :pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A - :pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest - :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) - :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) - :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A - :pypi:`pytest-testinfra` Test infrastructures Nov 13, 2023 5 - Production/Stable pytest !=3.0.2 - :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 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) - :pypi:`pytest-testobject` Plugin to use TestObject Suites with Pytest Sep 24, 2019 4 - Beta pytest (>=3.1.1) - :pypi:`pytest-testpluggy` set your encoding Jan 07, 2022 N/A pytest - :pypi:`pytest-testrail` pytest plugin for creating TestRail runs and adding results Aug 27, 2020 N/A pytest (>=3.6) - :pypi:`pytest-testrail2` A pytest plugin to upload results to TestRail. Feb 10, 2023 N/A pytest (<8.0,>=7.2.0) - :pypi:`pytest-testrail-api-client` TestRail Api Python Client Dec 14, 2021 N/A pytest - :pypi:`pytest-testrail-appetize` pytest plugin for creating TestRail runs and adding results Sep 29, 2021 N/A N/A - :pypi:`pytest-testrail-client` pytest plugin for Testrail Sep 29, 2020 5 - Production/Stable N/A - :pypi:`pytest-testrail-e2e` pytest plugin for creating TestRail runs and adding results Oct 11, 2021 N/A pytest (>=3.6) - :pypi:`pytest-testrail-integrator` Pytest plugin for sending report to testrail system. Aug 01, 2022 N/A pytest (>=6.2.5) - :pypi:`pytest-testrail-ns` pytest plugin for creating TestRail runs and adding results Aug 12, 2022 N/A N/A - :pypi:`pytest-testrail-plugin` PyTest plugin for TestRail Apr 21, 2020 3 - Alpha pytest - :pypi:`pytest-testrail-reporter` Sep 10, 2018 N/A N/A - :pypi:`pytest-testreport` Dec 01, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-testreport-new` Oct 07, 2023 4 - Beta pytest >=3.5.0 - :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) - :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) - :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) - :pypi:`pytest-tesults` Tesults plugin for pytest Jul 21, 2023 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A - :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A - :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A - :pypi:`pytest-thread` Jul 07, 2023 N/A N/A - :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) - :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest - :pypi:`pytest-timeassert-ethan` execution duration Dec 25, 2023 N/A pytest - :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A - :pypi:`pytest-timeout` pytest plugin to abort hanging tests Oct 08, 2023 5 - Production/Stable pytest >=5.0.0 - :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A - :pypi:`pytest-timer` A timer plugin for pytest Dec 26, 2023 N/A pytest - :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A - :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) - :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Jan 04, 2024 5 - Production/Stable pytest - :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) - :pypi:`pytest-tipsi-django` Nov 17, 2021 4 - Beta pytest (>=6.0.0) - :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Nov 04, 2020 4 - Beta pytest (>=3.3.0) - :pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-tm4j-reporter` Cloud Jira Test Management (TM4J) PyTest reporter plugin Sep 01, 2020 N/A pytest - :pypi:`pytest-tmnet` A small example package Mar 01, 2022 N/A N/A - :pypi:`pytest-tmp-files` Utilities to create temporary file hierarchies in pytest. Dec 08, 2023 N/A pytest - :pypi:`pytest-tmpfs` A pytest plugin that helps you on using a temporary filesystem for testing. Aug 29, 2022 N/A pytest - :pypi:`pytest-tmreport` this is a vue-element ui report for pytest Aug 12, 2022 N/A N/A - :pypi:`pytest-tmux` A pytest plugin that enables tmux driven tests Apr 22, 2023 4 - Beta N/A - :pypi:`pytest-todo` A small plugin for the pytest testing framework, marking TODO comments as failure May 23, 2019 4 - Beta pytest - :pypi:`pytest-tomato` Mar 01, 2019 5 - Production/Stable N/A - :pypi:`pytest-toolbelt` This is just a collection of utilities for pytest, but don't really belong in pytest proper. Aug 12, 2019 3 - Alpha N/A - :pypi:`pytest-toolbox` Numerous useful plugins for pytest. Apr 07, 2018 N/A pytest (>=3.5.0) - :pypi:`pytest-tools` Pytest tools Oct 21, 2022 4 - Beta N/A - :pypi:`pytest-tornado` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Jun 17, 2020 5 - Production/Stable pytest (>=3.6) - :pypi:`pytest-tornado5` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Nov 16, 2018 5 - Production/Stable pytest (>=3.6) - :pypi:`pytest-tornado-yen3` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Oct 15, 2018 5 - Production/Stable N/A - :pypi:`pytest-tornasync` py.test plugin for testing Python 3.5+ Tornado code Jul 15, 2019 3 - Alpha pytest (>=3.0) - :pypi:`pytest-trace` Save OpenTelemetry spans generated during testing Jun 19, 2022 N/A pytest (>=4.6) - :pypi:`pytest-track` Feb 26, 2021 3 - Alpha pytest (>=3.0) - :pypi:`pytest-translations` Test your translation files. Sep 11, 2023 5 - Production/Stable pytest (>=7) - :pypi:`pytest-travis-fold` Folds captured output sections in Travis CI build log Nov 29, 2017 4 - Beta pytest (>=2.6.0) - :pypi:`pytest-trello` Plugin for py.test that integrates trello using markers Nov 20, 2015 5 - Production/Stable N/A - :pypi:`pytest-trepan` Pytest plugin for trepan debugger. Jul 28, 2018 5 - Production/Stable N/A - :pypi:`pytest-trialtemp` py.test plugin for using the same _trial_temp working directory as trial Jun 08, 2015 N/A N/A - :pypi:`pytest-trio` Pytest plugin for trio Nov 01, 2022 N/A pytest (>=7.2.0) - :pypi:`pytest-trytond` Pytest plugin for the Tryton server framework Nov 04, 2022 4 - Beta pytest (>=5) - :pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) - :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A - :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A - :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A - :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A - :pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3) - :pypi:`pytest-typechecker` Run type checkers on specified test files Feb 04, 2022 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-typhoon-config` A Typhoon HIL plugin that facilitates test parameter configuration at runtime Apr 07, 2022 5 - Production/Stable N/A - :pypi:`pytest-typhoon-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 - :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest - :pypi:`pytest-ui-failed-screenshot` UI自动测试失败时自动截图,并将截图加入到测试报告中 Dec 06, 2022 N/A N/A - :pypi:`pytest-ui-failed-screenshot-allure` UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 Dec 06, 2022 N/A N/A - :pypi:`pytest-unflakable` Unflakable plugin for PyTest Nov 12, 2023 4 - Beta pytest >=6.2.0 - :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) - :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) - :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) - :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A - :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) - :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A - :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) - :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A - :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) - :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest - :pypi:`pytest-valgrind` May 19, 2021 N/A N/A - :pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures May 27, 2023 5 - Production/Stable pytest>=7.0.0 - :pypi:`pytest-variant` Variant support for Pytest Jun 06, 2022 N/A N/A - :pypi:`pytest-vcr` Plugin for managing VCR.py cassettes Apr 26, 2019 5 - Production/Stable pytest (>=3.6.0) - :pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Jun 20, 2022 5 - Production/Stable pytest (>=6.2.2) - :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 Nov 23, 2023 4 - Beta pytest - :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Dec 19, 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 - :pypi:`pytest-visual` Nov 01, 2023 3 - Alpha pytest >=7.0.0 - :pypi:`pytest-vnc` VNC client for Pytest Nov 06, 2023 N/A pytest - :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest - :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A - :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest - :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) - :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Jun 01, 2023 N/A pytest (>=7.0.0) - :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A - :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A - :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-wake` Nov 07, 2023 N/A pytest - :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A - :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 24, 2023 4 - Beta N/A - :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A - :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest - :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 13, 2023 N/A pytest >= 7.0.0 - :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable Oct 18, 2023 N/A pytest>=7.3.1 - :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A - :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) - :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A - :pypi:`pytest-winnotify` Windows tray notifications for py.test results. Apr 22, 2016 N/A N/A - :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 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) - :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Sep 29, 2023 4 - Beta pytest (>=7.3,<8.0) - :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) - :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A - :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A - :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Dec 28, 2023 N/A pytest<8,>=7.4.0 - :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest - :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Sep 23, 2023 4 - Beta pytest (>=2.8) - :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A - :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) - :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) - :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A - :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (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 Dec 18, 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) - :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) - :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) - :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A - :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Jan 11, 2024 N/A pytest (>=7.2.2,<8.0.0) - :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 - :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) - :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A - :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jan 08, 2024 5 - Production/Stable pytest (>=4.5.0) - :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Jan 16, 2024 N/A pytest (>=7.4.2,<8.0.0) - :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A - :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) - :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest - =============================================== ======================================================================================================================================================================================================== ============== ===================== ================================================ + =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ + name summary last_release status requires + =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ + :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A + :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) + :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A + :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A + :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) + :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) + :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Nov 08, 2023 N/A pytest >=5.4.0 + :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) + :pypi:`pytest-adf` Pytest plugin for writing Azure Data Factory integration tests May 10, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-ads-testplan` Azure DevOps Test Case reporting for pytest tests Sep 15, 2022 N/A N/A + :pypi:`pytest-affected` Nov 06, 2023 N/A N/A + :pypi:`pytest-agent` Service that exposes a REST API that can be used to interract remotely with Pytest. It is shipped with a dashboard that enables running tests in a more convenient way. Nov 25, 2021 N/A N/A + :pypi:`pytest-aggreport` pytest plugin for pytest-repeat that generate aggregate report of the same test cases with additional statistics details. Mar 07, 2021 4 - Beta pytest (>=6.2.2) + :pypi:`pytest-aio` Pytest plugin for testing async python code Feb 03, 2023 4 - Beta pytest + :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A + :pypi:`pytest-aiogram` May 06, 2023 N/A N/A + :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Sep 06, 2023 4 - Beta pytest >=6.1.0 + :pypi:`pytest-aiohttp-client` Pytest \`client\` fixture for the Aiohttp Jan 10, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-aiomoto` pytest-aiomoto Jun 24, 2023 N/A pytest (>=7.0,<8.0) + :pypi:`pytest-aioresponses` py.test integration for aioresponses Jul 29, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 + :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) + :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 06, 2023 N/A pytest (>=6.0) + :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest + :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) + :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) + :pypi:`pytest-allure-collection` pytest plugin to collect allure markers without running any tests Apr 13, 2023 N/A pytest + :pypi:`pytest-allure-dsl` pytest plugin to test case doc string dls instructions Oct 25, 2020 4 - Beta pytest + :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) + :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest + :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Dec 06, 2023 N/A pytest >=7.3.1 + :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest + :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jan 18, 2024 5 - Production/Stable pytest >=6 + :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A + :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) + :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A + :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 Jan 18, 2024 N/A pytest + :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 + :pypi:`pytest-apistellar` apistellar plugin for pytest. Jun 18, 2019 N/A N/A + :pypi:`pytest-appengine` AppEngine integration that works well with pytest-django Feb 27, 2017 N/A N/A + :pypi:`pytest-appium` Pytest plugin for appium Dec 05, 2019 N/A N/A + :pypi:`pytest-approvaltests` A plugin to use approvaltests with pytest May 08, 2022 4 - Beta pytest (>=7.0.1) + :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Dec 12, 2023 5 - Production/Stable pytest + :pypi:`pytest-archon` Rule your architecture like a real developer Dec 18, 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 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 Dec 20, 2023 4 - Beta N/A + :pypi:`pytest-asptest` test Answer Set Programming programs Apr 28, 2018 4 - Beta N/A + :pypi:`pytest-assertcount` Plugin to count actual number of asserts in pytest Oct 23, 2022 N/A pytest (>=5.0.0) + :pypi:`pytest-assertions` Pytest Assertions Apr 27, 2022 N/A N/A + :pypi:`pytest-assertutil` pytest-assertutil May 10, 2019 N/A N/A + :pypi:`pytest-assert-utils` Useful assertion utilities for use with pytest Apr 14, 2022 3 - Alpha N/A + :pypi:`pytest-assume` A pytest plugin that allows multiple failures per test Jun 24, 2021 N/A pytest (>=2.7) + :pypi:`pytest-assurka` A pytest plugin for Assurka Studio Aug 04, 2022 N/A N/A + :pypi:`pytest-ast-back-to-python` A plugin for pytest devs to view how assertion rewriting recodes the AST Sep 29, 2019 4 - Beta N/A + :pypi:`pytest-asteroid` PyTest plugin for docker-based testing on database images Aug 15, 2022 N/A pytest (>=6.2.5,<8.0.0) + :pypi:`pytest-astropy` Meta-package containing dependencies for testing Sep 26, 2023 5 - Production/Stable pytest >=4.6 + :pypi:`pytest-astropy-header` pytest plugin to add diagnostic information to the header of the test output Sep 06, 2022 3 - Alpha pytest (>=4.6) + :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest + :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A + :pypi:`pytest-asyncio` Pytest support for asyncio Jan 16, 2024 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进行自定义 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 + :pypi:`pytest-autocap` automatically capture test & fixture stdout/stderr to files May 15, 2022 N/A pytest (<7.2,>=7.1.2) + :pypi:`pytest-autochecklog` automatically check condition and log all the checks Apr 25, 2015 4 - Beta N/A + :pypi:`pytest-automation` pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. May 20, 2022 N/A pytest (>=7.0.0) + :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' + :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A + :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest + :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest + :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A + :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A + :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) + :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest + :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest + :pypi:`pytest-azure-devops` Simplifies using azure devops parallel strategy (https://docs.microsoft.com/en-us/azure/devops/pipelines/test/parallel-testing-any-test-runner) with pytest. Jun 20, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-azurepipelines` Formatting PyTest output for Azure Pipelines UI Oct 06, 2023 5 - Production/Stable pytest (>=5.0.0) + :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) + :pypi:`pytest-bdd` BDD for pytest Dec 02, 2023 6 - Mature pytest (>=6.2.0) + :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) + :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 15, 2023 N/A pytest >=7.1.3 + :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) + :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A + :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest + :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest + :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A + :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A + :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A + :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) + :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A + :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A + :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) + :pypi:`pytest-black` A pytest plugin to enable format checking with black Oct 05, 2020 4 - Beta N/A + :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' + :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-blame` A pytest plugin helps developers to debug by providing useful commits history. May 04, 2019 N/A pytest (>=4.4.0) + :pypi:`pytest-blender` Blender Pytest plugin. Aug 10, 2023 N/A pytest ; extra == 'dev' + :pypi:`pytest-blink1` Pytest plugin to emit notifications via the Blink(1) RGB LED Jan 07, 2018 4 - Beta N/A + :pypi:`pytest-blockage` Disable network requests during a test run. Dec 21, 2021 N/A pytest + :pypi:`pytest-blocker` pytest plugin to mark a test as blocker and skip all other tests Sep 07, 2015 4 - Beta N/A + :pypi:`pytest-blue` A pytest plugin that adds a \`blue\` fixture for printing stuff in blue. Sep 05, 2022 N/A N/A + :pypi:`pytest-board` Local continuous test runner with pytest and watchdog. Jan 20, 2019 N/A N/A + :pypi:`pytest-boost-xml` Plugin for pytest to generate boost xml reports Nov 30, 2022 4 - Beta N/A + :pypi:`pytest-bootstrap` Mar 04, 2022 N/A N/A + :pypi:`pytest-bpdb` A py.test plug-in to enable drop to bpdb debugger on test failure. Jan 19, 2015 2 - Pre-Alpha N/A + :pypi:`pytest-bravado` Pytest-bravado automatically generates from OpenAPI specification client fixtures. Feb 15, 2022 N/A N/A + :pypi:`pytest-breakword` Use breakword with pytest Aug 04, 2021 N/A pytest (>=6.2.4,<7.0.0) + :pypi:`pytest-breed-adapter` A simple plugin to connect with breed-server Nov 07, 2018 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-briefcase` A pytest plugin for running tests on a Briefcase project. Jun 14, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-browser` A pytest plugin for console based browser test selection just after the collection phase Dec 10, 2016 3 - Alpha N/A + :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A + :pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A + :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest + :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Sep 23, 2023 5 - Production/Stable pytest >=7.1.0 + :pypi:`pytest-bugtong-tag` pytest-bugtong-tag is a plugin for pytest Jan 16, 2022 N/A N/A + :pypi:`pytest-bugzilla` py.test bugzilla integration plugin May 05, 2010 4 - Beta N/A + :pypi:`pytest-bugzilla-notifier` A plugin that allows you to execute create, update, and read information from BugZilla bugs Jun 15, 2018 4 - Beta pytest (>=2.9.2) + :pypi:`pytest-buildkite` Plugin for pytest that automatically publishes coverage and pytest report annotations to Buildkite. Jul 13, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-builtin-types` Nov 17, 2021 N/A pytest + :pypi:`pytest-bwrap` Run your tests in Bubblewrap sandboxes Oct 26, 2018 3 - Alpha N/A + :pypi:`pytest-cache` pytest plugin with mechanisms for caching across test runs Jun 04, 2013 3 - Alpha N/A + :pypi:`pytest-cache-assert` Cache assertion data to simplify regression testing of complex serializable data Aug 14, 2023 5 - Production/Stable pytest (>=6.0.0) + :pypi:`pytest-cagoule` Pytest plugin to only run tests affected by changes Jan 01, 2020 3 - Alpha N/A + :pypi:`pytest-cairo` Pytest support for cairo-lang and starknet Apr 17, 2022 N/A pytest + :pypi:`pytest-call-checker` Small pytest utility to easily create test doubles Oct 16, 2022 4 - Beta pytest (>=7.1.3,<8.0.0) + :pypi:`pytest-camel-collect` Enable CamelCase-aware pytest class collection Aug 02, 2020 N/A pytest (>=2.9) + :pypi:`pytest-canonical-data` A plugin which allows to compare results with canonical results, based on previous runs May 08, 2020 2 - Pre-Alpha pytest (>=3.5.0) + :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A + :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A + :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest + :pypi:`pytest-cases` Separate test code from test cases in pytest. Jan 12, 2024 5 - Production/Stable N/A + :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A + :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) + :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 14, 2024 N/A N/A + :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A + :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A + :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A + :pypi:`pytest-change-demo` turn . into √,turn F into x Mar 02, 2022 N/A pytest + :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest + :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest + :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 18, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 + :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A + :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A + :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest>=7.0 + :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 Dec 26, 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 + :pypi:`pytest-circleci-parallelized-rjp` Parallelize pytest across CircleCI workers. Jun 21, 2022 N/A pytest + :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest + :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A + :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) + :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 25, 2023 4 - Beta N/A + :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) + :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) + :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A + :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-cmake` Provide CMake module for Pytest Jul 19, 2023 N/A pytest<8,>=4 + :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) + :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest + :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A + :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Nov 29, 2022 4 - Beta pytest (>=4.6.0) + :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A + :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Sep 01, 2023 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest + :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A + :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A + :pypi:`pytest-collect-interface-info-plugin` Get executed interface information in pytest interface automation framework Sep 25, 2023 4 - Beta N/A + :pypi:`pytest-collector` Python package for collecting pytest. Aug 02, 2022 N/A pytest (>=7.0,<8.0) + :pypi:`pytest-collect-pytest-interinfo` A simple plugin to use with pytest Sep 26, 2023 4 - Beta N/A + :pypi:`pytest-colordots` Colorizes the progress indicators Oct 06, 2017 5 - Production/Stable N/A + :pypi:`pytest-commander` An interactive GUI test runner for PyTest Aug 17, 2021 N/A pytest (<7.0.0,>=6.2.4) + :pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method May 15, 2022 N/A pytest (>=3.6,<8) + :pypi:`pytest-compare` pytest plugin for comparing call arguments. Jun 22, 2023 5 - Production/Stable N/A + :pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1) + :pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A + :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A + :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) + :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest + :pypi:`pytest-container` Pytest fixtures for writing container based tests Sep 26, 2023 4 - Beta pytest (>=3.10) + :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A + :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A + :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) + :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Jan 27, 2024 3 - Alpha pytest + :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 + :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A + :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A + :pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A + :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A + :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' + :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 26, 2023 N/A N/A + :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A + :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) + :pypi:`pytest-crayons` A pytest plugin for colorful print statements Oct 08, 2023 N/A pytest + :pypi:`pytest-create` pytest-create Feb 15, 2023 1 - Planning N/A + :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest + :pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A + :pypi:`pytest-csv` CSV output for pytest. Apr 22, 2021 N/A pytest (>=6.0) + :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Jul 01, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) + :pypi:`pytest-curio` Pytest support for curio. Oct 07, 2020 N/A N/A + :pypi:`pytest-curl-report` pytest plugin to generate curl command line report Dec 11, 2016 4 - Beta N/A + :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A + :pypi:`pytest-custom-exit-code` Exit pytest test session with custom exit code in different scenarios Aug 07, 2019 4 - Beta pytest (>=4.0.2) + :pypi:`pytest-custom-nodeid` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 07, 2021 N/A N/A + :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest + :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A + :pypi:`pytest-cython` A plugin for testing Cython extension modules Feb 16, 2023 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest + :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Aug 16, 2020 N/A pytest (>=6.0.1) ; extra == 'test' + :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A + :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A + :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest + :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 + :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) + :pypi:`pytest-datadir-ng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Dec 25, 2019 5 - Production/Stable pytest + :pypi:`pytest-datadir-nng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Nov 09, 2022 5 - Production/Stable pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-data-extractor` A pytest plugin to extract relevant metadata about tests into an external file (currently only json support) Jul 19, 2022 N/A pytest (>=7.0.1) + :pypi:`pytest-data-file` Fixture "data" and "case_data" for test from yaml file Dec 04, 2019 N/A N/A + :pypi:`pytest-datafiles` py.test plugin to create a 'tmp_path' containing predefined files/directories. Feb 24, 2023 5 - Production/Stable pytest (>=3.6) + :pypi:`pytest-datafixtures` Data fixtures for pytest made simple Dec 05, 2020 5 - Production/Stable N/A + :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest + :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A + :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jan 08, 2023 5 - Production/Stable pytest + :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A + :pypi:`pytest-data-suites` Class-based pytest parametrization Jul 24, 2022 N/A pytest (>=6.0,<8.0) + :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) + :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Dec 04, 2019 N/A N/A + :pypi:`pytest-dbfixtures` Databases fixtures plugin for py.test. Dec 07, 2016 4 - Beta N/A + :pypi:`pytest-db-plugin` Nov 27, 2021 N/A pytest (>=5.0) + :pypi:`pytest-dbt` Unit test dbt models with standard python tooling Jun 08, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) + :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-dbt-core` Pytest extension for dbt. Aug 25, 2023 N/A pytest >=6.2.5 ; extra == 'test' + :pypi:`pytest-dbt-postgres` Pytest tooling to unittest DBT & Postgres models Jan 02, 2024 N/A pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A + :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) + :pypi:`pytest-dc` Manages Docker containers during your integration tests Aug 16, 2023 5 - Production/Stable pytest >=3.3 + :pypi:`pytest-deadfixtures` A simple plugin to list unused fixtures in pytest Jul 23, 2020 5 - Production/Stable N/A + :pypi:`pytest-deduplicate` Identifies duplicate unit tests Aug 12, 2023 4 - Beta pytest + :pypi:`pytest-deepcov` deepcov Mar 30, 2021 N/A N/A + :pypi:`pytest-defer` Aug 24, 2021 N/A N/A + :pypi:`pytest-demo-plugin` pytest示例插件 May 15, 2021 N/A N/A + :pypi:`pytest-dependency` Manage dependencies of tests Dec 31, 2023 4 - Beta N/A + :pypi:`pytest-depends` Tests that depend on other tests Apr 05, 2020 5 - Production/Stable pytest (>=3) + :pypi:`pytest-deprecate` Mark tests as testing a deprecated feature with a warning note. Jul 01, 2019 N/A N/A + :pypi:`pytest-describe` Describe-style plugin for pytest Apr 09, 2023 5 - Production/Stable pytest (<8,>=4.6) + :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest + :pypi:`pytest-devpi-server` DevPI server fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-dhos` Common fixtures for pytest in DHOS services and libraries Sep 07, 2022 N/A N/A + :pypi:`pytest-diamond` pytest plugin for diamond Aug 31, 2015 4 - Beta N/A + :pypi:`pytest-dicom` pytest plugin to provide DICOM fixtures Dec 19, 2018 3 - Alpha pytest + :pypi:`pytest-dictsdiff` Jul 26, 2019 N/A N/A + :pypi:`pytest-diff` A simple plugin to use with pytest Mar 30, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all' + :pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0) + :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 11, 2023 4 - Beta pytest>=7.3.2 + :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A + :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 + :pypi:`pytest-django` A Django plugin for pytest. Nov 08, 2023 5 - Production/Stable pytest >=7.0.0 + :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) + :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest + :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A + :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A + :pypi:`pytest-django-class` A pytest plugin for running django in class-scoped fixtures Aug 08, 2023 4 - Beta N/A + :pypi:`pytest-django-docker-pg` Jan 05, 2024 5 - Production/Stable pytest >=7.0.0 + :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) + :pypi:`pytest-django-factories` Factories for your Django models that can be used as Pytest fixtures. Nov 12, 2020 4 - Beta N/A + :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 + :pypi:`pytest-django-gcir` A Django plugin for pytest. Mar 06, 2018 5 - Production/Stable N/A + :pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4) + :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Aug 27, 2023 5 - Production/Stable N/A + :pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A + :pypi:`pytest-django-liveserver-ssl` Jan 20, 2022 3 - Alpha N/A + :pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A + :pypi:`pytest-django-ordering` A pytest plugin for preserving the order in which Django runs tests. Jul 25, 2019 5 - Production/Stable pytest (>=2.3.0) + :pypi:`pytest-django-queries` Generate performance reports from your django database performance tests. Mar 01, 2021 N/A N/A + :pypi:`pytest-djangorestframework` A djangorestframework plugin for pytest Aug 11, 2019 4 - Beta N/A + :pypi:`pytest-django-rq` A pytest plugin to help writing unit test for django-rq Apr 13, 2020 4 - Beta N/A + :pypi:`pytest-django-sqlcounts` py.test plugin for reporting the number of SQLs executed per django testcase. Jun 16, 2015 4 - Beta N/A + :pypi:`pytest-django-testing-postgresql` Use a temporary PostgreSQL database with pytest-django Jan 31, 2022 4 - Beta N/A + :pypi:`pytest-doc` A documentation plugin for py.test. Jun 28, 2015 5 - Production/Stable N/A + :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) + :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A + :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Jan 27, 2024 N/A pytest <8.0,>=4.0 + :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Feb 16, 2022 4 - Beta pytest + :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A + :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) + :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) + :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) + :pypi:`pytest-docker-fixtures` pytest docker fixtures Nov 17, 2023 3 - Alpha N/A + :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Feb 09, 2022 4 - Beta pytest + :pypi:`pytest-docker-haproxy-fixtures` Pytest fixtures for testing with haproxy. Feb 09, 2022 4 - Beta pytest + :pypi:`pytest-docker-pexpect` pytest plugin for writing functional tests with pexpect and docker Jan 14, 2019 N/A pytest + :pypi:`pytest-docker-postgresql` A simple plugin to use with pytest Sep 24, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-docker-py` Easy to use, simple to extend, pytest plugin that minimally leverages docker-py. Nov 27, 2018 N/A pytest (==4.0.0) + :pypi:`pytest-docker-registry-fixtures` Pytest fixtures for testing with docker registries. Apr 08, 2022 4 - Beta pytest + :pypi:`pytest-docker-service` pytest plugin to start docker container Jan 03, 2024 3 - Alpha pytest (>=7.1.3) + :pypi:`pytest-docker-squid-fixtures` Pytest fixtures for testing with squid. Feb 09, 2022 4 - Beta pytest + :pypi:`pytest-docker-tools` Docker integration tests for pytest Feb 17, 2022 4 - Beta pytest (>=6.0.1) + :pypi:`pytest-docs` Documentation tool for pytest Nov 11, 2018 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-docstyle` pytest plugin to run pydocstyle Mar 23, 2020 3 - Alpha N/A + :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A + :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A + :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Dec 13, 2023 5 - Production/Stable 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 Dec 14, 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) + :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) + :pypi:`pytest-dot-only-pkcopley` A Pytest marker for only running a single test Oct 27, 2023 N/A N/A + :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest + :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) + :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A + :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection May 23, 2020 4 - Beta pytest (>=2.7) + :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 18, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) + :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest + :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A + :pypi:`pytest-duration-insights` Jun 25, 2021 N/A N/A + :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Apr 22, 2022 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A + :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Jun 12, 2023 5 - Production/Stable pytest + :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A + :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A + :pypi:`pytest-easyread` pytest plugin that makes terminal printouts of the reports easier to read Nov 17, 2017 N/A N/A + :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" + :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A + :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A + :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 + :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest + :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Sep 13, 2023 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) + :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) + :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-email` Send execution result email Jul 08, 2020 N/A pytest + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jan 22, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 22, 2024 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) + :pypi:`pytest-enabler` Enable installed pytest plugins Dec 23, 2023 5 - Production/Stable pytest >=6 ; extra == 'testing' + :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A + :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest + :pypi:`pytest-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. 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) + :pypi:`pytest-envvars` Pytest plugin to validate use of envvars on your tests Jun 13, 2020 5 - Production/Stable pytest (>=3.0.0) + :pypi:`pytest-env-yaml` Apr 02, 2019 N/A N/A + :pypi:`pytest-eradicate` pytest plugin to check for commented out code Sep 08, 2020 N/A pytest (>=2.4.2) + :pypi:`pytest-error-for-skips` Pytest plugin to treat skipped tests a test failure Dec 19, 2019 4 - Beta pytest (>=4.6) + :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A + :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' + :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) + :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' + :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Jan 24, 2024 4 - Beta pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 + :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A + :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A + :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest + :pypi:`pytest-executable` pytest plugin for testing executables Oct 07, 2023 N/A pytest <8,>=5 + :pypi:`pytest-execution-timer` A timer for the phases of Pytest's execution. Dec 24, 2021 4 - Beta N/A + :pypi:`pytest-expect` py.test plugin to store test expectations and mark tests based on them Apr 21, 2016 4 - Beta N/A + :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-expecter` Better testing with expecter and pytest. Sep 18, 2022 5 - Production/Stable N/A + :pypi:`pytest-expectr` This plugin is used to expect multiple assert using pytest framework. Oct 05, 2018 N/A pytest (>=2.4.2) + :pypi:`pytest-expect-test` A fixture to support expect tests in pytest Apr 10, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-experiments` A pytest plugin to help developers of research-oriented software projects keep track of the results of their numerical experiments. Dec 13, 2021 4 - Beta pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-explicit` A Pytest plugin to ignore certain marked tests by default Jun 15, 2021 5 - Production/Stable pytest + :pypi:`pytest-exploratory` Interactive console for pytest. Aug 18, 2023 N/A pytest (>=6.2) + :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A + :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' + :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest + :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest + :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A + :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) + :pypi:`pytest-factoryboy` Factory Boy support for pytest. Oct 10, 2023 6 - Mature pytest (>=6.2) + :pypi:`pytest-factoryboy-fixtures` Generates pytest fixtures that allow the use of type hinting Jun 25, 2020 N/A N/A + :pypi:`pytest-factoryboy-state` Simple factoryboy random state management Mar 22, 2022 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-failed-screen-record` Create a video of the screen when pytest fails Jan 05, 2023 4 - Beta pytest (>=7.1.2d,<8.0.0) + :pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A + :pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0) + :pypi:`pytest-fail-slow` Fail tests that take too long to run Oct 21, 2023 N/A pytest >=6.0 + :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A + :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A + :pypi:`pytest-falcon-client` Pytest \`client\` fixture for the Falcon Framework Mar 19, 2019 N/A N/A + :pypi:`pytest-fantasy` Pytest plugin for Flask Fantasy Framework Mar 14, 2019 N/A N/A + :pypi:`pytest-fastapi` Dec 27, 2020 N/A N/A + :pypi:`pytest-fastapi-deps` A fixture which allows easy replacement of fastapi dependencies for testing Jul 20, 2022 5 - Production/Stable pytest + :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) + :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest + :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) + :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) + :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A + :pypi:`pytest-filecov` A pytest plugin to detect unused files Jun 27, 2021 4 - Beta pytest + :pypi:`pytest-filedata` easily load data from files Jan 17, 2019 4 - Beta N/A + :pypi:`pytest-filemarker` A pytest plugin that runs marked tests when files change. Dec 01, 2020 N/A pytest + :pypi:`pytest-file-watcher` Pytest-File-Watcher is a CLI tool that watches for changes in your code and runs pytest on the changed files. Mar 23, 2023 N/A pytest + :pypi:`pytest-filter-case` run test cases filter by mark Nov 05, 2020 N/A N/A + :pypi:`pytest-filter-subpackage` Pytest plugin for filtering based on sub-packages Dec 12, 2022 3 - Alpha pytest (>=3.0) + :pypi:`pytest-find-dependencies` A pytest plugin to find dependencies between tests Apr 09, 2022 4 - Beta pytest (>=4.3.0) + :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) + :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) + :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest + :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Nov 09, 2023 4 - Beta pytest >=3.5.0 + :pypi:`pytest-fixture-config` Fixture configuration utils for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-fixture-maker` Pytest plugin to load fixtures from YAML files Sep 21, 2021 N/A N/A + :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A + :pypi:`pytest-fixture-order` pytest plugin to control fixture evaluation order May 16, 2022 5 - Production/Stable pytest (>=3.0) + :pypi:`pytest-fixture-ref` Lets users reference fixtures without name matching magic. Nov 17, 2022 4 - Beta N/A + :pypi:`pytest-fixture-rtttg` Warn or fail on fixture name clash Feb 23, 2022 N/A pytest (>=7.0.1,<8.0.0) + :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A + :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest + :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest + :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Mar 18, 2022 4 - Beta pytest (>=7.0) + :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jul 10, 2023 5 - Production/Stable pytest + :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) + :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) + :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) + :pypi:`pytest-flaptastic` Flaptastic py.test plugin Mar 17, 2019 N/A N/A + :pypi:`pytest-flask` A set of py.test fixtures to test Flask applications. Oct 23, 2023 5 - Production/Stable pytest >=5.2 + :pypi:`pytest-flask-ligand` Pytest fixtures and helper functions to use for testing flask-ligand microservices. Apr 25, 2023 4 - Beta pytest (~=7.3) + :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) + :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) + :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest + :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jun 26, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest + :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest + :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A + :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A + :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A + :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Oct 29, 2023 4 - Beta pytest>=7.0.0 + :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 + :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A + :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) + :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) + :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 Dec 15, 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. Dec 18, 2023 3 - Alpha pytest + :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest + :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) + :pypi:`pytest-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. Jan 25, 2024 N/A pytest>=3.6 + :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 + :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest + :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A + :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) + :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A + :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A + :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A + :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 + :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A + :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest + :pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest + :pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2) + :pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest + :pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A + :pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A + :pypi:`pytest-group-by-class` A Pytest plugin for running a subset of your tests by splitting them in to groups of classes. Jun 27, 2023 5 - Production/Stable pytest (>=2.5) + :pypi:`pytest-growl` Growl notifications for pytest results. Jan 13, 2014 5 - Production/Stable N/A + :pypi:`pytest-grpc` pytest plugin for grpc May 01, 2020 N/A pytest (>=3.6.0) + :pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Feb 05, 2023 N/A N/A + :pypi:`pytest-hammertime` Display "🔨 " instead of "." for passed pytest tests. Jul 28, 2018 N/A pytest + :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Jun 10, 2022 5 - Production/Stable N/A + :pypi:`pytest-helm-chart` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Jun 15, 2020 4 - Beta pytest (>=5.4.2,<6.0.0) + :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Sep 13, 2023 4 - Beta pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A + :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest + :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) + :pypi:`pytest-henry` Aug 29, 2023 N/A N/A + :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 Jan 14, 2024 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 Jan 21, 2024 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` Jan 06, 2024 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. Dec 25, 2023 N/A pytest + :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) + :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) + :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) + :pypi:`pytest-html` pytest plugin for generating HTML reports Nov 07, 2023 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A + :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-html-merger` Pytest HTML reports merging utility Nov 11, 2023 N/A N/A + :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Jan 17, 2024 5 - Production/Stable N/A + :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) + :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A + :pypi:`pytest-html-report-merger` Oct 23, 2023 N/A N/A + :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A + :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A + :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 + :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A + :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A + :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A + :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-httpx` Send responses to httpx. Dec 21, 2023 5 - Production/Stable pytest ==7.* + :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) + :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest + :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A + :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest + :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Jan 24, 2024 3 - Alpha pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 + :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest + :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A + :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Dec 13, 2023 5 - Production/Stable N/A + :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A + :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. 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 + :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A + :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A + :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A + :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A + :pypi:`pytest-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. Dec 13, 2023 5 - Production/Stable pytest + :pypi:`pytest-inmanta-extensions` Inmanta tests package Jan 04, 2024 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) + :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) + :pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0) + :pypi:`pytest-integration` Organizing pytests by integration or not Nov 17, 2022 N/A N/A + :pypi:`pytest-integration-mark` Automatic integration test marking and excluding plugin for pytest 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. Jan 26, 2024 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 + :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A + :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest + :pypi:`pytest-isort` py.test plugin to check import ordering using isort Oct 31, 2022 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 22, 2020 4 - Beta N/A + :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A + :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A + :pypi:`pytest-jasmine` Run jasmine tests from your pytest test suite Nov 04, 2017 1 - Planning N/A + :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) + :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Jun 12, 2023 3 - Alpha N/A + :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Sep 08, 2023 4 - Beta pytest >=6.2.4 + :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest + :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) + :pypi:`pytest-json` Generate JSON test reports Jan 18, 2016 4 - Beta N/A + :pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Mar 14, 2023 4 - Beta N/A + :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A + :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) + :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 + :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Dec 05, 2023 4 - Beta pytest + :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest + :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest + :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest + :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-keep-together` Pytest plugin to customize test ordering by running all 'related' tests together Dec 07, 2022 5 - Production/Stable pytest + :pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Oct 01, 2023 N/A pytest (>=7.1) + :pypi:`pytest-kind` Kubernetes test support with KIND for pytest Nov 30, 2022 5 - Production/Stable N/A + :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) + :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A + :pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A + :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A + :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-kwparametrize` Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks Jan 22, 2021 N/A pytest (>=6) + :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. Aug 20, 2022 3 - Alpha pytest (>=3.6,<8) + :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A + :pypi:`pytest-langchain` Pytest-style test runner for langchain agents Feb 26, 2023 N/A pytest + :pypi:`pytest-lark` Create fancy and clear HTML test reports. Nov 05, 2023 N/A N/A + :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) + :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A + :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. May 28, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest + :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A + :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest + :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A + :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest + :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A + :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest + :pypi:`pytest-line-profiler` Profile code executed by pytest Aug 10, 2023 4 - Beta pytest >=3.5.0 + :pypi:`pytest-line-profiler-apn` Profile code executed by pytest Dec 05, 2022 N/A pytest (>=3.5.0) + :pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) + :pypi:`pytest-listener` A simple network listener May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-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. 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 + :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A + :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) + :pypi:`pytest-lock` pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. Jan 27, 2024 N/A pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-lockable` lockable resource plugin for pytest Jan 24, 2024 5 - Production/Stable pytest + :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) + :pypi:`pytest-log` print log Aug 15, 2021 N/A pytest (>=3.8) + :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) + :pypi:`pytest-logdog` Pytest plugin to test logging Jun 15, 2021 1 - Planning pytest (>=6.2.0) + :pypi:`pytest-logfest` Pytest plugin providing three logger fixtures with basic or full writing to log files Jul 21, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) + :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A + :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-logikal` Common testing environment Jan 27, 2024 5 - Production/Stable pytest ==7.4.4 + :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A + :pypi:`pytest-loguru` Pytest Loguru Oct 04, 2023 5 - Production/Stable pytest + :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) + :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 13, 2023 3 - Alpha pytest + :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 + :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) + :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) + :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 09, 2023 N/A N/A + :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A + :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) + :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A + :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest + :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A + :pypi:`pytest-matcher` Keep a ChangeLog Jan 15, 2024 5 - Production/Stable pytest + :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) + :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A + :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) + :pypi:`pytest-maxcov` Compute the maximum coverage available through pytest with the minimum execution time cost Sep 24, 2023 N/A pytest (>=7.4.0,<8.0.0) + :pypi:`pytest-maybe-context` Simplify tests with warning and exception cases. Apr 16, 2023 N/A pytest (>=7,<8) + :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' + :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) + :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) + :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Oct 08, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Jan 19, 2024 N/A pytest (>=7.4.3) + :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) + :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A + :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 + :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) + :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A + :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) + :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) + :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A + :pypi:`pytest-metadata` pytest plugin for test session metadata 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 Jan 16, 2024 N/A pytest + :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) + :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) + :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Jan 04, 2024 N/A pytest >=5.0.0 + :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A + :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) + :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Oct 19, 2023 5 - Production/Stable pytest >=5.0 + :pypi:`pytest-mock-api` A mock API server with configurable routes and responses available as a fixture. Feb 13, 2019 1 - Planning pytest (>=4.0.0) + :pypi:`pytest-mock-generator` A pytest fixture wrapper for https://pypi.org/project/mock-generator May 16, 2022 5 - Production/Stable N/A + :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest + :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A + :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Sep 25, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) + :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest + :pypi:`pytest-modified-env` Pytest plugin to fail a test if it leaves modified \`os.environ\` afterwards. Jan 29, 2022 4 - Beta N/A + :pypi:`pytest-modifyjunit` Utility for adding additional properties to junit xml for IDM QE Jan 10, 2019 N/A N/A + :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest + :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) + :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) + :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jul 20, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A + :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest + :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A + :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A + :pypi:`pytest-moto` Fixtures for integration tests of AWS services,uses moto mocking library. Aug 28, 2015 1 - Planning N/A + :pypi:`pytest-motor` A pytest plugin for motor, the non-blocking MongoDB driver. Jul 21, 2021 3 - Alpha pytest + :pypi:`pytest-mp` A test batcher for multiprocessed Pytest runs May 23, 2018 4 - Beta pytest + :pypi:`pytest-mpi` pytest plugin to collect information from tests Jan 08, 2022 3 - Alpha pytest + :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest + :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Jul 23, 2022 4 - Beta pytest + :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) + :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Aug 03, 2023 4 - Beta pytest (<8) ; extra == 'test' + :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A + :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest + :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A + :pypi:`pytest-multithreading-allure` pytest_multithreading_allure Nov 25, 2022 N/A N/A + :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) + :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) + :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" + :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jul 25, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 + :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 + :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 + :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest + :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) + :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Oct 26, 2023 N/A pytest <7.3,>=3.5.0 + :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A + :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest + :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) + :pypi:`pytest-nginx` nginx fixture for pytest Aug 12, 2017 5 - Production/Stable N/A + :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A + :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest + :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jan 11, 2024 N/A pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest + :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A + :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A + :pypi:`pytest-nocustom` Run all tests without custom markers Jul 07, 2021 5 - Production/Stable N/A + :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) + :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A + :pypi:`pytest-notice` Send pytest execution result email Nov 05, 2020 N/A N/A + :pypi:`pytest-notification` A pytest plugin for sending a desktop notification and playing a sound upon completion of tests Jun 19, 2020 N/A pytest (>=4) + :pypi:`pytest-notifier` A pytest plugin to notify test result Jun 12, 2020 3 - Alpha pytest + :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) + :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A + :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Oct 11, 2023 5 - Production/Stable N/A + :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 + :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest + :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A + :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-odoo` py.test plugin to run Odoo tests Jul 06, 2023 4 - Beta pytest (>=7.2.0) + :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A + :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A + :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 May 16, 2023 N/A N/A + :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A + :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" + :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 11, 2023 4 - Beta N/A + :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A + :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) + :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Oct 01, 2023 N/A pytest + :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Jun 02, 2022 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest + :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 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 + :pypi:`pytest-otel` pytest-otel report OpenTelemetry traces about test executed Jan 18, 2023 N/A N/A + :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A + :pypi:`pytest-owner` Add owner mark for tests Apr 25, 2022 N/A N/A + :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A + :pypi:`pytest-pahrametahrize` Parametrize your tests with a Boston accent. Nov 24, 2021 4 - Beta pytest (>=6.0,<7.0) + :pypi:`pytest-parallel` a pytest plugin for parallel and concurrent testing Oct 10, 2021 3 - Alpha pytest (>=3.0.0) + :pypi:`pytest-parallel-39` a pytest plugin for parallel and concurrent testing Jul 12, 2021 3 - Alpha pytest (>=3.0.0) + :pypi:`pytest-parallelize-tests` pytest plugin that parallelizes test execution across multiple hosts Jan 27, 2023 4 - Beta N/A + :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) + :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) + :pypi:`pytest-parameterize-from-files` A pytest plugin that parameterizes tests from data files. Jan 27, 2024 4 - Beta pytest>=7.2.0 + :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A + :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) + :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest + :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest + :pypi:`pytest-param-scope` pytest parametrize scope fixture workaround Oct 18, 2023 N/A pytest + :pypi:`pytest-parawtf` Finally spell paramete?ri[sz]e correctly Dec 03, 2018 4 - Beta pytest (>=3.6.0) + :pypi:`pytest-pass` Check out https://github.com/elilutsky/pytest-pass Dec 04, 2019 N/A N/A + :pypi:`pytest-passrunner` Pytest plugin providing the 'run_on_pass' marker Feb 10, 2021 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-paste-config` Allow setting the path to a paste config file Sep 18, 2013 3 - Alpha N/A + :pypi:`pytest-patch` An automagic \`patch\` fixture that can patch objects directly or by name. Apr 29, 2023 3 - Alpha pytest (>=7.0.0) + :pypi:`pytest-patches` A contextmanager pytest fixture for handling multiple mock patches Aug 30, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-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 + :pypi:`pytest-pep8` pytest plugin to check PEP8 requirements Apr 27, 2014 N/A N/A + :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) + :pypi:`pytest-perf` Run performance tests against the mainline code. Jun 02, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) + :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A + :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) + :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) + :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) + :pypi:`pytest-picked` Run the tests related to the changed files Jul 27, 2023 N/A pytest (>=3.7.0) + :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) + :pypi:`pytest-pikachu` Show surprise when tests are passing Aug 05, 2021 5 - Production/Stable pytest + :pypi:`pytest-pilot` Slice in your test base thanks to powerful markers. Oct 09, 2020 5 - Production/Stable N/A + :pypi:`pytest-pingguo-pytest-plugin` pingguo test Oct 26, 2022 4 - Beta N/A + :pypi:`pytest-pings` 🦊 The pytest plugin for Firefox Telemetry 📊 Jun 29, 2019 3 - Alpha pytest (>=5.0.0) + :pypi:`pytest-pinned` A simple pytest plugin for pinning tests Sep 17, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-pinpoint` A pytest plugin which runs SBFL algorithms to detect faults. Sep 25, 2020 N/A pytest (>=4.4.0) + :pypi:`pytest-pipeline` Pytest plugin for functional testing of data analysispipelines Jan 24, 2017 3 - Alpha N/A + :pypi:`pytest-pitch` runs tests in an order such that coverage increases as fast as possible Nov 02, 2023 4 - Beta pytest >=7.3.1 + :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) + :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A + :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Oct 09, 2023 N/A pytest (<8.0.0,>=6.2.4) + :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A + :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A + :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A + :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A + :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A + :pypi:`pytest-plone` Pytest plugin to test Plone addons Jan 05, 2023 3 - Alpha pytest + :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Jan 10, 2024 5 - Production/Stable pytest >=7.4.2 + :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A + :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A + :pypi:`pytest-pokie` Pokie plugin for pytest Oct 19, 2023 5 - Production/Stable N/A + :pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A + :pypi:`pytest-polarion-collect` pytest plugin for collecting polarion test cases data Jun 18, 2020 3 - Alpha pytest + :pypi:`pytest-polecat` Provides Polecat pytest fixtures Aug 12, 2019 4 - Beta N/A + :pypi:`pytest-ponyorm` PonyORM in Pytest Oct 31, 2018 N/A pytest (>=3.1.1) + :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) + :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A + :pypi:`pytest-pook` Pytest plugin for pook Dec 23, 2023 4 - Beta pytest + :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest + :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 + :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) + :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) + :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 + :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) + :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A + :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Aug 25, 2023 5 - Production/Stable pytest>=7.4 + :pypi:`pytest-priority` pytest plugin for add priority for tests Jul 23, 2023 N/A N/A + :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) + :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A + :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A + :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest + :pypi:`pytest-prosper` Test helpers for Prosper projects Sep 24, 2018 N/A N/A + :pypi:`pytest-prysk` Pytest plugin for prysk Dec 30, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) + :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) + :pypi:`pytest-pudb` Pytest PuDB debugger integration Oct 25, 2018 3 - Alpha pytest (>=2.0) + :pypi:`pytest-pumpkin-spice` A pytest plugin that makes your test reporting pumpkin-spiced Sep 18, 2022 4 - Beta N/A + :pypi:`pytest-purkinje` py.test plugin for purkinje test runner Oct 28, 2017 2 - Pre-Alpha N/A + :pypi:`pytest-pusher` pytest plugin for push report to minio Jan 06, 2023 5 - Production/Stable pytest (>=3.6) + :pypi:`pytest-py125` Dec 03, 2022 N/A N/A + :pypi:`pytest-pycharm` Plugin for py.test to enter PyCharm debugger on uncaught exceptions Aug 13, 2020 5 - Production/Stable pytest (>=2.3) + :pypi:`pytest-pycodestyle` pytest plugin to run pycodestyle Oct 28, 2022 3 - Alpha N/A + :pypi:`pytest-pydev` py.test plugin to connect to a remote debug server with PyDev or PyCharm. Nov 15, 2017 3 - Alpha N/A + :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A + :pypi:`pytest-pylint` pytest plugin to check source code with pylint Oct 06, 2023 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-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 Dec 09, 2023 N/A pytest + :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A + :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) + :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A + :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest + :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Nov 03, 2023 N/A pytest + :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Jan 26, 2024 4 - Beta pytest >=7.0.0 + :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Jan 02, 2024 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 + :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) + :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) + :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest + :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) + :pypi:`pytest-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 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 Dec 22, 2023 5 - Production/Stable pytest >=3.0.0 + :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A + :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) + :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Jul 05, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-race` Race conditions tester for pytest Jun 07, 2022 4 - Beta N/A + :pypi:`pytest-rage` pytest plugin to implement PEP712 Oct 21, 2011 3 - Alpha N/A + :pypi:`pytest-rail` pytest plugin for creating TestRail runs and adding results May 02, 2022 N/A pytest (>=3.6) + :pypi:`pytest-railflow-testrail-reporter` Generate json reports along with specified metadata defined in test markers. Jun 29, 2022 5 - Production/Stable pytest + :pypi:`pytest-raises` An implementation of pytest.raises as a pytest.mark fixture Apr 23, 2020 N/A pytest (>=3.2.2) + :pypi:`pytest-raisesregexp` Simple pytest plugin to look for regex in Exceptions Dec 18, 2015 N/A N/A + :pypi:`pytest-raisin` Plugin enabling the use of exception instances with pytest.raises Feb 06, 2022 N/A pytest + :pypi:`pytest-random` py.test plugin to randomize tests Apr 28, 2013 3 - Alpha N/A + :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Aug 15, 2023 5 - Production/Stable pytest + :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A + :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A + :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 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. 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 Dec 06, 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) + :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest + :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A + :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A + :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest + :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 + :pypi:`pytest-regtest` "pytest plugin for snapshot regression testing" Jan 22, 2024 N/A pytest>7.2 + :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A + :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) + :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A + :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Sep 26, 2023 5 - Production/Stable pytest >=4.6 + :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest + :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest + :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest + :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jan 11, 2024 5 - Production/Stable pytest + :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest + :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A + :pypi:`pytest-reporter` Generate Pytest reports with templates Jul 22, 2021 4 - Beta pytest + :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Jun 05, 2023 4 - Beta N/A + :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A + :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A + :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest + :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest + :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Dec 06, 2023 N/A pytest >=3.8.0 + :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A + :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) + :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A + :pypi:`pytest-requests-futures` Pytest Plugin to Mock Requests Futures Jul 06, 2022 5 - Production/Stable pytest + :pypi:`pytest-requires` A pytest plugin to elegantly skip tests with optional requirements Dec 21, 2021 4 - Beta pytest (>=3.5.0) + :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 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 Jan 10, 2024 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 + :pypi:`pytest-responsemock` Simplified requests calls mocking for pytest Mar 10, 2022 5 - Production/Stable N/A + :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) + :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jul 10, 2023 5 - Production/Stable pytest + :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 + :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 + :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) + :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Jan 04, 2024 N/A pytest >=7.0.0 + :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) + :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A + :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest + :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) + :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest + :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) + :pypi:`pytest-richtrace` A pytest plugin that displays the names and information of the pytest hook functions as they are executed. Jun 20, 2023 N/A N/A + :pypi:`pytest-ringo` pytest plugin to test webapplications using the Ringo webframework Sep 27, 2017 3 - Alpha N/A + :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) + :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest + :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest + :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A + :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) + :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) + :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A + :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A + :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Oct 31, 2023 4 - Beta N/A + :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest + :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A + :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest + :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest + :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 + :pypi:`pytest-runtime-yoyo` run case mark timeout Jun 12, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-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 Jan 23, 2024 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. Jan 25, 2024 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 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. Jan 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-selenium-enhancer` pytest plugin for Selenium Apr 29, 2022 5 - Production/Stable N/A + :pypi:`pytest-selenium-pdiff` A pytest package implementing perceptualdiff for Selenium tests. Apr 06, 2017 2 - Pre-Alpha N/A + :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A + :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A + :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest + :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A + :pypi:`pytest-servers` pytest servers Dec 19, 2023 3 - Alpha pytest >=6.2 + :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A + :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest + :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A + :pypi:`pytest-session_to_file` pytest-session_to_file is a py.test plugin for capturing and saving to file the stdout of py.test. Oct 01, 2015 3 - Alpha N/A + :pypi:`pytest-setupinfo` Displaying setup info during pytest command run Jan 23, 2023 N/A N/A + :pypi:`pytest-sftpserver` py.test plugin to locally test sftp server connections. Sep 16, 2019 4 - Beta N/A + :pypi:`pytest-shard` Dec 11, 2020 4 - Beta pytest + :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) + :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A + :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Jul 02, 2023 5 - Production/Stable pytest (>=7.1.0) + :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest + :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 + :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-simplehttpserver` Simple pytest fixture to spin up an HTTP server Jun 24, 2021 4 - Beta N/A + :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A + :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest + :pypi:`pytest-single-file-logging` Allow for multiple processes to log to a single file May 05, 2016 4 - Beta pytest (>=2.8.1) + :pypi:`pytest-skip-markers` Pytest Salt Plugin Jan 04, 2024 5 - Production/Stable pytest >=7.1.0 + :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 + :pypi:`pytest-slow-last` Run tests in order of execution time (faster tests first) Dec 10, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) + :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A + :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A + :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest + :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A + :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest + :pypi:`pytest-smtp-test-server` pytest plugin for using \`smtp-test-server\` as a fixture Dec 03, 2023 2 - Pre-Alpha pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) + :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A + :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-snapshot-with-message-generator` A plugin for snapshot testing with pytest. Jul 25, 2023 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-snmpserver` May 12, 2021 N/A N/A + :pypi:`pytest-snowflake-bdd` Setup test data and run tests on snowflake in BDD style! Jan 05, 2022 4 - Beta pytest (>=6.2.0) + :pypi:`pytest-socket` Pytest Plugin to disable socket calls during tests Feb 03, 2023 4 - Beta pytest (>=3.6.3) + :pypi:`pytest-sofaepione` Test the installation of SOFA and the SofaEpione plugin. Aug 17, 2022 N/A N/A + :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest + :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' + :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) + :pypi:`pytest-sort` Tools for sorting test cases Jan 07, 2024 N/A pytest >=7.4.0 + :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) + :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest + :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest + :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest + :pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A + :pypi:`pytest-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. 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 Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A + :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) + :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Jun 11, 2022 6 - Mature pytest (<8.0,>=7.1.2) + :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Apr 12, 2023 4 - Beta pytest (>=5,<8) + :pypi:`pytest-split-ext` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Sep 23, 2023 4 - Beta pytest (>=5,<8) + :pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) + :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) + :pypi:`pytest-split-tests-tresorit` Feb 22, 2021 1 - Planning N/A + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jan 12, 2024 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 + :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Mar 15, 2023 3 - Alpha pytest (>=2.0) + :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 19, 2023 4 - Beta pytest (>=7.0) + :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest + :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest + :pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A pytest>=6.2.0 + :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest + :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A + :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-static` pytest-static Jan 15, 2024 1 - Planning pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) + :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest + :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A + :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A + :pypi:`pytest-stf` pytest plugin for openSTF Oct 10, 2023 N/A pytest >=5.0 + :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A + :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) + :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) + :pypi:`pytest-structlog` Structured logging assertions Dec 18, 2022 N/A pytest + :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A + :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A + :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) + :pypi:`pytest-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) + :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) + :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Apr 10, 2023 4 - Beta pytest (>=6.2.0) + :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A + :pypi:`pytest-suite-timeout` A pytest plugin for ensuring max suite time Jan 26, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A + :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A + :pypi:`pytest-synodic` Synodic Pytest utilities Jan 12, 2024 N/A pytest>=7.4.4 + :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) + :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A + :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A + :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A + :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) + :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Jul 15, 2023 5 - Production/Stable pytest (>=3.0) + :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A + :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) + :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) + :pypi:`pytest-tcp` A Pytest plugin for test prioritization Dec 10, 2023 4 - Beta pytest >=7.4.3 + :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) + :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A + :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A + :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Dec 10, 2020 5 - Production/Stable N/A + :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A + :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) + :pypi:`pytest-terra-fixt` Terraform and Terragrunt fixtures for pytest Sep 15, 2022 N/A pytest (==6.2.5) + :pypi:`pytest-terraform` A pytest plugin for using terraform fixtures Jun 20, 2023 N/A pytest (>=6.0) + :pypi:`pytest-terraform-fixture` generate terraform resources to use with pytest Nov 14, 2018 4 - Beta N/A + :pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A + :pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest + :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) + :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A + :pypi:`pytest-testinfra` Test infrastructures Nov 13, 2023 5 - Production/Stable pytest !=3.0.2 + :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 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) + :pypi:`pytest-testobject` Plugin to use TestObject Suites with Pytest Sep 24, 2019 4 - Beta pytest (>=3.1.1) + :pypi:`pytest-testpluggy` set your encoding Jan 07, 2022 N/A pytest + :pypi:`pytest-testrail` pytest plugin for creating TestRail runs and adding results Aug 27, 2020 N/A pytest (>=3.6) + :pypi:`pytest-testrail2` A pytest plugin to upload results to TestRail. Feb 10, 2023 N/A pytest (<8.0,>=7.2.0) + :pypi:`pytest-testrail-api-client` TestRail Api Python Client Dec 14, 2021 N/A pytest + :pypi:`pytest-testrail-appetize` pytest plugin for creating TestRail runs and adding results Sep 29, 2021 N/A N/A + :pypi:`pytest-testrail-client` pytest plugin for Testrail Sep 29, 2020 5 - Production/Stable N/A + :pypi:`pytest-testrail-e2e` pytest plugin for creating TestRail runs and adding results Oct 11, 2021 N/A pytest (>=3.6) + :pypi:`pytest-testrail-integrator` Pytest plugin for sending report to testrail system. Aug 01, 2022 N/A pytest (>=6.2.5) + :pypi:`pytest-testrail-ns` pytest plugin for creating TestRail runs and adding results Aug 12, 2022 N/A N/A + :pypi:`pytest-testrail-plugin` PyTest plugin for TestRail Apr 21, 2020 3 - Alpha pytest + :pypi:`pytest-testrail-reporter` Sep 10, 2018 N/A N/A + :pypi:`pytest-testreport` Dec 01, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-testreport-new` Oct 07, 2023 4 - Beta pytest >=3.5.0 + :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) + :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) + :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) + :pypi:`pytest-tesults` Tesults plugin for pytest Jul 21, 2023 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A + :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A + :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A + :pypi:`pytest-thread` Jul 07, 2023 N/A N/A + :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) + :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest + :pypi:`pytest-timeassert-ethan` execution duration Dec 25, 2023 N/A pytest + :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A + :pypi:`pytest-timeout` pytest plugin to abort hanging tests Oct 08, 2023 5 - Production/Stable pytest >=5.0.0 + :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A + :pypi:`pytest-timer` A timer plugin for pytest Dec 26, 2023 N/A pytest + :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A + :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) + :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Jan 04, 2024 5 - Production/Stable pytest + :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) + :pypi:`pytest-tipsi-django` Nov 17, 2021 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Nov 04, 2020 4 - Beta pytest (>=3.3.0) + :pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-tm4j-reporter` Cloud Jira Test Management (TM4J) PyTest reporter plugin Sep 01, 2020 N/A pytest + :pypi:`pytest-tmnet` A small example package Mar 01, 2022 N/A N/A + :pypi:`pytest-tmp-files` Utilities to create temporary file hierarchies in pytest. Dec 08, 2023 N/A pytest + :pypi:`pytest-tmpfs` A pytest plugin that helps you on using a temporary filesystem for testing. Aug 29, 2022 N/A pytest + :pypi:`pytest-tmreport` this is a vue-element ui report for pytest Aug 12, 2022 N/A N/A + :pypi:`pytest-tmux` A pytest plugin that enables tmux driven tests Apr 22, 2023 4 - Beta N/A + :pypi:`pytest-todo` A small plugin for the pytest testing framework, marking TODO comments as failure May 23, 2019 4 - Beta pytest + :pypi:`pytest-tomato` Mar 01, 2019 5 - Production/Stable N/A + :pypi:`pytest-toolbelt` This is just a collection of utilities for pytest, but don't really belong in pytest proper. Aug 12, 2019 3 - Alpha N/A + :pypi:`pytest-toolbox` Numerous useful plugins for pytest. Apr 07, 2018 N/A pytest (>=3.5.0) + :pypi:`pytest-tools` Pytest tools Oct 21, 2022 4 - Beta N/A + :pypi:`pytest-tornado` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Jun 17, 2020 5 - Production/Stable pytest (>=3.6) + :pypi:`pytest-tornado5` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Nov 16, 2018 5 - Production/Stable pytest (>=3.6) + :pypi:`pytest-tornado-yen3` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Oct 15, 2018 5 - Production/Stable N/A + :pypi:`pytest-tornasync` py.test plugin for testing Python 3.5+ Tornado code Jul 15, 2019 3 - Alpha pytest (>=3.0) + :pypi:`pytest-trace` Save OpenTelemetry spans generated during testing Jun 19, 2022 N/A pytest (>=4.6) + :pypi:`pytest-track` Feb 26, 2021 3 - Alpha pytest (>=3.0) + :pypi:`pytest-translations` Test your translation files. Sep 11, 2023 5 - Production/Stable pytest (>=7) + :pypi:`pytest-travis-fold` Folds captured output sections in Travis CI build log Nov 29, 2017 4 - Beta pytest (>=2.6.0) + :pypi:`pytest-trello` Plugin for py.test that integrates trello using markers Nov 20, 2015 5 - Production/Stable N/A + :pypi:`pytest-trepan` Pytest plugin for trepan debugger. Jul 28, 2018 5 - Production/Stable N/A + :pypi:`pytest-trialtemp` py.test plugin for using the same _trial_temp working directory as trial Jun 08, 2015 N/A N/A + :pypi:`pytest-trio` Pytest plugin for trio Nov 01, 2022 N/A pytest (>=7.2.0) + :pypi:`pytest-trytond` Pytest plugin for the Tryton server framework Nov 04, 2022 4 - Beta pytest (>=5) + :pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) + :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A + :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A + :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A + :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A + :pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3) + :pypi:`pytest-typechecker` Run type checkers on specified test files Feb 04, 2022 N/A pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-typhoon-config` A Typhoon HIL plugin that facilitates test parameter configuration at runtime Apr 07, 2022 5 - Production/Stable N/A + :pypi:`pytest-typhoon-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 + :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest + :pypi:`pytest-ui-failed-screenshot` UI自动测试失败时自动截图,并将截图加入到测试报告中 Dec 06, 2022 N/A N/A + :pypi:`pytest-ui-failed-screenshot-allure` UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 Dec 06, 2022 N/A N/A + :pypi:`pytest-unflakable` Unflakable plugin for PyTest Nov 12, 2023 4 - Beta pytest >=6.2.0 + :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) + :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) + :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) + :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A + :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A + :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A + :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest + :pypi:`pytest-valgrind` May 19, 2021 N/A N/A + :pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures May 27, 2023 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-variant` Variant support for Pytest Jun 06, 2022 N/A N/A + :pypi:`pytest-vcr` Plugin for managing VCR.py cassettes Apr 26, 2019 5 - Production/Stable pytest (>=3.6.0) + :pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Jun 20, 2022 5 - Production/Stable pytest (>=6.2.2) + :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 Nov 23, 2023 4 - Beta pytest + :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Dec 19, 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 + :pypi:`pytest-visual` Nov 01, 2023 3 - Alpha pytest >=7.0.0 + :pypi:`pytest-vnc` VNC client for Pytest Nov 06, 2023 N/A pytest + :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest + :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A + :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest + :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) + :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Jun 01, 2023 N/A pytest (>=7.0.0) + :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A + :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A + :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-wake` Nov 07, 2023 N/A pytest + :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A + :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 24, 2023 4 - Beta N/A + :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A + :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest + :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 13, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A + :pypi:`pytest-when` Utility which makes mocking more readable and controllable Jan 25, 2024 N/A pytest>=7.3.1 + :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A + :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) + :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A + :pypi:`pytest-winnotify` Windows tray notifications for py.test results. Apr 22, 2016 N/A N/A + :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 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) + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Sep 29, 2023 4 - Beta pytest (>=7.3,<8.0) + :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) + :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A + :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A + :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Dec 28, 2023 N/A pytest<8,>=7.4.0 + :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest + :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Sep 23, 2023 4 - Beta pytest (>=2.8) + :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A + :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) + :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) + :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (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 Dec 18, 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) + :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) + :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) + :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A + :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Jan 11, 2024 N/A pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 + :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) + :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A + :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jan 08, 2024 5 - Production/Stable pytest (>=4.5.0) + :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Jan 16, 2024 N/A pytest (>=7.4.2,<8.0.0) + :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A + :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) + :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest + =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -2140,6 +2144,13 @@ This list contains 1359 plugins. A pytest plugin that reports test results to the BeakerLib framework + :pypi:`pytest-beartype` + *last release*: Jan 25, 2024, + *status*: N/A, + *requires*: pytest + + Pytest plugin to run your tests with beartype checking enabled. + :pypi:`pytest-beds` *last release*: Jun 07, 2016, *status*: 4 - Beta, @@ -2918,7 +2929,7 @@ This list contains 1359 plugins. The pytest plugin for your Cookiecutter templates. 🍪 :pypi:`pytest-copie` - *last release*: Nov 14, 2023, + *last release*: Jan 27, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3667,7 +3678,7 @@ This list contains 1359 plugins. An RST Documentation Generator for pytest-based test suites :pypi:`pytest-docker` - *last release*: Sep 01, 2023, + *last release*: Jan 27, 2024, *status*: N/A, *requires*: pytest <8.0,>=4.0 @@ -3953,13 +3964,6 @@ This list contains 1359 plugins. pytest-easy-addoption: Easy way to work with pytest addoption - :pypi:`pytest-easy-api` - *last release*: Mar 26, 2018, - *status*: N/A, - *requires*: N/A - - Simple API testing with pytest - :pypi:`pytest-easyMPI` *last release*: Oct 21, 2020, *status*: N/A, @@ -4045,56 +4049,56 @@ This list contains 1359 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jan 18, 2024, + *last release*: Jan 22, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jan 18, 2024, + *last release*: Jan 22, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jan 18, 2024, + *last release*: Jan 22, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jan 18, 2024, + *last release*: Jan 22, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jan 18, 2024, + *last release*: Jan 22, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jan 18, 2024, + *last release*: Jan 22, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jan 18, 2024, + *last release*: Jan 22, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Jan 18, 2024, + *last release*: Jan 22, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4247,6 +4251,13 @@ This list contains 1359 plugins. Applies eventlet monkey-patch as a pytest plugin. + :pypi:`pytest-evm` + *last release*: Jan 24, 2024, + *status*: 4 - Beta, + *requires*: pytest (>=7.4.3,<8.0.0) + + The testing package containing tools to test Web3-based projects + :pypi:`pytest-examples` *last release*: Jul 11, 2023, *status*: 4 - Beta, @@ -4927,9 +4938,9 @@ This list contains 1359 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Dec 20, 2023, + *last release*: Jan 25, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest>=3.6 A set of pytest fixtures for testing Girder applications. @@ -5193,7 +5204,7 @@ This list contains 1359 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jan 20, 2024, + *last release*: Jan 21, 2024, *status*: 3 - Alpha, *requires*: pytest ==7.4.3 @@ -5410,7 +5421,7 @@ This list contains 1359 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Dec 22, 2023, + *last release*: Jan 24, 2024, *status*: 3 - Alpha, *requires*: pytest (>=7.0.0,<8.0.0) @@ -5620,7 +5631,7 @@ This list contains 1359 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Jan 03, 2024, + *last release*: Jan 26, 2024, *status*: 4 - Beta, *requires*: pytest @@ -6109,8 +6120,15 @@ This list contains 1359 plugins. Pytest plugin for AWS integration tests + :pypi:`pytest-lock` + *last release*: Jan 27, 2024, + *status*: N/A, + *requires*: pytest (>=7.4.3,<8.0.0) + + pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. + :pypi:`pytest-lockable` - *last release*: Nov 06, 2023, + *last release*: Jan 24, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -6173,9 +6191,9 @@ This list contains 1359 plugins. :pypi:`pytest-logikal` - *last release*: Jul 17, 2023, + *last release*: Jan 27, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (==7.4.0) + *requires*: pytest ==7.4.4 Common testing environment @@ -7166,6 +7184,13 @@ This list contains 1359 plugins. Configure pytest fixtures using a combination of"parametrize" and markers + :pypi:`pytest-parameterize-from-files` + *last release*: Jan 27, 2024, + *status*: 4 - Beta, + *requires*: pytest>=7.2.0 + + A pytest plugin that parameterizes tests from data files. + :pypi:`pytest-parametrization` *last release*: May 22, 2022, *status*: 5 - Production/Stable, @@ -7846,7 +7871,7 @@ This list contains 1359 plugins. PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report :pypi:`pytest-pyright` - *last release*: Aug 20, 2023, + *last release*: Jan 26, 2024, *status*: 4 - Beta, *requires*: pytest >=7.0.0 @@ -8147,7 +8172,7 @@ This list contains 1359 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Jan 15, 2024, + *last release*: Jan 22, 2024, *status*: N/A, *requires*: pytest>7.2 @@ -8658,7 +8683,7 @@ This list contains 1359 plugins. A Pytest plugin that builds and creates docker containers :pypi:`pytest-salt-factories` - *last release*: Nov 25, 2023, + *last release*: Jan 23, 2024, *status*: 4 - Beta, *requires*: pytest (>=6.0.0) @@ -8700,7 +8725,7 @@ This list contains 1359 plugins. :pypi:`pytest-sbase` - *last release*: Jan 19, 2024, + *last release*: Jan 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8763,7 +8788,7 @@ This list contains 1359 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jan 19, 2024, + *last release*: Jan 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9518,6 +9543,13 @@ This list contains 1359 plugins. A simple plugin to use with pytest + :pypi:`pytest-suite-timeout` + *last release*: Jan 26, 2024, + *status*: N/A, + *requires*: pytest>=7.0.0 + + A pytest plugin for ensuring max suite time + :pypi:`pytest-supercov` *last release*: Jul 02, 2023, *status*: N/A, @@ -10611,7 +10643,7 @@ This list contains 1359 plugins. Welian API Automation test framework pytest plugin :pypi:`pytest-when` - *last release*: Oct 18, 2023, + *last release*: Jan 25, 2024, *status*: N/A, *requires*: pytest>=7.3.1 From 14d3707818e0beaab2a3ce4f4fa95ee5a147b75e Mon Sep 17 00:00:00 2001 From: Russell Martin Date: Sun, 28 Jan 2024 21:07:18 -0500 Subject: [PATCH 0401/1271] Catch `OSError` from `getpass.getuser()` (#11875) - Previously, `getpass.getuser()` would leak an ImportError if the USERNAME environment variable was not set on Windows because the `pwd` module cannot be imported. - Starting in Python 3.13.0a3, it only raises `OSError`. Fixes #11874 --- AUTHORS | 1 + changelog/11875.bugfix.rst | 1 + src/_pytest/tmpdir.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/11875.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 803bb2b183f..bea58204686 100644 --- a/AUTHORS +++ b/AUTHORS @@ -340,6 +340,7 @@ Ronny Pfannschmidt Ross Lawley Ruaridh Williamson Russel Winder +Russell Martin Ryan Puddephatt Ryan Wooden Sadra Barikbin diff --git a/changelog/11875.bugfix.rst b/changelog/11875.bugfix.rst new file mode 100644 index 00000000000..d646be6314f --- /dev/null +++ b/changelog/11875.bugfix.rst @@ -0,0 +1 @@ +Correctly handle errors from :func:`getpass.getuser` in Python 3.13. diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 937b1687ab8..75391adbcf8 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -204,7 +204,7 @@ def get_user() -> Optional[str]: import getpass return getpass.getuser() - except (ImportError, KeyError): + except (ImportError, OSError, KeyError): return None From 5855f65d0fbc57c0fa3196d87c0fe2e9bc420868 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:42:27 -0300 Subject: [PATCH 0402/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#11878) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.3 to 0.23.4. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.3...v0.23.4) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 0839b18c9fa..d6f7fe59ba7 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.2.0 django==5.0 -pytest-asyncio==0.23.3 +pytest-asyncio==0.23.4 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 # pytest-bdd==7.0.1 From c0dfc451861a0fbf9b9659e8f8d723ea730a5619 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 10:42:51 -0300 Subject: [PATCH 0403/1271] build(deps): Bump hynek/build-and-inspect-python-package (#11877) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.0.0 to 2.0.1. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.0.0...v2.0.1) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5d5015f187e..0d48982d601 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.0.0 + uses: hynek/build-and-inspect-python-package@v2.0.1 deploy: if: github.repository == 'pytest-dev/pytest' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3d6f00bb747..363cbe901fc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.0.0 + uses: hynek/build-and-inspect-python-package@v2.0.1 build: needs: [package] From cb57bf50b183d62068d8f0e21ed71bdcde5fdb3a Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 30 Jan 2024 06:58:22 -0300 Subject: [PATCH 0404/1271] Pin back pytest-asyncio to 8.0.0 compatible release (#11889) The current version (0.23.4) explicitly does not support pytest 8 yet, so we fallback to the previous release in the hope that at least our integration tests pass. --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d6f7fe59ba7..0839b18c9fa 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.2.0 django==5.0 -pytest-asyncio==0.23.4 +pytest-asyncio==0.23.3 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 # pytest-bdd==7.0.1 From 21bec6cfbed7ae36478aeff956919727c2bb8641 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 30 Jan 2024 09:41:18 -0300 Subject: [PATCH 0405/1271] Add changelog entry about FixtureManager.getfixtureclosure changing (#11887) As discussed in #11868. --- doc/en/changelog.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index fc36a5dcf0d..6f67b7ba16c 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -266,6 +266,10 @@ These are breaking changes where deprecation was not possible. therefore fail on the newly-re-emitted warnings. +- The internal ``FixtureManager.getfixtureclosure`` method has changed. Plugins which use this method or + which subclass ``FixtureManager`` and overwrite that method will need to adapt to the change. + + Deprecations ------------ From 407d9841428f037e0ada71f7ca028f7d1171c6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Tue, 30 Jan 2024 16:20:30 +0100 Subject: [PATCH 0406/1271] Fix an edge case where ExceptionInfo._stringify_exception could crash pytest.raises (#11879) Co-authored-by: Bruno Oliveira Co-authored-by: Zac Hatfield-Dodds --- AUTHORS | 1 + changelog/11879.bugfix.rst | 1 + src/_pytest/_code/code.py | 13 ++++++++++++- testing/python/raises.py | 13 +++++++++++++ 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 changelog/11879.bugfix.rst diff --git a/AUTHORS b/AUTHORS index bea58204686..87909762263 100644 --- a/AUTHORS +++ b/AUTHORS @@ -93,6 +93,7 @@ Christopher Dignam Christopher Gilling Claire Cecil Claudio Madotto +Clément M.T. Robert CrazyMerlyn Cristian Vera Cyrus Maden diff --git a/changelog/11879.bugfix.rst b/changelog/11879.bugfix.rst new file mode 100644 index 00000000000..70b6cce72e7 --- /dev/null +++ b/changelog/11879.bugfix.rst @@ -0,0 +1 @@ +Fix an edge case where ``ExceptionInfo._stringify_exception`` could crash :func:`pytest.raises`. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index d99b5236661..39bbc3c140a 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -699,10 +699,21 @@ def getrepr( return fmt.repr_excinfo(self) def _stringify_exception(self, exc: BaseException) -> str: + try: + notes = getattr(exc, "__notes__", []) + except KeyError: + # Workaround for https://github.com/python/cpython/issues/98778 on + # Python <= 3.9, and some 3.10 and 3.11 patch versions. + HTTPError = getattr(sys.modules.get("urllib.error", None), "HTTPError", ()) + if sys.version_info[:2] <= (3, 11) and isinstance(exc, HTTPError): + notes = [] + else: + raise + return "\n".join( [ str(exc), - *getattr(exc, "__notes__", []), + *notes, ] ) diff --git a/testing/python/raises.py b/testing/python/raises.py index 47b22f28a92..369a66a9f50 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -302,3 +302,16 @@ class NotAnException: with pytest.raises(("hello", NotAnException)): # type: ignore[arg-type] pass # pragma: no cover assert "must be a BaseException type, not str" in str(excinfo.value) + + def test_issue_11872(self) -> None: + """Regression test for #11872. + + urllib.error.HTTPError on Python<=3.9 raises KeyError instead of + AttributeError on invalid attribute access. + + https://github.com/python/cpython/issues/98778 + """ + from urllib.error import HTTPError + + with pytest.raises(HTTPError, match="Not Found"): + raise HTTPError(code=404, msg="Not Found", fp=None, hdrs=None, url="") # type: ignore [arg-type] From 899a6cf2cef5f74e7f85fb22ec3449fbd57a5aae Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 29 Jan 2024 21:54:52 -0300 Subject: [PATCH 0407/1271] Replace reorder-python-imports by isort due to black incompatibility Unfortunately black and reorder-python-imports are no longer compatible, and from the looks of it probably will not be compatible anytime soon: https://github.com/asottile/reorder-python-imports/issues/367 https://github.com/asottile/reorder-python-imports/issues/366 https://github.com/psf/black/issues/4175 This replaces `reorder-python-imports` by `isort` configured in a way to yield roughtly the same results. Closes #11885 --- .pre-commit-config.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 26ca339b961..244fe48e052 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 23.12.1 + rev: 24.1.1 hooks: - id: black args: [--safe, --quiet] @@ -36,11 +36,12 @@ repos: additional_dependencies: - flake8-typing-imports==1.12.0 - flake8-docstrings==1.5.0 -- repo: https://github.com/asottile/reorder-python-imports - rev: v3.12.0 +- repo: https://github.com/pycqa/isort + rev: 5.13.2 hooks: - - id: reorder-python-imports - args: ['--application-directories=.:src', --py38-plus] + - id: isort + name: isort + args: [--force-single-line, --profile=black] - repo: https://github.com/asottile/pyupgrade rev: v3.15.0 hooks: From 8b54596639f41dfac070030ef20394b9001fe63c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 30 Jan 2024 16:34:23 -0300 Subject: [PATCH 0408/1271] Run pre-commit on all files Running pre-commit on all files after replacing reorder-python-imports by isort. --- bench/bench.py | 3 ++- doc/en/conf.py | 3 ++- doc/en/example/multipython.py | 2 +- scripts/update-plugin-list.py | 1 - src/_pytest/__init__.py | 3 ++- src/_pytest/_argcomplete.py | 1 + src/_pytest/_code/__init__.py | 1 + src/_pytest/_code/code.py | 26 +++++++++---------- src/_pytest/_code/source.py | 6 ++--- src/_pytest/_io/__init__.py | 1 - src/_pytest/_io/terminalwriter.py | 4 +-- src/_pytest/_py/error.py | 1 + src/_pytest/_py/path.py | 15 +++++------ src/_pytest/assertion/rewrite.py | 17 +++++++----- src/_pytest/assertion/truncate.py | 2 +- src/_pytest/cacheprovider.py | 1 + src/_pytest/compat.py | 1 - src/_pytest/config/__init__.py | 9 ++++--- src/_pytest/deprecated.py | 1 + src/_pytest/faulthandler.py | 1 - src/_pytest/fixtures.py | 7 ++--- src/_pytest/freeze_support.py | 1 + src/_pytest/hookspec.py | 4 +-- src/_pytest/junitxml.py | 1 - src/_pytest/legacypath.py | 1 + src/_pytest/main.py | 7 +++-- src/_pytest/mark/__init__.py | 1 + src/_pytest/mark/expression.py | 1 + src/_pytest/mark/structures.py | 18 +++++-------- src/_pytest/monkeypatch.py | 6 ++--- src/_pytest/nodes.py | 9 +++---- src/_pytest/outcomes.py | 1 + src/_pytest/pastebin.py | 3 +-- src/_pytest/pytester.py | 21 +++++---------- src/_pytest/pytester_assertions.py | 1 + src/_pytest/python.py | 9 ++++--- src/_pytest/python_api.py | 6 ++--- src/_pytest/recwarn.py | 13 +++------- src/_pytest/reports.py | 9 +++---- src/_pytest/scope.py | 2 +- src/_pytest/stash.py | 1 - src/_pytest/timing.py | 1 + src/_pytest/unittest.py | 3 ++- src/pytest/__main__.py | 1 + testing/_py/test_local.py | 5 ++-- testing/code/test_excinfo.py | 1 - .../unittest/test_unittest_asyncio.py | 1 - .../unittest/test_unittest_asynctest.py | 1 - testing/freeze/create_executable.py | 4 ++- testing/freeze/runtests_script.py | 1 + testing/freeze/tox_run.py | 1 + testing/io/test_terminalwriter.py | 1 - testing/logging/test_reporting.py | 3 ++- testing/python/integration.py | 3 ++- testing/test_assertrewrite.py | 3 ++- testing/test_config.py | 6 ++--- testing/test_debugging.py | 1 - testing/test_error_diffs.py | 2 +- testing/test_faulthandler.py | 1 + testing/test_mark.py | 6 +++-- testing/test_meta.py | 1 + testing/test_reports.py | 6 ++--- tox.ini | 2 ++ 63 files changed, 133 insertions(+), 142 deletions(-) diff --git a/bench/bench.py b/bench/bench.py index c40fc8636c0..c314b4f56bf 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -2,9 +2,10 @@ if __name__ == "__main__": import cProfile - import pytest # NOQA import pstats + import pytest # NOQA + script = sys.argv[1:] if len(sys.argv) > 1 else ["empty.py"] cProfile.run("pytest.cmdline.main(%r)" % script, "prof") p = pstats.Stats("prof") diff --git a/doc/en/conf.py b/doc/en/conf.py index 2bc18be5828..bb5737d7a57 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -440,9 +440,10 @@ def configure_logging(app: "sphinx.application.Sphinx") -> None: """Configure Sphinx's WarningHandler to handle (expected) missing include.""" - import sphinx.util.logging import logging + import sphinx.util.logging + class WarnLogFilter(logging.Filter): def filter(self, record: logging.LogRecord) -> bool: """Ignore warnings about missing include with "only" directive. diff --git a/doc/en/example/multipython.py b/doc/en/example/multipython.py index 8d76ed483e8..1354cb37c45 100644 --- a/doc/en/example/multipython.py +++ b/doc/en/example/multipython.py @@ -1,12 +1,12 @@ """Module containing a parametrized tests testing cross-python serialization via the pickle module.""" + import shutil import subprocess import textwrap import pytest - pythonlist = ["python3.9", "python3.10", "python3.11"] diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 0f811b778ed..287073f576e 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -19,7 +19,6 @@ from requests_cache import SQLiteCache from tqdm import tqdm - FILE_HEAD = r""" .. Note this file is autogenerated by scripts/update-plugin-list.py - usually weekly via github action diff --git a/src/_pytest/__init__.py b/src/_pytest/__init__.py index 8a406c5c751..9062768eae3 100644 --- a/src/_pytest/__init__.py +++ b/src/_pytest/__init__.py @@ -1,7 +1,8 @@ __all__ = ["__version__", "version_tuple"] try: - from ._version import version as __version__, version_tuple + from ._version import version as __version__ + from ._version import version_tuple except ImportError: # pragma: no cover # broken installation, we don't even try # unknown only works because we do poor mans version compare diff --git a/src/_pytest/_argcomplete.py b/src/_pytest/_argcomplete.py index 6a8083770ae..c2ec1797fbc 100644 --- a/src/_pytest/_argcomplete.py +++ b/src/_pytest/_argcomplete.py @@ -61,6 +61,7 @@ which should throw a KeyError: 'COMPLINE' (which is properly set by the global argcomplete script). """ + import argparse import os import sys diff --git a/src/_pytest/_code/__init__.py b/src/_pytest/_code/__init__.py index 511d0dde661..f82c3d2b030 100644 --- a/src/_pytest/_code/__init__.py +++ b/src/_pytest/_code/__init__.py @@ -1,4 +1,5 @@ """Python inspection/code generation API.""" + from .code import Code from .code import ExceptionInfo from .code import filter_traceback diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 39bbc3c140a..8b38a8e7835 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -278,9 +278,9 @@ def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool: Mostly for internal use. """ - tbh: Union[ - bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool] - ] = False + tbh: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]] = ( + False + ) for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals): # in normal cases, f_locals and f_globals are dictionaries # however via `exec(...)` / `eval(...)` they can be other types @@ -377,12 +377,10 @@ def cut( return self @overload - def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: - ... + def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: ... @overload - def __getitem__(self, key: slice) -> "Traceback": - ... + def __getitem__(self, key: slice) -> "Traceback": ... def __getitem__( self, key: Union["SupportsIndex", slice] @@ -1056,13 +1054,13 @@ def repr_excinfo( # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 if isinstance(e, BaseExceptionGroup): - reprtraceback: Union[ - ReprTracebackNative, ReprTraceback - ] = ReprTracebackNative( - traceback.format_exception( - type(excinfo_.value), - excinfo_.value, - excinfo_.traceback[0]._rawentry, + reprtraceback: Union[ReprTracebackNative, ReprTraceback] = ( + ReprTracebackNative( + traceback.format_exception( + type(excinfo_.value), + excinfo_.value, + excinfo_.traceback[0]._rawentry, + ) ) ) else: diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index efee1fad3bf..a85b14371e2 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -47,12 +47,10 @@ def __eq__(self, other: object) -> bool: __hash__ = None # type: ignore @overload - def __getitem__(self, key: int) -> str: - ... + def __getitem__(self, key: int) -> str: ... @overload - def __getitem__(self, key: slice) -> "Source": - ... + def __getitem__(self, key: slice) -> "Source": ... def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]: if isinstance(key, int): diff --git a/src/_pytest/_io/__init__.py b/src/_pytest/_io/__init__.py index db001e918cb..a804cb549b4 100644 --- a/src/_pytest/_io/__init__.py +++ b/src/_pytest/_io/__init__.py @@ -1,7 +1,6 @@ from .terminalwriter import get_terminal_width from .terminalwriter import TerminalWriter - __all__ = [ "TerminalWriter", "get_terminal_width", diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 56107d56647..89221796aea 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -1,4 +1,5 @@ """Helper functions for writing to terminals and files.""" + import os import shutil import sys @@ -10,7 +11,6 @@ from .wcwidth import wcswidth - # This code was initially copied from py 1.8.1, file _io/terminalwriter.py. @@ -210,8 +210,8 @@ def _highlight( from pygments.lexers.python import PythonLexer as Lexer elif lexer == "diff": from pygments.lexers.diff import DiffLexer as Lexer - from pygments import highlight import pygments.util + from pygments import highlight except ImportError: return source else: diff --git a/src/_pytest/_py/error.py b/src/_pytest/_py/error.py index 0b8f2d535ef..4b08d3b7a2e 100644 --- a/src/_pytest/_py/error.py +++ b/src/_pytest/_py/error.py @@ -1,4 +1,5 @@ """create errno-specific classes for IO or os calls.""" + from __future__ import annotations import errno diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 04b1695f174..44262a524ea 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -204,12 +204,10 @@ class Stat: if TYPE_CHECKING: @property - def size(self) -> int: - ... + def size(self) -> int: ... @property - def mtime(self) -> float: - ... + def mtime(self) -> float: ... def __getattr__(self, name: str) -> Any: return getattr(self._osstatresult, "st_" + name) @@ -962,12 +960,10 @@ def ensure(self, *args, **kwargs): return p @overload - def stat(self, raising: Literal[True] = ...) -> Stat: - ... + def stat(self, raising: Literal[True] = ...) -> Stat: ... @overload - def stat(self, raising: Literal[False]) -> Stat | None: - ... + def stat(self, raising: Literal[False]) -> Stat | None: ... def stat(self, raising: bool = True) -> Stat | None: """Return an os.stat() tuple.""" @@ -1168,7 +1164,8 @@ def sysexec(self, *argv: os.PathLike[str], **popen_opts: Any) -> str: where the 'self' path points to executable. The process is directly invoked and not through a system shell. """ - from subprocess import Popen, PIPE + from subprocess import PIPE + from subprocess import Popen popen_opts.pop("stdout", None) popen_opts.pop("stderr", None) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 149101e716f..c24263e0663 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -1,4 +1,5 @@ """Rewrite assertion AST to produce nice error messages.""" + import ast import errno import functools @@ -33,15 +34,16 @@ from _pytest._io.saferepr import saferepr from _pytest._version import version from _pytest.assertion import util -from _pytest.assertion.util import ( # noqa: F401 - format_explanation as _format_explanation, -) from _pytest.config import Config from _pytest.main import Session from _pytest.pathlib import absolutepath from _pytest.pathlib import fnmatch_ex from _pytest.stash import StashKey +# fmt: off +from _pytest.assertion.util import format_explanation as _format_explanation # noqa:F401, isort:skip +# fmt:on + if TYPE_CHECKING: from _pytest.assertion import AssertionState @@ -669,9 +671,9 @@ def __init__( self.enable_assertion_pass_hook = False self.source = source self.scope: tuple[ast.AST, ...] = () - self.variables_overwrite: defaultdict[ - tuple[ast.AST, ...], Dict[str, str] - ] = defaultdict(dict) + self.variables_overwrite: defaultdict[tuple[ast.AST, ...], Dict[str, str]] = ( + defaultdict(dict) + ) def run(self, mod: ast.Module) -> None: """Find all assert statements in *mod* and rewrite them.""" @@ -858,9 +860,10 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: the expression is false. """ if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1: - from _pytest.warning_types import PytestAssertRewriteWarning import warnings + from _pytest.warning_types import PytestAssertRewriteWarning + # TODO: This assert should not be needed. assert self.module_path is not None warnings.warn_explicit( diff --git a/src/_pytest/assertion/truncate.py b/src/_pytest/assertion/truncate.py index 16de27f256e..1e586567240 100644 --- a/src/_pytest/assertion/truncate.py +++ b/src/_pytest/assertion/truncate.py @@ -3,6 +3,7 @@ Current default behaviour is to truncate assertion explanations at terminal lines, unless running with an assertions verbosity level of at least 2 or running on CI. """ + from typing import List from typing import Optional @@ -10,7 +11,6 @@ from _pytest.config import Config from _pytest.nodes import Item - DEFAULT_MAX_LINES = 8 DEFAULT_MAX_CHARS = 8 * 80 USAGE_MSG = "use '-vv' to show" diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index ee68cc38c79..87ef38b5e43 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -112,6 +112,7 @@ def warn(self, fmt: str, *, _ispytest: bool = False, **args: object) -> None: """ check_ispytest(_ispytest) import warnings + from _pytest.warning_types import PytestCacheWarning warnings.warn( diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index ad8558b1f51..821b422f39f 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -17,7 +17,6 @@ from typing import NoReturn from typing import TypeVar - _T = TypeVar("_T") _S = TypeVar("_S") diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index c0e1e195f0d..7bab69b7abf 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -66,9 +66,10 @@ from _pytest.warning_types import warn_explicit_for if TYPE_CHECKING: + from .argparsing import Argument + from .argparsing import Parser from _pytest._code.code import _TracebackStyle from _pytest.terminal import TerminalReporter - from .argparsing import Argument, Parser _PluggyPlugin = object @@ -973,7 +974,8 @@ def __init__( *, invocation_params: Optional[InvocationParams] = None, ) -> None: - from .argparsing import Parser, FILE_OR_DIR + from .argparsing import FILE_OR_DIR + from .argparsing import Parser if invocation_params is None: invocation_params = self.InvocationParams( @@ -1390,8 +1392,9 @@ def _validate_plugins(self) -> None: return # Imported lazily to improve start-up time. + from packaging.requirements import InvalidRequirement + from packaging.requirements import Requirement from packaging.version import Version - from packaging.requirements import InvalidRequirement, Requirement plugin_info = self.pluginmanager.list_plugin_distinfo() plugin_dist_info = {dist.project_name: dist.version for _, dist in plugin_info} diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 1bc2cf57e80..0f611aa5ce4 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -8,6 +8,7 @@ :class:`PytestWarning`, or :class:`UnformattedWarning` in case of warnings which need to format their messages. """ + from warnings import warn from _pytest.warning_types import PytestDeprecationWarning diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index 1bccd18c636..824aec58eea 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -8,7 +8,6 @@ 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]() diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index d7d8a720bc5..7000cdab82d 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -67,7 +67,6 @@ from _pytest.scope import HIGH_SCOPES from _pytest.scope import Scope - if TYPE_CHECKING: from typing import Deque @@ -1231,8 +1230,7 @@ def fixture( Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] ] = ..., name: Optional[str] = ..., -) -> FixtureFunction: - ... +) -> FixtureFunction: ... @overload @@ -1246,8 +1244,7 @@ def fixture( # noqa: F811 Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] ] = ..., name: Optional[str] = None, -) -> FixtureFunctionMarker: - ... +) -> FixtureFunctionMarker: ... def fixture( # noqa: F811 diff --git a/src/_pytest/freeze_support.py b/src/_pytest/freeze_support.py index 9f8ea231fed..d028058e365 100644 --- a/src/_pytest/freeze_support.py +++ b/src/_pytest/freeze_support.py @@ -1,5 +1,6 @@ """Provides a function to report all internal modules for using freezing tools.""" + import types from typing import Iterator from typing import List diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 3c27dcf911a..0aace8c3493 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -19,12 +19,12 @@ import warnings from typing import Literal - from _pytest._code.code import ExceptionRepr from _pytest._code.code import ExceptionInfo + from _pytest._code.code import ExceptionRepr + from _pytest.config import _PluggyPlugin from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config import PytestPluginManager - from _pytest.config import _PluggyPlugin from _pytest.config.argparsing import Parser from _pytest.fixtures import FixtureDef from _pytest.fixtures import SubRequest diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index f01afd91578..a198e1d2363 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -34,7 +34,6 @@ from _pytest.stash import StashKey from _pytest.terminal import TerminalReporter - xml_key = StashKey["LogXML"]() diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index cb9a3624392..5dafea402b3 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -15,6 +15,7 @@ from iniconfig import SectionWrapper import py + from _pytest.cacheprovider import Cache from _pytest.config import Config from _pytest.config import hookimpl diff --git a/src/_pytest/main.py b/src/_pytest/main.py index f7e47cece1e..a75e53a0cd7 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -1,4 +1,5 @@ """Core implementation of the testing process: init, session, runtest loop.""" + import argparse import dataclasses import fnmatch @@ -721,14 +722,12 @@ def _collect_path( @overload def perform_collect( self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ... - ) -> Sequence[nodes.Item]: - ... + ) -> Sequence[nodes.Item]: ... @overload def perform_collect( # noqa: F811 self, args: Optional[Sequence[str]] = ..., genitems: bool = ... - ) -> Sequence[Union[nodes.Item, nodes.Collector]]: - ... + ) -> Sequence[Union[nodes.Item, nodes.Collector]]: ... def perform_collect( # noqa: F811 self, args: Optional[Sequence[str]] = None, genitems: bool = True diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index bcee802f3b1..ec5023c9173 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -1,4 +1,5 @@ """Generic mechanism for marking and selecting python functions.""" + import dataclasses from typing import AbstractSet from typing import Collection diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index b995518bf92..5fa0ccaa7b5 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -14,6 +14,7 @@ - ident evaluates to True of False according to a provided matcher function. - or/and/not evaluate according to the usual boolean semantics. """ + import ast import dataclasses import enum diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index e3580cf6fca..544e1dccf97 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -434,12 +434,10 @@ def store_mark(obj, mark: Mark) -> None: class _SkipMarkDecorator(MarkDecorator): @overload # type: ignore[override,misc,no-overload-impl] - def __call__(self, arg: Markable) -> Markable: - ... + def __call__(self, arg: Markable) -> Markable: ... @overload - def __call__(self, reason: str = ...) -> "MarkDecorator": - ... + def __call__(self, reason: str = ...) -> "MarkDecorator": ... class _SkipifMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] @@ -447,13 +445,11 @@ def __call__( # type: ignore[override] condition: Union[str, bool] = ..., *conditions: Union[str, bool], reason: str = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _XfailMarkDecorator(MarkDecorator): @overload # type: ignore[override,misc,no-overload-impl] - def __call__(self, arg: Markable) -> Markable: - ... + def __call__(self, arg: Markable) -> Markable: ... @overload def __call__( @@ -466,8 +462,7 @@ def __call__( None, Type[BaseException], Tuple[Type[BaseException], ...] ] = ..., strict: bool = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _ParametrizeMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] @@ -483,8 +478,7 @@ def __call__( # type: ignore[override] ] ] = ..., scope: Optional[_ScopeName] = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _UsefixturesMarkDecorator(MarkDecorator): def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override] diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index 01c74d6eb43..7b678017f0f 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -169,8 +169,7 @@ def setattr( name: object, value: Notset = ..., raising: bool = ..., - ) -> None: - ... + ) -> None: ... @overload def setattr( @@ -179,8 +178,7 @@ def setattr( name: str, value: object, raising: bool = ..., - ) -> None: - ... + ) -> None: ... def setattr( self, diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 2d6ad7b8fff..5260b003f84 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -41,8 +41,8 @@ if TYPE_CHECKING: # Imported here due to circular import. - from _pytest.main import Session from _pytest._code.code import _TracebackStyle + from _pytest.main import Session SEP = "/" @@ -104,6 +104,7 @@ class Node(abc.ABC, metaclass=NodeMeta): ``Collector``\'s are the internal nodes of the tree, and ``Item``\'s are the leaf nodes. """ + # Use __slots__ to make attribute access faster. # Note that __dict__ is still available. __slots__ = ( @@ -325,12 +326,10 @@ def iter_markers_with_node( yield node, mark @overload - def get_closest_marker(self, name: str) -> Optional[Mark]: - ... + def get_closest_marker(self, name: str) -> Optional[Mark]: ... @overload - def get_closest_marker(self, name: str, default: Mark) -> Mark: - ... + def get_closest_marker(self, name: str, default: Mark) -> Mark: ... def get_closest_marker( self, name: str, default: Optional[Mark] = None diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 8710ba3e85d..eb51e7f7e87 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -1,5 +1,6 @@ """Exception classes and constants handling test outcomes as well as functions creating them.""" + import sys from typing import Any from typing import Callable diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 48470337468..440d6ec5f1f 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -12,7 +12,6 @@ from _pytest.stash import StashKey from _pytest.terminal import TerminalReporter - pastebinfile_key = StashKey[IO[bytes]]() @@ -74,8 +73,8 @@ def create_new_paste(contents: Union[str, bytes]) -> str: :returns: URL to the pasted contents, or an error message. """ import re - from urllib.request import urlopen from urllib.parse import urlencode + from urllib.request import urlopen params = {"code": contents, "lexer": "text", "expiry": "1week"} url = "https://bpa.st" diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 69a24c7c90b..ae8709e5ed6 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -244,8 +244,7 @@ def __repr__(self) -> str: if TYPE_CHECKING: # The class has undetermined attributes, this tells mypy about it. - def __getattr__(self, key: str): - ... + def __getattr__(self, key: str): ... @final @@ -326,15 +325,13 @@ def getcall(self, name: str) -> RecordedHookCall: def getreports( self, names: "Literal['pytest_collectreport']", - ) -> Sequence[CollectReport]: - ... + ) -> Sequence[CollectReport]: ... @overload def getreports( self, names: "Literal['pytest_runtest_logreport']", - ) -> Sequence[TestReport]: - ... + ) -> Sequence[TestReport]: ... @overload def getreports( @@ -343,8 +340,7 @@ def getreports( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: - ... + ) -> Sequence[Union[CollectReport, TestReport]]: ... def getreports( self, @@ -391,15 +387,13 @@ def matchreport( def getfailures( self, names: "Literal['pytest_collectreport']", - ) -> Sequence[CollectReport]: - ... + ) -> Sequence[CollectReport]: ... @overload def getfailures( self, names: "Literal['pytest_runtest_logreport']", - ) -> Sequence[TestReport]: - ... + ) -> Sequence[TestReport]: ... @overload def getfailures( @@ -408,8 +402,7 @@ def getfailures( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: - ... + ) -> Sequence[Union[CollectReport, TestReport]]: ... def getfailures( self, diff --git a/src/_pytest/pytester_assertions.py b/src/_pytest/pytester_assertions.py index 657e4db5fc3..d20c2bb5999 100644 --- a/src/_pytest/pytester_assertions.py +++ b/src/_pytest/pytester_assertions.py @@ -1,4 +1,5 @@ """Helper plugin for pytester; should not be loaded on its own.""" + # This plugin contains assertions used by pytester. pytester cannot # contain them itself, since it is imported by the `pytest` module, # hence cannot be subject to assertion rewriting, which requires a diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 5fa32260b78..d069d7038a6 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -81,7 +81,6 @@ from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning - _PYTEST_DIR = Path(_pytest.__file__).parent @@ -1793,9 +1792,11 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: if self.config.getoption("tbstyle", "auto") == "auto": if len(ntraceback) > 2: ntraceback = Traceback( - entry - if i == 0 or i == len(ntraceback) - 1 - else entry.with_repr_style("short") + ( + entry + if i == 0 or i == len(ntraceback) - 1 + else entry.with_repr_style("short") + ) for i, entry in enumerate(ntraceback) ) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index c32d75b44b7..f398902ffe0 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -779,8 +779,7 @@ def raises( expected_exception: Union[Type[E], Tuple[Type[E], ...]], *, match: Optional[Union[str, Pattern[str]]] = ..., -) -> "RaisesContext[E]": - ... +) -> "RaisesContext[E]": ... @overload @@ -789,8 +788,7 @@ def raises( # noqa: F811 func: Callable[..., Any], *args: Any, **kwargs: Any, -) -> _pytest._code.ExceptionInfo[E]: - ... +) -> _pytest._code.ExceptionInfo[E]: ... def raises( # noqa: F811 diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 57d4bb47ccc..e8c8aff8baf 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -22,7 +22,6 @@ from _pytest.fixtures import fixture from _pytest.outcomes import fail - T = TypeVar("T") @@ -42,15 +41,13 @@ def recwarn() -> Generator["WarningsRecorder", None, None]: @overload def deprecated_call( *, match: Optional[Union[str, Pattern[str]]] = ... -) -> "WarningsRecorder": - ... +) -> "WarningsRecorder": ... @overload def deprecated_call( # noqa: F811 func: Callable[..., T], *args: Any, **kwargs: Any -) -> T: - ... +) -> T: ... def deprecated_call( # noqa: F811 @@ -92,8 +89,7 @@ def warns( expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ..., *, match: Optional[Union[str, Pattern[str]]] = ..., -) -> "WarningsChecker": - ... +) -> "WarningsChecker": ... @overload @@ -102,8 +98,7 @@ def warns( # noqa: F811 func: Callable[..., T], *args: Any, **kwargs: Any, -) -> T: - ... +) -> T: ... def warns( # noqa: F811 diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index ddf7f298321..44eaec90854 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -71,8 +71,7 @@ def __init__(self, **kw: Any) -> None: if TYPE_CHECKING: # Can have arbitrary fields given to __init__(). - def __getattr__(self, key: str) -> Any: - ... + def __getattr__(self, key: str) -> Any: ... def toterminal(self, out: TerminalWriter) -> None: if hasattr(self, "node"): @@ -609,9 +608,9 @@ def deserialize_repr_crash(repr_crash_dict: Optional[Dict[str, Any]]): description, ) ) - exception_info: Union[ - ExceptionChainRepr, ReprExceptionInfo - ] = ExceptionChainRepr(chain) + exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = ( + ExceptionChainRepr(chain) + ) else: exception_info = ReprExceptionInfo( reprtraceback=reprtraceback, diff --git a/src/_pytest/scope.py b/src/_pytest/scope.py index 98edaf40225..d15c12705cd 100644 --- a/src/_pytest/scope.py +++ b/src/_pytest/scope.py @@ -7,12 +7,12 @@ Also this makes the module light to import, as it should. """ + from enum import Enum from functools import total_ordering from typing import Literal from typing import Optional - _ScopeName = Literal["session", "package", "module", "class", "function"] diff --git a/src/_pytest/stash.py b/src/_pytest/stash.py index e61d75b95f7..7b111981bb0 100644 --- a/src/_pytest/stash.py +++ b/src/_pytest/stash.py @@ -5,7 +5,6 @@ from typing import TypeVar from typing import Union - __all__ = ["Stash", "StashKey"] diff --git a/src/_pytest/timing.py b/src/_pytest/timing.py index 925163a5858..096a6776873 100644 --- a/src/_pytest/timing.py +++ b/src/_pytest/timing.py @@ -5,6 +5,7 @@ Fixture "mock_timing" also interacts with this module for pytest's own tests. """ + from time import perf_counter from time import sleep from time import time diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index ce06b7d9bc4..3bdb0610e74 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -33,6 +33,7 @@ if TYPE_CHECKING: import unittest + import twisted.trial.unittest _SysExcInfoType = Union[ @@ -397,8 +398,8 @@ def excstore( def check_testcase_implements_trial_reporter(done: List[int] = []) -> None: if done: return - from zope.interface import classImplements from twisted.trial.itrial import IReporter + from zope.interface import classImplements classImplements(TestCaseFunction, IReporter) done.append(1) diff --git a/src/pytest/__main__.py b/src/pytest/__main__.py index b170152937b..9e08e3ebc20 100644 --- a/src/pytest/__main__.py +++ b/src/pytest/__main__.py @@ -1,4 +1,5 @@ """The pytest entry point.""" + import pytest if __name__ == "__main__": diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index ba19aef38ae..b97080ed007 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -7,10 +7,11 @@ import warnings from unittest import mock -import pytest from py import error from py.path import local +import pytest + @contextlib.contextmanager def ignore_encoding_warning(): @@ -1367,8 +1368,8 @@ def test_realpath_file(self, tmpdir): assert realpath.basename == "file" def test_owner(self, path1, tmpdir): - from pwd import getpwuid # type:ignore[attr-defined] from grp import getgrgid # type:ignore[attr-defined] + from pwd import getpwuid # type:ignore[attr-defined] stat = path1.stat() assert stat.path == path1 diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index a9982b4f323..36625cfb5ae 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -24,7 +24,6 @@ from _pytest.pytester import LineMatcher from _pytest.pytester import Pytester - if TYPE_CHECKING: from _pytest._code.code import _TracebackStyle diff --git a/testing/example_scripts/unittest/test_unittest_asyncio.py b/testing/example_scripts/unittest/test_unittest_asyncio.py index a82ddaebcc3..f0c394ee36e 100644 --- a/testing/example_scripts/unittest/test_unittest_asyncio.py +++ b/testing/example_scripts/unittest/test_unittest_asyncio.py @@ -2,7 +2,6 @@ from typing import List from unittest import IsolatedAsyncioTestCase - teardowns: List[None] = [] diff --git a/testing/example_scripts/unittest/test_unittest_asynctest.py b/testing/example_scripts/unittest/test_unittest_asynctest.py index b3f03e3256b..a5a0ec22c09 100644 --- a/testing/example_scripts/unittest/test_unittest_asynctest.py +++ b/testing/example_scripts/unittest/test_unittest_asynctest.py @@ -5,7 +5,6 @@ import asynctest - teardowns: List[None] = [] diff --git a/testing/freeze/create_executable.py b/testing/freeze/create_executable.py index 998df7b1ca7..3803b3b24ec 100644 --- a/testing/freeze/create_executable.py +++ b/testing/freeze/create_executable.py @@ -1,8 +1,10 @@ """Generate an executable with pytest runner embedded using PyInstaller.""" + if __name__ == "__main__": - import pytest import subprocess + import pytest + hidden = [] for x in pytest.freeze_includes(): hidden.extend(["--hidden-import", x]) diff --git a/testing/freeze/runtests_script.py b/testing/freeze/runtests_script.py index 591863016ac..ef63a2d15b9 100644 --- a/testing/freeze/runtests_script.py +++ b/testing/freeze/runtests_script.py @@ -5,6 +5,7 @@ if __name__ == "__main__": import sys + import pytest sys.exit(pytest.main()) diff --git a/testing/freeze/tox_run.py b/testing/freeze/tox_run.py index 678a69c858a..7fd63cf1218 100644 --- a/testing/freeze/tox_run.py +++ b/testing/freeze/tox_run.py @@ -2,6 +2,7 @@ Called by tox.ini: uses the generated executable to run the tests in ./tests/ directory. """ + if __name__ == "__main__": import os import sys diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index a13f9a4bcd9..0b83b5531df 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -13,7 +13,6 @@ from _pytest._io import terminalwriter from _pytest.monkeypatch import MonkeyPatch - # These tests were initially copied from py 1.8.1. diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 92fd72300f4..f6ac9c3b213 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -831,9 +831,10 @@ def test_live_logging_suspends_capture( We parametrize the test to also make sure _LiveLoggingStreamHandler works correctly if no capture manager plugin is installed. """ - import logging import contextlib + import logging from functools import partial + from _pytest.logging import _LiveLoggingStreamHandler class MockCaptureManager: diff --git a/testing/python/integration.py b/testing/python/integration.py index dbe1b1a00f5..3ff92d92f9a 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -43,9 +43,10 @@ def f(x): assert values == ("x",) def test_getfuncargnames_patching(self): - from _pytest.compat import getfuncargnames from unittest.mock import patch + from _pytest.compat import getfuncargnames + class T: def original(self, x, y, z): pass diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index a4386b3a8fa..0d1f9854bec 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1037,8 +1037,8 @@ def test_meta_path(): assert pytester.runpytest().ret == 0 def test_write_pyc(self, pytester: Pytester, tmp_path) -> None: - from _pytest.assertion.rewrite import _write_pyc from _pytest.assertion import AssertionState + from _pytest.assertion.rewrite import _write_pyc config = pytester.parseconfig() state = AssertionState(config, "rewrite") @@ -1088,6 +1088,7 @@ def test_read_pyc(self, tmp_path: Path) -> None: an exception that is propagated to the caller. """ import py_compile + from _pytest.assertion.rewrite import _read_pyc source = tmp_path / "source.py" diff --git a/testing/test_config.py b/testing/test_config.py index 45bcce4ea7f..5a18b9e419f 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2109,9 +2109,9 @@ def test_pytest_plugins_in_non_top_level_conftest_unsupported_pyargs( args = ("--pyargs", "pkg") if use_pyargs else () res = pytester.runpytest(*args) assert res.ret == (0 if use_pyargs else 2) - msg = ( - msg - ) = "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported" + msg = msg = ( + "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported" + ) if use_pyargs: assert msg not in res.stdout.str() else: diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 1cd46ae487a..c0b99797b4e 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -9,7 +9,6 @@ from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester - _ENVIRON_PYTHONBREAKPOINT = os.environ.get("PYTHONBREAKPOINT", "") diff --git a/testing/test_error_diffs.py b/testing/test_error_diffs.py index cad7a17c047..6494a44fb12 100644 --- a/testing/test_error_diffs.py +++ b/testing/test_error_diffs.py @@ -4,10 +4,10 @@ See https://github.com/pytest-dev/pytest/issues/3333 for details. """ + import pytest from _pytest.pytester import Pytester - TESTCASES = [ pytest.param( """ diff --git a/testing/test_faulthandler.py b/testing/test_faulthandler.py index 22545ea214c..b7142835dea 100644 --- a/testing/test_faulthandler.py +++ b/testing/test_faulthandler.py @@ -114,6 +114,7 @@ def test_cancel_timeout_on_hook(monkeypatch, hook_name) -> None: to timeout before entering pdb (pytest-dev/pytest-faulthandler#12) or any other interactive exception (pytest-dev/pytest-faulthandler#14).""" import faulthandler + from _pytest import faulthandler as faulthandler_plugin called = [] diff --git a/testing/test_mark.py b/testing/test_mark.py index 45acf050486..e37fc6c5339 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -943,7 +943,8 @@ def test_parameterset_for_parametrize_marks( ) config = pytester.parseconfig() - from _pytest.mark import pytest_configure, get_empty_parameterset_mark + from _pytest.mark import get_empty_parameterset_mark + from _pytest.mark import pytest_configure pytest_configure(config) result_mark = get_empty_parameterset_mark(config, ["a"], all) @@ -967,7 +968,8 @@ def test_parameterset_for_fail_at_collect(pytester: Pytester) -> None: ) config = pytester.parseconfig() - from _pytest.mark import pytest_configure, get_empty_parameterset_mark + from _pytest.mark import get_empty_parameterset_mark + from _pytest.mark import pytest_configure pytest_configure(config) diff --git a/testing/test_meta.py b/testing/test_meta.py index 9201bd21611..40ed95d6b47 100644 --- a/testing/test_meta.py +++ b/testing/test_meta.py @@ -3,6 +3,7 @@ This ensures all internal packages can be imported without needing the pytest namespace being set, which is critical for the initialization of xdist. """ + import pkgutil import subprocess import sys diff --git a/testing/test_reports.py b/testing/test_reports.py index ae2b68cdb7e..d65358a8fe6 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -296,9 +296,9 @@ def test_a(): reprec = pytester.inline_run() if report_class is TestReport: - reports: Union[ - Sequence[TestReport], Sequence[CollectReport] - ] = reprec.getreports("pytest_runtest_logreport") + reports: Union[Sequence[TestReport], Sequence[CollectReport]] = ( + reprec.getreports("pytest_runtest_logreport") + ) # we have 3 reports: setup/call/teardown assert len(reports) == 3 # get the call report diff --git a/tox.ini b/tox.ini index e4ad300a932..b5c28029fc8 100644 --- a/tox.ini +++ b/tox.ini @@ -200,6 +200,8 @@ extend-ignore = D302 ; Docstring Content Issues D400,D401,D401,D402,D405,D406,D407,D408,D409,D410,D411,D412,D413,D414,D415,D416,D417 + ; Unused imports + F401 [isort] From e885013c6bb49e90f8b7a34583e0f249f5de9bb7 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Tue, 30 Jan 2024 21:00:38 +0100 Subject: [PATCH 0409/1271] fix incorrect example for group_contains (#11892) --- doc/en/how-to/assert.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 5c7d125febe..7b027744695 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -154,7 +154,7 @@ method to test for exceptions returned as part of an :class:`ExceptionGroup`: .. code-block:: python def test_exception_in_group(): - with pytest.raises(RuntimeError) as excinfo: + with pytest.raises(ExceptionGroup) as excinfo: raise ExceptionGroup( "Group message", [ @@ -176,7 +176,7 @@ exception at a specific level; exceptions contained directly in the top .. code-block:: python def test_exception_in_group_at_given_depth(): - with pytest.raises(RuntimeError) as excinfo: + with pytest.raises(ExceptionGroup) as excinfo: raise ExceptionGroup( "Group message", [ From 3be2a9d655b5b0af388971ab39893b68d703d88d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 31 Jan 2024 07:50:49 -0300 Subject: [PATCH 0410/1271] Update and rename .gitblameignore to .git-blame-ignore-revs Seems like `.git-blame-ignore-revs` is the standard used and also automatically detected by GitHub: https://github.blog/changelog/2022-03-24-ignore-commits-in-the-blame-view-beta/ --- .gitblameignore => .git-blame-ignore-revs | 3 +++ 1 file changed, 3 insertions(+) rename .gitblameignore => .git-blame-ignore-revs (88%) diff --git a/.gitblameignore b/.git-blame-ignore-revs similarity index 88% rename from .gitblameignore rename to .git-blame-ignore-revs index 0cb298b024d..249ce70226f 100644 --- a/.gitblameignore +++ b/.git-blame-ignore-revs @@ -26,3 +26,6 @@ afc607cfd81458d4e4f3b1f3cf8cc931b933907e # move argument parser to own file c9df77cbd6a365dcb73c39618e4842711817e871 + +# Replace reorder-python-imports by isort due to black incompatibility (#11896) +8b54596639f41dfac070030ef20394b9001fe63c From 4546d5445aaefe6a03957db028c263521dfb5c4b Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 31 Jan 2024 13:53:21 +0100 Subject: [PATCH 0411/1271] Upgrade blacken-doc to black's 2024 style (#11899) --- .pre-commit-config.yaml | 2 +- doc/en/deprecations.rst | 63 ++++++++++++---------------------- doc/en/funcarg_compare.rst | 9 ++--- doc/en/historical-notes.rst | 6 ++-- doc/en/how-to/fixtures.rst | 6 ++-- doc/en/how-to/skipping.rst | 30 ++++++---------- doc/en/reference/reference.rst | 9 ++--- 7 files changed, 42 insertions(+), 83 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 244fe48e052..52429647741 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: rev: 1.16.0 hooks: - id: blacken-docs - additional_dependencies: [black==23.7.0] + additional_dependencies: [black==24.1.1] - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 76cc3482ad3..b9a59d7910f 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -33,13 +33,11 @@ have been available since years and should be used instead. .. code-block:: python @pytest.mark.tryfirst - def pytest_runtest_call(): - ... + def pytest_runtest_call(): ... # or - def pytest_runtest_call(): - ... + def pytest_runtest_call(): ... pytest_runtest_call.tryfirst = True @@ -49,8 +47,7 @@ should be changed to: .. code-block:: python @pytest.hookimpl(tryfirst=True) - def pytest_runtest_call(): - ... + def pytest_runtest_call(): ... Changed ``hookimpl`` attributes: @@ -146,8 +143,7 @@ Applying a mark to a fixture function never had any effect, but it is a common u @pytest.mark.usefixtures("clean_database") @pytest.fixture - def user() -> User: - ... + def user() -> User: ... Users expected in this case that the ``usefixtures`` mark would have its intended effect of using the ``clean_database`` fixture when ``user`` was invoked, when in fact it has no effect at all. @@ -308,11 +304,9 @@ they are in fact part of the ``nose`` support. def teardown(self): self.resource.close() - def test_foo(self): - ... + def test_foo(self): ... - def test_bar(self): - ... + def test_bar(self): ... @@ -327,11 +321,9 @@ Native pytest support uses ``setup_method`` and ``teardown_method`` (see :ref:`x def teardown_method(self): self.resource.close() - def test_foo(self): - ... + def test_foo(self): ... - def test_bar(self): - ... + def test_bar(self): ... This is easy to do in an entire code base by doing a simple find/replace. @@ -346,17 +338,14 @@ Code using `@with_setup `_ such as this: from nose.tools import with_setup - def setup_some_resource(): - ... + def setup_some_resource(): ... - def teardown_some_resource(): - ... + def teardown_some_resource(): ... @with_setup(setup_some_resource, teardown_some_resource) - def test_foo(): - ... + def test_foo(): ... Will also need to be ported to a supported pytest style. One way to do it is using a fixture: @@ -365,12 +354,10 @@ Will also need to be ported to a supported pytest style. One way to do it is usi import pytest - def setup_some_resource(): - ... + def setup_some_resource(): ... - def teardown_some_resource(): - ... + def teardown_some_resource(): ... @pytest.fixture @@ -380,8 +367,7 @@ Will also need to be ported to a supported pytest style. One way to do it is usi teardown_some_resource() - def test_foo(some_resource): - ... + def test_foo(some_resource): ... .. _`with-setup-nose`: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup @@ -500,8 +486,7 @@ Implement the :hook:`pytest_load_initial_conftests` hook instead. .. code-block:: python - def pytest_cmdline_preparse(config: Config, args: List[str]) -> None: - ... + def pytest_cmdline_preparse(config: Config, args: List[str]) -> None: ... # becomes: @@ -509,8 +494,7 @@ Implement the :hook:`pytest_load_initial_conftests` hook instead. def pytest_load_initial_conftests( early_config: Config, parser: Parser, args: List[str] - ) -> None: - ... + ) -> None: ... Collection changes in pytest 8 @@ -925,8 +909,7 @@ Applying marks to values of a ``pytest.mark.parametrize`` call is now deprecated (50, 500), ], ) - def test_foo(a, b): - ... + def test_foo(a, b): ... This code applies the ``pytest.mark.xfail(reason="flaky")`` mark to the ``(6, 36)`` value of the above parametrization call. @@ -949,8 +932,7 @@ To update the code, use ``pytest.param``: (50, 500), ], ) - def test_foo(a, b): - ... + def test_foo(a, b): ... .. _pytest_funcarg__ prefix deprecated: @@ -1101,15 +1083,13 @@ This is just a matter of renaming the fixture as the API is the same: .. code-block:: python - def test_foo(record_xml_property): - ... + def test_foo(record_xml_property): ... Change to: .. code-block:: python - def test_foo(record_property): - ... + def test_foo(record_property): ... .. _passing command-line string to pytest.main deprecated: @@ -1271,8 +1251,7 @@ Example of usage: .. code-block:: python - class MySymbol: - ... + class MySymbol: ... def pytest_namespace(): diff --git a/doc/en/funcarg_compare.rst b/doc/en/funcarg_compare.rst index 27def534b54..8b900d30f20 100644 --- a/doc/en/funcarg_compare.rst +++ b/doc/en/funcarg_compare.rst @@ -99,8 +99,7 @@ sets. pytest-2.3 introduces a decorator for use on the factory itself: .. code-block:: python @pytest.fixture(params=["mysql", "pg"]) - def db(request): - ... # use request.param + def db(request): ... # use request.param Here the factory will be invoked twice (with the respective "mysql" and "pg" values set as ``request.param`` attributes) and all of @@ -141,8 +140,7 @@ argument: .. code-block:: python @pytest.fixture() - def db(request): - ... + def db(request): ... The name under which the funcarg resource can be requested is ``db``. @@ -151,8 +149,7 @@ aka: .. code-block:: python - def pytest_funcarg__db(request): - ... + def pytest_funcarg__db(request): ... But it is then not possible to define scoping and parametrization. diff --git a/doc/en/historical-notes.rst b/doc/en/historical-notes.rst index ae32c28f3ec..5eb527c582b 100644 --- a/doc/en/historical-notes.rst +++ b/doc/en/historical-notes.rst @@ -227,8 +227,7 @@ to use strings: @pytest.mark.skipif("sys.version_info >= (3,3)") - def test_function(): - ... + def test_function(): ... During test function setup the skipif condition is evaluated by calling ``eval('sys.version_info >= (3,0)', namespace)``. The namespace contains @@ -262,8 +261,7 @@ configuration value which you might have added: .. code-block:: python @pytest.mark.skipif("not config.getvalue('db')") - def test_function(): - ... + def test_function(): ... The equivalent with "boolean conditions" is: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index ade0d809e38..bc45c3a29bf 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1721,8 +1721,7 @@ You can specify multiple fixtures like this: .. code-block:: python @pytest.mark.usefixtures("cleandir", "anotherfixture") - def test(): - ... + def test(): ... and you may specify fixture usage at the test module level using :globalvar:`pytestmark`: @@ -1750,8 +1749,7 @@ into an ini-file: @pytest.mark.usefixtures("my_other_fixture") @pytest.fixture - def my_fixture_that_sadly_wont_use_my_other_fixture(): - ... + def my_fixture_that_sadly_wont_use_my_other_fixture(): ... This generates a deprecation warning, and will become an error in Pytest 8. diff --git a/doc/en/how-to/skipping.rst b/doc/en/how-to/skipping.rst index 1fc6f5e0889..09a19766f99 100644 --- a/doc/en/how-to/skipping.rst +++ b/doc/en/how-to/skipping.rst @@ -47,8 +47,7 @@ which may be passed an optional ``reason``: .. code-block:: python @pytest.mark.skip(reason="no way of currently testing this") - def test_the_unknown(): - ... + def test_the_unknown(): ... Alternatively, it is also possible to skip imperatively during test execution or setup @@ -93,8 +92,7 @@ when run on an interpreter earlier than Python3.10: @pytest.mark.skipif(sys.version_info < (3, 10), reason="requires python3.10 or higher") - def test_function(): - ... + def test_function(): ... If the condition evaluates to ``True`` during collection, the test function will be skipped, with the specified reason appearing in the summary when using ``-rs``. @@ -112,8 +110,7 @@ You can share ``skipif`` markers between modules. Consider this test module: @minversion - def test_function(): - ... + def test_function(): ... You can import the marker and reuse it in another test module: @@ -124,8 +121,7 @@ You can import the marker and reuse it in another test module: @minversion - def test_anotherfunction(): - ... + def test_anotherfunction(): ... For larger test suites it's usually a good idea to have one file where you define the markers which you then consistently apply @@ -232,8 +228,7 @@ expect a test to fail: .. code-block:: python @pytest.mark.xfail - def test_function(): - ... + def test_function(): ... This test will run but no traceback will be reported when it fails. Instead, terminal reporting will list it in the "expected to fail" (``XFAIL``) or "unexpectedly @@ -275,8 +270,7 @@ that condition as the first parameter: .. code-block:: python @pytest.mark.xfail(sys.platform == "win32", reason="bug in a 3rd party library") - def test_function(): - ... + def test_function(): ... Note that you have to pass a reason as well (see the parameter description at :ref:`pytest.mark.xfail ref`). @@ -289,8 +283,7 @@ You can specify the motive of an expected failure with the ``reason`` parameter: .. code-block:: python @pytest.mark.xfail(reason="known parser issue") - def test_function(): - ... + def test_function(): ... ``raises`` parameter @@ -302,8 +295,7 @@ a single exception, or a tuple of exceptions, in the ``raises`` argument. .. code-block:: python @pytest.mark.xfail(raises=RuntimeError) - def test_function(): - ... + def test_function(): ... Then the test will be reported as a regular failure if it fails with an exception not mentioned in ``raises``. @@ -317,8 +309,7 @@ even executed, use the ``run`` parameter as ``False``: .. code-block:: python @pytest.mark.xfail(run=False) - def test_function(): - ... + def test_function(): ... This is specially useful for xfailing tests that are crashing the interpreter and should be investigated later. @@ -334,8 +325,7 @@ You can change this by setting the ``strict`` keyword-only parameter to ``True`` .. code-block:: python @pytest.mark.xfail(strict=True) - def test_function(): - ... + def test_function(): ... This will make ``XPASS`` ("unexpectedly passing") results from this test to fail the test suite. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 46aba0af943..4f0b1835b4d 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -164,8 +164,7 @@ Add warning filters to marked test items. .. code-block:: python @pytest.mark.filterwarnings("ignore:.*usage will be deprecated.*:DeprecationWarning") - def test_foo(): - ... + def test_foo(): ... .. _`pytest.mark.parametrize ref`: @@ -276,8 +275,7 @@ For example: .. code-block:: python @pytest.mark.timeout(10, "slow", method="thread") - def test_function(): - ... + def test_function(): ... Will create and attach a :class:`Mark ` object to the collected :class:`Item `, which can then be accessed by fixtures or hooks with @@ -294,8 +292,7 @@ Example for using multiple custom markers: @pytest.mark.timeout(10, "slow", method="thread") @pytest.mark.slow - def test_function(): - ... + def test_function(): ... When :meth:`Node.iter_markers <_pytest.nodes.Node.iter_markers>` or :meth:`Node.iter_markers_with_node <_pytest.nodes.Node.iter_markers_with_node>` is used with multiple markers, the marker closest to the function will be iterated over first. The above example will result in ``@pytest.mark.slow`` followed by ``@pytest.mark.timeout(...)``. From 046f64751bf205df695f11d298bfd87d553e1314 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 31 Jan 2024 13:59:14 +0100 Subject: [PATCH 0412/1271] Fix a duplicate assignment in test_config.py Taken from https://github.com/pytest-dev/pytest/pull/11885 that was closed. --- testing/test_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_config.py b/testing/test_config.py index 5a18b9e419f..df109e5b601 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2109,7 +2109,7 @@ def test_pytest_plugins_in_non_top_level_conftest_unsupported_pyargs( args = ("--pyargs", "pkg") if use_pyargs else () res = pytester.runpytest(*args) assert res.ret == (0 if use_pyargs else 2) - msg = msg = ( + msg = ( "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported" ) if use_pyargs: From 4588653b2497ed25976b7aaff225b889fb476756 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 31 Jan 2024 21:12:33 +0100 Subject: [PATCH 0413/1271] Migrate from autoflake, black, isort, pyupgrade, flake8 and pydocstyle, to ruff ruff is faster and handle everything we had prior. isort configuration done based on the indication from https://github.com/astral-sh/ruff/issues/4670, previousely based on reorder-python-import (#11896) flake8-docstrings was a wrapper around pydocstyle (now archived) that explicitly asks to use ruff in https://github.com/PyCQA/pydocstyle/pull/658. flake8-typing-import is useful mainly for project that support python 3.7 and the one useful check will be implemented in https://github.com/astral-sh/ruff/issues/2302 We need to keep blacken-doc because ruff does not handle detection of python code inside .md and .rst. The direct link to the repo is now used to avoid a redirection. Manual fixes: - Lines that became too long - % formatting that was not done automatically - type: ignore that were moved around - noqa of hard to fix issues (UP031 generally) - fmt: off and fmt: on that is not really identical between black and ruff - autofix re-order in pre-commit from faster to slower Co-authored-by: Ran Benita --- .pre-commit-config.yaml | 46 ++------- README.rst | 3 - bench/bench.py | 1 + bench/bench_argcomplete.py | 1 + bench/skip.py | 1 + bench/unit_test.py | 1 + doc/en/conf.py | 1 + .../global_testmodule_config/conftest.py | 1 + doc/en/example/assertion/test_failures.py | 1 + doc/en/example/multipython.py | 21 ++-- doc/en/example/xfail_demo.py | 1 + extra/get_issues.py | 1 + pyproject.toml | 52 ++++++++++ scripts/generate-gh-release-notes.py | 2 +- scripts/prepare-release-pr.py | 2 +- scripts/towncrier-draft-to-file.py | 2 +- scripts/update-plugin-list.py | 7 +- src/_pytest/_argcomplete.py | 2 +- src/_pytest/_code/__init__.py | 1 + src/_pytest/_code/code.py | 56 +++++------ src/_pytest/_code/source.py | 10 +- src/_pytest/_io/__init__.py | 1 + src/_pytest/_io/pprint.py | 2 +- src/_pytest/_io/saferepr.py | 5 +- src/_pytest/_io/terminalwriter.py | 7 +- src/_pytest/_io/wcwidth.py | 2 +- src/_pytest/_py/error.py | 1 + src/_pytest/_py/path.py | 43 ++++---- src/_pytest/assertion/__init__.py | 2 +- src/_pytest/assertion/rewrite.py | 37 +++---- src/_pytest/assertion/truncate.py | 1 + src/_pytest/assertion/util.py | 7 +- src/_pytest/cacheprovider.py | 9 +- src/_pytest/capture.py | 11 +-- src/_pytest/compat.py | 9 +- src/_pytest/config/__init__.py | 29 +++--- src/_pytest/config/argparsing.py | 7 +- src/_pytest/config/findpaths.py | 7 +- src/_pytest/debugging.py | 6 +- src/_pytest/deprecated.py | 1 + src/_pytest/doctest.py | 11 ++- src/_pytest/faulthandler.py | 3 +- src/_pytest/fixtures.py | 54 +++++----- src/_pytest/helpconfig.py | 13 +-- src/_pytest/hookspec.py | 3 +- src/_pytest/junitxml.py | 12 +-- src/_pytest/legacypath.py | 3 +- src/_pytest/logging.py | 17 ++-- src/_pytest/main.py | 12 ++- src/_pytest/mark/__init__.py | 5 +- src/_pytest/mark/expression.py | 1 + src/_pytest/mark/structures.py | 31 +++--- src/_pytest/monkeypatch.py | 23 ++--- src/_pytest/nodes.py | 15 +-- src/_pytest/outcomes.py | 3 +- src/_pytest/pastebin.py | 5 +- src/_pytest/pathlib.py | 25 +++-- src/_pytest/pytester.py | 50 +++++----- src/_pytest/python.py | 50 +++++----- src/_pytest/python_api.py | 30 +++--- src/_pytest/recwarn.py | 17 ++-- src/_pytest/reports.py | 26 +++-- src/_pytest/runner.py | 4 +- src/_pytest/scope.py | 1 + src/_pytest/setuponly.py | 4 +- src/_pytest/setupplan.py | 2 +- src/_pytest/skipping.py | 6 +- src/_pytest/stash.py | 1 + src/_pytest/stepwise.py | 3 +- src/_pytest/terminal.py | 21 ++-- src/_pytest/threadexception.py | 2 +- src/_pytest/timing.py | 1 + src/_pytest/tmpdir.py | 6 +- src/_pytest/unittest.py | 13 +-- src/_pytest/unraisableexception.py | 2 +- src/_pytest/warning_types.py | 8 +- src/_pytest/warnings.py | 6 +- src/py.py | 1 + src/pytest/__init__.py | 1 + src/pytest/__main__.py | 1 + testing/_py/test_local.py | 6 +- testing/acceptance_test.py | 2 +- testing/code/test_code.py | 2 +- testing/code/test_excinfo.py | 25 ++--- testing/conftest.py | 3 +- testing/deprecated_test.py | 2 +- .../acceptance/fixture_mock_integration.py | 1 + .../collect_stats/generate_folders.py | 1 + .../unittest/test_unittest_asyncio.py | 1 + .../unittest/test_unittest_asynctest.py | 1 + testing/io/test_pprint.py | 4 +- testing/io/test_saferepr.py | 14 +-- testing/io/test_terminalwriter.py | 5 +- testing/io/test_wcwidth.py | 2 +- testing/logging/test_fixture.py | 3 +- testing/logging/test_reporting.py | 68 +++++-------- testing/python/approx.py | 9 +- testing/python/collect.py | 10 +- testing/python/fixtures.py | 20 ++-- testing/python/integration.py | 2 +- testing/python/metafunc.py | 15 ++- testing/python/raises.py | 2 +- testing/test_argcomplete.py | 5 +- testing/test_assertion.py | 15 +-- testing/test_assertrewrite.py | 21 ++-- testing/test_cacheprovider.py | 39 +++----- testing/test_capture.py | 61 +++++------- testing/test_collection.py | 20 ++-- testing/test_compat.py | 5 +- testing/test_config.py | 36 +++---- testing/test_conftest.py | 4 +- testing/test_debugging.py | 10 +- testing/test_doctest.py | 98 +++++++------------ testing/test_error_diffs.py | 3 +- testing/test_faulthandler.py | 2 +- testing/test_findpaths.py | 2 +- testing/test_helpconfig.py | 2 +- testing/test_junitxml.py | 55 +++++------ testing/test_legacypath.py | 2 +- testing/test_link_resolve.py | 6 +- testing/test_main.py | 18 ++-- testing/test_mark.py | 18 ++-- testing/test_mark_expression.py | 2 +- testing/test_monkeypatch.py | 4 +- testing/test_nodes.py | 7 +- testing/test_parseopt.py | 12 +-- testing/test_pastebin.py | 2 +- testing/test_pathlib.py | 6 +- testing/test_pluginmanager.py | 2 +- testing/test_pytester.py | 10 +- testing/test_python_path.py | 2 +- testing/test_recwarn.py | 4 +- testing/test_reports.py | 16 ++- testing/test_runner.py | 7 +- testing/test_runner_xunit.py | 8 +- testing/test_scope.py | 2 +- testing/test_session.py | 2 +- testing/test_setuponly.py | 2 +- testing/test_skipping.py | 19 ++-- testing/test_stash.py | 2 +- testing/test_stepwise.py | 2 +- testing/test_terminal.py | 43 ++++---- testing/test_threadexception.py | 2 +- testing/test_tmpdir.py | 15 ++- testing/test_unittest.py | 38 +++---- testing/test_unraisableexception.py | 3 +- testing/test_warning_types.py | 5 +- testing/test_warnings.py | 17 ++-- tox.ini | 24 ----- 149 files changed, 799 insertions(+), 971 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 52429647741..032fe8c4d8b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,14 +1,10 @@ repos: -- repo: https://github.com/psf/black - rev: 24.1.1 - hooks: - - id: black - args: [--safe, --quiet] -- repo: https://github.com/asottile/blacken-docs - rev: 1.16.0 - hooks: - - id: blacken-docs - additional_dependencies: [black==24.1.1] +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: "v0.1.15" + hooks: + - id: ruff + args: ["--fix"] + - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.5.0 hooks: @@ -20,33 +16,11 @@ repos: - id: debug-statements exclude: _pytest/(debugging|hookspec).py language_version: python3 -- repo: https://github.com/PyCQA/autoflake - rev: v2.2.1 - hooks: - - id: autoflake - name: autoflake - args: ["--in-place", "--remove-unused-variables", "--remove-all-unused-imports"] - language: python - files: \.py$ -- repo: https://github.com/PyCQA/flake8 - rev: 7.0.0 - hooks: - - id: flake8 - language_version: python3 - additional_dependencies: - - flake8-typing-imports==1.12.0 - - flake8-docstrings==1.5.0 -- repo: https://github.com/pycqa/isort - rev: 5.13.2 - hooks: - - id: isort - name: isort - args: [--force-single-line, --profile=black] -- repo: https://github.com/asottile/pyupgrade - rev: v3.15.0 +- repo: https://github.com/adamchainz/blacken-docs + rev: 1.16.0 hooks: - - id: pyupgrade - args: [--py38-plus] + - id: blacken-docs + additional_dependencies: [black==24.1.1] - repo: https://github.com/asottile/setup-cfg-fmt rev: v2.5.0 hooks: diff --git a/README.rst b/README.rst index 6e4772b04ac..fba23872ec8 100644 --- a/README.rst +++ b/README.rst @@ -27,9 +27,6 @@ :target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main :alt: pre-commit.ci status -.. image:: https://img.shields.io/badge/code%20style-black-000000.svg - :target: https://github.com/psf/black - .. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg :target: https://www.codetriage.com/pytest-dev/pytest diff --git a/bench/bench.py b/bench/bench.py index c314b4f56bf..91e380a80d7 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -1,5 +1,6 @@ import sys + if __name__ == "__main__": import cProfile import pstats diff --git a/bench/bench_argcomplete.py b/bench/bench_argcomplete.py index 335733df72b..459a12f9314 100644 --- a/bench/bench_argcomplete.py +++ b/bench/bench_argcomplete.py @@ -4,6 +4,7 @@ # FastFilesCompleter 0.7383 1.0760 import timeit + imports = [ "from argcomplete.completers import FilesCompleter as completer", "from _pytest._argcomplete import FastFilesCompleter as completer", diff --git a/bench/skip.py b/bench/skip.py index f0c9d1ddbef..fd5c292d92c 100644 --- a/bench/skip.py +++ b/bench/skip.py @@ -1,5 +1,6 @@ import pytest + SKIP = True diff --git a/bench/unit_test.py b/bench/unit_test.py index ad52069dbfd..d3db111e1ae 100644 --- a/bench/unit_test.py +++ b/bench/unit_test.py @@ -1,5 +1,6 @@ from unittest import TestCase # noqa: F401 + for i in range(15000): exec( f""" diff --git a/doc/en/conf.py b/doc/en/conf.py index bb5737d7a57..cf889eb7a86 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -23,6 +23,7 @@ from _pytest import __version__ as version + if TYPE_CHECKING: import sphinx.application diff --git a/doc/en/example/assertion/global_testmodule_config/conftest.py b/doc/en/example/assertion/global_testmodule_config/conftest.py index 7cdf18cdbc1..4aa7ec23bd1 100644 --- a/doc/en/example/assertion/global_testmodule_config/conftest.py +++ b/doc/en/example/assertion/global_testmodule_config/conftest.py @@ -2,6 +2,7 @@ import pytest + mydir = os.path.dirname(__file__) diff --git a/doc/en/example/assertion/test_failures.py b/doc/en/example/assertion/test_failures.py index 350518b43c7..19d862f60b7 100644 --- a/doc/en/example/assertion/test_failures.py +++ b/doc/en/example/assertion/test_failures.py @@ -1,6 +1,7 @@ import os.path import shutil + failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py") pytest_plugins = ("pytester",) diff --git a/doc/en/example/multipython.py b/doc/en/example/multipython.py index 1354cb37c45..861ae9e528d 100644 --- a/doc/en/example/multipython.py +++ b/doc/en/example/multipython.py @@ -7,6 +7,7 @@ import pytest + pythonlist = ["python3.9", "python3.10", "python3.11"] @@ -32,14 +33,12 @@ def dumps(self, obj): dumpfile = self.picklefile.with_name("dump.py") dumpfile.write_text( textwrap.dedent( - r""" + rf""" import pickle - f = open({!r}, 'wb') - s = pickle.dump({!r}, f, protocol=2) + f = open({str(self.picklefile)!r}, 'wb') + s = pickle.dump({obj!r}, f, protocol=2) f.close() - """.format( - str(self.picklefile), obj - ) + """ ) ) subprocess.run((self.pythonpath, str(dumpfile)), check=True) @@ -48,17 +47,15 @@ def load_and_is_true(self, expression): loadfile = self.picklefile.with_name("load.py") loadfile.write_text( textwrap.dedent( - r""" + rf""" import pickle - f = open({!r}, 'rb') + f = open({str(self.picklefile)!r}, 'rb') obj = pickle.load(f) f.close() - res = eval({!r}) + res = eval({expression!r}) if not res: raise SystemExit(1) - """.format( - str(self.picklefile), expression - ) + """ ) ) print(loadfile) diff --git a/doc/en/example/xfail_demo.py b/doc/en/example/xfail_demo.py index 01e6da1ad2e..1040c89298d 100644 --- a/doc/en/example/xfail_demo.py +++ b/doc/en/example/xfail_demo.py @@ -1,5 +1,6 @@ import pytest + xfail = pytest.mark.xfail diff --git a/extra/get_issues.py b/extra/get_issues.py index 4aaa3c3ec31..716233ccba1 100644 --- a/extra/get_issues.py +++ b/extra/get_issues.py @@ -3,6 +3,7 @@ import requests + issues_url = "https://api.github.com/repos/pytest-dev/pytest/issues" diff --git a/pyproject.toml b/pyproject.toml index d45597b77c8..4a7e58fdb83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -123,3 +123,55 @@ target-version = ['py38'] [tool.check-wheel-contents] # W009: Wheel contains multiple toplevel library entries ignore = "W009" + +[tool.ruff] +src = ["src"] +line-length = 88 +select = [ + "D", # pydocstyle + "E", # pycodestyle + "F", # pyflakes + "I", # isort + "UP", # pyupgrade + "W", # pycodestyle +] +ignore = [ + # pycodestyle ignore + # pytest can do weird low-level things, and we usually know + # what we're doing when we use type(..) is ... + "E721", # Do not compare types, use `isinstance()` + # pydocstyle ignore + "D100", # Missing docstring in public module + "D101", # Missing docstring in public class + "D102", # Missing docstring in public method + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "D105", # Missing docstring in magic method + "D106", # Missing docstring in public nested class + "D107", # Missing docstring in `__init__` + "D209", # [*] Multi-line docstring closing quotes should be on a separate line + "D205", # 1 blank line required between summary line and description + "D400", # First line should end with a period + "D401", # First line of docstring should be in imperative mood + "D402", # First line should not be the function's signature + "D404", # First word of the docstring should not be "This" + "D415", # First line should end with a period, question mark, or exclamation point +] + +[tool.ruff.format] +docstring-code-format = true + +[tool.ruff.lint.pycodestyle] +# In order to be able to format for 88 char in ruff format +max-line-length = 120 + +[tool.ruff.lint.pydocstyle] +convention = "pep257" + +[tool.ruff.lint.isort] +force-single-line = true +combine-as-imports = true +force-sort-within-sections = true +order-by-type = false +known-local-folder = ["pytest", "_pytest"] +lines-after-imports = 2 diff --git a/scripts/generate-gh-release-notes.py b/scripts/generate-gh-release-notes.py index d22a5cf4c44..c27f5774b6e 100644 --- a/scripts/generate-gh-release-notes.py +++ b/scripts/generate-gh-release-notes.py @@ -8,9 +8,9 @@ Requires Python3.6+. """ +from pathlib import Path import re import sys -from pathlib import Path from typing import Sequence import pypandoc diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index ce8242a74a3..d2216b6fca3 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -14,8 +14,8 @@ `pytest bot ` commit author. """ import argparse -import re from pathlib import Path +import re from subprocess import check_call from subprocess import check_output from subprocess import run diff --git a/scripts/towncrier-draft-to-file.py b/scripts/towncrier-draft-to-file.py index 7b2748aa840..f771295a01f 100644 --- a/scripts/towncrier-draft-to-file.py +++ b/scripts/towncrier-draft-to-file.py @@ -1,6 +1,6 @@ # mypy: disallow-untyped-defs -import sys from subprocess import call +import sys def main() -> int: diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 287073f576e..7c5ac927796 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -11,13 +11,14 @@ import packaging.version import platformdirs -import tabulate -import wcwidth from requests_cache import CachedResponse from requests_cache import CachedSession from requests_cache import OriginalResponse from requests_cache import SQLiteCache +import tabulate from tqdm import tqdm +import wcwidth + FILE_HEAD = r""" .. Note this file is autogenerated by scripts/update-plugin-list.py - usually weekly via github action @@ -85,7 +86,6 @@ def project_response_with_refresh( force refresh in case of last serial mismatch """ - response = session.get(f"https://pypi.org/pypi/{name}/json") if int(response.headers.get("X-PyPI-Last-Serial", -1)) != last_serial: response = session.get(f"https://pypi.org/pypi/{name}/json", refresh=True) @@ -184,7 +184,6 @@ def version_sort_key(version_string: str) -> Any: def plugin_definitions(plugins: Iterable[PluginInfo]) -> Iterator[str]: """Return RST for the plugin list that fits better on a vertical page.""" - for plugin in plugins: yield dedent( f""" diff --git a/src/_pytest/_argcomplete.py b/src/_pytest/_argcomplete.py index c2ec1797fbc..c24f925202a 100644 --- a/src/_pytest/_argcomplete.py +++ b/src/_pytest/_argcomplete.py @@ -63,9 +63,9 @@ """ import argparse +from glob import glob import os import sys -from glob import glob from typing import Any from typing import List from typing import Optional diff --git a/src/_pytest/_code/__init__.py b/src/_pytest/_code/__init__.py index f82c3d2b030..b0a418e9555 100644 --- a/src/_pytest/_code/__init__.py +++ b/src/_pytest/_code/__init__.py @@ -10,6 +10,7 @@ from .source import getrawcode from .source import Source + __all__ = [ "Code", "ExceptionInfo", diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 8b38a8e7835..0662eb8cba5 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -2,14 +2,14 @@ import ast import dataclasses import inspect -import os -import re -import sys -import traceback from inspect import CO_VARARGS from inspect import CO_VARKEYWORDS from io import StringIO +import os from pathlib import Path +import re +import sys +import traceback from traceback import format_exception_only from types import CodeType from types import FrameType @@ -51,6 +51,7 @@ from _pytest.pathlib import absolutepath from _pytest.pathlib import bestrelpath + if sys.version_info[:2] < (3, 11): from exceptiongroup import BaseExceptionGroup @@ -278,9 +279,9 @@ def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool: Mostly for internal use. """ - tbh: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]] = ( - False - ) + tbh: Union[ + bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool] + ] = False for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals): # in normal cases, f_locals and f_globals are dictionaries # however via `exec(...)` / `eval(...)` they can be other types @@ -377,10 +378,12 @@ def cut( return self @overload - def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: ... + def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: + ... @overload - def __getitem__(self, key: slice) -> "Traceback": ... + def __getitem__(self, key: slice) -> "Traceback": + ... def __getitem__( self, key: Union["SupportsIndex", slice] @@ -485,9 +488,10 @@ def from_exception( .. versionadded:: 7.4 """ - assert ( - exception.__traceback__ - ), "Exceptions passed to ExcInfo.from_exception(...) must have a non-None __traceback__." + assert exception.__traceback__, ( + "Exceptions passed to ExcInfo.from_exception(...)" + " must have a non-None __traceback__." + ) exc_info = (type(exception), exception, exception.__traceback__) return cls.from_exc_info(exc_info, exprinfo) @@ -586,9 +590,7 @@ def traceback(self, value: Traceback) -> None: def __repr__(self) -> str: if self._excinfo is None: return "" - return "<{} {} tblen={}>".format( - self.__class__.__name__, saferepr(self._excinfo[1]), len(self.traceback) - ) + return f"<{self.__class__.__name__} {saferepr(self._excinfo[1])} tblen={len(self.traceback)}>" def exconly(self, tryshort: bool = False) -> str: """Return the exception as a string. @@ -1016,13 +1018,8 @@ def _truncate_recursive_traceback( extraline: Optional[str] = ( "!!! Recursion error detected, but an error occurred locating the origin of recursion.\n" " The following exception happened when comparing locals in the stack frame:\n" - " {exc_type}: {exc_msg}\n" - " Displaying first and last {max_frames} stack frames out of {total}." - ).format( - exc_type=type(e).__name__, - exc_msg=str(e), - max_frames=max_frames, - total=len(traceback), + f" {type(e).__name__}: {str(e)}\n" + f" Displaying first and last {max_frames} stack frames out of {len(traceback)}." ) # Type ignored because adding two instances of a List subtype # currently incorrectly has type List instead of the subtype. @@ -1054,13 +1051,13 @@ def repr_excinfo( # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 if isinstance(e, BaseExceptionGroup): - reprtraceback: Union[ReprTracebackNative, ReprTraceback] = ( - ReprTracebackNative( - traceback.format_exception( - type(excinfo_.value), - excinfo_.value, - excinfo_.traceback[0]._rawentry, - ) + reprtraceback: Union[ + ReprTracebackNative, ReprTraceback + ] = ReprTracebackNative( + traceback.format_exception( + type(excinfo_.value), + excinfo_.value, + excinfo_.traceback[0]._rawentry, ) ) else: @@ -1229,7 +1226,6 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: the "E" prefix) using syntax highlighting, taking care to not highlighting the ">" character, as doing so might break line continuations. """ - if not self.lines: return diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index a85b14371e2..69f580e2055 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -1,11 +1,10 @@ # mypy: allow-untyped-defs import ast +from bisect import bisect_right import inspect import textwrap import tokenize import types -import warnings -from bisect import bisect_right from typing import Iterable from typing import Iterator from typing import List @@ -13,6 +12,7 @@ from typing import overload from typing import Tuple from typing import Union +import warnings class Source: @@ -47,10 +47,12 @@ def __eq__(self, other: object) -> bool: __hash__ = None # type: ignore @overload - def __getitem__(self, key: int) -> str: ... + def __getitem__(self, key: int) -> str: + ... @overload - def __getitem__(self, key: slice) -> "Source": ... + def __getitem__(self, key: slice) -> "Source": + ... def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]: if isinstance(key, int): diff --git a/src/_pytest/_io/__init__.py b/src/_pytest/_io/__init__.py index a804cb549b4..db001e918cb 100644 --- a/src/_pytest/_io/__init__.py +++ b/src/_pytest/_io/__init__.py @@ -1,6 +1,7 @@ from .terminalwriter import get_terminal_width from .terminalwriter import TerminalWriter + __all__ = [ "TerminalWriter", "get_terminal_width", diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 6ec5d540107..75e9a7123b5 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -15,9 +15,9 @@ # useful, thank small children who sleep at night. import collections as _collections import dataclasses as _dataclasses +from io import StringIO as _StringIO import re import types as _types -from io import StringIO as _StringIO from typing import Any from typing import Callable from typing import Dict diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index c51578ed488..9f33fced676 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -19,8 +19,8 @@ def _format_repr_exception(exc: BaseException, obj: object) -> str: raise except BaseException as exc: exc_info = f"unpresentable exception ({_try_repr_or_str(exc)})" - return "<[{} raised in repr()] {} object at 0x{:x}>".format( - exc_info, type(obj).__name__, id(obj) + return ( + f"<[{exc_info} raised in repr()] {type(obj).__name__} object at 0x{id(obj):x}>" ) @@ -108,7 +108,6 @@ def saferepr( This function is a wrapper around the Repr/reprlib functionality of the stdlib. """ - return SafeRepr(maxsize, use_ascii).repr(obj) diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 89221796aea..16449b780c7 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -11,6 +11,7 @@ from .wcwidth import wcswidth + # This code was initially copied from py 1.8.1, file _io/terminalwriter.py. @@ -183,9 +184,7 @@ def _write_source(self, lines: Sequence[str], indents: Sequence[str] = ()) -> No """ if indents and len(indents) != len(lines): raise ValueError( - "indents size ({}) should have same size as lines ({})".format( - len(indents), len(lines) - ) + f"indents size ({len(indents)}) should have same size as lines ({len(lines)})" ) if not indents: indents = [""] * len(lines) @@ -210,8 +209,8 @@ def _highlight( from pygments.lexers.python import PythonLexer as Lexer elif lexer == "diff": from pygments.lexers.diff import DiffLexer as Lexer - import pygments.util from pygments import highlight + import pygments.util except ImportError: return source else: diff --git a/src/_pytest/_io/wcwidth.py b/src/_pytest/_io/wcwidth.py index e5c7bf4d868..53803133519 100644 --- a/src/_pytest/_io/wcwidth.py +++ b/src/_pytest/_io/wcwidth.py @@ -1,5 +1,5 @@ -import unicodedata from functools import lru_cache +import unicodedata @lru_cache(100) diff --git a/src/_pytest/_py/error.py b/src/_pytest/_py/error.py index 4b08d3b7a2e..68f1eed7ec0 100644 --- a/src/_pytest/_py/error.py +++ b/src/_pytest/_py/error.py @@ -9,6 +9,7 @@ from typing import TYPE_CHECKING from typing import TypeVar + if TYPE_CHECKING: from typing_extensions import ParamSpec diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 44262a524ea..af02d67b95f 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -3,15 +3,11 @@ from __future__ import annotations import atexit +from contextlib import contextmanager import fnmatch import importlib.util import io import os -import posixpath -import sys -import uuid -import warnings -from contextlib import contextmanager from os.path import abspath from os.path import dirname from os.path import exists @@ -20,18 +16,23 @@ from os.path import isfile from os.path import islink from os.path import normpath +import posixpath from stat import S_ISDIR from stat import S_ISLNK from stat import S_ISREG +import sys from typing import Any from typing import Callable from typing import cast from typing import Literal from typing import overload from typing import TYPE_CHECKING +import uuid +import warnings from . import error + # Moved from local.py. iswin32 = sys.platform == "win32" or (getattr(os, "_name", False) == "nt") @@ -204,10 +205,12 @@ class Stat: if TYPE_CHECKING: @property - def size(self) -> int: ... + def size(self) -> int: + ... @property - def mtime(self) -> float: ... + def mtime(self) -> float: + ... def __getattr__(self, name: str) -> Any: return getattr(self._osstatresult, "st_" + name) @@ -674,7 +677,7 @@ def new(self, **kw): else: kw.setdefault("dirname", dirname) kw.setdefault("sep", self.sep) - obj.strpath = normpath("%(dirname)s%(sep)s%(basename)s" % kw) + obj.strpath = normpath("{dirname}{sep}{basename}".format(**kw)) return obj def _getbyspec(self, spec: str) -> list[str]: @@ -759,7 +762,10 @@ def open(self, mode="r", ensure=False, encoding=None): # expected "Callable[[str, Any, Any], TextIOWrapper]" [arg-type] # Which seems incorrect, given io.open supports the given argument types. return error.checked_call( - io.open, self.strpath, mode, encoding=encoding # type:ignore[arg-type] + io.open, + self.strpath, + mode, + encoding=encoding, # type:ignore[arg-type] ) return error.checked_call(open, self.strpath, mode) @@ -778,11 +784,11 @@ def check(self, **kw): valid checkers:: - file=1 # is a file - file=0 # is not a file (may not even exist) - dir=1 # is a dir - link=1 # is a link - exists=1 # exists + file = 1 # is a file + file = 0 # is not a file (may not even exist) + dir = 1 # is a dir + link = 1 # is a link + exists = 1 # exists You can specify multiple checker definitions, for example:: @@ -960,10 +966,12 @@ def ensure(self, *args, **kwargs): return p @overload - def stat(self, raising: Literal[True] = ...) -> Stat: ... + def stat(self, raising: Literal[True] = ...) -> Stat: + ... @overload - def stat(self, raising: Literal[False]) -> Stat | None: ... + def stat(self, raising: Literal[False]) -> Stat | None: + ... def stat(self, raising: bool = True) -> Stat | None: """Return an os.stat() tuple.""" @@ -1275,7 +1283,8 @@ def mkdtemp(cls, rootdir=None): # error: Argument 1 has incompatible type overloaded function; expected "Callable[[str], str]" [arg-type] # Which seems incorrect, given tempfile.mkdtemp supports the given argument types. path = error.checked_call( - tempfile.mkdtemp, dir=str(rootdir) # type:ignore[arg-type] + tempfile.mkdtemp, + dir=str(rootdir), # type:ignore[arg-type] ) return cls(path) diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index 93365697890..ea71230e129 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -16,6 +16,7 @@ from _pytest.config.argparsing import Parser from _pytest.nodes import Item + if TYPE_CHECKING: from _pytest.main import Session @@ -129,7 +130,6 @@ def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: reporting via the pytest_assertrepr_compare hook. This sets up this custom comparison for the test. """ - ihook = item.ihook def callbinrepr(op, left: object, right: object) -> Optional[str]: diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index c24263e0663..0ab6eaa1393 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -1,6 +1,7 @@ """Rewrite assertion AST to produce nice error messages.""" import ast +from collections import defaultdict import errno import functools import importlib.abc @@ -10,13 +11,12 @@ import itertools import marshal import os +from pathlib import Path +from pathlib import PurePath import struct import sys import tokenize import types -from collections import defaultdict -from pathlib import Path -from pathlib import PurePath from typing import Callable from typing import Dict from typing import IO @@ -40,6 +40,7 @@ from _pytest.pathlib import fnmatch_ex from _pytest.stash import StashKey + # fmt: off from _pytest.assertion.util import format_explanation as _format_explanation # noqa:F401, isort:skip # fmt:on @@ -671,9 +672,9 @@ def __init__( self.enable_assertion_pass_hook = False self.source = source self.scope: tuple[ast.AST, ...] = () - self.variables_overwrite: defaultdict[tuple[ast.AST, ...], Dict[str, str]] = ( - defaultdict(dict) - ) + self.variables_overwrite: defaultdict[ + tuple[ast.AST, ...], Dict[str, str] + ] = defaultdict(dict) def run(self, mod: ast.Module) -> None: """Find all assert statements in *mod* and rewrite them.""" @@ -1019,9 +1020,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: ] ): pytest_temp = self.variable() - self.variables_overwrite[self.scope][ - v.left.target.id - ] = v.left # type:ignore[assignment] + self.variables_overwrite[self.scope][v.left.target.id] = v.left # type:ignore[assignment] v.left.target.id = pytest_temp self.push_format_context() res, expl = self.visit(v) @@ -1065,9 +1064,7 @@ def visit_Call(self, call: ast.Call) -> Tuple[ast.Name, str]: if isinstance(arg, ast.Name) and arg.id in self.variables_overwrite.get( self.scope, {} ): - arg = self.variables_overwrite[self.scope][ - arg.id - ] # type:ignore[assignment] + arg = self.variables_overwrite[self.scope][arg.id] # type:ignore[assignment] res, expl = self.visit(arg) arg_expls.append(expl) new_args.append(res) @@ -1075,9 +1072,7 @@ def visit_Call(self, call: ast.Call) -> Tuple[ast.Name, str]: if isinstance( keyword.value, ast.Name ) and keyword.value.id in self.variables_overwrite.get(self.scope, {}): - keyword.value = self.variables_overwrite[self.scope][ - keyword.value.id - ] # type:ignore[assignment] + keyword.value = self.variables_overwrite[self.scope][keyword.value.id] # type:ignore[assignment] res, expl = self.visit(keyword.value) new_kwargs.append(ast.keyword(keyword.arg, res)) if keyword.arg: @@ -1114,13 +1109,9 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: if isinstance( comp.left, ast.Name ) and comp.left.id in self.variables_overwrite.get(self.scope, {}): - comp.left = self.variables_overwrite[self.scope][ - comp.left.id - ] # type:ignore[assignment] + comp.left = self.variables_overwrite[self.scope][comp.left.id] # type:ignore[assignment] if isinstance(comp.left, ast.NamedExpr): - self.variables_overwrite[self.scope][ - comp.left.target.id - ] = comp.left # type:ignore[assignment] + self.variables_overwrite[self.scope][comp.left.target.id] = comp.left # type:ignore[assignment] left_res, left_expl = self.visit(comp.left) if isinstance(comp.left, (ast.Compare, ast.BoolOp)): left_expl = f"({left_expl})" @@ -1138,9 +1129,7 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: and next_operand.target.id == left_res.id ): next_operand.target.id = self.variable() - self.variables_overwrite[self.scope][ - left_res.id - ] = next_operand # type:ignore[assignment] + self.variables_overwrite[self.scope][left_res.id] = next_operand # type:ignore[assignment] next_res, next_expl = self.visit(next_operand) if isinstance(next_operand, (ast.Compare, ast.BoolOp)): next_expl = f"({next_expl})" diff --git a/src/_pytest/assertion/truncate.py b/src/_pytest/assertion/truncate.py index 1e586567240..902d4baf846 100644 --- a/src/_pytest/assertion/truncate.py +++ b/src/_pytest/assertion/truncate.py @@ -11,6 +11,7 @@ from _pytest.config import Config from _pytest.nodes import Item + DEFAULT_MAX_LINES = 8 DEFAULT_MAX_CHARS = 8 * 80 USAGE_MSG = "use '-vv' to show" diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index d2f67994c30..33dcd4628de 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -15,13 +15,14 @@ from typing import Sequence from unicodedata import normalize -import _pytest._code from _pytest import outcomes +import _pytest._code from _pytest._io.pprint import PrettyPrinter from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr_unlimited from _pytest.config import Config + # The _reprcompare attribute on the util module is used by the new assertion # interpretation code and assertion rewriter to detect this plugin was # loaded and in turn call the hooks defined here as part of the @@ -302,8 +303,8 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]: if i > 42: i -= 10 # Provide some context explanation += [ - "Skipping {} identical trailing " - "characters in diff, use -v to show".format(i) + f"Skipping {i} identical trailing " + "characters in diff, use -v to show" ] left = left[:-i] right = right[:-i] diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 87ef38b5e43..5ccd2168ddf 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -32,6 +32,7 @@ from _pytest.nodes import File from _pytest.reports import TestReport + README_CONTENT = """\ # pytest cache directory # @@ -368,15 +369,13 @@ def pytest_collection_modifyitems( noun = "failure" if self._previously_failed_count == 1 else "failures" suffix = " first" if self.config.getoption("failedfirst") else "" - self._report_status = "rerun previous {count} {noun}{suffix}".format( - count=self._previously_failed_count, suffix=suffix, noun=noun + self._report_status = ( + f"rerun previous {self._previously_failed_count} {noun}{suffix}" ) if self._skipped_files > 0: files_noun = "file" if self._skipped_files == 1 else "files" - self._report_status += " (skipped {files} {files_noun})".format( - files=self._skipped_files, files_noun=files_noun - ) + self._report_status += f" (skipped {self._skipped_files} {files_noun})" else: self._report_status = "no previously failed tests, " if self.config.getoption("last_failed_no_failures") == "none": diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index c89763344a6..b9e0950285b 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -4,9 +4,9 @@ import collections import contextlib import io +from io import UnsupportedOperation import os import sys -from io import UnsupportedOperation from tempfile import TemporaryFile from types import TracebackType from typing import Any @@ -39,6 +39,7 @@ from _pytest.nodes import Item from _pytest.reports import CollectReport + _CaptureMethod = Literal["fd", "sys", "no", "tee-sys"] @@ -790,9 +791,7 @@ def set_fixture(self, capture_fixture: "CaptureFixture[Any]") -> None: current_fixture = self._capture_fixture.request.fixturename requested_fixture = capture_fixture.request.fixturename capture_fixture.request.raiseerror( - "cannot use {} and {} at the same time".format( - requested_fixture, current_fixture - ) + f"cannot use {requested_fixture} and {current_fixture} at the same time" ) self._capture_fixture = capture_fixture @@ -988,7 +987,6 @@ def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]: Returns an instance of :class:`CaptureFixture[str] `. Example: - .. code-block:: python def test_output(capsys): @@ -1016,7 +1014,6 @@ def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, Returns an instance of :class:`CaptureFixture[bytes] `. Example: - .. code-block:: python def test_output(capsysbinary): @@ -1044,7 +1041,6 @@ def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]: Returns an instance of :class:`CaptureFixture[str] `. Example: - .. code-block:: python def test_system_echo(capfd): @@ -1072,7 +1068,6 @@ def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, N Returns an instance of :class:`CaptureFixture[bytes] `. Example: - .. code-block:: python def test_system_echo(capfdbinary): diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 821b422f39f..32e635255f5 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -6,17 +6,18 @@ import enum import functools import inspect -import os -import sys from inspect import Parameter from inspect import signature +import os from pathlib import Path +import sys from typing import Any from typing import Callable from typing import Final from typing import NoReturn from typing import TypeVar + _T = TypeVar("_T") _S = TypeVar("_S") @@ -243,9 +244,7 @@ def get_real_func(obj): from _pytest._io.saferepr import saferepr raise ValueError( - ("could not find real function of {start}\nstopped at {current}").format( - start=saferepr(start_obj), current=saferepr(obj) - ) + f"could not find real function of {saferepr(start_obj)}\nstopped at {saferepr(obj)}" ) if isinstance(obj, functools.partial): obj = obj.func diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 7bab69b7abf..8c2f05239a0 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -5,18 +5,17 @@ import copy import dataclasses import enum +from functools import lru_cache import glob import importlib.metadata import inspect import os +from pathlib import Path import re import shlex import sys -import types -import warnings -from functools import lru_cache -from pathlib import Path from textwrap import dedent +import types from types import FunctionType from typing import Any from typing import Callable @@ -37,6 +36,7 @@ from typing import Type from typing import TYPE_CHECKING from typing import Union +import warnings from pluggy import HookimplMarker from pluggy import HookimplOpts @@ -44,15 +44,15 @@ from pluggy import HookspecOpts from pluggy import PluginManager -import _pytest._code -import _pytest.deprecated -import _pytest.hookspec from .exceptions import PrintHelp as PrintHelp from .exceptions import UsageError as UsageError from .findpaths import determine_setup +import _pytest._code from _pytest._code import ExceptionInfo from _pytest._code import filter_traceback from _pytest._io import TerminalWriter +import _pytest.deprecated +import _pytest.hookspec from _pytest.outcomes import fail from _pytest.outcomes import Skipped from _pytest.pathlib import absolutepath @@ -65,6 +65,7 @@ from _pytest.warning_types import PytestConfigWarning from _pytest.warning_types import warn_explicit_for + if TYPE_CHECKING: from .argparsing import Argument from .argparsing import Parser @@ -813,7 +814,7 @@ def import_plugin(self, modname: str, consider_entry_points: bool = False) -> No def _get_plugin_specs_as_list( - specs: Union[None, types.ModuleType, str, Sequence[str]] + specs: Union[None, types.ModuleType, str, Sequence[str]], ) -> List[str]: """Parse a plugins specification into a list of plugin names.""" # None means empty. @@ -1374,12 +1375,7 @@ def _checkversion(self) -> None: if Version(minver) > Version(pytest.__version__): raise pytest.UsageError( - "%s: 'minversion' requires pytest-%s, actual pytest-%s'" - % ( - self.inipath, - minver, - pytest.__version__, - ) + f"{self.inipath}: 'minversion' requires pytest-{minver}, actual pytest-{pytest.__version__}'" ) def _validate_config_options(self) -> None: @@ -1614,9 +1610,7 @@ def _get_override_ini_value(self, name: str) -> Optional[str]: key, user_ini_value = ini_config.split("=", 1) except ValueError as e: raise UsageError( - "-o/--override-ini expects option=value style (got: {!r}).".format( - ini_config - ) + f"-o/--override-ini expects option=value style (got: {ini_config!r})." ) from e else: if key == name: @@ -1674,7 +1668,6 @@ def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: can be used to explicitly use the global verbosity level. Example: - .. code-block:: ini # content of pytest.ini diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index a31278f32a0..18cf4600aa1 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -1,8 +1,8 @@ # mypy: allow-untyped-defs import argparse +from gettext import gettext import os import sys -from gettext import gettext from typing import Any from typing import Callable from typing import cast @@ -21,6 +21,7 @@ from _pytest.config.exceptions import UsageError from _pytest.deprecated import check_ispytest + FILE_OR_DIR = "file_or_dir" @@ -216,7 +217,7 @@ def addini( def get_ini_default_for_type( - type: Optional[Literal["string", "paths", "pathlist", "args", "linelist", "bool"]] + type: Optional[Literal["string", "paths", "pathlist", "args", "linelist", "bool"]], ) -> Any: """ Used by addini to get the default value for a given ini-option type, when @@ -448,7 +449,7 @@ def _parse_optional( ) -> Optional[Tuple[Optional[argparse.Action], str, Optional[str]]]: if not arg_string: return None - if not arg_string[0] in self.prefix_chars: + if arg_string[0] not in self.prefix_chars: return None if arg_string in self._option_string_actions: action = self._option_string_actions[arg_string] diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 8e69a46fd6f..96f3536514e 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -1,6 +1,6 @@ import os -import sys from pathlib import Path +import sys from typing import Dict from typing import Iterable from typing import List @@ -37,7 +37,6 @@ def load_config_dict_from_file( Return None if the file does not contain valid pytest configuration. """ - # Configuration from ini files are obtained from the [pytest] section, if present. if filepath.suffix == ".ini": iniconfig = _parse_ini_config(filepath) @@ -213,9 +212,7 @@ def determine_setup( rootdir = absolutepath(os.path.expandvars(rootdir_cmd_arg)) if not rootdir.is_dir(): raise UsageError( - "Directory '{}' not found. Check your '--rootdir' option.".format( - rootdir - ) + f"Directory '{rootdir}' not found. Check your '--rootdir' option." ) assert rootdir is not None return rootdir, inipath, inicfg or {} diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index aaac3e1b9c3..cb157cd6724 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -4,7 +4,6 @@ import functools import sys import types -import unittest from typing import Any from typing import Callable from typing import Generator @@ -14,6 +13,7 @@ from typing import Type from typing import TYPE_CHECKING from typing import Union +import unittest from _pytest import outcomes from _pytest._code import ExceptionInfo @@ -26,6 +26,7 @@ from _pytest.nodes import Node from _pytest.reports import BaseReport + if TYPE_CHECKING: from _pytest.capture import CaptureManager from _pytest.runner import CallInfo @@ -264,8 +265,7 @@ def _init_pdb(cls, method, *args, **kwargs): elif capturing: tw.sep( ">", - "PDB %s (IO-capturing turned off for %s)" - % (method, capturing), + f"PDB {method} (IO-capturing turned off for {capturing})", ) else: tw.sep(">", f"PDB {method}") diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 0f611aa5ce4..56271c9578e 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -15,6 +15,7 @@ from _pytest.warning_types import PytestRemovedIn9Warning from _pytest.warning_types import UnformattedWarning + # set of plugins which have been integrated into the core; we use this list to ignore # them during registration to avoid conflicts DEPRECATED_EXTERNAL_PLUGINS = { diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 6a5bc75774e..fdf84d3002c 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -1,16 +1,15 @@ # mypy: allow-untyped-defs """Discover and run doctests in modules and test files.""" import bdb +from contextlib import contextmanager import functools import inspect import os +from pathlib import Path import platform import sys import traceback import types -import warnings -from contextlib import contextmanager -from pathlib import Path from typing import Any from typing import Callable from typing import Dict @@ -24,6 +23,7 @@ from typing import Type from typing import TYPE_CHECKING from typing import Union +import warnings from _pytest import outcomes from _pytest._code.code import ExceptionInfo @@ -45,6 +45,7 @@ from _pytest.python_api import approx from _pytest.warning_types import PytestWarning + if TYPE_CHECKING: import doctest @@ -486,9 +487,9 @@ def _mock_aware_unwrap( return real_unwrap(func, stop=lambda obj: _is_mocked(obj) or _stop(func)) except Exception as e: warnings.warn( - "Got %r when unwrapping %r. This is usually caused " + f"Got {e!r} when unwrapping {func!r}. This is usually caused " "by a violation of Python's object protocol; see e.g. " - "https://github.com/pytest-dev/pytest/issues/5080" % (e, func), + "https://github.com/pytest-dev/pytest/issues/5080", PytestWarning, ) raise diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index 824aec58eea..083bcb83739 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -2,11 +2,12 @@ import sys from typing import Generator -import pytest from _pytest.config import Config from _pytest.config.argparsing import Parser from _pytest.nodes import Item from _pytest.stash import StashKey +import pytest + fault_handler_original_stderr_fd_key = StashKey[int]() fault_handler_stderr_fd_key = StashKey[int]() diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 7000cdab82d..a4e03f80cc0 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1,13 +1,12 @@ # mypy: allow-untyped-defs import abc +from collections import defaultdict +from collections import deque +from contextlib import suppress import dataclasses import functools import inspect import os -import warnings -from collections import defaultdict -from collections import deque -from contextlib import suppress from pathlib import Path from typing import AbstractSet from typing import Any @@ -31,6 +30,7 @@ from typing import TYPE_CHECKING from typing import TypeVar from typing import Union +import warnings import _pytest from _pytest import nodes @@ -67,6 +67,7 @@ from _pytest.scope import HIGH_SCOPES from _pytest.scope import Scope + if TYPE_CHECKING: from typing import Deque @@ -601,13 +602,9 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: fixtures_not_supported = getattr(funcitem, "nofuncargs", False) if has_params and fixtures_not_supported: msg = ( - "{name} does not support fixtures, maybe unittest.TestCase subclass?\n" - "Node id: {nodeid}\n" - "Function type: {typename}" - ).format( - name=funcitem.name, - nodeid=funcitem.nodeid, - typename=type(funcitem).__name__, + f"{funcitem.name} does not support fixtures, maybe unittest.TestCase subclass?\n" + f"Node id: {funcitem.nodeid}\n" + f"Function type: {type(funcitem).__name__}" ) fail(msg, pytrace=False) if has_params: @@ -740,9 +737,7 @@ def node(self): if node is None and scope is Scope.Class: # Fallback to function item itself. node = self._pyfuncitem - assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format( - scope, self._pyfuncitem - ) + assert node, f'Could not obtain a node for scope "{scope}" for function {self._pyfuncitem!r}' return node def _check_scope( @@ -845,8 +840,8 @@ def formatrepr(self) -> "FixtureLookupErrorRepr": if faclist: available.add(name) if self.argname in available: - msg = " recursive dependency involving fixture '{}' detected".format( - self.argname + msg = ( + f" recursive dependency involving fixture '{self.argname}' detected" ) else: msg = f"fixture '{self.argname}' not found" @@ -940,15 +935,13 @@ def _eval_scope_callable( result = scope_callable(fixture_name=fixture_name, config=config) # type: ignore[call-arg] except Exception as e: raise TypeError( - "Error evaluating {} while defining fixture '{}'.\n" - "Expected a function with the signature (*, fixture_name, config)".format( - scope_callable, fixture_name - ) + f"Error evaluating {scope_callable} while defining fixture '{fixture_name}'.\n" + "Expected a function with the signature (*, fixture_name, config)" ) from e if not isinstance(result, str): fail( - "Expected {} to return a 'str' while defining fixture '{}', but it returned:\n" - "{!r}".format(scope_callable, fixture_name, result), + f"Expected {scope_callable} to return a 'str' while defining fixture '{fixture_name}', but it returned:\n" + f"{result!r}", pytrace=False, ) return result @@ -1090,9 +1083,7 @@ def cache_key(self, request: SubRequest) -> object: return request.param_index if not hasattr(request, "param") else request.param def __repr__(self) -> str: - return "".format( - self.argname, self.scope, self.baseid - ) + return f"" def resolve_fixture_function( @@ -1113,7 +1104,8 @@ def resolve_fixture_function( # Handle the case where fixture is defined not in a test class, but some other class # (for example a plugin class with a fixture), see #2270. if hasattr(fixturefunc, "__self__") and not isinstance( - request.instance, fixturefunc.__self__.__class__ # type: ignore[union-attr] + request.instance, + fixturefunc.__self__.__class__, # type: ignore[union-attr] ): return fixturefunc fixturefunc = getimfunc(fixturedef.func) @@ -1208,9 +1200,7 @@ def __call__(self, function: FixtureFunction) -> FixtureFunction: if name == "request": location = getlocation(function) fail( - "'request' is a reserved word for fixtures, use another name:\n {}".format( - location - ), + f"'request' is a reserved word for fixtures, use another name:\n {location}", pytrace=False, ) @@ -1230,7 +1220,8 @@ def fixture( Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] ] = ..., name: Optional[str] = ..., -) -> FixtureFunction: ... +) -> FixtureFunction: + ... @overload @@ -1244,7 +1235,8 @@ def fixture( # noqa: F811 Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] ] = ..., name: Optional[str] = None, -) -> FixtureFunctionMarker: ... +) -> FixtureFunctionMarker: + ... def fixture( # noqa: F811 diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 4f7d351729d..aa8bf65c73f 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -1,19 +1,19 @@ # mypy: allow-untyped-defs """Version info, help messages, tracing configuration.""" +from argparse import Action import os import sys -from argparse import Action from typing import Generator from typing import List from typing import Optional from typing import Union -import pytest from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config import PrintHelp from _pytest.config.argparsing import Parser from _pytest.terminal import TerminalReporter +import pytest class HelpAction(Action): @@ -109,9 +109,8 @@ def pytest_cmdline_parse() -> Generator[None, Config, Config]: path = config.option.debug debugfile = open(path, "w", encoding="utf-8") debugfile.write( - "versions pytest-%s, " - "python-%s\ninvocation_dir=%s\ncwd=%s\nargs=%s\n\n" - % ( + "versions pytest-{}, " + "python-{}\ninvocation_dir={}\ncwd={}\nargs={}\n\n".format( pytest.__version__, ".".join(map(str, sys.version_info)), config.invocation_params.dir, @@ -137,9 +136,7 @@ def unset_tracing() -> None: def showversion(config: Config) -> None: if config.option.version > 1: sys.stdout.write( - "This is pytest version {}, imported from {}\n".format( - pytest.__version__, pytest.__file__ - ) + f"This is pytest version {pytest.__version__}, imported from {pytest.__file__}\n" ) plugininfo = getpluginversioninfo(config) if plugininfo: diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 0aace8c3493..58f4986ec7e 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -14,10 +14,11 @@ from pluggy import HookspecMarker + if TYPE_CHECKING: import pdb - import warnings from typing import Literal + import warnings from _pytest._code.code import ExceptionInfo from _pytest._code.code import ExceptionRepr diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index a198e1d2363..7a952231c33 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -7,12 +7,11 @@ Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd """ +from datetime import datetime import functools import os import platform import re -import xml.etree.ElementTree as ET -from datetime import datetime from typing import Callable from typing import Dict from typing import List @@ -20,8 +19,8 @@ from typing import Optional from typing import Tuple from typing import Union +import xml.etree.ElementTree as ET -import pytest from _pytest import nodes from _pytest import timing from _pytest._code.code import ExceptionRepr @@ -33,6 +32,8 @@ from _pytest.reports import TestReport from _pytest.stash import StashKey from _pytest.terminal import TerminalReporter +import pytest + xml_key = StashKey["LogXML"]() @@ -273,9 +274,7 @@ def _warn_incompatibility_with_xunit2( if xml is not None and xml.family not in ("xunit1", "legacy"): request.node.warn( PytestWarning( - "{fixture_name} is incompatible with junit_family '{family}' (use 'legacy' or 'xunit1')".format( - fixture_name=fixture_name, family=xml.family - ) + f"{fixture_name} is incompatible with junit_family '{xml.family}' (use 'legacy' or 'xunit1')" ) ) @@ -367,7 +366,6 @@ def test_foo(record_testsuite_property): `pytest-xdist `__ plugin. See :issue:`7767` for details. """ - __tracebackhide__ = True def record_func(name: str, value: object) -> None: diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index 5dafea402b3..b56f3a6fb63 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -2,9 +2,9 @@ """Add backward compatibility support for the legacy py path type.""" import dataclasses import os +from pathlib import Path import shlex import subprocess -from pathlib import Path from typing import Final from typing import final from typing import List @@ -34,6 +34,7 @@ from _pytest.terminal import TerminalReporter from _pytest.tmpdir import TempPathFactory + if TYPE_CHECKING: import pexpect diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 5565a6b3f9f..aa3a33e6377 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -1,17 +1,17 @@ # mypy: allow-untyped-defs """Access and control log capturing.""" -import io -import logging -import os -import re from contextlib import contextmanager from contextlib import nullcontext from datetime import datetime from datetime import timedelta from datetime import timezone +import io from io import StringIO +import logging from logging import LogRecord +import os from pathlib import Path +import re from types import TracebackType from typing import AbstractSet from typing import Dict @@ -44,6 +44,7 @@ from _pytest.stash import StashKey from _pytest.terminal import TerminalReporter + if TYPE_CHECKING: logging_StreamHandler = logging.StreamHandler[StringIO] else: @@ -116,7 +117,6 @@ def add_color_level(self, level: int, *color_opts: str) -> None: .. warning:: This is an experimental API. """ - assert self._fmt is not None levelname_fmt_match = self.LEVELNAME_FMT_REGEX.search(self._fmt) if not levelname_fmt_match: @@ -183,7 +183,6 @@ def _get_auto_indent(auto_indent_option: Union[int, str, bool, None]) -> int: 0 (auto-indent turned off) or >0 (explicitly set indentation position). """ - if auto_indent_option is None: return 0 elif isinstance(auto_indent_option, bool): @@ -625,9 +624,9 @@ def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[i except ValueError as e: # Python logging does not recognise this as a logging level raise UsageError( - "'{}' is not recognized as a logging level name for " - "'{}'. Please consider passing the " - "logging level num instead.".format(log_level, setting_name) + f"'{log_level}' is not recognized as a logging level name for " + f"'{setting_name}'. Please consider passing the " + "logging level num instead." ) from e diff --git a/src/_pytest/main.py b/src/_pytest/main.py index a75e53a0cd7..4907a4256d4 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -6,9 +6,8 @@ import functools import importlib import os -import sys -import warnings from pathlib import Path +import sys from typing import AbstractSet from typing import Callable from typing import Dict @@ -23,11 +22,12 @@ from typing import Sequence from typing import Tuple from typing import Union +import warnings import pluggy -import _pytest._code from _pytest import nodes +import _pytest._code from _pytest.config import Config from _pytest.config import directory_arg from _pytest.config import ExitCode @@ -722,12 +722,14 @@ def _collect_path( @overload def perform_collect( self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ... - ) -> Sequence[nodes.Item]: ... + ) -> Sequence[nodes.Item]: + ... @overload def perform_collect( # noqa: F811 self, args: Optional[Sequence[str]] = ..., genitems: bool = ... - ) -> Sequence[Union[nodes.Item, nodes.Collector]]: ... + ) -> Sequence[Union[nodes.Item, nodes.Collector]]: + ... def perform_collect( # noqa: F811 self, args: Optional[Sequence[str]] = None, genitems: bool = True diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index ec5023c9173..77dabd95dec 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -24,6 +24,7 @@ from _pytest.config.argparsing import Parser from _pytest.stash import StashKey + if TYPE_CHECKING: from _pytest.nodes import Item @@ -268,8 +269,8 @@ def pytest_configure(config: Config) -> None: if empty_parameterset not in ("skip", "xfail", "fail_at_collect", None, ""): raise UsageError( - "{!s} must be one of skip, xfail or fail_at_collect" - " but it is {!r}".format(EMPTY_PARAMETERSET_OPTION, empty_parameterset) + f"{EMPTY_PARAMETERSET_OPTION!s} must be one of skip, xfail or fail_at_collect" + f" but it is {empty_parameterset!r}" ) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 5fa0ccaa7b5..78b7fda696b 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -27,6 +27,7 @@ from typing import Optional from typing import Sequence + __all__ = [ "Expression", "ParseError", diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 544e1dccf97..7c8501d7314 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -2,7 +2,6 @@ import collections.abc import dataclasses import inspect -import warnings from typing import Any from typing import Callable from typing import Collection @@ -22,6 +21,7 @@ from typing import TYPE_CHECKING from typing import TypeVar from typing import Union +import warnings from .._code import getfslineno from ..compat import ascii_escaped @@ -33,6 +33,7 @@ from _pytest.outcomes import fail from _pytest.warning_types import PytestUnknownMarkWarning + if TYPE_CHECKING: from ..nodes import Node @@ -112,7 +113,6 @@ def extract_from( Enforce tuple wrapping so single argument tuple values don't get decomposed and break tests. """ - if isinstance(parameterset, cls): return parameterset if force_tuple: @@ -272,8 +272,8 @@ class MarkDecorator: ``MarkDecorators`` are created with ``pytest.mark``:: - mark1 = pytest.mark.NAME # Simple MarkDecorator - mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator + mark1 = pytest.mark.NAME # Simple MarkDecorator + mark2 = pytest.mark.NAME(name1=value) # Parametrized MarkDecorator and can then be applied as decorators to test functions:: @@ -394,7 +394,7 @@ def get_unpacked_marks( def normalize_mark_list( - mark_list: Iterable[Union[Mark, MarkDecorator]] + mark_list: Iterable[Union[Mark, MarkDecorator]], ) -> Iterable[Mark]: """ Normalize an iterable of Mark or MarkDecorator objects into a list of marks @@ -434,10 +434,12 @@ def store_mark(obj, mark: Mark) -> None: class _SkipMarkDecorator(MarkDecorator): @overload # type: ignore[override,misc,no-overload-impl] - def __call__(self, arg: Markable) -> Markable: ... + def __call__(self, arg: Markable) -> Markable: + ... @overload - def __call__(self, reason: str = ...) -> "MarkDecorator": ... + def __call__(self, reason: str = ...) -> "MarkDecorator": + ... class _SkipifMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] @@ -445,11 +447,13 @@ def __call__( # type: ignore[override] condition: Union[str, bool] = ..., *conditions: Union[str, bool], reason: str = ..., - ) -> MarkDecorator: ... + ) -> MarkDecorator: + ... class _XfailMarkDecorator(MarkDecorator): @overload # type: ignore[override,misc,no-overload-impl] - def __call__(self, arg: Markable) -> Markable: ... + def __call__(self, arg: Markable) -> Markable: + ... @overload def __call__( @@ -462,7 +466,8 @@ def __call__( None, Type[BaseException], Tuple[Type[BaseException], ...] ] = ..., strict: bool = ..., - ) -> MarkDecorator: ... + ) -> MarkDecorator: + ... class _ParametrizeMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] @@ -478,7 +483,8 @@ def __call__( # type: ignore[override] ] ] = ..., scope: Optional[_ScopeName] = ..., - ) -> MarkDecorator: ... + ) -> MarkDecorator: + ... class _UsefixturesMarkDecorator(MarkDecorator): def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override] @@ -498,9 +504,10 @@ class MarkGenerator: import pytest + @pytest.mark.slowtest def test_function(): - pass + pass applies a 'slowtest' :class:`Mark` on ``test_function``. """ diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index 7b678017f0f..e96a938681f 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -1,10 +1,9 @@ # mypy: allow-untyped-defs """Monkeypatching and mocking functionality.""" +from contextlib import contextmanager import os import re import sys -import warnings -from contextlib import contextmanager from typing import Any from typing import final from typing import Generator @@ -16,10 +15,12 @@ from typing import Tuple from typing import TypeVar from typing import Union +import warnings from _pytest.fixtures import fixture from _pytest.warning_types import PytestWarning + RE_IMPORT_ERROR_NAME = re.compile(r"^No module named (.*)$") @@ -90,9 +91,7 @@ def annotated_getattr(obj: object, name: str, ann: str) -> object: obj = getattr(obj, name) except AttributeError as e: raise AttributeError( - "{!r} object at {} has no attribute {!r}".format( - type(obj).__name__, ann, name - ) + f"{type(obj).__name__!r} object at {ann} has no attribute {name!r}" ) from e return obj @@ -142,7 +141,6 @@ def context(cls) -> Generator["MonkeyPatch", None, None]: which undoes any patching done inside the ``with`` block upon exit. Example: - .. code-block:: python import functools @@ -169,7 +167,8 @@ def setattr( name: object, value: Notset = ..., raising: bool = ..., - ) -> None: ... + ) -> None: + ... @overload def setattr( @@ -178,7 +177,8 @@ def setattr( name: str, value: object, raising: bool = ..., - ) -> None: ... + ) -> None: + ... def setattr( self, @@ -320,10 +320,8 @@ def setenv(self, name: str, value: str, prepend: Optional[str] = None) -> None: if not isinstance(value, str): warnings.warn( # type: ignore[unreachable] PytestWarning( - "Value of environment variable {name} type should be str, but got " - "{value!r} (type: {type}); converted to str implicitly".format( - name=name, value=value, type=type(value).__name__ - ) + f"Value of environment variable {name} type should be str, but got " + f"{value!r} (type: {type(value).__name__}); converted to str implicitly" ), stacklevel=2, ) @@ -343,7 +341,6 @@ def delenv(self, name: str, raising: bool = True) -> None: def syspath_prepend(self, path) -> None: """Prepend ``path`` to ``sys.path`` list of import locations.""" - if self._savesyspath is None: self._savesyspath = sys.path[:] sys.path.insert(0, str(path)) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 5260b003f84..48f7d584168 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -1,9 +1,8 @@ # mypy: allow-untyped-defs import abc -import os -import warnings from functools import cached_property from inspect import signature +import os from pathlib import Path from typing import Any from typing import Callable @@ -20,6 +19,7 @@ from typing import TYPE_CHECKING from typing import TypeVar from typing import Union +import warnings import pluggy @@ -39,6 +39,7 @@ from _pytest.stash import Stash from _pytest.warning_types import PytestWarning + if TYPE_CHECKING: # Imported here due to circular import. from _pytest._code.code import _TracebackStyle @@ -229,9 +230,7 @@ def warn(self, warning: Warning) -> None: # enforce type checks here to avoid getting a generic type error later otherwise. if not isinstance(warning, Warning): raise ValueError( - "warning must be an instance of Warning or subclass, got {!r}".format( - warning - ) + f"warning must be an instance of Warning or subclass, got {warning!r}" ) path, lineno = get_fslocation_from_item(self) assert lineno is not None @@ -326,10 +325,12 @@ def iter_markers_with_node( yield node, mark @overload - def get_closest_marker(self, name: str) -> Optional[Mark]: ... + def get_closest_marker(self, name: str) -> Optional[Mark]: + ... @overload - def get_closest_marker(self, name: str, default: Mark) -> Mark: ... + def get_closest_marker(self, name: str, default: Mark) -> Mark: + ... def get_closest_marker( self, name: str, default: Optional[Mark] = None diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index eb51e7f7e87..e2a816f5850 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -239,8 +239,7 @@ def importorskip( if verattr is None or Version(verattr) < Version(minversion): raise Skipped( - "module %r has __version__ %r, required is: %r" - % (modname, verattr, minversion), + f"module {modname!r} has __version__ {verattr!r}, required is: {minversion!r}", allow_module_level=True, ) return mod diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 440d6ec5f1f..98ba5c9c154 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -1,16 +1,17 @@ # mypy: allow-untyped-defs """Submit failure or test session information to a pastebin service.""" -import tempfile from io import StringIO +import tempfile from typing import IO from typing import Union -import pytest from _pytest.config import Config from _pytest.config import create_terminal_writer from _pytest.config.argparsing import Parser from _pytest.stash import StashKey from _pytest.terminal import TerminalReporter +import pytest + pastebinfile_key = StashKey[IO[bytes]]() diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 929d8c88ea3..1e0891153e5 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,21 +1,16 @@ # mypy: allow-untyped-defs import atexit import contextlib -import fnmatch -import importlib.util -import itertools -import os -import shutil -import sys -import types -import uuid -import warnings from enum import Enum from errno import EBADF from errno import ELOOP from errno import ENOENT from errno import ENOTDIR +import fnmatch from functools import partial +import importlib.util +import itertools +import os from os.path import expanduser from os.path import expandvars from os.path import isabs @@ -23,6 +18,9 @@ from pathlib import Path from pathlib import PurePath from posixpath import sep as posix_sep +import shutil +import sys +import types from types import ModuleType from typing import Callable from typing import Dict @@ -35,11 +33,14 @@ from typing import Type from typing import TypeVar from typing import Union +import uuid +import warnings from _pytest.compat import assert_never from _pytest.outcomes import skip from _pytest.warning_types import PytestWarning + LOCK_TIMEOUT = 60 * 60 * 24 * 3 @@ -102,9 +103,7 @@ def on_rm_rf_error( if func not in (os.open,): warnings.warn( PytestWarning( - "(rm_rf) unknown function {} when removing {}:\n{}: {}".format( - func, path, type(exc), exc - ) + f"(rm_rf) unknown function {func} when removing {path}:\n{type(exc)}: {exc}" ) ) return False @@ -243,7 +242,7 @@ def make_numbered_dir(root: Path, prefix: str, mode: int = 0o700) -> Path: else: raise OSError( "could not create numbered dir with prefix " - "{prefix} in {root} after 10 tries".format(prefix=prefix, root=root) + f"{prefix} in {root} after 10 tries" ) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index ae8709e5ed6..5190bc35a25 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -5,19 +5,19 @@ """ import collections.abc import contextlib +from fnmatch import fnmatch import gc import importlib +from io import StringIO import locale import os +from pathlib import Path import platform import re import shutil import subprocess import sys import traceback -from fnmatch import fnmatch -from io import StringIO -from pathlib import Path from typing import Any from typing import Callable from typing import Dict @@ -70,6 +70,7 @@ from _pytest.tmpdir import TempPathFactory from _pytest.warning_types import PytestWarning + if TYPE_CHECKING: import pexpect @@ -187,7 +188,7 @@ def pytest_runtest_protocol(self, item: Item) -> Generator[None, object, object] "*** After:", *(str(f) for f in lines2), "***** %s FD leakage detected" % len(leaked_files), - "*** function %s:%s: %s " % item.location, + "*** function {}:{}: {} ".format(*item.location), "See issue #2366", ] item.warn(PytestWarning("\n".join(error))) @@ -244,7 +245,8 @@ def __repr__(self) -> str: if TYPE_CHECKING: # The class has undetermined attributes, this tells mypy about it. - def __getattr__(self, key: str): ... + def __getattr__(self, key: str): + ... @final @@ -325,13 +327,15 @@ def getcall(self, name: str) -> RecordedHookCall: def getreports( self, names: "Literal['pytest_collectreport']", - ) -> Sequence[CollectReport]: ... + ) -> Sequence[CollectReport]: + ... @overload def getreports( self, names: "Literal['pytest_runtest_logreport']", - ) -> Sequence[TestReport]: ... + ) -> Sequence[TestReport]: + ... @overload def getreports( @@ -340,7 +344,8 @@ def getreports( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: ... + ) -> Sequence[Union[CollectReport, TestReport]]: + ... def getreports( self, @@ -372,14 +377,12 @@ def matchreport( values.append(rep) if not values: raise ValueError( - "could not find test report matching %r: " - "no test reports at all!" % (inamepart,) + f"could not find test report matching {inamepart!r}: " + "no test reports at all!" ) if len(values) > 1: raise ValueError( - "found 2 or more testreports matching {!r}: {}".format( - inamepart, values - ) + f"found 2 or more testreports matching {inamepart!r}: {values}" ) return values[0] @@ -387,13 +390,15 @@ def matchreport( def getfailures( self, names: "Literal['pytest_collectreport']", - ) -> Sequence[CollectReport]: ... + ) -> Sequence[CollectReport]: + ... @overload def getfailures( self, names: "Literal['pytest_runtest_logreport']", - ) -> Sequence[TestReport]: ... + ) -> Sequence[TestReport]: + ... @overload def getfailures( @@ -402,7 +407,8 @@ def getfailures( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: ... + ) -> Sequence[Union[CollectReport, TestReport]]: + ... def getfailures( self, @@ -801,7 +807,6 @@ def makefile(self, ext: str, *args: str, **kwargs: str) -> Path: The first created file. Examples: - .. code-block:: python pytester.makefile(".txt", "line1", "line2") @@ -855,7 +860,6 @@ def makepyfile(self, *args, **kwargs) -> Path: existing files. Examples: - .. code-block:: python def test_something(pytester): @@ -875,7 +879,6 @@ def maketxtfile(self, *args, **kwargs) -> Path: existing files. Examples: - .. code-block:: python def test_something(pytester): @@ -1265,9 +1268,7 @@ def getitem( for item in items: if item.name == funcname: return item - assert 0, "{!r} item not found in module:\n{}\nitems: {}".format( - funcname, source, items - ) + assert 0, f"{funcname!r} item not found in module:\n{source}\nitems: {items}" def getitems(self, source: Union[str, "os.PathLike[str]"]) -> List[Item]: """Return all test items collected from the module. @@ -1426,10 +1427,7 @@ def run( def handle_timeout() -> None: __tracebackhide__ = True - timeout_message = ( - "{seconds} second timeout expired running:" - " {command}".format(seconds=timeout, command=cmdargs) - ) + timeout_message = f"{timeout} second timeout expired running: {cmdargs}" popen.kill() popen.wait() diff --git a/src/_pytest/python.py b/src/_pytest/python.py index d069d7038a6..d0d7447336b 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1,18 +1,17 @@ # mypy: allow-untyped-defs """Python test discovery, setup and run of test functions.""" import abc +from collections import Counter +from collections import defaultdict import dataclasses import enum import fnmatch +from functools import partial import inspect import itertools import os -import types -import warnings -from collections import Counter -from collections import defaultdict -from functools import partial from pathlib import Path +import types from typing import Any from typing import Callable from typing import Dict @@ -29,6 +28,7 @@ from typing import Set from typing import Tuple from typing import Union +import warnings import _pytest from _pytest import fixtures @@ -81,6 +81,7 @@ from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning + _PYTEST_DIR = Path(_pytest.__file__).parent @@ -263,8 +264,8 @@ def pytest_pycollect_makeitem( elif getattr(obj, "__test__", True): if is_generator(obj): res: Function = Function.from_parent(collector, name=name) - reason = "yield tests were removed in pytest 4.0 - {name} will be ignored".format( - name=name + reason = ( + f"yield tests were removed in pytest 4.0 - {name} will be ignored" ) res.add_marker(MARK_GEN.xfail(run=False, reason=reason)) res.warn(PytestCollectionWarning(reason)) @@ -524,12 +525,12 @@ def importtestmodule( except ImportPathMismatchError as e: raise nodes.Collector.CollectError( "import file mismatch:\n" - "imported module %r has this __file__ attribute:\n" - " %s\n" + "imported module {!r} has this __file__ attribute:\n" + " {}\n" "which is not the same as the test file we want to collect:\n" - " %s\n" + " {}\n" "HINT: remove __pycache__ / .pyc files and/or use a " - "unique basename for your test file modules" % e.args + "unique basename for your test file modules".format(*e.args) ) from e except ImportError as e: exc_info = ExceptionInfo.from_current() @@ -542,10 +543,10 @@ def importtestmodule( ) formatted_tb = str(exc_repr) raise nodes.Collector.CollectError( - "ImportError while importing test module '{path}'.\n" + f"ImportError while importing test module '{path}'.\n" "Hint: make sure your test modules/packages have valid Python names.\n" "Traceback:\n" - "{traceback}".format(path=path, traceback=formatted_tb) + f"{formatted_tb}" ) from e except skip.Exception as e: if e.allow_module_level: @@ -765,9 +766,8 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: assert self.parent is not None self.warn( PytestCollectionWarning( - "cannot collect test class %r because it has a " - "__init__ constructor (from: %s)" - % (self.obj.__name__, self.parent.nodeid) + f"cannot collect test class {self.obj.__name__!r} because it has a " + f"__init__ constructor (from: {self.parent.nodeid})" ) ) return [] @@ -775,9 +775,8 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: assert self.parent is not None self.warn( PytestCollectionWarning( - "cannot collect test class %r because it has a " - "__new__ constructor (from: %s)" - % (self.obj.__name__, self.parent.nodeid) + f"cannot collect test class {self.obj.__name__!r} because it has a " + f"__new__ constructor (from: {self.parent.nodeid})" ) ) return [] @@ -1432,17 +1431,14 @@ def _resolve_args_directness( for arg in indirect: if arg not in argnames: fail( - "In {}: indirect fixture '{}' doesn't exist".format( - self.function.__name__, arg - ), + f"In {self.function.__name__}: indirect fixture '{arg}' doesn't exist", pytrace=False, ) arg_directness[arg] = "indirect" else: fail( - "In {func}: expected Sequence or boolean for indirect, got {type}".format( - type=type(indirect).__name__, func=self.function.__name__ - ), + f"In {self.function.__name__}: expected Sequence or boolean" + f" for indirect, got {type(indirect).__name__}", pytrace=False, ) return arg_directness @@ -1464,9 +1460,7 @@ def _validate_if_using_arg_names( if arg not in self.fixturenames: if arg in default_arg_names: fail( - "In {}: function already takes an argument '{}' with a default value".format( - func_name, arg - ), + f"In {func_name}: function already takes an argument '{arg}' with a default value", pytrace=False, ) else: diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index f398902ffe0..bd3de2897a1 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -1,10 +1,10 @@ # mypy: allow-untyped-defs -import math -import pprint from collections.abc import Collection from collections.abc import Sized from decimal import Decimal +import math from numbers import Complex +import pprint from types import TracebackType from typing import Any from typing import Callable @@ -27,6 +27,7 @@ from _pytest.compat import STRING_TYPES from _pytest.outcomes import fail + if TYPE_CHECKING: from numpy import ndarray @@ -238,9 +239,7 @@ class ApproxMapping(ApproxBase): with numeric values (the keys can be anything).""" def __repr__(self) -> str: - return "approx({!r})".format( - {k: self._approx_scalar(v) for k, v in self.expected.items()} - ) + return f"approx({({k: self._approx_scalar(v) for k, v in self.expected.items()})!r})" def _repr_compare(self, other_side: Mapping[object, float]) -> List[str]: import math @@ -315,9 +314,7 @@ def __repr__(self) -> str: seq_type = type(self.expected) if seq_type not in (tuple, list): seq_type = list - return "approx({!r})".format( - seq_type(self._approx_scalar(x) for x in self.expected) - ) + return f"approx({seq_type(self._approx_scalar(x) for x in self.expected)!r})" def _repr_compare(self, other_side: Sequence[float]) -> List[str]: import math @@ -697,7 +694,6 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: ``approx`` falls back to strict equality for nonnumeric types instead of raising ``TypeError``. """ - # Delegate the comparison to a class that knows how to deal with the type # of the expected value (e.g. int, float, list, dict, numpy.array, etc). # @@ -779,7 +775,8 @@ def raises( expected_exception: Union[Type[E], Tuple[Type[E], ...]], *, match: Optional[Union[str, Pattern[str]]] = ..., -) -> "RaisesContext[E]": ... +) -> "RaisesContext[E]": + ... @overload @@ -788,7 +785,8 @@ def raises( # noqa: F811 func: Callable[..., Any], *args: Any, **kwargs: Any, -) -> _pytest._code.ExceptionInfo[E]: ... +) -> _pytest._code.ExceptionInfo[E]: + ... def raises( # noqa: F811 @@ -837,10 +835,10 @@ def raises( # noqa: F811 The ``match`` argument searches the formatted exception string, which includes any `PEP-678 `__ ``__notes__``: - >>> with pytest.raises(ValueError, match=r'had a note added'): # doctest: +SKIP - ... e = ValueError("value must be 42") - ... e.add_note("had a note added") - ... raise e + >>> with pytest.raises(ValueError, match=r"had a note added"): # doctest: +SKIP + ... e = ValueError("value must be 42") + ... e.add_note("had a note added") + ... raise e The context manager produces an :class:`ExceptionInfo` object which can be used to inspect the details of the captured exception:: @@ -855,7 +853,7 @@ def raises( # noqa: F811 Given that ``pytest.raises`` matches subclasses, be wary of using it to match :class:`Exception` like this:: with pytest.raises(Exception): # Careful, this will catch ANY exception raised. - some_function() + some_function() Because :class:`Exception` is the base class of almost all exceptions, it is easy for this to hide real bugs, where the user wrote this expecting a specific exception, but some other exception is being diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index e8c8aff8baf..ddd4c9a7b70 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -1,8 +1,7 @@ # mypy: allow-untyped-defs """Record warnings during test function execution.""" -import re -import warnings from pprint import pformat +import re from types import TracebackType from typing import Any from typing import Callable @@ -17,11 +16,13 @@ from typing import Type from typing import TypeVar from typing import Union +import warnings from _pytest.deprecated import check_ispytest from _pytest.fixtures import fixture from _pytest.outcomes import fail + T = TypeVar("T") @@ -41,13 +42,15 @@ def recwarn() -> Generator["WarningsRecorder", None, None]: @overload def deprecated_call( *, match: Optional[Union[str, Pattern[str]]] = ... -) -> "WarningsRecorder": ... +) -> "WarningsRecorder": + ... @overload def deprecated_call( # noqa: F811 func: Callable[..., T], *args: Any, **kwargs: Any -) -> T: ... +) -> T: + ... def deprecated_call( # noqa: F811 @@ -89,7 +92,8 @@ def warns( expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ..., *, match: Optional[Union[str, Pattern[str]]] = ..., -) -> "WarningsChecker": ... +) -> "WarningsChecker": + ... @overload @@ -98,7 +102,8 @@ def warns( # noqa: F811 func: Callable[..., T], *args: Any, **kwargs: Any, -) -> T: ... +) -> T: + ... def warns( # noqa: F811 diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 44eaec90854..7cdb70e324b 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -1,7 +1,7 @@ # mypy: allow-untyped-defs import dataclasses -import os from io import StringIO +import os from pprint import pprint from typing import Any from typing import cast @@ -37,6 +37,7 @@ from _pytest.nodes import Item from _pytest.outcomes import skip + if TYPE_CHECKING: from _pytest.runner import CallInfo @@ -46,7 +47,7 @@ def getworkerinfoline(node): return node._workerinfocache except AttributeError: d = node.workerinfo - ver = "%s.%s.%s" % d["version_info"][:3] + ver = "{}.{}.{}".format(*d["version_info"][:3]) node._workerinfocache = s = "[{}] {} -- Python {} {}".format( d["id"], d["sysplatform"], ver, d["executable"] ) @@ -71,7 +72,8 @@ def __init__(self, **kw: Any) -> None: if TYPE_CHECKING: # Can have arbitrary fields given to __init__(). - def __getattr__(self, key: str) -> Any: ... + def __getattr__(self, key: str) -> Any: + ... def toterminal(self, out: TerminalWriter) -> None: if hasattr(self, "node"): @@ -313,9 +315,7 @@ def __init__( self.__dict__.update(extra) def __repr__(self) -> str: - return "<{} {!r} when={!r} outcome={!r}>".format( - self.__class__.__name__, self.nodeid, self.when, self.outcome - ) + return f"<{self.__class__.__name__} {self.nodeid!r} when={self.when!r} outcome={self.outcome!r}>" @classmethod def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport": @@ -430,9 +430,7 @@ def location( # type:ignore[override] return (self.fspath, None, self.fspath) def __repr__(self) -> str: - return "".format( - self.nodeid, len(self.result), self.outcome - ) + return f"" class CollectErrorRepr(TerminalRepr): @@ -444,7 +442,7 @@ def toterminal(self, out: TerminalWriter) -> None: def pytest_report_to_serializable( - report: Union[CollectReport, TestReport] + report: Union[CollectReport, TestReport], ) -> Optional[Dict[str, Any]]: if isinstance(report, (TestReport, CollectReport)): data = report._to_json() @@ -476,7 +474,7 @@ def _report_to_json(report: BaseReport) -> Dict[str, Any]: """ def serialize_repr_entry( - entry: Union[ReprEntry, ReprEntryNative] + entry: Union[ReprEntry, ReprEntryNative], ) -> Dict[str, Any]: data = dataclasses.asdict(entry) for key, value in data.items(): @@ -608,9 +606,9 @@ def deserialize_repr_crash(repr_crash_dict: Optional[Dict[str, Any]]): description, ) ) - exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = ( - ExceptionChainRepr(chain) - ) + exception_info: Union[ + ExceptionChainRepr, ReprExceptionInfo + ] = ExceptionChainRepr(chain) else: exception_info = ReprExceptionInfo( reprtraceback=reprtraceback, diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 44fded69bb1..d25fdb73836 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -37,6 +37,7 @@ from _pytest.outcomes import Skipped from _pytest.outcomes import TEST_OUTCOME + if sys.version_info[:2] < (3, 11): from exceptiongroup import BaseExceptionGroup @@ -94,8 +95,7 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None: if verbose < 2 and rep.duration < durations_min: tr.write_line("") tr.write_line( - "(%s durations < %gs hidden. Use -vv to show these durations.)" - % (len(dlist) - i, durations_min) + f"({len(dlist) - i} durations < {durations_min:g}s hidden. Use -vv to show these durations.)" ) break tr.write_line(f"{rep.duration:02.2f}s {rep.when:<8} {rep.nodeid}") diff --git a/src/_pytest/scope.py b/src/_pytest/scope.py index d15c12705cd..2c6e23208f2 100644 --- a/src/_pytest/scope.py +++ b/src/_pytest/scope.py @@ -13,6 +13,7 @@ from typing import Literal from typing import Optional + _ScopeName = Literal["session", "package", "module", "class", "function"] diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index 0f104580693..c87de1e32fb 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -2,7 +2,6 @@ from typing import Optional from typing import Union -import pytest from _pytest._io.saferepr import saferepr from _pytest.config import Config from _pytest.config import ExitCode @@ -10,6 +9,7 @@ from _pytest.fixtures import FixtureDef from _pytest.fixtures import SubRequest from _pytest.scope import Scope +import pytest def pytest_addoption(parser: Parser) -> None: @@ -74,7 +74,7 @@ def _show_fixture_action( scope_indent = list(reversed(Scope)).index(fixturedef._scope) tw.write(" " * 2 * scope_indent) tw.write( - "{step} {scope} {fixture}".format( + "{step} {scope} {fixture}".format( # noqa: UP032 (Readability) step=msg.ljust(8), # align the output to TEARDOWN scope=fixturedef.scope[0].upper(), fixture=fixturedef.argname, diff --git a/src/_pytest/setupplan.py b/src/_pytest/setupplan.py index 1a4ebdd99ca..13c0df84ea1 100644 --- a/src/_pytest/setupplan.py +++ b/src/_pytest/setupplan.py @@ -1,12 +1,12 @@ from typing import Optional from typing import Union -import pytest from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config.argparsing import Parser from _pytest.fixtures import FixtureDef from _pytest.fixtures import SubRequest +import pytest def pytest_addoption(parser: Parser) -> None: diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 617f7bb853c..4799ae6496a 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -1,11 +1,11 @@ # mypy: allow-untyped-defs """Support for skip/xfail functions and markers.""" +from collections.abc import Mapping import dataclasses import os import platform import sys import traceback -from collections.abc import Mapping from typing import Generator from typing import Optional from typing import Tuple @@ -105,9 +105,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool, ): if not isinstance(dictionary, Mapping): raise ValueError( - "pytest_markeval_namespace() needs to return a dict, got {!r}".format( - dictionary - ) + f"pytest_markeval_namespace() needs to return a dict, got {dictionary!r}" ) globals_.update(dictionary) if hasattr(item, "obj"): diff --git a/src/_pytest/stash.py b/src/_pytest/stash.py index 7b111981bb0..e61d75b95f7 100644 --- a/src/_pytest/stash.py +++ b/src/_pytest/stash.py @@ -5,6 +5,7 @@ from typing import TypeVar from typing import Union + __all__ = ["Stash", "StashKey"] diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index 74ad9dbd4dd..3ebebc288f8 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -2,12 +2,13 @@ from typing import Optional from typing import TYPE_CHECKING -import pytest from _pytest import nodes from _pytest.config import Config from _pytest.config.argparsing import Parser from _pytest.main import Session from _pytest.reports import TestReport +import pytest + if TYPE_CHECKING: from _pytest.cacheprovider import Cache diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 42b85b56dbc..62dafe703ed 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -4,16 +4,15 @@ This is a good source for looking at the various reporting hooks. """ import argparse +from collections import Counter import dataclasses import datetime +from functools import partial import inspect +from pathlib import Path import platform import sys import textwrap -import warnings -from collections import Counter -from functools import partial -from pathlib import Path from typing import Any from typing import Callable from typing import ClassVar @@ -31,16 +30,17 @@ from typing import Tuple from typing import TYPE_CHECKING from typing import Union +import warnings import pluggy -import _pytest._version from _pytest import nodes from _pytest import timing from _pytest._code import ExceptionInfo from _pytest._code.code import ExceptionRepr from _pytest._io import TerminalWriter from _pytest._io.wcwidth import wcswidth +import _pytest._version from _pytest.assertion.util import running_on_ci from _pytest.config import _PluggyPlugin from _pytest.config import Config @@ -55,6 +55,7 @@ from _pytest.reports import CollectReport from _pytest.reports import TestReport + if TYPE_CHECKING: from _pytest.main import Session @@ -671,8 +672,8 @@ def _get_progress_information_message(self) -> str: return f" [ {collected} / {collected} ]" else: if collected: - return " [{:3d}%]".format( - len(self._progress_nodeids_reported) * 100 // collected + return ( + f" [{len(self._progress_nodeids_reported) * 100 // collected:3d}%]" ) return " [100%]" @@ -757,9 +758,7 @@ def pytest_sessionstart(self, session: "Session") -> None: if pypy_version_info: verinfo = ".".join(map(str, pypy_version_info[:3])) msg += f"[pypy-{verinfo}-{pypy_version_info[3]}]" - msg += ", pytest-{}, pluggy-{}".format( - _pytest._version.version, pluggy.__version__ - ) + msg += f", pytest-{_pytest._version.version}, pluggy-{pluggy.__version__}" if ( self.verbosity > 0 or self.config.option.debug @@ -1464,7 +1463,7 @@ def _plugin_nameversions(plugininfo) -> List[str]: values: List[str] = [] for plugin, dist in plugininfo: # Gets us name and version! - name = "{dist.project_name}-{dist.version}".format(dist=dist) + name = f"{dist.project_name}-{dist.version}" # Questionable convenience, but it keeps things short. if name.startswith("pytest-"): name = name[7:] diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index 0b5902d66a8..09faf661b91 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -1,12 +1,12 @@ import threading import traceback -import warnings from types import TracebackType from typing import Any from typing import Callable from typing import Generator from typing import Optional from typing import Type +import warnings import pytest diff --git a/src/_pytest/timing.py b/src/_pytest/timing.py index 096a6776873..0541dc8e0a1 100644 --- a/src/_pytest/timing.py +++ b/src/_pytest/timing.py @@ -10,4 +10,5 @@ from time import sleep from time import time + __all__ = ["perf_counter", "sleep", "time"] diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 75391adbcf8..1cb9fbbe0e0 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -2,10 +2,10 @@ """Support for providing temporary directories to test functions.""" import dataclasses import os -import re -import tempfile from pathlib import Path +import re from shutil import rmtree +import tempfile from typing import Any from typing import Dict from typing import final @@ -32,6 +32,7 @@ from _pytest.reports import TestReport from _pytest.stash import StashKey + tmppath_result_key = StashKey[Dict[str, bool]]() RetentionType = Literal["all", "failed", "none"] @@ -268,7 +269,6 @@ def tmp_path( The returned object is a :class:`pathlib.Path` object. """ - path = _mk_tmp(request, tmp_path_factory) yield path diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 3bdb0610e74..29a53ad5ca1 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -15,7 +15,6 @@ from typing import Union import _pytest._code -import pytest from _pytest.compat import getimfunc from _pytest.compat import is_async_function from _pytest.config import hookimpl @@ -30,6 +29,8 @@ from _pytest.python import Function from _pytest.python import Module from _pytest.runner import CallInfo +import pytest + if TYPE_CHECKING: import unittest @@ -203,7 +204,9 @@ def _addexcinfo(self, rawexcinfo: "_SysExcInfoType") -> None: # Unwrap potential exception info (see twisted trial support below). rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo) try: - excinfo = _pytest._code.ExceptionInfo[BaseException].from_exc_info(rawexcinfo) # type: ignore[arg-type] + excinfo = _pytest._code.ExceptionInfo[BaseException].from_exc_info( + rawexcinfo # type: ignore[arg-type] + ) # Invoke the attributes to trigger storing the traceback # trial causes some issue there. excinfo.value @@ -223,7 +226,7 @@ def _addexcinfo(self, rawexcinfo: "_SysExcInfoType") -> None: except BaseException: fail( "ERROR: Unknown Incompatible Exception " - "representation:\n%r" % (rawexcinfo,), + f"representation:\n{rawexcinfo!r}", pytrace=False, ) except KeyboardInterrupt: @@ -348,9 +351,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None: # handled internally, and doesn't reach here. unittest = sys.modules.get("unittest") if ( - unittest - and call.excinfo - and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined] + unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined] ): excinfo = call.excinfo call2 = CallInfo[None].from_call( diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index 8c0a2d9ae95..f649267abf1 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -1,12 +1,12 @@ import sys import traceback -import warnings from types import TracebackType from typing import Any from typing import Callable from typing import Generator from typing import Optional from typing import Type +import warnings import pytest diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index 6c109b03f0a..a5884f29582 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -1,12 +1,12 @@ import dataclasses import inspect -import warnings from types import FunctionType from typing import Any from typing import final from typing import Generic from typing import Type from typing import TypeVar +import warnings class PytestWarning(UserWarning): @@ -73,11 +73,7 @@ class PytestExperimentalApiWarning(PytestWarning, FutureWarning): @classmethod def simple(cls, apiname: str) -> "PytestExperimentalApiWarning": - return cls( - "{apiname} is an experimental api that may change over time".format( - apiname=apiname - ) - ) + return cls(f"{apiname} is an experimental api that may change over time") @final diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index de4b0830f98..22590892f8d 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -1,18 +1,18 @@ # mypy: allow-untyped-defs -import sys -import warnings from contextlib import contextmanager +import sys from typing import Generator from typing import Literal from typing import Optional +import warnings -import pytest from _pytest.config import apply_warning_filters from _pytest.config import Config from _pytest.config import parse_warning_filter from _pytest.main import Session from _pytest.nodes import Item from _pytest.terminal import TerminalReporter +import pytest def pytest_configure(config: Config) -> None: diff --git a/src/py.py b/src/py.py index c997903363a..d1c39d203a8 100644 --- a/src/py.py +++ b/src/py.py @@ -6,6 +6,7 @@ import _pytest._py.error as error import _pytest._py.path as path + sys.modules["py.error"] = error sys.modules["py.path"] = path diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 449cb39b82d..20829aa585f 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -81,6 +81,7 @@ from _pytest.warning_types import PytestUnraisableExceptionWarning from _pytest.warning_types import PytestWarning + set_trace = __pytestPDB.set_trace diff --git a/src/pytest/__main__.py b/src/pytest/__main__.py index 9e08e3ebc20..e4cb67d5dd5 100644 --- a/src/pytest/__main__.py +++ b/src/pytest/__main__.py @@ -2,5 +2,6 @@ import pytest + if __name__ == "__main__": raise SystemExit(pytest.console_main()) diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index b97080ed007..57c953f17a5 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -4,8 +4,8 @@ import os import sys import time -import warnings from unittest import mock +import warnings from py import error from py.path import local @@ -183,7 +183,7 @@ def test_listdir_fnmatchstring(self, path1): def test_listdir_filter(self, path1): p = path1.listdir(lambda x: x.check(dir=1)) assert path1.join("sampledir") in p - assert not path1.join("samplefile") in p + assert path1.join("samplefile") not in p def test_listdir_sorted(self, path1): p = path1.listdir(lambda x: x.check(basestarts="sample"), sort=True) @@ -203,7 +203,7 @@ def test_visit_norecurse(self, path1): for i in path1.visit(None, lambda x: x.basename != "sampledir"): lst.append(i.relto(path1)) assert "sampledir" in lst - assert not path1.sep.join(["sampledir", "otherfile"]) in lst + assert path1.sep.join(["sampledir", "otherfile"]) not in lst @pytest.mark.parametrize( "fil", diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 64e65f313f2..0264aa28856 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -6,10 +6,10 @@ import sys import types -import pytest from _pytest.config import ExitCode from _pytest.pathlib import symlink_or_skip from _pytest.pytester import Pytester +import pytest def prepend_pythonpath(*dirs) -> str: diff --git a/testing/code/test_code.py b/testing/code/test_code.py index a59af4a49e6..57ab4cdfddb 100644 --- a/testing/code/test_code.py +++ b/testing/code/test_code.py @@ -4,13 +4,13 @@ from types import FrameType from unittest import mock -import pytest from _pytest._code import Code from _pytest._code import ExceptionInfo from _pytest._code import Frame from _pytest._code import Source from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ReprFuncArgs +import pytest def test_ne() -> None: diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 36625cfb5ae..846e23b2a0d 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -4,16 +4,15 @@ import importlib import io import operator +from pathlib import Path import queue import re import sys import textwrap -from pathlib import Path from typing import Any from typing import TYPE_CHECKING import _pytest._code -import pytest from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ExceptionInfo from _pytest._code.code import FormattedExcinfo @@ -23,6 +22,8 @@ from _pytest.pathlib import import_path from _pytest.pytester import LineMatcher from _pytest.pytester import Pytester +import pytest + if TYPE_CHECKING: from _pytest._code.code import _TracebackStyle @@ -1173,9 +1174,7 @@ def f(): "funcargs": funcargs, "tbfilter": tbfilter, }, - id="style={},showlocals={},funcargs={},tbfilter={}".format( - style, showlocals, funcargs, tbfilter - ), + id=f"style={style},showlocals={showlocals},funcargs={funcargs},tbfilter={tbfilter}", ) for style in ["long", "short", "line", "no", "native", "value", "auto"] for showlocals in (True, False) @@ -1339,7 +1338,7 @@ def test_exc_repr_chain_suppression(self, importasmod, mode, tw_mock): """ raise_suffix = " from None" if mode == "from_none" else "" mod = importasmod( - """ + f""" def f(): try: g() @@ -1347,9 +1346,7 @@ def f(): raise AttributeError(){raise_suffix} def g(): raise ValueError() - """.format( - raise_suffix=raise_suffix - ) + """ ) excinfo = pytest.raises(AttributeError, mod.f) r = excinfo.getrepr(style="long", chain=mode != "explicit_suppress") @@ -1361,9 +1358,7 @@ def g(): assert tw_mock.lines[2] == " try:" assert tw_mock.lines[3] == " g()" assert tw_mock.lines[4] == " except Exception:" - assert tw_mock.lines[5] == "> raise AttributeError(){}".format( - raise_suffix - ) + assert tw_mock.lines[5] == f"> raise AttributeError(){raise_suffix}" assert tw_mock.lines[6] == "E AttributeError" assert tw_mock.lines[7] == "" line = tw_mock.get_write_msg(8) @@ -1394,7 +1389,7 @@ def test_exc_chain_repr_without_traceback(self, importasmod, reason, description """ exc_handling_code = " from e" if reason == "cause" else "" mod = importasmod( - """ + f""" def f(): try: g() @@ -1402,9 +1397,7 @@ def f(): raise RuntimeError('runtime problem'){exc_handling_code} def g(): raise ValueError('invalid value') - """.format( - exc_handling_code=exc_handling_code - ) + """ ) with pytest.raises(RuntimeError) as excinfo: diff --git a/testing/conftest.py b/testing/conftest.py index 0912285d845..b7e2d6111af 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -5,9 +5,10 @@ from typing import Generator from typing import List -import pytest from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest + if sys.gettrace(): diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 752ccc91be0..52752d4e8e9 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -1,7 +1,7 @@ # mypy: allow-untyped-defs -import pytest from _pytest import deprecated from _pytest.pytester import Pytester +import pytest from pytest import PytestDeprecationWarning diff --git a/testing/example_scripts/acceptance/fixture_mock_integration.py b/testing/example_scripts/acceptance/fixture_mock_integration.py index d607e959dcd..36e711f40eb 100644 --- a/testing/example_scripts/acceptance/fixture_mock_integration.py +++ b/testing/example_scripts/acceptance/fixture_mock_integration.py @@ -4,6 +4,7 @@ import pytest + config = {"mykey": "ORIGINAL"} diff --git a/testing/example_scripts/perf_examples/collect_stats/generate_folders.py b/testing/example_scripts/perf_examples/collect_stats/generate_folders.py index 3d8e77e88bf..17085e50b54 100644 --- a/testing/example_scripts/perf_examples/collect_stats/generate_folders.py +++ b/testing/example_scripts/perf_examples/collect_stats/generate_folders.py @@ -2,6 +2,7 @@ import argparse import pathlib + HERE = pathlib.Path(__file__).parent TEST_CONTENT = (HERE / "template_test.py").read_bytes() diff --git a/testing/example_scripts/unittest/test_unittest_asyncio.py b/testing/example_scripts/unittest/test_unittest_asyncio.py index f0c394ee36e..a82ddaebcc3 100644 --- a/testing/example_scripts/unittest/test_unittest_asyncio.py +++ b/testing/example_scripts/unittest/test_unittest_asyncio.py @@ -2,6 +2,7 @@ from typing import List from unittest import IsolatedAsyncioTestCase + teardowns: List[None] = [] diff --git a/testing/example_scripts/unittest/test_unittest_asynctest.py b/testing/example_scripts/unittest/test_unittest_asynctest.py index a5a0ec22c09..b3f03e3256b 100644 --- a/testing/example_scripts/unittest/test_unittest_asynctest.py +++ b/testing/example_scripts/unittest/test_unittest_asynctest.py @@ -5,6 +5,7 @@ import asynctest + teardowns: List[None] = [] diff --git a/testing/io/test_pprint.py b/testing/io/test_pprint.py index 3432c63f688..15fe6611280 100644 --- a/testing/io/test_pprint.py +++ b/testing/io/test_pprint.py @@ -1,16 +1,16 @@ -import textwrap from collections import ChainMap from collections import Counter from collections import defaultdict from collections import deque from collections import OrderedDict from dataclasses import dataclass +import textwrap from types import MappingProxyType from types import SimpleNamespace from typing import Any -import pytest from _pytest._io.pprint import PrettyPrinter +import pytest @dataclass diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index 4091747d50a..eefa3f72b88 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -1,8 +1,8 @@ # mypy: allow-untyped-defs -import pytest from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr_unlimited +import pytest def test_simple_repr(): @@ -59,9 +59,7 @@ class BrokenReprException(Exception): obj = BrokenRepr(BrokenReprException("omg even worse")) s2 = saferepr(obj) assert s2 == ( - "<[unpresentable exception ({!s}) raised in repr()] BrokenRepr object at 0x{:x}>".format( - exp_exc, id(obj) - ) + f"<[unpresentable exception ({exp_exc!s}) raised in repr()] BrokenRepr object at 0x{id(obj):x}>" ) @@ -99,14 +97,12 @@ def __repr__(self): baseexc_str = BaseException("__str__") obj = BrokenObj(RaisingOnStrRepr([BaseException])) assert saferepr(obj) == ( - "<[unpresentable exception ({!r}) " - "raised in repr()] BrokenObj object at 0x{:x}>".format(baseexc_str, id(obj)) + f"<[unpresentable exception ({baseexc_str!r}) " + f"raised in repr()] BrokenObj object at 0x{id(obj):x}>" ) obj = BrokenObj(RaisingOnStrRepr([RaisingOnStrRepr([BaseException])])) assert saferepr(obj) == ( - "<[{!r} raised in repr()] BrokenObj object at 0x{:x}>".format( - baseexc_str, id(obj) - ) + f"<[{baseexc_str!r} raised in repr()] BrokenObj object at 0x{id(obj):x}>" ) with pytest.raises(KeyboardInterrupt): diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index 0b83b5531df..afa8d5cae87 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -1,17 +1,18 @@ # mypy: allow-untyped-defs import io import os +from pathlib import Path import re import shutil import sys -from pathlib import Path from typing import Generator from typing import Optional from unittest import mock -import pytest from _pytest._io import terminalwriter from _pytest.monkeypatch import MonkeyPatch +import pytest + # These tests were initially copied from py 1.8.1. diff --git a/testing/io/test_wcwidth.py b/testing/io/test_wcwidth.py index 7cc74df5d07..9ed2a6d3c49 100644 --- a/testing/io/test_wcwidth.py +++ b/testing/io/test_wcwidth.py @@ -1,6 +1,6 @@ -import pytest from _pytest._io.wcwidth import wcswidth from _pytest._io.wcwidth import wcwidth +import pytest @pytest.mark.parametrize( diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index f4912aecce4..2e16913f099 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -3,9 +3,10 @@ import logging from typing import Iterator -import pytest from _pytest.logging import caplog_records_key from _pytest.pytester import Pytester +import pytest + logger = logging.getLogger(__name__) sublogger = logging.getLogger(__name__ + ".baz") diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index f6ac9c3b213..7ef334950ef 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -4,12 +4,12 @@ import re from typing import cast -import pytest from _pytest.capture import CaptureManager from _pytest.config import ExitCode from _pytest.fixtures import FixtureRequest from _pytest.pytester import Pytester from _pytest.terminal import TerminalReporter +import pytest def test_nothing_logged(pytester: Pytester) -> None: @@ -177,13 +177,11 @@ def teardown_function(function): def test_log_cli_enabled_disabled(pytester: Pytester, enabled: bool) -> None: msg = "critical message logged by test" pytester.makepyfile( - """ + f""" import logging def test_log_cli(): - logging.critical("{}") - """.format( - msg - ) + logging.critical("{msg}") + """ ) if enabled: pytester.makeini( @@ -710,13 +708,11 @@ def test_log_file_ini(pytester: Pytester) -> None: log_file = str(pytester.path.joinpath("pytest.log")) pytester.makeini( - """ + f""" [pytest] - log_file={} + log_file={log_file} log_file_level=WARNING - """.format( - log_file - ) + """ ) pytester.makepyfile( """ @@ -749,13 +745,11 @@ def test_log_file_ini_level(pytester: Pytester) -> None: log_file = str(pytester.path.joinpath("pytest.log")) pytester.makeini( - """ + f""" [pytest] - log_file={} + log_file={log_file} log_file_level = INFO - """.format( - log_file - ) + """ ) pytester.makepyfile( """ @@ -788,13 +782,11 @@ def test_log_file_unicode(pytester: Pytester) -> None: log_file = str(pytester.path.joinpath("pytest.log")) pytester.makeini( - """ + f""" [pytest] - log_file={} + log_file={log_file} log_file_level = INFO - """.format( - log_file - ) + """ ) pytester.makepyfile( """\ @@ -832,8 +824,8 @@ def test_live_logging_suspends_capture( is installed. """ import contextlib - import logging from functools import partial + import logging from _pytest.logging import _LiveLoggingStreamHandler @@ -924,13 +916,11 @@ def test_collection_logging_to_file(pytester: Pytester) -> None: log_file = str(pytester.path.joinpath("pytest.log")) pytester.makeini( - """ + f""" [pytest] - log_file={} + log_file={log_file} log_file_level = INFO - """.format( - log_file - ) + """ ) pytester.makepyfile( @@ -962,14 +952,12 @@ def test_log_in_hooks(pytester: Pytester) -> None: log_file = str(pytester.path.joinpath("pytest.log")) pytester.makeini( - """ + f""" [pytest] - log_file={} + log_file={log_file} log_file_level = INFO log_cli=true - """.format( - log_file - ) + """ ) pytester.makeconftest( """ @@ -998,14 +986,12 @@ def test_log_in_runtest_logreport(pytester: Pytester) -> None: log_file = str(pytester.path.joinpath("pytest.log")) pytester.makeini( - """ + f""" [pytest] - log_file={} + log_file={log_file} log_file_level = INFO log_cli=true - """.format( - log_file - ) + """ ) pytester.makeconftest( """ @@ -1039,19 +1025,17 @@ def test_log_set_path(pytester: Pytester) -> None: """ ) pytester.makeconftest( - """ + f""" import os import pytest @pytest.hookimpl(wrapper=True, tryfirst=True) def pytest_runtest_setup(item): config = item.config logging_plugin = config.pluginmanager.get_plugin("logging-plugin") - report_file = os.path.join({}, item._request.node.name) + report_file = os.path.join({repr(report_dir_base)}, item._request.node.name) logging_plugin.set_log_path(report_file) return (yield) - """.format( - repr(report_dir_base) - ) + """ ) pytester.makepyfile( """ diff --git a/testing/python/approx.py b/testing/python/approx.py index 132855b0440..079667bd093 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1,18 +1,19 @@ # mypy: allow-untyped-defs -import operator from contextlib import contextmanager from decimal import Decimal from fractions import Fraction from math import sqrt +import operator from operator import eq from operator import ne from typing import Optional -import pytest from _pytest.pytester import Pytester from _pytest.python_api import _recursive_sequence_map +import pytest from pytest import approx + inf, nan = float("inf"), float("nan") @@ -38,9 +39,7 @@ def set_continue(self): class MyDocTestRunner(doctest.DocTestRunner): def report_failure(self, out, test, example, got): raise AssertionError( - "'{}' evaluates to '{}', not '{}'".format( - example.source.strip(), got.strip(), example.want.strip() - ) + f"'{example.source.strip()}' evaluates to '{got.strip()}', not '{example.want.strip()}'" ) return MyDocTestRunner() diff --git a/testing/python/collect.py b/testing/python/collect.py index 683b6281252..4d1f97b34bb 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -6,7 +6,6 @@ from typing import Dict import _pytest._code -import pytest from _pytest.config import ExitCode from _pytest.main import Session from _pytest.monkeypatch import MonkeyPatch @@ -14,6 +13,7 @@ from _pytest.pytester import Pytester from _pytest.python import Class from _pytest.python import Function +import pytest class TestModule: @@ -54,13 +54,11 @@ def test_import_prepend_append( monkeypatch.syspath_prepend(str(root1)) p.write_text( textwrap.dedent( - """\ + f"""\ import x456 def test(): - assert x456.__file__.startswith({!r}) - """.format( - str(root2) - ) + assert x456.__file__.startswith({str(root2)!r}) + """ ), encoding="utf-8", ) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index d232742ea2b..62f25cb0b3a 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1,10 +1,9 @@ # mypy: allow-untyped-defs import os +from pathlib import Path import sys import textwrap -from pathlib import Path -import pytest from _pytest.compat import getfuncargnames from _pytest.config import ExitCode from _pytest.fixtures import deduplicate_names @@ -13,6 +12,7 @@ from _pytest.pytester import get_public_names from _pytest.pytester import Pytester from _pytest.python import Function +import pytest def test_getfuncargnames_functions(): @@ -1288,7 +1288,7 @@ def test_nothing(badscope): @pytest.mark.parametrize("scope", ["function", "session"]) def test_parameters_without_eq_semantics(self, scope, pytester: Pytester) -> None: pytester.makepyfile( - """ + f""" class NoEq1: # fails on `a == b` statement def __eq__(self, _): raise RuntimeError @@ -1310,9 +1310,7 @@ def test1(no_eq): def test2(no_eq): pass - """.format( - scope=scope - ) + """ ) result = pytester.runpytest() result.stdout.fnmatch_lines(["*4 passed*"]) @@ -2199,7 +2197,7 @@ def test_arg(arg2): pass def test_check(): assert values == ["new1", "new2", "fin2", "fin1"] - """ + """ # noqa: UP031 (python syntax issues) % locals() ) reprec = pytester.inline_run("-s") @@ -3087,8 +3085,8 @@ def test_baz(base, fix2): pass def test_other(): pass - """ - % {"scope": scope} + """ # noqa: UP031 (python syntax issues) + % {"scope": scope} # noqa: UP031 (python syntax issues) ) reprec = pytester.inline_run("-lvs") reprec.assertoutcome(passed=3) @@ -3287,7 +3285,7 @@ def myscoped(request): assert request.config def test_func(): pass - """ + """ # noqa: UP031 (python syntax issues) % (scope, ok.split(), error.split()) ) reprec = pytester.inline_run("-l") @@ -3308,7 +3306,7 @@ def arg(request): assert request.config def test_func(arg): pass - """ + """ # noqa: UP031 (python syntax issues) % (scope, ok.split(), error.split()) ) reprec = pytester.inline_run() diff --git a/testing/python/integration.py b/testing/python/integration.py index 3ff92d92f9a..a6c14ece407 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -1,9 +1,9 @@ # mypy: allow-untyped-defs -import pytest from _pytest._code import getfslineno from _pytest.fixtures import getfixturemarker from _pytest.pytester import Pytester from _pytest.python import Function +import pytest def test_wrapped_getfslineno() -> None: diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 8f41975f3e7..e132725e130 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -14,7 +14,6 @@ from typing import Tuple from typing import Union -import pytest from _pytest import fixtures from _pytest import python from _pytest.compat import getfuncargnames @@ -24,6 +23,8 @@ from _pytest.python import Function from _pytest.python import IdMaker from _pytest.scope import Scope +import pytest + # import hypothesis # from hypothesis import strategies @@ -1941,7 +1942,7 @@ def test_increment(n, expected): @pytest.mark.parametrize("strict", [True, False]) def test_xfail_passing_is_xpass(self, pytester: Pytester, strict: bool) -> None: - s = """ + s = f""" import pytest m = pytest.mark.xfail("sys.version_info > (0, 0, 0)", reason="some bug", strict={strict}) @@ -1953,9 +1954,7 @@ def test_xfail_passing_is_xpass(self, pytester: Pytester, strict: bool) -> None: ]) def test_increment(n, expected): assert n + 1 == expected - """.format( - strict=strict - ) + """ pytester.makepyfile(s) reprec = pytester.inline_run() passed, failed = (2, 1) if strict else (3, 0) @@ -2006,7 +2005,7 @@ def test_limit(limit, myfixture): @pytest.mark.parametrize("strict", [True, False]) def test_parametrize_marked_value(self, pytester: Pytester, strict: bool) -> None: - s = """ + s = f""" import pytest @pytest.mark.parametrize(("n", "expected"), [ @@ -2021,9 +2020,7 @@ def test_parametrize_marked_value(self, pytester: Pytester, strict: bool) -> Non ]) def test_increment(n, expected): assert n + 1 == expected - """.format( - strict=strict - ) + """ pytester.makepyfile(s) reprec = pytester.inline_run() passed, failed = (0, 2) if strict else (2, 0) diff --git a/testing/python/raises.py b/testing/python/raises.py index 369a66a9f50..35d7f1a44f0 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -2,9 +2,9 @@ import re import sys -import pytest from _pytest.outcomes import Failed from _pytest.pytester import Pytester +import pytest class TestRaises: diff --git a/testing/test_argcomplete.py b/testing/test_argcomplete.py index 6813d8f13c8..0c41c0286a4 100644 --- a/testing/test_argcomplete.py +++ b/testing/test_argcomplete.py @@ -1,10 +1,11 @@ # mypy: allow-untyped-defs +from pathlib import Path import subprocess import sys -from pathlib import Path -import pytest from _pytest.monkeypatch import MonkeyPatch +import pytest + # Test for _argcomplete but not specific for any application. diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 640890e9a11..f8196efea3e 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -9,14 +9,14 @@ import attr -import _pytest.assertion as plugin -import pytest from _pytest import outcomes +import _pytest.assertion as plugin from _pytest.assertion import truncate from _pytest.assertion import util from _pytest.config import Config as _Config from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest def mock_config(verbose: int = 0, assertion_override: Optional[int] = None): @@ -182,11 +182,9 @@ def test_pytest_plugins_rewrite_module_names( """ plugins = '"ham"' if mode == "str" else '["ham"]' contents = { - "conftest.py": """ + "conftest.py": f""" pytest_plugins = {plugins} - """.format( - plugins=plugins - ), + """, "ham.py": """ import pytest """, @@ -854,9 +852,7 @@ def __repr__(self): assert "raised in repr" in expl[0] assert expl[2:] == [ "(pytest_assertion plugin: representation of details failed:" - " {}:{}: ValueError: 42.".format( - __file__, A.__repr__.__code__.co_firstlineno + 1 - ), + f" {__file__}:{A.__repr__.__code__.co_firstlineno + 1}: ValueError: 42.", " Probably an object has a faulty __repr__.)", ] @@ -1399,7 +1395,6 @@ def test_truncates_at_1_line_when_first_line_is_GT_max_chars(self) -> None: def test_full_output_truncated(self, monkeypatch, pytester: Pytester) -> None: """Test against full runpytest() output.""" - line_count = 7 line_len = 100 expected_truncated_lines = 2 diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 0d1f9854bec..6e1a9d54e77 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1,17 +1,16 @@ # mypy: allow-untyped-defs import ast import errno +from functools import partial import glob import importlib import marshal import os +from pathlib import Path import py_compile import stat import sys import textwrap -import zipfile -from functools import partial -from pathlib import Path from typing import cast from typing import Dict from typing import Generator @@ -20,9 +19,9 @@ from typing import Optional from typing import Set from unittest import mock +import zipfile import _pytest._code -import pytest from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest.assertion import util from _pytest.assertion.rewrite import _get_assertion_exprs @@ -36,6 +35,7 @@ from _pytest.config import ExitCode from _pytest.pathlib import make_numbered_dir from _pytest.pytester import Pytester +import pytest def rewrite(src: str) -> ast.Module: @@ -781,11 +781,10 @@ def test_zipfile(self, pytester: Pytester) -> None: f.close() z.chmod(256) pytester.makepyfile( - """ + f""" import sys - sys.path.append(%r) + sys.path.append({z_fn!r}) import test_gum.test_lizard""" - % (z_fn,) ) assert pytester.runpytest().ret == ExitCode.NO_TESTS_COLLECTED @@ -1857,10 +1856,10 @@ def test_simple(): result.assert_outcomes(passed=1) +# fmt: off @pytest.mark.parametrize( ("src", "expected"), ( - # fmt: off pytest.param(b"", {}, id="trivial"), pytest.param( b"def x(): assert 1\n", @@ -1937,9 +1936,9 @@ def test_simple(): {1: "5"}, id="no newline at end of file", ), - # fmt: on ), ) +# fmt: on def test_get_assertion_exprs(src, expected) -> None: assert _get_assertion_exprs(src) == expected @@ -2035,9 +2034,7 @@ def test_foo(): assert test_foo_pyc.is_file() # normal file: not touched by pytest, normal cache tag - bar_init_pyc = get_cache_dir(bar_init) / "__init__.{cache_tag}.pyc".format( - cache_tag=sys.implementation.cache_tag - ) + bar_init_pyc = get_cache_dir(bar_init) / f"__init__.{sys.implementation.cache_tag}.pyc" assert bar_init_pyc.is_file() diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 73f5687d387..c020b77f978 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -1,15 +1,16 @@ # mypy: allow-untyped-defs import os -import shutil from pathlib import Path +import shutil from typing import Generator from typing import List -import pytest from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester from _pytest.tmpdir import TempPathFactory +import pytest + pytest_plugins = ("pytester",) @@ -134,12 +135,10 @@ def test_cachefuncarg(cache): def test_custom_rel_cache_dir(self, pytester: Pytester) -> None: rel_cache_dir = os.path.join("custom_cache_dir", "subdir") pytester.makeini( - """ + f""" [pytest] - cache_dir = {cache_dir} - """.format( - cache_dir=rel_cache_dir - ) + cache_dir = {rel_cache_dir} + """ ) pytester.makepyfile(test_errored="def test_error():\n assert False") pytester.runpytest() @@ -151,12 +150,10 @@ def test_custom_abs_cache_dir( tmp = tmp_path_factory.mktemp("tmp") abs_cache_dir = tmp / "custom_cache_dir" pytester.makeini( - """ + f""" [pytest] - cache_dir = {cache_dir} - """.format( - cache_dir=abs_cache_dir - ) + cache_dir = {abs_cache_dir} + """ ) pytester.makepyfile(test_errored="def test_error():\n assert False") pytester.runpytest() @@ -170,9 +167,7 @@ def test_custom_cache_dir_with_env_var( """ [pytest] cache_dir = {cache_dir} - """.format( - cache_dir="$env_var" - ) + """.format(cache_dir="$env_var") ) pytester.makepyfile(test_errored="def test_error():\n assert False") pytester.runpytest() @@ -201,12 +196,10 @@ def test_cache_reportheader_external_abspath( pytester.makepyfile("def test_hello(): pass") pytester.makeini( - """ + f""" [pytest] - cache_dir = {abscache} - """.format( - abscache=external_cache - ) + cache_dir = {external_cache} + """ ) result = pytester.runpytest("-v") result.stdout.fnmatch_lines([f"cachedir: {external_cache}"]) @@ -646,13 +639,11 @@ def test(): assert 0 assert result.ret == 1 pytester.makepyfile( - """ + f""" import pytest @pytest.{mark} def test(): assert 0 - """.format( - mark=mark - ) + """ ) result = pytester.runpytest() assert result.ret == 0 diff --git a/testing/test_capture.py b/testing/test_capture.py index c49eeb67314..0521c3b6b04 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1,17 +1,16 @@ # mypy: allow-untyped-defs import contextlib import io +from io import UnsupportedOperation import os import subprocess import sys import textwrap -from io import UnsupportedOperation from typing import BinaryIO from typing import cast from typing import Generator from typing import TextIO -import pytest from _pytest import capture from _pytest.capture import _get_multicapture from _pytest.capture import CaptureFixture @@ -21,6 +20,8 @@ from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest + # note: py.io capture tests where copied from # pylib 1.4.20.dev2 (rev 13d9af95547e) @@ -503,13 +504,11 @@ def test_capture_is_represented_on_failure_issue128( self, pytester: Pytester, method ) -> None: p = pytester.makepyfile( - """\ - def test_hello(cap{}): + f"""\ + def test_hello(cap{method}): print("xxx42xxx") assert 0 - """.format( - method - ) + """ ) result = pytester.runpytest(p) result.stdout.fnmatch_lines(["xxx42xxx"]) @@ -624,7 +623,7 @@ def test_disabled_capture_fixture( self, pytester: Pytester, fixture: str, no_capture: bool ) -> None: pytester.makepyfile( - """\ + f"""\ def test_disabled({fixture}): print('captured before') with {fixture}.disabled(): @@ -634,9 +633,7 @@ def test_disabled({fixture}): def test_normal(): print('test_normal executed') - """.format( - fixture=fixture - ) + """ ) args = ("-s",) if no_capture else () result = pytester.runpytest_subprocess(*args) @@ -681,7 +678,7 @@ def test_fixture_use_by_other_fixtures(self, pytester: Pytester, fixture) -> Non """Ensure that capsys and capfd can be used by other fixtures during setup and teardown.""" pytester.makepyfile( - """\ + f"""\ import sys import pytest @@ -703,9 +700,7 @@ def test_captured_print(captured_print): out, err = captured_print assert out == 'stdout contents begin\\n' assert err == 'stderr contents begin\\n' - """.format( - fixture=fixture - ) + """ ) result = pytester.runpytest_subprocess() result.stdout.fnmatch_lines(["*1 passed*"]) @@ -718,7 +713,7 @@ def test_fixture_use_by_other_fixtures_teardown( ) -> None: """Ensure we can access setup and teardown buffers from teardown when using capsys/capfd (##3033)""" pytester.makepyfile( - """\ + f"""\ import sys import pytest import os @@ -735,9 +730,7 @@ def fix({cap}): def test_a(fix): print("call out") sys.stderr.write("call err\\n") - """.format( - cap=cap - ) + """ ) reprec = pytester.inline_run() reprec.assertoutcome(passed=1) @@ -1049,16 +1042,12 @@ def test_simple_resume_suspend(self) -> None: pytest.raises(AssertionError, cap.suspend) assert repr(cap) == ( - "".format( - cap.targetfd_save, cap.tmpfile - ) + f"" ) # Should not crash with missing "_old". assert isinstance(cap.syscapture, capture.SysCapture) assert repr(cap.syscapture) == ( - " _state='done' tmpfile={!r}>".format( - cap.syscapture.tmpfile - ) + f" _state='done' tmpfile={cap.syscapture.tmpfile!r}>" ) def test_capfd_sys_stdout_mode(self, capfd) -> None: @@ -1199,7 +1188,6 @@ class TestTeeStdCapture(TestStdCapture): def test_capturing_error_recursive(self) -> None: r"""For TeeStdCapture since we passthrough stderr/stdout, cap1 should get all output, while cap2 should only get "cap2\n".""" - with self.getcapture() as cap1: print("cap1") with self.getcapture() as cap2: @@ -1394,28 +1382,27 @@ def test_capture_again(): def test_capturing_and_logging_fundamentals(pytester: Pytester, method: str) -> None: # here we check a fundamental feature p = pytester.makepyfile( - """ + f""" import sys, os, logging from _pytest import capture cap = capture.MultiCapture( in_=None, out=None, - err=capture.%s, + err=capture.{method}, ) cap.start_capturing() logging.warning("hello1") outerr = cap.readouterr() - print("suspend, captured %%s" %%(outerr,)) + print("suspend, captured %s" %(outerr,)) logging.warning("hello2") cap.pop_outerr_to_orig() logging.warning("hello3") outerr = cap.readouterr() - print("suspend2, captured %%s" %% (outerr,)) + print("suspend2, captured %s" % (outerr,)) """ - % (method,) ) result = pytester.runpython(p) result.stdout.fnmatch_lines( @@ -1581,16 +1568,16 @@ def test_capture_with_live_logging( # capture should work with live cli logging pytester.makepyfile( - """ + f""" import logging import sys logger = logging.getLogger(__name__) - def test_capture({0}): + def test_capture({capture_fixture}): print("hello") sys.stderr.write("world\\n") - captured = {0}.readouterr() + captured = {capture_fixture}.readouterr() assert captured.out == "hello\\n" assert captured.err == "world\\n" @@ -1598,11 +1585,9 @@ def test_capture({0}): print("next") logging.info("something") - captured = {0}.readouterr() + captured = {capture_fixture}.readouterr() assert captured.out == "next\\n" - """.format( - capture_fixture - ) + """ ) result = pytester.runpytest_subprocess("--log-cli-level=INFO") diff --git a/testing/test_collection.py b/testing/test_collection.py index f1552b6aea9..8e41e0fae78 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1,13 +1,12 @@ # mypy: allow-untyped-defs import os +from pathlib import Path import pprint import shutil import sys import textwrap -from pathlib import Path from typing import List -import pytest from _pytest.config import ExitCode from _pytest.fixtures import FixtureRequest from _pytest.main import _in_venv @@ -17,6 +16,7 @@ from _pytest.pathlib import symlink_or_skip from _pytest.pytester import HookRecorder from _pytest.pytester import Pytester +import pytest def ensure_file(file_path: Path) -> Path: @@ -1282,21 +1282,19 @@ def test_collect_with_chdir_during_import(pytester: Pytester) -> None: subdir = pytester.mkdir("sub") pytester.path.joinpath("conftest.py").write_text( textwrap.dedent( - """ + f""" import os - os.chdir(%r) + os.chdir({str(subdir)!r}) """ - % (str(subdir),) ), encoding="utf-8", ) pytester.makepyfile( - """ + f""" def test_1(): import os - assert os.getcwd() == %r + assert os.getcwd() == {str(subdir)!r} """ - % (str(subdir),) ) result = pytester.runpytest() result.stdout.fnmatch_lines(["*1 passed in*"]) @@ -1639,13 +1637,11 @@ def test_conftest(self, pytester: Pytester) -> None: pytester.makepyfile( **{ "tests/conftest.py": "", - "tests/test_foo.py": """ + "tests/test_foo.py": f""" import sys def test_check(): assert r"{tests_dir}" not in sys.path - """.format( - tests_dir=tests_dir - ), + """, } ) result = pytester.runpytest("-v", "--import-mode=importlib") diff --git a/testing/test_compat.py b/testing/test_compat.py index 53d3df14a5e..4ea90535489 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -1,13 +1,12 @@ # mypy: allow-untyped-defs import enum -import sys from functools import cached_property from functools import partial from functools import wraps +import sys from typing import TYPE_CHECKING from typing import Union -import pytest from _pytest.compat import _PytestWrapper from _pytest.compat import assert_never from _pytest.compat import get_real_func @@ -16,6 +15,8 @@ from _pytest.compat import safe_isclass from _pytest.outcomes import OutcomeException from _pytest.pytester import Pytester +import pytest + if TYPE_CHECKING: from typing_extensions import Literal diff --git a/testing/test_config.py b/testing/test_config.py index df109e5b601..f2651dbeb53 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2,10 +2,10 @@ import dataclasses import importlib.metadata import os +from pathlib import Path import re import sys import textwrap -from pathlib import Path from typing import Any from typing import Dict from typing import List @@ -15,7 +15,6 @@ from typing import Union import _pytest._code -import pytest from _pytest.config import _get_plugin_specs_as_list from _pytest.config import _iter_rewritable_modules from _pytest.config import _strtobool @@ -32,6 +31,7 @@ from _pytest.monkeypatch import MonkeyPatch from _pytest.pathlib import absolutepath from _pytest.pytester import Pytester +import pytest class TestParseIni: @@ -51,12 +51,10 @@ def test_getcfg_and_config( monkeypatch.chdir(sub) (tmp_path / filename).write_text( textwrap.dedent( - """\ + f"""\ [{section}] name = value - """.format( - section=section - ) + """ ), encoding="utf-8", ) @@ -126,12 +124,10 @@ def test_tox_ini_wrong_version(self, pytester: Pytester) -> None: def test_ini_names(self, pytester: Pytester, name, section) -> None: pytester.path.joinpath(name).write_text( textwrap.dedent( - """ + f""" [{section}] minversion = 3.36 - """.format( - section=section - ) + """ ), encoding="utf-8", ) @@ -865,7 +861,6 @@ def test_addini_default_values(self, pytester: Pytester) -> None: """Tests the default values for configuration based on config type """ - pytester.makeconftest( """ def pytest_addoption(parser): @@ -1676,11 +1671,9 @@ def test_override_ini_names(self, pytester: Pytester, name: str) -> None: section = "[pytest]" if name != "setup.cfg" else "[tool:pytest]" pytester.path.joinpath(name).write_text( textwrap.dedent( - """ + f""" {section} - custom = 1.0""".format( - section=section - ) + custom = 1.0""" ), encoding="utf-8", ) @@ -1845,8 +1838,8 @@ def test_addopts_from_ini_not_concatenated(self, pytester: Pytester) -> None: result = pytester.runpytest("cache_dir=ignored") result.stderr.fnmatch_lines( [ - "%s: error: argument -o/--override-ini: expected one argument (via addopts config)" - % (pytester._request.config._parser.optparser.prog,) + f"{pytester._request.config._parser.optparser.prog}: error: " + f"argument -o/--override-ini: expected one argument (via addopts config)" ] ) assert result.ret == _pytest.config.ExitCode.USAGE_ERROR @@ -1934,8 +1927,8 @@ def pytest_addoption(parser): result.stderr.fnmatch_lines( [ "ERROR: usage: *", - "%s: error: argument --invalid-option-should-allow-for-help: expected one argument" - % (pytester._request.config._parser.optparser.prog,), + f"{pytester._request.config._parser.optparser.prog}: error: " + f"argument --invalid-option-should-allow-for-help: expected one argument", ] ) # Does not display full/default help. @@ -2094,7 +2087,6 @@ def test_pytest_plugins_in_non_top_level_conftest_unsupported_pyargs( self, pytester: Pytester, use_pyargs: bool ) -> None: """When using --pyargs, do not emit the warning about non-top-level conftest warnings (#4039, #4044)""" - files = { "src/pkg/__init__.py": "", "src/pkg/conftest.py": "", @@ -2109,9 +2101,7 @@ def test_pytest_plugins_in_non_top_level_conftest_unsupported_pyargs( args = ("--pyargs", "pkg") if use_pyargs else () res = pytester.runpytest(*args) assert res.ret == (0 if use_pyargs else 2) - msg = ( - "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported" - ) + msg = "Defining 'pytest_plugins' in a non-top-level conftest is no longer supported" if use_pyargs: assert msg not in res.stdout.str() else: diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 33d2e38dcd0..bb74fa75d61 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,7 +1,7 @@ # mypy: allow-untyped-defs import os -import textwrap from pathlib import Path +import textwrap from typing import cast from typing import Dict from typing import Generator @@ -10,13 +10,13 @@ from typing import Sequence from typing import Union -import pytest from _pytest.config import ExitCode from _pytest.config import PytestPluginManager from _pytest.monkeypatch import MonkeyPatch from _pytest.pathlib import symlink_or_skip from _pytest.pytester import Pytester from _pytest.tmpdir import TempPathFactory +import pytest def ConftestWithSetinitial(path) -> PytestPluginManager: diff --git a/testing/test_debugging.py b/testing/test_debugging.py index c0b99797b4e..02ad700a609 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -4,10 +4,11 @@ from typing import List import _pytest._code -import pytest from _pytest.debugging import _validate_usepdb_cls from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest + _ENVIRON_PYTHONBREAKPOINT = os.environ.get("PYTHONBREAKPOINT", "") @@ -1186,7 +1187,7 @@ def test_2(): def test_pdb_suspends_fixture_capturing(pytester: Pytester, fixture: str) -> None: """Using "-s" with pytest should suspend/resume fixture capturing.""" p1 = pytester.makepyfile( - """ + f""" def test_inner({fixture}): import sys @@ -1201,9 +1202,7 @@ def test_inner({fixture}): out, err = {fixture}.readouterr() assert out =="out_inner_before\\nout_inner_after\\n" assert err =="err_inner_before\\nerr_inner_after\\n" - """.format( - fixture=fixture - ) + """ ) child = pytester.spawn_pytest(str(p1) + " -s") @@ -1276,7 +1275,6 @@ def runcall(self, *args, **kwds): def test_raises_bdbquit_with_eoferror(pytester: Pytester) -> None: """It is not guaranteed that DontReadFromInput's read is called.""" - p1 = pytester.makepyfile( """ def input_without_read(*args, **kwargs): diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 110e0557cab..835e0e1e6f4 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,12 +1,11 @@ # mypy: allow-untyped-defs import inspect +from pathlib import Path import sys import textwrap -from pathlib import Path from typing import Callable from typing import Optional -import pytest from _pytest.doctest import _get_checker from _pytest.doctest import _is_main_py from _pytest.doctest import _is_mocked @@ -16,6 +15,7 @@ from _pytest.doctest import DoctestModule from _pytest.doctest import DoctestTextfile from _pytest.pytester import Pytester +import pytest class TestDoctests: @@ -183,19 +183,15 @@ def test_multiple_patterns(self, pytester: Pytester): def test_encoding(self, pytester, test_string, encoding): """Test support for doctest_encoding ini option.""" pytester.makeini( - """ + f""" [pytest] - doctest_encoding={} - """.format( - encoding - ) - ) - doctest = """ - >>> "{}" - {} - """.format( - test_string, repr(test_string) + doctest_encoding={encoding} + """ ) + doctest = f""" + >>> "{test_string}" + {repr(test_string)} + """ fn = pytester.path / "test_encoding.txt" fn.write_text(doctest, encoding=encoding) @@ -902,23 +898,19 @@ def test_allow_unicode(self, pytester, config_mode): comment = "#doctest: +ALLOW_UNICODE" pytester.maketxtfile( - test_doc=""" + test_doc=f""" >>> b'12'.decode('ascii') {comment} '12' - """.format( - comment=comment - ) + """ ) pytester.makepyfile( - foo=""" + foo=f""" def foo(): ''' >>> b'12'.decode('ascii') {comment} '12' ''' - """.format( - comment=comment - ) + """ ) reprec = pytester.inline_run("--doctest-modules") reprec.assertoutcome(passed=2) @@ -941,23 +933,19 @@ def test_allow_bytes(self, pytester, config_mode): comment = "#doctest: +ALLOW_BYTES" pytester.maketxtfile( - test_doc=""" + test_doc=f""" >>> b'foo' {comment} 'foo' - """.format( - comment=comment - ) + """ ) pytester.makepyfile( - foo=""" + foo=f""" def foo(): ''' >>> b'foo' {comment} 'foo' ''' - """.format( - comment=comment - ) + """ ) reprec = pytester.inline_run("--doctest-modules") reprec.assertoutcome(passed=2) @@ -1034,7 +1022,7 @@ def test_number_precision(self, pytester, config_mode): comment = "#doctest: +NUMBER" pytester.maketxtfile( - test_doc=""" + test_doc=f""" Scalars: @@ -1086,9 +1074,7 @@ def test_number_precision(self, pytester, config_mode): >>> 'abc' {comment} 'abc' >>> None {comment} - """.format( - comment=comment - ) + """ ) reprec = pytester.inline_run() reprec.assertoutcome(passed=1) @@ -1116,12 +1102,10 @@ def test_number_precision(self, pytester, config_mode): ) def test_number_non_matches(self, pytester, expression, output): pytester.maketxtfile( - test_doc=""" + test_doc=f""" >>> {expression} #doctest: +NUMBER {output} - """.format( - expression=expression, output=output - ) + """ ) reprec = pytester.inline_run() reprec.assertoutcome(passed=0, failed=1) @@ -1302,15 +1286,13 @@ def test_fixture_scopes(self, pytester, scope, enable_doctest): See #1057 and #1100. """ pytester.makeconftest( - """ + f""" import pytest @pytest.fixture(autouse=True, scope="{scope}") def auto(request): return 99 - """.format( - scope=scope - ) + """ ) pytester.makepyfile( test_1=''' @@ -1338,15 +1320,13 @@ def test_fixture_module_doctest_scopes( See #1057 and #1100. """ pytester.makeconftest( - """ + f""" import pytest @pytest.fixture(autouse={autouse}, scope="{scope}") def auto(request): return 99 - """.format( - scope=scope, autouse=autouse - ) + """ ) if use_fixture_in_doctest: pytester.maketxtfile( @@ -1372,7 +1352,7 @@ def test_auto_use_request_attributes(self, pytester, scope): behave as expected when requested for a doctest item. """ pytester.makeconftest( - """ + f""" import pytest @pytest.fixture(autouse=True, scope="{scope}") @@ -1384,9 +1364,7 @@ def auto(request): if "{scope}" == 'function': assert request.function is None return 99 - """.format( - scope=scope - ) + """ ) pytester.maketxtfile( test_doc=""" @@ -1409,16 +1387,14 @@ def test_namespace_doctestfile(self, pytester, scope): simple text file doctest """ pytester.makeconftest( - """ + f""" import pytest import contextlib @pytest.fixture(autouse=True, scope="{scope}") def add_contextlib(doctest_namespace): doctest_namespace['cl'] = contextlib - """.format( - scope=scope - ) + """ ) p = pytester.maketxtfile( """ @@ -1436,16 +1412,14 @@ def test_namespace_pyfile(self, pytester, scope): simple Python file docstring doctest """ pytester.makeconftest( - """ + f""" import pytest import contextlib @pytest.fixture(autouse=True, scope="{scope}") def add_contextlib(doctest_namespace): doctest_namespace['cl'] = contextlib - """.format( - scope=scope - ) + """ ) p = pytester.makepyfile( """ @@ -1548,16 +1522,14 @@ def test_doctest_report_invalid(self, pytester: Pytester): def test_doctest_mock_objects_dont_recurse_missbehaved(mock_module, pytester: Pytester): pytest.importorskip(mock_module) pytester.makepyfile( - """ + f""" from {mock_module} import call class Example(object): ''' >>> 1 + 1 2 ''' - """.format( - mock_module=mock_module - ) + """ ) result = pytester.runpytest("--doctest-modules") result.stdout.fnmatch_lines(["* 1 passed *"]) @@ -1572,7 +1544,7 @@ def __getattr__(self, _): "stop", [None, _is_mocked, lambda f: None, lambda f: False, lambda f: True] ) def test_warning_on_unwrap_of_broken_object( - stop: Optional[Callable[[object], object]] + stop: Optional[Callable[[object], object]], ) -> None: bad_instance = Broken() assert inspect.unwrap.__module__ == "inspect" @@ -1606,7 +1578,7 @@ def test_is_setup_py_different_encoding(tmp_path: Path, mod: str) -> None: setup_py = tmp_path.joinpath("setup.py") contents = ( "# -*- coding: cp1252 -*-\n" - 'from {} import setup; setup(name="foo", description="€")\n'.format(mod) + f'from {mod} import setup; setup(name="foo", description="€")\n' ) setup_py.write_bytes(contents.encode("cp1252")) assert _is_setup_py(setup_py) diff --git a/testing/test_error_diffs.py b/testing/test_error_diffs.py index 6494a44fb12..f290eb1679f 100644 --- a/testing/test_error_diffs.py +++ b/testing/test_error_diffs.py @@ -5,8 +5,9 @@ """ -import pytest from _pytest.pytester import Pytester +import pytest + TESTCASES = [ pytest.param( diff --git a/testing/test_faulthandler.py b/testing/test_faulthandler.py index b7142835dea..a3363de9816 100644 --- a/testing/test_faulthandler.py +++ b/testing/test_faulthandler.py @@ -2,8 +2,8 @@ import io import sys -import pytest from _pytest.pytester import Pytester +import pytest def test_enabled(pytester: Pytester) -> None: diff --git a/testing/test_findpaths.py b/testing/test_findpaths.py index 0759ba55158..260b9d07c9c 100644 --- a/testing/test_findpaths.py +++ b/testing/test_findpaths.py @@ -3,12 +3,12 @@ from pathlib import Path from textwrap import dedent -import pytest from _pytest.config import UsageError from _pytest.config.findpaths import get_common_ancestor from _pytest.config.findpaths import get_dirs_from_args from _pytest.config.findpaths import is_fs_root from _pytest.config.findpaths import load_config_dict_from_file +import pytest class TestLoadConfigDictFromFile: diff --git a/testing/test_helpconfig.py b/testing/test_helpconfig.py index 272d4d29065..4906ef5c8f0 100644 --- a/testing/test_helpconfig.py +++ b/testing/test_helpconfig.py @@ -1,7 +1,7 @@ # mypy: allow-untyped-defs -import pytest from _pytest.config import ExitCode from _pytest.pytester import Pytester +import pytest def test_version_verbose(pytester: Pytester, pytestconfig, monkeypatch) -> None: diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 88749c0c851..9b8030e7da3 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1,8 +1,8 @@ # mypy: allow-untyped-defs -import os -import platform from datetime import datetime +import os from pathlib import Path +import platform from typing import cast from typing import List from typing import Optional @@ -13,7 +13,6 @@ import xmlschema -import pytest from _pytest.config import Config from _pytest.junitxml import bin_xml_escape from _pytest.junitxml import LogXML @@ -23,6 +22,7 @@ from _pytest.reports import BaseReport from _pytest.reports import TestReport from _pytest.stash import Stash +import pytest @pytest.fixture(scope="session") @@ -1283,12 +1283,10 @@ def test_record_fixtures_without_junitxml( pytester: Pytester, fixture_name: str ) -> None: pytester.makepyfile( - """ + f""" def test_record({fixture_name}): {fixture_name}("foo", "bar") - """.format( - fixture_name=fixture_name - ) + """ ) result = pytester.runpytest() assert result.ret == 0 @@ -1336,7 +1334,7 @@ def test_record_fixtures_xunit2( """ ) pytester.makepyfile( - """ + f""" import pytest @pytest.fixture @@ -1344,9 +1342,7 @@ def other({fixture_name}): {fixture_name}("bar", 1) def test_record({fixture_name}, other): {fixture_name}("foo", "<1"); - """.format( - fixture_name=fixture_name - ) + """ ) result, dom = run_and_parse(family=None) @@ -1356,10 +1352,8 @@ def test_record({fixture_name}, other): "*test_record_fixtures_xunit2.py:6:*record_xml_attribute is an experimental feature" ) expected_lines = [ - "*test_record_fixtures_xunit2.py:6:*{fixture_name} is incompatible " - "with junit_family 'xunit2' (use 'legacy' or 'xunit1')".format( - fixture_name=fixture_name - ) + f"*test_record_fixtures_xunit2.py:6:*{fixture_name} is incompatible " + "with junit_family 'xunit2' (use 'legacy' or 'xunit1')" ] result.stdout.fnmatch_lines(expected_lines) @@ -1476,7 +1470,12 @@ def test_pass(): result.stdout.no_fnmatch_line("*INTERNALERROR*") - items = sorted("%(classname)s %(name)s" % x for x in dom.find_by_tag("testcase")) + items = sorted( + "%(classname)s %(name)s" % x # noqa: UP031 + # dom is a DomNode not a mapping, it's not possible to ** it. + for x in dom.find_by_tag("testcase") + ) + import pprint pprint.pprint(items) @@ -1611,13 +1610,11 @@ def test_set_suite_name( ) -> None: if suite_name: pytester.makeini( - """ + f""" [pytest] junit_suite_name={suite_name} - junit_family={family} - """.format( - suite_name=suite_name, family=xunit_family - ) + junit_family={xunit_family} + """ ) expected = suite_name else: @@ -1698,14 +1695,12 @@ def test_logging_passing_tests_disabled_does_not_log_test_output( pytester: Pytester, run_and_parse: RunAndParse, xunit_family: str ) -> None: pytester.makeini( - """ + f""" [pytest] junit_log_passing_tests=False junit_logging=system-out - junit_family={family} - """.format( - family=xunit_family - ) + junit_family={xunit_family} + """ ) pytester.makepyfile( """ @@ -1735,13 +1730,11 @@ def test_logging_passing_tests_disabled_logs_output_for_failing_test_issue5430( xunit_family: str, ) -> None: pytester.makeini( - """ + f""" [pytest] junit_log_passing_tests=False - junit_family={family} - """.format( - family=xunit_family - ) + junit_family={xunit_family} + """ ) pytester.makepyfile( """ diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index 72899b60df8..6b933a6d9b0 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -1,11 +1,11 @@ # mypy: allow-untyped-defs from pathlib import Path -import pytest from _pytest.fixtures import TopRequest from _pytest.legacypath import LEGACY_PATH from _pytest.legacypath import TempdirFactory from _pytest.legacypath import Testdir +import pytest def test_item_fspath(pytester: pytest.Pytester) -> None: diff --git a/testing/test_link_resolve.py b/testing/test_link_resolve.py index c9d307f8802..0461cd75554 100644 --- a/testing/test_link_resolve.py +++ b/testing/test_link_resolve.py @@ -1,11 +1,11 @@ # mypy: allow-untyped-defs +from contextlib import contextmanager import os.path +from pathlib import Path +from string import ascii_lowercase import subprocess import sys import textwrap -from contextlib import contextmanager -from pathlib import Path -from string import ascii_lowercase from _pytest.pytester import Pytester diff --git a/testing/test_main.py b/testing/test_main.py index b1abf2c7178..d92fa21d365 100644 --- a/testing/test_main.py +++ b/testing/test_main.py @@ -1,17 +1,17 @@ # mypy: allow-untyped-defs import argparse import os +from pathlib import Path import re import sys -from pathlib import Path from typing import Optional -import pytest from _pytest.config import ExitCode from _pytest.config import UsageError from _pytest.main import resolve_collection_argument from _pytest.main import validate_basetemp from _pytest.pytester import Pytester +import pytest @pytest.mark.parametrize( @@ -25,19 +25,17 @@ def test_wrap_session_notify_exception(ret_exc, pytester: Pytester) -> None: returncode, exc = ret_exc c1 = pytester.makeconftest( - """ + f""" import pytest def pytest_sessionstart(): - raise {exc}("boom") + raise {exc.__name__}("boom") def pytest_internalerror(excrepr, excinfo): returncode = {returncode!r} if returncode is not False: pytest.exit("exiting after %s..." % excinfo.typename, returncode={returncode!r}) - """.format( - returncode=returncode, exc=exc.__name__ - ) + """ ) result = pytester.runpytest() if returncode: @@ -85,13 +83,11 @@ def test_wrap_session_exit_sessionfinish( returncode: Optional[int], pytester: Pytester ) -> None: pytester.makeconftest( - """ + f""" import pytest def pytest_sessionfinish(): pytest.exit(reason="exit_pytest_sessionfinish", returncode={returncode}) - """.format( - returncode=returncode - ) + """ ) result = pytester.runpytest() if returncode: diff --git a/testing/test_mark.py b/testing/test_mark.py index e37fc6c5339..4604baafdfa 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -5,13 +5,13 @@ from typing import Optional from unittest import mock -import pytest from _pytest.config import ExitCode from _pytest.mark import MarkGenerator from _pytest.mark.structures import EMPTY_PARAMETERSET_OPTION from _pytest.nodes import Collector from _pytest.nodes import Node from _pytest.pytester import Pytester +import pytest class TestMark: @@ -934,12 +934,10 @@ def test_parameterset_for_parametrize_marks( ) -> None: if mark is not None: pytester.makeini( - """ + f""" [pytest] - {}={} - """.format( - EMPTY_PARAMETERSET_OPTION, mark - ) + {EMPTY_PARAMETERSET_OPTION}={mark} + """ ) config = pytester.parseconfig() @@ -959,12 +957,10 @@ def test_parameterset_for_parametrize_marks( def test_parameterset_for_fail_at_collect(pytester: Pytester) -> None: pytester.makeini( - """ + f""" [pytest] - {}=fail_at_collect - """.format( - EMPTY_PARAMETERSET_OPTION - ) + {EMPTY_PARAMETERSET_OPTION}=fail_at_collect + """ ) config = pytester.parseconfig() diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index f3643e7b409..a7a9cf3044a 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -1,8 +1,8 @@ from typing import Callable -import pytest from _pytest.mark.expression import Expression from _pytest.mark.expression import ParseError +import pytest def evaluate(input: str, matcher: Callable[[str], bool]) -> bool: diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 3a1045d6708..12be774beca 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -1,16 +1,16 @@ # mypy: allow-untyped-defs import os +from pathlib import Path import re import sys import textwrap -from pathlib import Path from typing import Dict from typing import Generator from typing import Type -import pytest from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest @pytest.fixture diff --git a/testing/test_nodes.py b/testing/test_nodes.py index 4efb39e036b..e019f163c2b 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -1,15 +1,15 @@ # mypy: allow-untyped-defs -import re -import warnings from pathlib import Path +import re from typing import cast from typing import Type +import warnings -import pytest from _pytest import nodes from _pytest.outcomes import OutcomeException from _pytest.pytester import Pytester from _pytest.warning_types import PytestWarning +import pytest def test_node_from_parent_disallowed_arguments() -> None: @@ -39,7 +39,6 @@ def test_subclassing_both_item_and_collector_deprecated( Verifies we warn on diamond inheritance as well as correctly managing legacy inheritance constructors with missing args as found in plugins. """ - # We do not expect any warnings messages to issued during class definition. with warnings.catch_warnings(): warnings.simplefilter("error") diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index b2d5479311c..4678d8bdba7 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -2,16 +2,16 @@ import argparse import locale import os +from pathlib import Path import shlex import subprocess import sys -from pathlib import Path -import pytest from _pytest.config import argparsing as parseopt from _pytest.config.exceptions import UsageError from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest @pytest.fixture @@ -315,9 +315,7 @@ def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: # http://stackoverflow.com/q/12589419/1307905 # so we use bash fp.write( - 'COMP_WORDBREAKS="$COMP_WORDBREAKS" {} -m pytest 8>&1 9>&2'.format( - shlex.quote(sys.executable) - ) + f'COMP_WORDBREAKS="$COMP_WORDBREAKS" {shlex.quote(sys.executable)} -m pytest 8>&1 9>&2' ) # alternative would be extended Pytester.{run(),_run(),popen()} to be able # to handle a keyword argument env that replaces os.environ in popen or @@ -335,9 +333,7 @@ def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: pytest.skip("argcomplete not available") elif not result.stdout.str(): pytest.skip( - "bash provided no output on stdout, argcomplete not available? (stderr={!r})".format( - result.stderr.str() - ) + f"bash provided no output on stdout, argcomplete not available? (stderr={result.stderr.str()!r})" ) else: result.stdout.fnmatch_lines(["--funcargs", "--fulltrace"]) diff --git a/testing/test_pastebin.py b/testing/test_pastebin.py index 277454f9b18..651a04da84a 100644 --- a/testing/test_pastebin.py +++ b/testing/test_pastebin.py @@ -4,9 +4,9 @@ from typing import List from typing import Union -import pytest from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest class TestPasteCapture: diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 99cd48503b8..075259009de 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1,17 +1,16 @@ # mypy: allow-untyped-defs import errno import os.path +from pathlib import Path import pickle import sys -import unittest.mock -from pathlib import Path from textwrap import dedent from types import ModuleType from typing import Any from typing import Generator from typing import Iterator +import unittest.mock -import pytest from _pytest.monkeypatch import MonkeyPatch from _pytest.pathlib import bestrelpath from _pytest.pathlib import commonpath @@ -31,6 +30,7 @@ from _pytest.pathlib import visit from _pytest.pytester import Pytester from _pytest.tmpdir import TempPathFactory +import pytest class TestFNMatcherPort: diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index ea44d8748b4..f68f143f433 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -5,7 +5,6 @@ import types from typing import List -import pytest from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config import PytestPluginManager @@ -14,6 +13,7 @@ from _pytest.monkeypatch import MonkeyPatch from _pytest.pathlib import import_path from _pytest.pytester import Pytester +import pytest @pytest.fixture diff --git a/testing/test_pytester.py b/testing/test_pytester.py index e35fb529427..84fb96ccb84 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -6,16 +6,16 @@ from types import ModuleType from typing import List -import _pytest.pytester as pytester_mod -import pytest from _pytest.config import ExitCode from _pytest.config import PytestPluginManager from _pytest.monkeypatch import MonkeyPatch +import _pytest.pytester as pytester_mod from _pytest.pytester import HookRecorder from _pytest.pytester import LineMatcher from _pytest.pytester import Pytester from _pytest.pytester import SysModulesSnapshot from _pytest.pytester import SysPathsSnapshot +import pytest def test_make_hook_recorder(pytester: Pytester) -> None: @@ -705,15 +705,13 @@ def test_spawn_uses_tmphome(pytester: Pytester) -> None: pytester._monkeypatch.setenv("CUSTOMENV", "42") p1 = pytester.makepyfile( - """ + f""" import os def test(): assert os.environ["HOME"] == {tmphome!r} assert os.environ["CUSTOMENV"] == "42" - """.format( - tmphome=tmphome - ) + """ ) child = pytester.spawn_pytest(str(p1)) out = child.read() diff --git a/testing/test_python_path.py b/testing/test_python_path.py index 4054134b480..73a8725680f 100644 --- a/testing/test_python_path.py +++ b/testing/test_python_path.py @@ -5,8 +5,8 @@ from typing import List from typing import Optional -import pytest from _pytest.pytester import Pytester +import pytest @pytest.fixture() diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 9d46c1fc870..e2b2eb8a2d5 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -1,12 +1,12 @@ # mypy: allow-untyped-defs -import warnings from typing import List from typing import Optional from typing import Type +import warnings -import pytest from _pytest.pytester import Pytester from _pytest.recwarn import WarningsRecorder +import pytest def test_recwarn_stacklevel(recwarn: WarningsRecorder) -> None: diff --git a/testing/test_reports.py b/testing/test_reports.py index d65358a8fe6..2de5ae60090 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -2,7 +2,6 @@ from typing import Sequence from typing import Union -import pytest from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ExceptionRepr from _pytest.config import Config @@ -10,6 +9,7 @@ from _pytest.python_api import approx from _pytest.reports import CollectReport from _pytest.reports import TestReport +import pytest class TestReportSerialization: @@ -279,7 +279,7 @@ def test_chained_exceptions( ) -> None: """Check serialization/deserialization of report objects containing chained exceptions (#5786)""" pytester.makepyfile( - """ + f""" def foo(): raise ValueError('value error') def test_a(): @@ -287,18 +287,16 @@ def test_a(): foo() except ValueError as e: raise RuntimeError('runtime error') from e - if {error_during_import}: + if {report_class is CollectReport}: test_a() - """.format( - error_during_import=report_class is CollectReport - ) + """ ) reprec = pytester.inline_run() if report_class is TestReport: - reports: Union[Sequence[TestReport], Sequence[CollectReport]] = ( - reprec.getreports("pytest_runtest_logreport") - ) + reports: Union[ + Sequence[TestReport], Sequence[CollectReport] + ] = reprec.getreports("pytest_runtest_logreport") # we have 3 reports: setup/call/teardown assert len(reports) == 3 # get the call report diff --git a/testing/test_runner.py b/testing/test_runner.py index d2007647eee..6b2b3105b0c 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1,16 +1,15 @@ # mypy: allow-untyped-defs +from functools import partial import inspect import os +from pathlib import Path import sys import types -from functools import partial -from pathlib import Path from typing import Dict from typing import List from typing import Tuple from typing import Type -import pytest from _pytest import outcomes from _pytest import reports from _pytest import runner @@ -20,6 +19,8 @@ from _pytest.monkeypatch import MonkeyPatch from _pytest.outcomes import OutcomeException from _pytest.pytester import Pytester +import pytest + if sys.version_info[:2] < (3, 11): from exceptiongroup import ExceptionGroup diff --git a/testing/test_runner_xunit.py b/testing/test_runner_xunit.py index dbdb51d2470..8076e20bc40 100644 --- a/testing/test_runner_xunit.py +++ b/testing/test_runner_xunit.py @@ -2,8 +2,8 @@ """Test correct setup/teardowns at module, class, and instance level.""" from typing import List -import pytest from _pytest.pytester import Pytester +import pytest def test_module_and_function_setup(pytester: Pytester) -> None: @@ -255,7 +255,7 @@ def test_setup_teardown_function_level_with_optional_argument( sys, "trace_setups_teardowns", trace_setups_teardowns, raising=False ) p = pytester.makepyfile( - """ + f""" import pytest import sys @@ -276,9 +276,7 @@ def teardown_method(self, {arg}): trace('teardown_method') def test_method_1(self): pass def test_method_2(self): pass - """.format( - arg=arg - ) + """ ) result = pytester.inline_run(p) result.assertoutcome(passed=4) diff --git a/testing/test_scope.py b/testing/test_scope.py index 09ee1343a80..1727c2ee1bb 100644 --- a/testing/test_scope.py +++ b/testing/test_scope.py @@ -1,7 +1,7 @@ import re -import pytest from _pytest.scope import Scope +import pytest def test_ordering() -> None: diff --git a/testing/test_session.py b/testing/test_session.py index 232e9c834a5..8624af478b1 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -1,8 +1,8 @@ # mypy: allow-untyped-defs -import pytest from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest class SessionTests: diff --git a/testing/test_setuponly.py b/testing/test_setuponly.py index 0f70383a63e..8638f5a6140 100644 --- a/testing/test_setuponly.py +++ b/testing/test_setuponly.py @@ -1,9 +1,9 @@ # mypy: allow-untyped-defs import sys -import pytest from _pytest.config import ExitCode from _pytest.pytester import Pytester +import pytest @pytest.fixture(params=["--setup-only", "--setup-plan", "--setup-show"], scope="module") diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 346dfa44e89..4391c06421b 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -2,12 +2,12 @@ import sys import textwrap -import pytest from _pytest.pytester import Pytester from _pytest.runner import runtestprotocol from _pytest.skipping import evaluate_skip_marks from _pytest.skipping import evaluate_xfail_marks from _pytest.skipping import pytest_runtest_setup +import pytest class TestEvaluation: @@ -76,14 +76,13 @@ def test_marked_one_arg_twice(self, pytester: Pytester) -> None: ] for i in range(0, 2): item = pytester.getitem( - """ + f""" import pytest - %s - %s + {lines[i]} + {lines[(i + 1) % 2]} def test_func(): pass """ - % (lines[i], lines[(i + 1) % 2]) ) skipped = evaluate_skip_marks(item) assert skipped @@ -607,7 +606,7 @@ def test_xfail_raises( @pytest.mark.xfail(raises=%s) def test_raises(): raise %s() - """ + """ # noqa: UP031 (python syntax issues) % (expected, actual) ) result = pytester.runpytest(p) @@ -909,7 +908,7 @@ def test_skipif_reporting(self, pytester: Pytester, params) -> None: @pytest.mark.skipif(%(params)s) def test_that(): assert 0 - """ + """ # noqa: UP031 (python syntax issues) % dict(params=params) ) result = pytester.runpytest(p, "-s", "-rs") @@ -935,15 +934,13 @@ def test_skipif_reporting_multiple( self, pytester: Pytester, marker, msg1, msg2 ) -> None: pytester.makepyfile( - test_foo=""" + test_foo=f""" import pytest @pytest.mark.{marker}(False, reason='first_condition') @pytest.mark.{marker}(True, reason='second_condition') def test_foobar(): assert 1 - """.format( - marker=marker - ) + """ ) result = pytester.runpytest("-s", "-rsxX") result.stdout.fnmatch_lines( diff --git a/testing/test_stash.py b/testing/test_stash.py index 2c9df4832e4..e523c4e6f2b 100644 --- a/testing/test_stash.py +++ b/testing/test_stash.py @@ -1,6 +1,6 @@ -import pytest from _pytest.stash import Stash from _pytest.stash import StashKey +import pytest def test_stash() -> None: diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index 4aa72d02496..472afea6620 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -1,11 +1,11 @@ # mypy: allow-untyped-defs from pathlib import Path -import pytest from _pytest.cacheprovider import Cache from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester from _pytest.stepwise import STEPWISE_CACHE_DIR +import pytest @pytest.fixture diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 283722887ae..0eb50926e33 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1,11 +1,11 @@ # mypy: allow-untyped-defs """Terminal reporting of the full testing process.""" import collections +from io import StringIO import os +from pathlib import Path import sys import textwrap -from io import StringIO -from pathlib import Path from types import SimpleNamespace from typing import cast from typing import Dict @@ -14,10 +14,8 @@ import pluggy -import _pytest.config -import _pytest.terminal -import pytest from _pytest._io.wcwidth import wcswidth +import _pytest.config from _pytest.config import Config from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch @@ -25,6 +23,7 @@ from _pytest.reports import BaseReport from _pytest.reports import CollectReport from _pytest.reports import TestReport +import _pytest.terminal from _pytest.terminal import _folded_skips from _pytest.terminal import _format_trimmed from _pytest.terminal import _get_line_with_reprcrash_message @@ -32,6 +31,8 @@ from _pytest.terminal import _plugin_nameversions from _pytest.terminal import getreportopt from _pytest.terminal import TerminalReporter +import pytest + DistInfo = collections.namedtuple("DistInfo", ["project_name", "version"]) @@ -156,7 +157,6 @@ def test_report_collect_after_half_a_second( self, pytester: Pytester, monkeypatch: MonkeyPatch ) -> None: """Test for "collecting" being updated after 0.5s""" - pytester.makepyfile( **{ "test1.py": """ @@ -869,13 +869,7 @@ def test_passes(): result.stdout.fnmatch_lines( [ "*===== test session starts ====*", - "platform %s -- Python %s*pytest-%s**pluggy-%s" - % ( - sys.platform, - verinfo, - pytest.__version__, - pluggy.__version__, - ), + f"platform {sys.platform} -- Python {verinfo}*pytest-{pytest.__version__}**pluggy-{pluggy.__version__}", "*test_header_trailer_info.py .*", "=* 1 passed*in *.[0-9][0-9]s *=", ] @@ -896,13 +890,7 @@ def test_passes(): result = pytester.runpytest("--no-header") verinfo = ".".join(map(str, sys.version_info[:3])) result.stdout.no_fnmatch_line( - "platform %s -- Python %s*pytest-%s**pluggy-%s" - % ( - sys.platform, - verinfo, - pytest.__version__, - pluggy.__version__, - ) + f"platform {sys.platform} -- Python {verinfo}*pytest-{pytest.__version__}**pluggy-{pluggy.__version__}" ) if request.config.pluginmanager.list_plugin_distinfo(): result.stdout.no_fnmatch_line("plugins: *") @@ -943,12 +931,10 @@ def test_header_absolute_testpath( tests = pytester.path.joinpath("tests") tests.mkdir() pytester.makepyprojecttoml( - """ + f""" [tool.pytest.ini_options] - testpaths = ['{}'] - """.format( - tests - ) + testpaths = ['{tests}'] + """ ) result = pytester.runpytest() result.stdout.fnmatch_lines( @@ -2413,7 +2399,12 @@ def markup(self, word: str, **markup: str): __tracebackhide__ = True if msg: rep.longrepr.reprcrash.message = msg # type: ignore - actual = _get_line_with_reprcrash_message(config, rep(), DummyTerminalWriter(), {}) # type: ignore + actual = _get_line_with_reprcrash_message( + config, # type: ignore[arg-type] + rep(), # type: ignore[arg-type] + DummyTerminalWriter(), # type: ignore[arg-type] + {}, + ) assert actual == expected if actual != f"{mocked_verbose_word} {mocked_pos}": diff --git a/testing/test_threadexception.py b/testing/test_threadexception.py index fd9a091ccc9..99837b94e8a 100644 --- a/testing/test_threadexception.py +++ b/testing/test_threadexception.py @@ -1,5 +1,5 @@ -import pytest from _pytest.pytester import Pytester +import pytest @pytest.mark.filterwarnings("default::pytest.PytestUnhandledThreadExceptionWarning") diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 42df6608811..331ee7da6c7 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -1,16 +1,15 @@ # mypy: allow-untyped-defs import dataclasses import os +from pathlib import Path import stat import sys -import warnings -from pathlib import Path from typing import Callable from typing import cast from typing import List from typing import Union +import warnings -import pytest from _pytest import pathlib from _pytest.config import Config from _pytest.monkeypatch import MonkeyPatch @@ -24,6 +23,7 @@ from _pytest.pytester import Pytester from _pytest.tmpdir import get_user from _pytest.tmpdir import TempPathFactory +import pytest def test_tmp_path_fixture(pytester: Pytester) -> None: @@ -242,12 +242,10 @@ def test_fixt(fixt): def test_mktemp(pytester: Pytester, basename: str, is_ok: bool) -> None: mytemp = pytester.mkdir("mytemp") p = pytester.makepyfile( - """ + f""" def test_abs_path(tmp_path_factory): - tmp_path_factory.mktemp('{}', numbered=False) - """.format( - basename - ) + tmp_path_factory.mktemp('{basename}', numbered=False) + """ ) result = pytester.runpytest(p, "--basetemp=%s" % mytemp) @@ -338,7 +336,6 @@ def test_tmp_path_fallback_uid_not_found(pytester: Pytester) -> None: """Test that tmp_path works even if the current process's user id does not correspond to a valid user. """ - pytester.makepyfile( """ def test_some(tmp_path): diff --git a/testing/test_unittest.py b/testing/test_unittest.py index fc967d99262..b5d182c14ad 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -3,10 +3,10 @@ import sys from typing import List -import pytest from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester +import pytest def test_simple_unittest(pytester: Pytester) -> None: @@ -353,22 +353,21 @@ def test_teareddown(): @pytest.mark.parametrize("type", ["Error", "Failure"]) def test_testcase_adderrorandfailure_defers(pytester: Pytester, type: str) -> None: pytester.makepyfile( - """ + f""" from unittest import TestCase import pytest class MyTestCase(TestCase): def run(self, result): excinfo = pytest.raises(ZeroDivisionError, lambda: 0/0) try: - result.add%s(self, excinfo._excinfo) + result.add{type}(self, excinfo._excinfo) except KeyboardInterrupt: raise except: - pytest.fail("add%s should not raise") + pytest.fail("add{type} should not raise") def test_hello(self): pass """ - % (type, type) ) result = pytester.runpytest() result.stdout.no_fnmatch_line("*should not raise*") @@ -400,14 +399,13 @@ def from_exc_info(cls, *args, **kwargs): mp.setattr(_pytest._code, 'ExceptionInfo', FakeExceptionInfo) try: excinfo = excinfo._excinfo - result.add%(type)s(self, excinfo) + result.add{type}(self, excinfo) finally: mp.undo() def test_hello(self): pass - """ - % locals() + """.format(**locals()) ) result = pytester.runpytest() result.stdout.fnmatch_lines( @@ -834,7 +832,7 @@ def test_passing_test_is_fail(self): @pytest.mark.parametrize("stmt", ["return", "yield"]) def test_unittest_setup_interaction(pytester: Pytester, stmt: str) -> None: pytester.makepyfile( - """ + f""" import unittest import pytest class MyTestCase(unittest.TestCase): @@ -856,9 +854,7 @@ def test_method2(self): def test_classattr(self): assert self.__class__.hello == "world" - """.format( - stmt=stmt - ) + """ ) result = pytester.runpytest() result.stdout.fnmatch_lines(["*3 passed*"]) @@ -1063,7 +1059,7 @@ def pytest_collection_modifyitems(items): ) pytester.makepyfile( - """ + f""" import pytest import {module} @@ -1082,9 +1078,7 @@ def test_two(self): assert self.fixture2 - """.format( - module=module, base=base - ) + """ ) result = pytester.runpytest("-s") @@ -1253,7 +1247,7 @@ def test_pdb_teardown_skipped_for_functions( monkeypatch.setattr(pytest, "track_pdb_teardown_skipped", tracked, raising=False) pytester.makepyfile( - """ + f""" import unittest import pytest @@ -1269,9 +1263,7 @@ def tearDown(self): def test_1(self): pass - """.format( - mark=mark - ) + """ ) result = pytester.runpytest_inprocess("--pdb") result.stdout.fnmatch_lines("* 1 skipped in *") @@ -1290,7 +1282,7 @@ def test_pdb_teardown_skipped_for_classes( monkeypatch.setattr(pytest, "track_pdb_teardown_skipped", tracked, raising=False) pytester.makepyfile( - """ + f""" import unittest import pytest @@ -1306,9 +1298,7 @@ def tearDown(self): def test_1(self): pass - """.format( - mark=mark - ) + """ ) result = pytester.runpytest_inprocess("--pdb") result.stdout.fnmatch_lines("* 1 skipped in *") diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index d255adb2b91..1657cfe4a84 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -1,7 +1,8 @@ import sys -import pytest from _pytest.pytester import Pytester +import pytest + PYPY = hasattr(sys, "pypy_version_info") diff --git a/testing/test_warning_types.py b/testing/test_warning_types.py index 0ea3f2976f8..a50d278bde2 100644 --- a/testing/test_warning_types.py +++ b/testing/test_warning_types.py @@ -1,9 +1,9 @@ # mypy: allow-untyped-defs import inspect -import pytest from _pytest import warning_types from _pytest.pytester import Pytester +import pytest @pytest.mark.parametrize( @@ -43,5 +43,6 @@ def test(): def test_warn_explicit_for_annotates_errors_with_location(): with pytest.raises(Warning, match="(?m)test\n at .*python_api.py:\\d+"): warning_types.warn_explicit_for( - pytest.raises, warning_types.PytestWarning("test") # type: ignore + pytest.raises, # type: ignore[arg-type] + warning_types.PytestWarning("test"), ) diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 2f0ab9b54bd..5a8a98015a2 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -1,14 +1,15 @@ # mypy: allow-untyped-defs import os import sys -import warnings from typing import List from typing import Optional from typing import Tuple +import warnings -import pytest from _pytest.fixtures import FixtureRequest from _pytest.pytester import Pytester +import pytest + WARNINGS_SUMMARY_HEADER = "warnings summary" @@ -20,13 +21,11 @@ def pyfile_with_warnings(pytester: Pytester, request: FixtureRequest) -> str: test_name = request.function.__name__ module_name = test_name.lstrip("test_") + "_module" test_file = pytester.makepyfile( - """ + f""" import {module_name} def test_func(): assert {module_name}.foo() == 1 - """.format( - module_name=module_name - ), + """, **{ module_name: """ import warnings @@ -437,7 +436,7 @@ class TestDeprecationWarningsByDefault: def create_file(self, pytester: Pytester, mark="") -> None: pytester.makepyfile( - """ + f""" import pytest, warnings warnings.warn(DeprecationWarning("collection")) @@ -445,9 +444,7 @@ def create_file(self, pytester: Pytester, mark="") -> None: {mark} def test_foo(): warnings.warn(PendingDeprecationWarning("test run")) - """.format( - mark=mark - ) + """ ) @pytest.mark.parametrize("customize_filters", [True, False]) diff --git a/tox.ini b/tox.ini index b5c28029fc8..0ac2ff2ddba 100644 --- a/tox.ini +++ b/tox.ini @@ -186,27 +186,3 @@ usedevelop = True deps = pypandoc commands = python scripts/generate-gh-release-notes.py {posargs} - -[flake8] -max-line-length = 120 -extend-ignore = - ; whitespace before ':' - E203 - ; Missing Docstrings - D100,D101,D102,D103,D104,D105,D106,D107 - ; Whitespace Issues - D202,D203,D204,D205,D209,D213 - ; Quotes Issues - D302 - ; Docstring Content Issues - D400,D401,D401,D402,D405,D406,D407,D408,D409,D410,D411,D412,D413,D414,D415,D416,D417 - ; Unused imports - F401 - - -[isort] -; This config mimics what reorder-python-imports does. -force_single_line = 1 -known_localfolder = pytest,_pytest -known_third_party = test_source,test_excinfo -force_alphabetical_sort_within_sections = 1 From 9ef905e7a080181cdcd8840e694cc45cfbe8b99a Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 1 Feb 2024 23:00:25 +0100 Subject: [PATCH 0414/1271] [.git-blame-ignore-revs] Add migration to ruff/ruff format and blacken-docs 2024's style --- .git-blame-ignore-revs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 249ce70226f..bce64a374be 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -23,9 +23,11 @@ afc607cfd81458d4e4f3b1f3cf8cc931b933907e 5f95dce95602921a70bfbc7d8de2f7712c5e4505 # ran pyupgrade-docs again 75d0b899bbb56d6849e9d69d83a9426ed3f43f8b - # move argument parser to own file c9df77cbd6a365dcb73c39618e4842711817e871 - # Replace reorder-python-imports by isort due to black incompatibility (#11896) 8b54596639f41dfac070030ef20394b9001fe63c +# Run blacken-docs with black's 2024's style +4546d5445aaefe6a03957db028c263521dfb5c4b +# Migration to ruff / ruff format +4588653b2497ed25976b7aaff225b889fb476756 From 514376fe29d09945983754f2a4855583255ba5d9 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 14:49:15 +0100 Subject: [PATCH 0415/1271] [ruff] Add ruff's check and autofix existing issues --- pyproject.toml | 7 +++++++ src/_pytest/_code/code.py | 2 +- src/_pytest/_py/path.py | 4 +--- src/_pytest/compat.py | 2 +- src/_pytest/config/__init__.py | 2 +- src/_pytest/fixtures.py | 8 ++++---- src/_pytest/junitxml.py | 2 +- src/_pytest/main.py | 4 ++-- src/_pytest/mark/structures.py | 2 +- src/_pytest/python.py | 2 +- src/_pytest/python_api.py | 6 +++--- src/_pytest/recwarn.py | 10 ++++------ testing/_py/test_local.py | 2 +- testing/logging/test_reporting.py | 2 +- testing/python/fixtures.py | 2 +- testing/python/raises.py | 4 ++-- testing/test_assertion.py | 8 ++++---- testing/test_doctest.py | 2 +- testing/test_pytester.py | 4 ++-- 19 files changed, 39 insertions(+), 36 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4a7e58fdb83..2021df4cf55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -133,6 +133,7 @@ select = [ "F", # pyflakes "I", # isort "UP", # pyupgrade + "RUF", # ruff "W", # pycodestyle ] ignore = [ @@ -156,6 +157,12 @@ ignore = [ "D402", # First line should not be the function's signature "D404", # First word of the docstring should not be "This" "D415", # First line should end with a period, question mark, or exclamation point + # ruff ignore + "RUF001", # String contains ambiguous character + "RUF003", # Comment contains ambiguous character + "RUF005", # Consider `(x, *y)` instead of concatenation + "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + "RUF015", # Prefer `next(iter(x))` over single element slice ] [tool.ruff.format] diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 0662eb8cba5..12168be607c 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1018,7 +1018,7 @@ def _truncate_recursive_traceback( extraline: Optional[str] = ( "!!! Recursion error detected, but an error occurred locating the origin of recursion.\n" " The following exception happened when comparing locals in the stack frame:\n" - f" {type(e).__name__}: {str(e)}\n" + f" {type(e).__name__}: {e!s}\n" f" Displaying first and last {max_frames} stack frames out of {len(traceback)}." ) # Type ignored because adding two instances of a List subtype diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index af02d67b95f..554cb4a67e8 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -1105,9 +1105,7 @@ def pyimport(self, modname=None, ensuresyspath=True): modname = self.purebasename spec = importlib.util.spec_from_file_location(modname, str(self)) if spec is None or spec.loader is None: - raise ImportError( - f"Can't find module {modname} at location {str(self)}" - ) + raise ImportError(f"Can't find module {modname} at location {self!s}") mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) return mod diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 32e635255f5..dbe22e4aa20 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -27,7 +27,7 @@ # https://www.python.org/dev/peps/pep-0484/#support-for-singleton-types-in-unions class NotSetType(enum.Enum): token = 0 -NOTSET: Final = NotSetType.token # noqa: E305 +NOTSET: Final = NotSetType.token # fmt: on diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 8c2f05239a0..f5efc8ec916 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -671,7 +671,7 @@ def _importconftest( if dirpath in path.parents or path == dirpath: if mod in mods: raise AssertionError( - f"While trying to load conftest path {str(conftestpath)}, " + f"While trying to load conftest path {conftestpath!s}, " f"found that the module {mod} is already loaded with path {mod.__file__}. " "This is not supposed to happen. Please report this issue to pytest." ) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index a4e03f80cc0..b0bbc0e0449 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1225,7 +1225,7 @@ def fixture( @overload -def fixture( # noqa: F811 +def fixture( fixture_function: None = ..., *, scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., @@ -1239,7 +1239,7 @@ def fixture( # noqa: F811 ... -def fixture( # noqa: F811 +def fixture( fixture_function: Optional[FixtureFunction] = None, *, scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = "function", @@ -1673,7 +1673,7 @@ def parsefactories( raise NotImplementedError() @overload - def parsefactories( # noqa: F811 + def parsefactories( self, node_or_obj: object, nodeid: Optional[str], @@ -1682,7 +1682,7 @@ def parsefactories( # noqa: F811 ) -> None: raise NotImplementedError() - def parsefactories( # noqa: F811 + def parsefactories( self, node_or_obj: Union[nodes.Node, object], nodeid: Union[str, NotSetType, None] = NOTSET, diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 7a952231c33..51becf97b0f 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -375,7 +375,7 @@ def record_func(name: str, value: object) -> None: xml = request.config.stash.get(xml_key, None) if xml is not None: - record_func = xml.add_global_property # noqa + record_func = xml.add_global_property return record_func diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 4907a4256d4..c9ef877d72e 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -726,12 +726,12 @@ def perform_collect( ... @overload - def perform_collect( # noqa: F811 + def perform_collect( self, args: Optional[Sequence[str]] = ..., genitems: bool = ... ) -> Sequence[Union[nodes.Item, nodes.Collector]]: ... - def perform_collect( # noqa: F811 + def perform_collect( self, args: Optional[Sequence[str]] = None, genitems: bool = True ) -> Sequence[Union[nodes.Item, nodes.Collector]]: """Perform the collection phase for this session. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 7c8501d7314..5a7f9b20240 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -406,7 +406,7 @@ def normalize_mark_list( for mark in mark_list: mark_obj = getattr(mark, "mark", mark) if not isinstance(mark_obj, Mark): - raise TypeError(f"got {repr(mark_obj)} instead of Mark") + raise TypeError(f"got {mark_obj!r} instead of Mark") yield mark_obj diff --git a/src/_pytest/python.py b/src/_pytest/python.py index d0d7447336b..a5ae4813425 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -358,7 +358,7 @@ def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str # hook is not called for them. # fmt: off class _EmptyClass: pass # noqa: E701 -IGNORED_ATTRIBUTES = frozenset.union( # noqa: E305 +IGNORED_ATTRIBUTES = frozenset.union( frozenset(), # Module. dir(types.ModuleType("empty_module")), diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index bd3de2897a1..336b052fc2f 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -730,7 +730,7 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: # Type ignored because the error is wrong -- not unreachable. and not isinstance(expected, STRING_TYPES) # type: ignore[unreachable] ): - msg = f"pytest.approx() only supports ordered sequences, but got: {repr(expected)}" + msg = f"pytest.approx() only supports ordered sequences, but got: {expected!r}" raise TypeError(msg) else: cls = ApproxScalar @@ -780,7 +780,7 @@ def raises( @overload -def raises( # noqa: F811 +def raises( expected_exception: Union[Type[E], Tuple[Type[E], ...]], func: Callable[..., Any], *args: Any, @@ -789,7 +789,7 @@ def raises( # noqa: F811 ... -def raises( # noqa: F811 +def raises( expected_exception: Union[Type[E], Tuple[Type[E], ...]], *args: Any, **kwargs: Any ) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]: r"""Assert that a code block/function call raises an exception type, or one of its subclasses. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index ddd4c9a7b70..40f6d2e5b7c 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -47,13 +47,11 @@ def deprecated_call( @overload -def deprecated_call( # noqa: F811 - func: Callable[..., T], *args: Any, **kwargs: Any -) -> T: +def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: ... -def deprecated_call( # noqa: F811 +def deprecated_call( func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any ) -> Union["WarningsRecorder", Any]: """Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning`` or ``FutureWarning``. @@ -97,7 +95,7 @@ def warns( @overload -def warns( # noqa: F811 +def warns( expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]], func: Callable[..., T], *args: Any, @@ -106,7 +104,7 @@ def warns( # noqa: F811 ... -def warns( # noqa: F811 +def warns( expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning, *args: Any, match: Optional[Union[str, Pattern[str]]] = None, diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 57c953f17a5..11519c7c115 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -17,7 +17,7 @@ def ignore_encoding_warning(): with warnings.catch_warnings(): with contextlib.suppress(NameError): # new in 3.10 - warnings.simplefilter("ignore", EncodingWarning) # type: ignore [name-defined] # noqa: F821 + warnings.simplefilter("ignore", EncodingWarning) # type: ignore [name-defined] yield diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 7ef334950ef..24eae19b7ba 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1032,7 +1032,7 @@ def test_log_set_path(pytester: Pytester) -> None: def pytest_runtest_setup(item): config = item.config logging_plugin = config.pluginmanager.get_plugin("logging-plugin") - report_file = os.path.join({repr(report_dir_base)}, item._request.node.name) + report_file = os.path.join({report_dir_base!r}, item._request.node.name) logging_plugin.set_log_path(report_file) return (yield) """ diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 62f25cb0b3a..432c46e8dec 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -3086,7 +3086,7 @@ def test_baz(base, fix2): def test_other(): pass """ # noqa: UP031 (python syntax issues) - % {"scope": scope} # noqa: UP031 (python syntax issues) + % {"scope": scope} ) reprec = pytester.inline_run("-lvs") reprec.assertoutcome(passed=3) diff --git a/testing/python/raises.py b/testing/python/raises.py index 35d7f1a44f0..ef6607d962a 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -147,7 +147,7 @@ def test_no_raise_message(self) -> None: try: pytest.raises(ValueError, int, "0") except pytest.fail.Exception as e: - assert e.msg == f"DID NOT RAISE {repr(ValueError)}" + assert e.msg == f"DID NOT RAISE {ValueError!r}" else: assert False, "Expected pytest.raises.Exception" @@ -155,7 +155,7 @@ def test_no_raise_message(self) -> None: with pytest.raises(ValueError): pass except pytest.fail.Exception as e: - assert e.msg == f"DID NOT RAISE {repr(ValueError)}" + assert e.msg == f"DID NOT RAISE {ValueError!r}" else: assert False, "Expected pytest.raises.Exception" diff --git a/testing/test_assertion.py b/testing/test_assertion.py index f8196efea3e..167541e1ece 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -914,16 +914,16 @@ def test_nfc_nfd_same_string(self) -> None: assert expl == [ r"'hyv\xe4' == 'hyva\u0308'", "", - f"- {str(right)}", - f"+ {str(left)}", + f"- {right!s}", + f"+ {left!s}", ] expl = callequal(left, right, verbose=2) assert expl == [ r"'hyv\xe4' == 'hyva\u0308'", "", - f"- {str(right)}", - f"+ {str(left)}", + f"- {right!s}", + f"+ {left!s}", ] diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 835e0e1e6f4..a7a0077ae7d 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -190,7 +190,7 @@ def test_encoding(self, pytester, test_string, encoding): ) doctest = f""" >>> "{test_string}" - {repr(test_string)} + {test_string!r} """ fn = pytester.path / "test_encoding.txt" fn.write_text(doctest, encoding=encoding) diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 84fb96ccb84..9c6081a56db 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -227,7 +227,7 @@ def test_inline_run_test_module_not_cleaned_up(self, pytester: Pytester) -> None def spy_factory(self): class SysModulesSnapshotSpy: - instances: List["SysModulesSnapshotSpy"] = [] # noqa: F821 + instances: List["SysModulesSnapshotSpy"] = [] def __init__(self, preserve=None) -> None: SysModulesSnapshotSpy.instances.append(self) @@ -725,7 +725,7 @@ def test_run_result_repr() -> None: # known exit code r = pytester_mod.RunResult(1, outlines, errlines, duration=0.5) assert repr(r) == ( - f"" ) From 180a16a34414dae308a26ff69315db3de6f54e68 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 15:07:29 +0100 Subject: [PATCH 0416/1271] [ruff] Fix ambiguous characters found in string and comment --- pyproject.toml | 2 -- testing/io/test_wcwidth.py | 2 +- testing/test_assertion.py | 2 +- testing/test_doctest.py | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2021df4cf55..d02beb0bc5d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -158,8 +158,6 @@ ignore = [ "D404", # First word of the docstring should not be "This" "D415", # First line should end with a period, question mark, or exclamation point # ruff ignore - "RUF001", # String contains ambiguous character - "RUF003", # Comment contains ambiguous character "RUF005", # Consider `(x, *y)` instead of concatenation "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` "RUF015", # Prefer `next(iter(x))` over single element slice diff --git a/testing/io/test_wcwidth.py b/testing/io/test_wcwidth.py index 9ed2a6d3c49..0989af00d07 100644 --- a/testing/io/test_wcwidth.py +++ b/testing/io/test_wcwidth.py @@ -15,7 +15,7 @@ ("\u1ABE", 0), ("\u0591", 0), ("🉐", 2), - ("$", 2), + ("$", 2), # noqa: RUF001 ], ) def test_wcwidth(c: str, expected: int) -> None: diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 167541e1ece..2fa6fbe3793 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1149,7 +1149,7 @@ class SimpleDataObjectTwo: def test_attrs_with_auto_detect_and_custom_eq(self) -> None: @attr.s( auto_detect=True - ) # attr.s doesn’t ignore a custom eq if auto_detect=True + ) # attr.s doesn't ignore a custom eq if auto_detect=True class SimpleDataObject: field_a = attr.ib() diff --git a/testing/test_doctest.py b/testing/test_doctest.py index a7a0077ae7d..3725284907a 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -729,7 +729,7 @@ def foo(): >>> name = 'с' # not letter 'c' but instead Cyrillic 's'. 'anything' """ - ''' + ''' # noqa: RUF001 ) result = pytester.runpytest("--doctest-modules") result.stdout.fnmatch_lines(["Got nothing", "* 1 failed in*"]) From 8967c527ff0760bcaafcfc4db874a0b1e9f86316 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 15:08:22 +0100 Subject: [PATCH 0417/1271] [ruff] Activate use next(iter(x)) instead of list(x)[0] and fix issue --- pyproject.toml | 1 - testing/python/collect.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d02beb0bc5d..723da45dd3e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -160,7 +160,6 @@ ignore = [ # ruff ignore "RUF005", # Consider `(x, *y)` instead of concatenation "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - "RUF015", # Prefer `next(iter(x))` over single element slice ] [tool.ruff.format] diff --git a/testing/python/collect.py b/testing/python/collect.py index 4d1f97b34bb..745550f0775 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1209,7 +1209,7 @@ def test_bar(self): classcol = pytester.collect_by_name(modcol, "TestClass") assert isinstance(classcol, Class) path, lineno, msg = classcol.reportinfo() - func = list(classcol.collect())[0] + func = next(iter(classcol.collect())) assert isinstance(func, Function) path, lineno, msg = func.reportinfo() From 233ab89f1302465e3a2708043efee9e029db5c78 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 15:12:50 +0100 Subject: [PATCH 0418/1271] [ruff] Fix all consider [*cats, garfield] instead of cats + [garfield] --- pyproject.toml | 1 - scripts/release.py | 2 +- src/_pytest/assertion/rewrite.py | 2 +- src/_pytest/assertion/truncate.py | 3 ++- src/_pytest/assertion/util.py | 4 ++-- src/_pytest/config/__init__.py | 3 ++- src/_pytest/config/argparsing.py | 2 +- src/_pytest/pytester.py | 6 +++--- src/_pytest/recwarn.py | 2 +- testing/code/test_excinfo.py | 2 +- testing/freeze/create_executable.py | 2 +- testing/python/fixtures.py | 2 +- testing/test_junitxml.py | 2 +- testing/test_terminal.py | 20 ++++++++------------ 14 files changed, 25 insertions(+), 28 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 723da45dd3e..c931114924a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -158,7 +158,6 @@ ignore = [ "D404", # First word of the docstring should not be "This" "D415", # First line should end with a period, question mark, or exclamation point # ruff ignore - "RUF005", # Consider `(x, *y)` instead of concatenation "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` ] diff --git a/scripts/release.py b/scripts/release.py index 66617feb5a9..73f5f52b1b0 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -107,7 +107,7 @@ def pre_release( def changelog(version: str, write_out: bool = False) -> None: addopts = [] if write_out else ["--draft"] - check_call(["towncrier", "--yes", "--version", version] + addopts) + check_call(["towncrier", "--yes", "--version", version, *addopts]) def main() -> None: diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 0ab6eaa1393..9f3b65e8fc9 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -925,7 +925,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: # If any hooks implement assert_pass hook hook_impl_test = ast.If( self.helper("_check_if_assertion_pass_impl"), - self.expl_stmts + [hook_call_pass], + [*self.expl_stmts, hook_call_pass], [], ) statements_pass = [hook_impl_test] diff --git a/src/_pytest/assertion/truncate.py b/src/_pytest/assertion/truncate.py index 902d4baf846..4fdfd86a519 100644 --- a/src/_pytest/assertion/truncate.py +++ b/src/_pytest/assertion/truncate.py @@ -92,7 +92,8 @@ def _truncate_explanation( else: # Add proper ellipsis when we were able to fit a full line exactly truncated_explanation[-1] = "..." - return truncated_explanation + [ + return [ + *truncated_explanation, "", f"...Full output truncated ({truncated_line_count} line" f"{'' if truncated_line_count == 1 else 's'} hidden), {USAGE_MSG}", diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 33dcd4628de..ca3df74903d 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -233,8 +233,8 @@ def assertrepr_compare( return None if explanation[0] != "": - explanation = [""] + explanation - return [summary] + explanation + explanation = ["", *explanation] + return [summary, *explanation] def _compare_eq_any( diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index f5efc8ec916..0d48ef48979 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -238,7 +238,8 @@ def directory_arg(path: str, optname: str) -> str: "helpconfig", # Provides -p. ) -default_plugins = essential_plugins + ( +default_plugins = ( + *essential_plugins, "python", "terminal", "debugging", diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 18cf4600aa1..da05acf398e 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -122,7 +122,7 @@ def _getparser(self) -> "MyOptionParser": from _pytest._argcomplete import filescompleter optparser = MyOptionParser(self, self.extra_info, prog=self.prog) - groups = self._groups + [self._anonymous] + groups = [*self._groups, self._anonymous] for group in groups: if group.options: desc = group.description or group.name diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 5190bc35a25..8002528b965 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1061,7 +1061,7 @@ def inline_runsource(self, source: str, *cmdlineargs) -> HookRecorder: :param cmdlineargs: Any extra command line arguments to use. """ p = self.makepyfile(source) - values = list(cmdlineargs) + [p] + values = [*list(cmdlineargs), p] return self.inline_run(*values) def inline_genitems(self, *args) -> Tuple[List[Item], HookRecorder]: @@ -1491,10 +1491,10 @@ def runpytest_subprocess( """ __tracebackhide__ = True p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700) - args = ("--basetemp=%s" % p,) + args + args = ("--basetemp=%s" % p, *args) plugins = [x for x in self.plugins if isinstance(x, str)] if plugins: - args = ("-p", plugins[0]) + args + args = ("-p", plugins[0], *args) args = self._getpytestargs() + args return self.run(*args, timeout=timeout) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 40f6d2e5b7c..aa58d43b405 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -79,7 +79,7 @@ def deprecated_call( """ __tracebackhide__ = True if func is not None: - args = (func,) + args + args = (func, *args) return warns( (DeprecationWarning, PendingDeprecationWarning, FutureWarning), *args, **kwargs ) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 846e23b2a0d..a0ee28d48b4 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1739,7 +1739,7 @@ def test(): def add_note(err: BaseException, msg: str) -> None: """Adds a note to an exception inplace.""" if sys.version_info < (3, 11): - err.__notes__ = getattr(err, "__notes__", []) + [msg] # type: ignore[attr-defined] + err.__notes__ = [*getattr(err, "__notes__", []), msg] # type: ignore[attr-defined] else: err.add_note(msg) diff --git a/testing/freeze/create_executable.py b/testing/freeze/create_executable.py index 3803b3b24ec..fbfda2e5d94 100644 --- a/testing/freeze/create_executable.py +++ b/testing/freeze/create_executable.py @@ -9,5 +9,5 @@ for x in pytest.freeze_includes(): hidden.extend(["--hidden-import", x]) hidden.extend(["--hidden-import", "distutils"]) - args = ["pyinstaller", "--noconfirm"] + hidden + ["runtests_script.py"] + args = ["pyinstaller", "--noconfirm", *hidden, "runtests_script.py"] subprocess.check_call(" ".join(args), shell=True) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 432c46e8dec..d0e8723cb87 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4536,5 +4536,5 @@ def test_fixt(custom): def test_deduplicate_names() -> None: items = deduplicate_names("abacd") assert items == ("a", "b", "c", "d") - items = deduplicate_names(items + ("g", "f", "g", "e", "b")) + items = deduplicate_names((*items, "g", "f", "g", "e", "b")) assert items == ("a", "b", "c", "d", "g", "f", "e") diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 9b8030e7da3..42104255b28 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -42,7 +42,7 @@ def __call__( self, *args: Union[str, "os.PathLike[str]"], family: Optional[str] = "xunit1" ) -> Tuple[RunResult, "DomNode"]: if family: - args = ("-o", "junit_family=" + family) + args + args = ("-o", "junit_family=" + family, *args) xml_path = self.pytester.path.joinpath("junit.xml") result = self.pytester.runpytest("--junitxml=%s" % xml_path, *args) if family == "xunit2": diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 0eb50926e33..22f041cedc8 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -417,8 +417,8 @@ def test_long_xfail(): result = pytester.runpytest("-v") result.stdout.fnmatch_lines( - common_output - + [ + [ + *common_output, "test_verbose_skip_reason.py::test_long_skip SKIPPED (1 cannot *...) *", "test_verbose_skip_reason.py::test_long_xfail XFAIL (2 cannot *...) *", ] @@ -426,17 +426,13 @@ def test_long_xfail(): result = pytester.runpytest("-vv") result.stdout.fnmatch_lines( - common_output - + [ - ( - "test_verbose_skip_reason.py::test_long_skip SKIPPED" - " (1 cannot do foobar" - ), + [ + *common_output, + "test_verbose_skip_reason.py::test_long_skip SKIPPED" + " (1 cannot do foobar", "because baz is missing due to I don't know what) *", - ( - "test_verbose_skip_reason.py::test_long_xfail XFAIL" - " (2 cannot do foobar" - ), + "test_verbose_skip_reason.py::test_long_xfail XFAIL" + " (2 cannot do foobar", "because baz is missing due to I don't know what) *", ] ) From cb5f7388581228530d554f7b559b986bf1a0d474 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 2 Feb 2024 21:29:30 +0200 Subject: [PATCH 0419/1271] Ignore isort on _version.py The file is generated. This makes `ruff src/` run cleanly (when not running through pre-commit). --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index c931114924a..ebfbe1a0320 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -178,3 +178,6 @@ force-sort-within-sections = true order-by-type = false known-local-folder = ["pytest", "_pytest"] lines-after-imports = 2 + +[tool.ruff.lint.per-file-ignores] +"src/_pytest/_version.py" = ["I001"] From 99e8129ba361fe81e72f4fb2fb127de0f0447d05 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 3 Feb 2024 18:37:49 +0200 Subject: [PATCH 0420/1271] compat: get rid of STRING_TYPES I think it only obfuscates the code, also calling `bytes` a string type is pretty misleading in Python 3. --- src/_pytest/compat.py | 3 --- src/_pytest/python.py | 3 +-- src/_pytest/python_api.py | 10 ++-------- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index dbe22e4aa20..26a45349a42 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -181,9 +181,6 @@ def _translate_non_printable(s: str) -> str: return s.translate(_non_printable_ascii_translate_table) -STRING_TYPES = bytes, str - - def _bytes_to_ascii(val: bytes) -> str: return val.decode("ascii", "backslashreplace") diff --git a/src/_pytest/python.py b/src/_pytest/python.py index a5ae4813425..10ca00890d4 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -50,7 +50,6 @@ from _pytest.compat import NOTSET from _pytest.compat import safe_getattr from _pytest.compat import safe_isclass -from _pytest.compat import STRING_TYPES from _pytest.config import Config from _pytest.config import ExitCode from _pytest.config import hookimpl @@ -998,7 +997,7 @@ def _idval_from_hook(self, val: object, argname: str) -> Optional[str]: def _idval_from_value(self, val: object) -> Optional[str]: """Try to make an ID for a parameter in a ParameterSet from its value, if the value type is supported.""" - if isinstance(val, STRING_TYPES): + if isinstance(val, (str, bytes)): return _ascii_escaped_by_config(val, self.config) elif val is None or isinstance(val, (float, int, bool, complex)): return str(val) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 336b052fc2f..7e51da3194a 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -24,7 +24,6 @@ from typing import Union import _pytest._code -from _pytest.compat import STRING_TYPES from _pytest.outcomes import fail @@ -721,15 +720,10 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: elif ( hasattr(expected, "__getitem__") and isinstance(expected, Sized) - # Type ignored because the error is wrong -- not unreachable. - and not isinstance(expected, STRING_TYPES) # type: ignore[unreachable] + and not isinstance(expected, (str, bytes)) ): cls = ApproxSequenceLike - elif ( - isinstance(expected, Collection) - # Type ignored because the error is wrong -- not unreachable. - and not isinstance(expected, STRING_TYPES) # type: ignore[unreachable] - ): + elif isinstance(expected, Collection) and not isinstance(expected, (str, bytes)): msg = f"pytest.approx() only supports ordered sequences, but got: {expected!r}" raise TypeError(msg) else: From 3ba40954007d56b0f0cef251660c127fe6540137 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 3 Feb 2024 18:42:05 +0200 Subject: [PATCH 0421/1271] compat: inline helpers into `ascii_escaped` The helpers don't add much. --- src/_pytest/compat.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 26a45349a42..14717e94147 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -177,22 +177,13 @@ def get_default_arg_names(function: Callable[..., Any]) -> tuple[str, ...]: ) -def _translate_non_printable(s: str) -> str: - return s.translate(_non_printable_ascii_translate_table) - - -def _bytes_to_ascii(val: bytes) -> str: - return val.decode("ascii", "backslashreplace") - - def ascii_escaped(val: bytes | str) -> str: r"""If val is pure ASCII, return it as an str, otherwise, escape bytes objects into a sequence of escaped bytes: b'\xc3\xb4\xc5\xd6' -> r'\xc3\xb4\xc5\xd6' - and escapes unicode objects into a sequence of escaped unicode - ids, e.g.: + and escapes strings into a sequence of escaped unicode ids, e.g.: r'4\nV\U00043efa\x0eMXWB\x1e\u3028\u15fd\xcd\U0007d944' @@ -203,10 +194,10 @@ def ascii_escaped(val: bytes | str) -> str: a UTF-8 string. """ if isinstance(val, bytes): - ret = _bytes_to_ascii(val) + ret = val.decode("ascii", "backslashreplace") else: ret = val.encode("unicode_escape").decode("ascii") - return _translate_non_printable(ret) + return ret.translate(_non_printable_ascii_translate_table) @dataclasses.dataclass From b28bb01c4ee2933847b53916164dedba69be2107 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 4 Feb 2024 00:19:52 +0000 Subject: [PATCH 0422/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 184 ++++++++++++++++++------------- 1 file changed, 108 insertions(+), 76 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 45f4de9110e..9ada47c7aff 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =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 Jan 16, 2024 4 - Beta pytest >=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Jan 28, 2024 4 - Beta pytest <8,>=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) @@ -124,6 +124,7 @@ This list contains 1363 plugins. :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A + :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Feb 02, 2024 N/A pytest (>=8.0.0,<9.0.0) :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest @@ -131,7 +132,7 @@ This list contains 1363 plugins. :pypi:`pytest-azurepipelines` Formatting PyTest output for Azure Pipelines UI Oct 06, 2023 5 - Production/Stable pytest (>=5.0.0) :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-base-url` pytest plugin for URL based testing Mar 27, 2022 5 - Production/Stable pytest (>=3.0.0,<8.0.0) + :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-bdd` BDD for pytest Dec 02, 2023 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 @@ -296,7 +297,7 @@ This list contains 1363 plugins. :pypi:`pytest-datafixtures` Data fixtures for pytest made simple Dec 05, 2020 5 - Production/Stable N/A :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A - :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jan 08, 2023 5 - Production/Stable pytest + :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jan 31, 2024 5 - Production/Stable pytest :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A :pypi:`pytest-data-suites` Class-based pytest parametrization Jul 24, 2022 N/A pytest (>=6.0,<8.0) :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) @@ -334,13 +335,13 @@ This list contains 1363 plugins. :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 - :pypi:`pytest-django` A Django plugin for pytest. Nov 08, 2023 5 - Production/Stable pytest >=7.0.0 + :pypi:`pytest-django` A Django plugin for pytest. Jan 30, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A :pypi:`pytest-django-class` A pytest plugin for running django in class-scoped fixtures Aug 08, 2023 4 - Beta N/A - :pypi:`pytest-django-docker-pg` Jan 05, 2024 5 - Production/Stable pytest >=7.0.0 + :pypi:`pytest-django-docker-pg` Jan 30, 2024 5 - Production/Stable pytest <8.0.0,>=7.0.0 :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) :pypi:`pytest-django-factories` Factories for your Django models that can be used as Pytest fixtures. Nov 12, 2020 4 - Beta N/A :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 @@ -359,7 +360,7 @@ This list contains 1363 plugins. :pypi:`pytest-doc` A documentation plugin for py.test. Jun 28, 2015 5 - Production/Stable N/A :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A - :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Jan 27, 2024 N/A pytest <8.0,>=4.0 + :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Feb 02, 2024 N/A pytest <9.0,>=4.0 :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Feb 16, 2022 4 - Beta pytest :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) @@ -400,6 +401,7 @@ This list contains 1363 plugins. :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Jun 12, 2023 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A + :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Jan 27, 2024 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A :pypi:`pytest-easyread` pytest plugin that makes terminal printouts of the reports easier to read Nov 17, 2017 N/A N/A :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" @@ -539,7 +541,7 @@ This list contains 1363 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jan 25, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jan 29, 2024 N/A pytest>=3.6 :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 @@ -577,7 +579,7 @@ This list contains 1363 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jan 21, 2024 3 - Alpha pytest ==7.4.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 03, 2024 3 - Alpha pytest ==7.4.4 :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` Jan 06, 2024 N/A N/A @@ -602,7 +604,7 @@ This list contains 1363 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Dec 21, 2023 5 - Production/Stable pytest ==7.* + :pypi:`pytest-httpx` Send responses to httpx. Jan 29, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -631,6 +633,7 @@ This list contains 1363 plugins. :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-insper` Pytest plugin for courses at Insper Feb 01, 2024 N/A pytest :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Nov 02, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) :pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0) @@ -639,13 +642,13 @@ This list contains 1363 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Jan 26, 2024 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Oct 31, 2023 5 - Production/Stable pytest <7.2.0,>=6 + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jan 29, 2024 5 - Production/Stable pytest <7.2.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Oct 31, 2022 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 22, 2020 4 - Beta N/A + :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A :pypi:`pytest-jasmine` Run jasmine tests from your pytest test suite Nov 04, 2017 1 - Planning N/A @@ -687,7 +690,7 @@ This list contains 1363 plugins. :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. May 28, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Feb 01, 2024 N/A pytest (>=7) :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A @@ -751,7 +754,7 @@ This list contains 1363 plugins. :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A - :pypi:`pytest-metadata` pytest plugin for test session metadata May 27, 2023 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-metadata` pytest plugin for test session metadata Feb 01, 2024 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 Jan 16, 2024 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) @@ -767,7 +770,7 @@ This list contains 1363 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Sep 25, 2023 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Feb 01, 2024 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -878,7 +881,7 @@ This list contains 1363 plugins. :pypi:`pytest-pep257` py.test plugin for pep257 Jul 09, 2016 N/A N/A :pypi:`pytest-pep8` pytest plugin to check PEP8 requirements Apr 27, 2014 N/A N/A :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) - :pypi:`pytest-perf` Run performance tests against the mainline code. Jun 02, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-perf` Run performance tests against the mainline code. Jan 28, 2024 5 - Production/Stable pytest >=6 ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) @@ -897,7 +900,7 @@ This list contains 1363 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Oct 09, 2023 N/A pytest (<8.0.0,>=6.2.4) + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Feb 02, 2024 N/A pytest (<9.0.0,>=6.2.4) :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A @@ -921,7 +924,7 @@ This list contains 1363 plugins. :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 20, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Jan 29, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 @@ -1080,16 +1083,16 @@ This list contains 1363 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 29, 2024 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 Nov 20, 2023 5 - Production/Stable pytest>=6.0.0 + :pypi:`pytest-selenium` pytest plugin for Selenium Feb 01, 2024 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. Jan 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jan 29, 2024 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 @@ -1125,6 +1128,7 @@ This list contains 1363 plugins. :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 + :pypi:`pytest-slow-first` Prioritize running the slowest tests first. Jan 30, 2024 4 - Beta pytest >=3.5.0 :pypi:`pytest-slow-last` Run tests in order of execution time (faster tests first) Dec 10, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A @@ -1139,7 +1143,7 @@ This list contains 1363 plugins. :pypi:`pytest-snapshot-with-message-generator` A plugin for snapshot testing with pytest. Jul 25, 2023 4 - Beta pytest (>=3.0.0) :pypi:`pytest-snmpserver` May 12, 2021 N/A N/A :pypi:`pytest-snowflake-bdd` Setup test data and run tests on snowflake in BDD style! Jan 05, 2022 4 - Beta pytest (>=6.2.0) - :pypi:`pytest-socket` Pytest Plugin to disable socket calls during tests Feb 03, 2023 4 - Beta pytest (>=3.6.3) + :pypi:`pytest-socket` Pytest Plugin to disable socket calls during tests Jan 28, 2024 4 - Beta pytest (>=6.2.5) :pypi:`pytest-sofaepione` Test the installation of SOFA and the SofaEpione plugin. Aug 17, 2022 N/A N/A :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' @@ -1156,8 +1160,8 @@ This list contains 1363 plugins. :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 Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) - :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Jun 11, 2022 6 - Mature pytest (<8.0,>=7.1.2) - :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Apr 12, 2023 4 - Beta pytest (>=5,<8) + :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Feb 01, 2024 6 - Mature pytest >=8.0.0 + :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Jan 29, 2024 4 - Beta pytest (>=5,<9) :pypi:`pytest-split-ext` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Sep 23, 2023 4 - Beta pytest (>=5,<8) :pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) @@ -1195,7 +1199,7 @@ This list contains 1363 plugins. :pypi:`pytest-subtesthack` A hack to explicitly set up and tear down fixtures. Jul 16, 2022 N/A N/A :pypi:`pytest-subtests` unittest subTest() support and subtests fixture May 15, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) - :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Apr 10, 2023 4 - Beta pytest (>=6.2.0) + :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Feb 01, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A :pypi:`pytest-suite-timeout` A pytest plugin for ensuring max suite time Jan 26, 2024 N/A pytest>=7.0.0 :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A @@ -1306,7 +1310,7 @@ This list contains 1363 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 Dec 01, 2023 4 - Beta N/A + :pypi:`pytest-typhoon-polarion` Typhoontest plugin for Siemens Polarion Feb 01, 2024 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 @@ -1325,7 +1329,7 @@ This list contains 1363 plugins. :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest :pypi:`pytest-valgrind` May 19, 2021 N/A N/A - :pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures May 27, 2023 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures Feb 01, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-variant` Variant support for Pytest Jun 06, 2022 N/A N/A :pypi:`pytest-vcr` Plugin for managing VCR.py cassettes Apr 26, 2019 5 - Production/Stable pytest (>=3.6.0) :pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Jun 20, 2022 5 - Production/Stable pytest (>=6.2.2) @@ -1348,13 +1352,13 @@ This list contains 1363 plugins. :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-wake` Nov 07, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A - :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jun 24, 2023 4 - Beta N/A + :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jan 28, 2024 4 - Beta N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 13, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable Jan 25, 2024 N/A pytest>=7.3.1 + :pypi:`pytest-when` Utility which makes mocking more readable and controllable Jan 30, 2024 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -1371,7 +1375,7 @@ This list contains 1363 plugins. :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Dec 28, 2023 N/A pytest<8,>=7.4.0 + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jan 28, 2024 N/A pytest<8.1,>=7.4.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Sep 23, 2023 4 - Beta pytest (>=2.8) :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A @@ -1393,7 +1397,7 @@ This list contains 1363 plugins. :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jan 08, 2024 5 - Production/Stable pytest (>=4.5.0) - :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Jan 16, 2024 N/A pytest (>=7.4.2,<8.0.0) + :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest @@ -1900,9 +1904,9 @@ This list contains 1363 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jan 16, 2024, + *last release*: Jan 28, 2024, *status*: 4 - Beta, - *requires*: pytest >=7.0.0 + *requires*: pytest <8,>=7.0.0 Pytest support for asyncio @@ -2032,6 +2036,13 @@ This list contains 1363 plugins. Protect your AWS credentials in unit tests + :pypi:`pytest-aws-fixtures` + *last release*: Feb 02, 2024, + *status*: N/A, + *requires*: pytest (>=8.0.0,<9.0.0) + + A series of fixtures to use in integration tests involving actual AWS services. + :pypi:`pytest-axe` *last release*: Nov 12, 2018, *status*: N/A, @@ -2082,9 +2093,9 @@ This list contains 1363 plugins. A bandit plugin for pytest :pypi:`pytest-base-url` - *last release*: Mar 27, 2022, + *last release*: Jan 31, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.0.0,<8.0.0) + *requires*: pytest>=7.0.0 pytest plugin for URL based testing @@ -3237,7 +3248,7 @@ This list contains 1363 plugins. A pytest plugin for managing an archive of test data. :pypi:`pytest-datarecorder` - *last release*: Jan 08, 2023, + *last release*: Jan 31, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -3503,7 +3514,7 @@ This list contains 1363 plugins. A pytest plugin to notify test results to a Discord channel. :pypi:`pytest-django` - *last release*: Nov 08, 2023, + *last release*: Jan 30, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=7.0.0 @@ -3545,9 +3556,9 @@ This list contains 1363 plugins. A pytest plugin for running django in class-scoped fixtures :pypi:`pytest-django-docker-pg` - *last release*: Jan 05, 2024, + *last release*: Jan 30, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.0.0 + *requires*: pytest <8.0.0,>=7.0.0 @@ -3678,9 +3689,9 @@ This list contains 1363 plugins. An RST Documentation Generator for pytest-based test suites :pypi:`pytest-docker` - *last release*: Jan 27, 2024, + *last release*: Feb 02, 2024, *status*: N/A, - *requires*: pytest <8.0,>=4.0 + *requires*: pytest <9.0,>=4.0 Simple pytest fixtures for Docker and Docker Compose based tests @@ -3964,6 +3975,13 @@ This list contains 1363 plugins. pytest-easy-addoption: Easy way to work with pytest addoption + :pypi:`pytest-easy-api` + *last release*: Jan 27, 2024, + *status*: N/A, + *requires*: N/A + + A package to prevent Dependency Confusion attacks against Yandex. + :pypi:`pytest-easyMPI` *last release*: Oct 21, 2020, *status*: N/A, @@ -4938,7 +4956,7 @@ This list contains 1363 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jan 25, 2024, + *last release*: Jan 29, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5204,9 +5222,9 @@ This list contains 1363 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jan 21, 2024, + *last release*: Feb 03, 2024, *status*: 3 - Alpha, - *requires*: pytest ==7.4.3 + *requires*: pytest ==7.4.4 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -5379,9 +5397,9 @@ This list contains 1363 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Dec 21, 2023, + *last release*: Jan 29, 2024, *status*: 5 - Production/Stable, - *requires*: pytest ==7.* + *requires*: pytest <9,>=7 Send responses to httpx. @@ -5581,6 +5599,13 @@ This list contains 1363 plugins. A simple image diff plugin for pytest + :pypi:`pytest-insper` + *last release*: Feb 01, 2024, + *status*: N/A, + *requires*: pytest + + Pytest plugin for courses at Insper + :pypi:`pytest-insta` *last release*: Nov 02, 2022, *status*: N/A, @@ -5638,7 +5663,7 @@ This list contains 1363 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Oct 31, 2023, + *last release*: Jan 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest <7.2.0,>=6 @@ -5680,7 +5705,7 @@ This list contains 1363 plugins. py.test plugin to check import ordering using isort :pypi:`pytest-it` - *last release*: Jan 22, 2020, + *last release*: Jan 29, 2024, *status*: 4 - Beta, *requires*: N/A @@ -5974,9 +5999,9 @@ This list contains 1363 plugins. It helps to use fixtures in pytest.mark.parametrize :pypi:`pytest-lazy-fixtures` - *last release*: May 28, 2023, + *last release*: Feb 01, 2024, *status*: N/A, - *requires*: pytest (>=7.2.1,<8.0.0) + *requires*: pytest (>=7) Allows you to use fixtures in @pytest.mark.parametrize. @@ -6422,7 +6447,7 @@ This list contains 1363 plugins. Pytest to Slack reporting plugin :pypi:`pytest-metadata` - *last release*: May 27, 2023, + *last release*: Feb 01, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -6534,7 +6559,7 @@ This list contains 1363 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Sep 25, 2023, + *last release*: Feb 01, 2024, *status*: N/A, *requires*: pytest (>=1.0) @@ -7311,9 +7336,9 @@ This list contains 1363 plugins. Change the exit code of pytest test sessions when a required percent of tests pass. :pypi:`pytest-perf` - *last release*: Jun 02, 2023, + *last release*: Jan 28, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6) ; extra == 'testing' + *requires*: pytest >=6 ; extra == 'testing' Run performance tests against the mainline code. @@ -7444,9 +7469,9 @@ This list contains 1363 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Oct 09, 2023, + *last release*: Feb 02, 2024, *status*: N/A, - *requires*: pytest (<8.0.0,>=6.2.4) + *requires*: pytest (<9.0.0,>=6.2.4) A pytest wrapper with fixtures for Playwright to automate web browsers @@ -7612,9 +7637,9 @@ This list contains 1363 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: May 20, 2023, + *last release*: Jan 29, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2) + *requires*: pytest >=6.2 Postgresql fixtures and fixture factories for Pytest. @@ -8725,7 +8750,7 @@ This list contains 1363 plugins. :pypi:`pytest-sbase` - *last release*: Jan 25, 2024, + *last release*: Jan 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8774,7 +8799,7 @@ This list contains 1363 plugins. A pytest plugin which allows to (de-)select tests from a file. :pypi:`pytest-selenium` - *last release*: Nov 20, 2023, + *last release*: Feb 01, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.0.0 @@ -8788,7 +8813,7 @@ This list contains 1363 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jan 25, 2024, + *last release*: Jan 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9039,6 +9064,13 @@ This list contains 1363 plugins. Sort tests by their last duration, slowest first + :pypi:`pytest-slow-first` + *last release*: Jan 30, 2024, + *status*: 4 - Beta, + *requires*: pytest >=3.5.0 + + Prioritize running the slowest tests first. + :pypi:`pytest-slow-last` *last release*: Dec 10, 2022, *status*: 4 - Beta, @@ -9138,9 +9170,9 @@ This list contains 1363 plugins. Setup test data and run tests on snowflake in BDD style! :pypi:`pytest-socket` - *last release*: Feb 03, 2023, + *last release*: Jan 28, 2024, *status*: 4 - Beta, - *requires*: pytest (>=3.6.3) + *requires*: pytest (>=6.2.5) Pytest Plugin to disable socket calls during tests @@ -9257,16 +9289,16 @@ This list contains 1363 plugins. Splinter plugin for pytest testing framework :pypi:`pytest-splinter4` - *last release*: Jun 11, 2022, + *last release*: Feb 01, 2024, *status*: 6 - Mature, - *requires*: pytest (<8.0,>=7.1.2) + *requires*: pytest >=8.0.0 Pytest plugin for the splinter automation library :pypi:`pytest-split` - *last release*: Apr 12, 2023, + *last release*: Jan 29, 2024, *status*: 4 - Beta, - *requires*: pytest (>=5,<8) + *requires*: pytest (>=5,<9) Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. @@ -9530,9 +9562,9 @@ This list contains 1363 plugins. pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. :pypi:`pytest-sugar` - *last release*: Apr 10, 2023, + *last release*: Feb 01, 2024, *status*: 4 - Beta, - *requires*: pytest (>=6.2.0) + *requires*: pytest >=6.2.0 pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). @@ -10307,7 +10339,7 @@ This list contains 1363 plugins. A Typhoon HIL plugin that facilitates test parameter configuration at runtime :pypi:`pytest-typhoon-polarion` - *last release*: Dec 01, 2023, + *last release*: Feb 01, 2024, *status*: 4 - Beta, *requires*: N/A @@ -10440,7 +10472,7 @@ This list contains 1363 plugins. :pypi:`pytest-variables` - *last release*: May 27, 2023, + *last release*: Feb 01, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -10601,7 +10633,7 @@ This list contains 1363 plugins. Local continuous test runner with pytest and watchdog. :pypi:`pytest-watcher` - *last release*: Jun 24, 2023, + *last release*: Jan 28, 2024, *status*: 4 - Beta, *requires*: N/A @@ -10643,7 +10675,7 @@ This list contains 1363 plugins. Welian API Automation test framework pytest plugin :pypi:`pytest-when` - *last release*: Jan 25, 2024, + *last release*: Jan 30, 2024, *status*: N/A, *requires*: pytest>=7.3.1 @@ -10762,9 +10794,9 @@ This list contains 1363 plugins. Extended logging for test and decorators :pypi:`pytest-xlsx` - *last release*: Dec 28, 2023, + *last release*: Jan 28, 2024, *status*: N/A, - *requires*: pytest<8,>=7.4.0 + *requires*: pytest<8.1,>=7.4.0 pytest plugin for generating test cases by xlsx(excel) @@ -10916,7 +10948,7 @@ This list contains 1363 plugins. Pytest connector for Zebrunner reporting :pypi:`pytest-zeebe` - *last release*: Jan 16, 2024, + *last release*: Feb 01, 2024, *status*: N/A, *requires*: pytest (>=7.4.2,<8.0.0) From 7eef4619d591e0720d20a770dd0f837a389ef415 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 4 Feb 2024 11:24:47 +0100 Subject: [PATCH 0423/1271] [flake8-bugbear] Add checks from flake8 bugbear --- pyproject.toml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index ebfbe1a0320..0876b1f33a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -128,6 +128,7 @@ ignore = "W009" src = ["src"] line-length = 88 select = [ + "B", # bugbear "D", # pydocstyle "E", # pycodestyle "F", # pyflakes @@ -137,6 +138,20 @@ select = [ "W", # pycodestyle ] ignore = [ + # bugbear ignore + "B004", # Using `hasattr(x, "__call__")` to test if x is callable is unreliable. + "B005", # Using `.strip()` with multi-character strings is misleading + "B006", # Do not use mutable data structures for argument defaults + "B007", # Loop control variable `i` not used within loop body + "B009", # Do not call `getattr` with a constant attribute value + "B010", # [*] Do not call `setattr` with a constant attribute value. + "B011", # Do not `assert False` (`python -O` removes these calls) + "B015", # Pointless comparison. Did you mean to assign a value? + "B017", # `pytest.raises(Exception)` should be considered evil + "B018", # Found useless expression. + "B023", # Function definition does not bind loop variable `warning` + "B028", # No explicit `stacklevel` keyword argument found + "B904", # Within an `except` clause, raise exceptions with `raise ... from err` # pycodestyle ignore # pytest can do weird low-level things, and we usually know # what we're doing when we use type(..) is ... @@ -181,3 +196,4 @@ lines-after-imports = 2 [tool.ruff.lint.per-file-ignores] "src/_pytest/_version.py" = ["I001"] +"src/_pytest/_py/**/*.py" = ["B", "PYI"] From fcb818b73ca7bd0d005cec8f9b5aba47c4876de3 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 4 Feb 2024 11:13:47 +0100 Subject: [PATCH 0424/1271] [flake8-bugbear] Re-raise all exceptions with proper exception chaining --- pyproject.toml | 1 - scripts/prepare-release-pr.py | 2 +- src/_pytest/_io/terminalwriter.py | 8 ++++---- src/_pytest/config/__init__.py | 6 +++--- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0876b1f33a5..bda2091a383 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -151,7 +151,6 @@ ignore = [ "B018", # Found useless expression. "B023", # Function definition does not bind loop variable `warning` "B028", # No explicit `stacklevel` keyword argument found - "B904", # Within an `except` clause, raise exceptions with `raise ... from err` # pycodestyle ignore # pytest can do weird low-level things, and we usually know # what we're doing when we use type(..) is ... diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index d2216b6fca3..8a9f0aa0f3b 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -79,7 +79,7 @@ def prepare_release_pr( ) except InvalidFeatureRelease as e: print(f"{Fore.RED}{e}") - raise SystemExit(1) + raise SystemExit(1) from None print(f"Version: {Fore.CYAN}{version}") diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 16449b780c7..badbb7e4a5f 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -232,17 +232,17 @@ def _highlight( # which may lead to the previous color being propagated to the # start of the expression, so reset first. return "\x1b[0m" + highlighted - except pygments.util.ClassNotFound: + except pygments.util.ClassNotFound as e: raise UsageError( "PYTEST_THEME environment variable had an invalid value: '{}'. " "Only valid pygment styles are allowed.".format( os.getenv("PYTEST_THEME") ) - ) - except pygments.util.OptionError: + ) from e + except pygments.util.OptionError as e: raise UsageError( "PYTEST_THEME_MODE environment variable had an invalid value: '{}'. " "The only allowed values are 'dark' and 'light'.".format( os.getenv("PYTEST_THEME_MODE") ) - ) + ) from e diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 0d48ef48979..cada2aa0978 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1848,13 +1848,13 @@ def parse_warning_filter( try: action: "warnings._ActionKind" = warnings._getaction(action_) # type: ignore[attr-defined] except warnings._OptionError as e: - raise UsageError(error_template.format(error=str(e))) + raise UsageError(error_template.format(error=str(e))) from None try: category: Type[Warning] = _resolve_warning_category(category_) except Exception: exc_info = ExceptionInfo.from_current() exception_text = exc_info.getrepr(style="native") - raise UsageError(error_template.format(error=exception_text)) + raise UsageError(error_template.format(error=exception_text)) from None if message and escape: message = re.escape(message) if module and escape: @@ -1867,7 +1867,7 @@ def parse_warning_filter( except ValueError as e: raise UsageError( error_template.format(error=f"invalid lineno {lineno_!r}: {e}") - ) + ) from None else: lineno = 0 return action, message, category, module, lineno From 52fba25ff94f01e510ff5e7f52da5bb74a32669e Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 21:13:43 +0100 Subject: [PATCH 0425/1271] [flake8-bugbear] Fix all the useless expressions that are justified --- pyproject.toml | 1 - scripts/update-plugin-list.py | 2 +- src/_pytest/unittest.py | 4 ++-- testing/_py/test_local.py | 4 ++-- testing/code/test_excinfo.py | 12 ++++++------ testing/test_compat.py | 4 ++-- testing/test_legacypath.py | 2 +- testing/test_mark.py | 2 +- 8 files changed, 15 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bda2091a383..7adb204674a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,7 +148,6 @@ ignore = [ "B011", # Do not `assert False` (`python -O` removes these calls) "B015", # Pointless comparison. Did you mean to assign a value? "B017", # `pytest.raises(Exception)` should be considered evil - "B018", # Found useless expression. "B023", # Function definition does not bind loop variable `warning` "B028", # No explicit `stacklevel` keyword argument found # pycodestyle ignore diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 7c5ac927796..2c57414c028 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -208,7 +208,7 @@ def main() -> None: f.write(f"This list contains {len(plugins)} plugins.\n\n") f.write(".. only:: not latex\n\n") - wcwidth # reference library that must exist for tabulate to work + _ = wcwidth # reference library that must exist for tabulate to work plugin_table = tabulate.tabulate(plugins, headers="keys", tablefmt="rst") f.write(indent(plugin_table, " ")) f.write("\n\n") diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 29a53ad5ca1..eccd7eca6c1 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -209,8 +209,8 @@ def _addexcinfo(self, rawexcinfo: "_SysExcInfoType") -> None: ) # Invoke the attributes to trigger storing the traceback # trial causes some issue there. - excinfo.value - excinfo.traceback + _ = excinfo.value + _ = excinfo.traceback except TypeError: try: try: diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 11519c7c115..0c8575c4ec7 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -1241,9 +1241,9 @@ class TestWINLocalPath: def test_owner_group_not_implemented(self, path1): with pytest.raises(NotImplementedError): - path1.stat().owner + _ = path1.stat().owner with pytest.raises(NotImplementedError): - path1.stat().group + _ = path1.stat().group def test_chmod_simple_int(self, path1): mode = path1.stat().mode diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index a0ee28d48b4..cce23bf87d4 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -387,7 +387,7 @@ def test_excinfo_no_python_sourcecode(tmp_path: Path) -> None: excinfo = pytest.raises(ValueError, template.render, h=h) for item in excinfo.traceback: print(item) # XXX: for some reason jinja.Template.render is printed in full - item.source # shouldn't fail + _ = item.source # shouldn't fail if isinstance(item.path, Path) and item.path.name == "test.txt": assert str(item.source) == "{{ h()}}:" @@ -418,7 +418,7 @@ def test_codepath_Queue_example() -> None: def test_match_succeeds(): with pytest.raises(ZeroDivisionError) as excinfo: - 0 // 0 + _ = 0 // 0 excinfo.match(r".*zero.*") @@ -584,7 +584,7 @@ def test_repr_source_excinfo(self) -> None: try: def f(): - 1 / 0 + _ = 1 / 0 f() @@ -601,7 +601,7 @@ def f(): print(line) assert lines == [ " def f():", - "> 1 / 0", + "> _ = 1 / 0", "E ZeroDivisionError: division by zero", ] @@ -638,7 +638,7 @@ def test_repr_source_failing_fullsource(self, monkeypatch) -> None: pr = FormattedExcinfo() try: - 1 / 0 + _ = 1 / 0 except ZeroDivisionError: excinfo = ExceptionInfo.from_current() @@ -1582,7 +1582,7 @@ def __getattr__(self, attr): return getattr(self, "_" + attr) with pytest.raises(RuntimeError) as excinfo: - RecursionDepthError().trigger + _ = RecursionDepthError().trigger assert "maximum recursion" in str(excinfo.getrepr()) diff --git a/testing/test_compat.py b/testing/test_compat.py index 4ea90535489..9e66e9ecae8 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -170,9 +170,9 @@ def raise_fail_outcome(self): def test_helper_failures() -> None: helper = ErrorsHelper() with pytest.raises(Exception): - helper.raise_exception + _ = helper.raise_exception with pytest.raises(OutcomeException): - helper.raise_fail_outcome + _ = helper.raise_fail_outcome def test_safe_getattr() -> None: diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index 6b933a6d9b0..850f14c58a0 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -108,7 +108,7 @@ def test_session_scoped_unavailable_attributes(self, session_request): AttributeError, match="path not available in session-scoped context", ): - session_request.fspath + _ = session_request.fspath @pytest.mark.parametrize("config_type", ["ini", "pyproject"]) diff --git a/testing/test_mark.py b/testing/test_mark.py index 4604baafdfa..6e183a17887 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -42,7 +42,7 @@ class SomeClass: def test_pytest_mark_name_starts_with_underscore(self) -> None: mark = MarkGenerator(_ispytest=True) with pytest.raises(AttributeError): - mark._some_name + _ = mark._some_name def test_marked_class_run_twice(pytester: Pytester) -> None: From e7bab63537ab66f2f750e72627c8fef3ccfddc9f Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 21:15:22 +0100 Subject: [PATCH 0426/1271] [flake8-bugbear] noqa all the useless comparison that are justified --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7adb204674a..062970ca774 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -146,7 +146,6 @@ ignore = [ "B009", # Do not call `getattr` with a constant attribute value "B010", # [*] Do not call `setattr` with a constant attribute value. "B011", # Do not `assert False` (`python -O` removes these calls) - "B015", # Pointless comparison. Did you mean to assign a value? "B017", # `pytest.raises(Exception)` should be considered evil "B023", # Function definition does not bind loop variable `warning` "B028", # No explicit `stacklevel` keyword argument found @@ -193,5 +192,6 @@ known-local-folder = ["pytest", "_pytest"] lines-after-imports = 2 [tool.ruff.lint.per-file-ignores] -"src/_pytest/_version.py" = ["I001"] "src/_pytest/_py/**/*.py" = ["B", "PYI"] +"src/_pytest/_version.py" = ["I001"] +"testing/python/approx.py" = ["B015"] From b62d4b352748729c9e36f450226d191335177730 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 21:21:39 +0100 Subject: [PATCH 0427/1271] [flake8-bugbear] Remove misleading multiple characters in lstrip See https://pylint.readthedocs.io/en/stable/user_guide/messages/error/bad-str-strip-call.html --- pyproject.toml | 1 - testing/test_warnings.py | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 062970ca774..89aab6a077e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -140,7 +140,6 @@ select = [ ignore = [ # bugbear ignore "B004", # Using `hasattr(x, "__call__")` to test if x is callable is unreliable. - "B005", # Using `.strip()` with multi-character strings is misleading "B006", # Do not use mutable data structures for argument defaults "B007", # Loop control variable `i` not used within loop body "B009", # Do not call `getattr` with a constant attribute value diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 5a8a98015a2..5b2f2713944 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -18,8 +18,7 @@ def pyfile_with_warnings(pytester: Pytester, request: FixtureRequest) -> str: """Create a test file which calls a function in a module which generates warnings.""" pytester.syspathinsert() - test_name = request.function.__name__ - module_name = test_name.lstrip("test_") + "_module" + module_name = request.function.__name__[len("test_") :] + "_module" test_file = pytester.makepyfile( f""" import {module_name} From 41ff3584d78091bf2753bb084b1f5ec8a97c3f51 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 4 Feb 2024 11:39:27 +0100 Subject: [PATCH 0428/1271] [flake8-bugbear] Fixes a B017 we can actually fix and noqa the two others --- pyproject.toml | 1 - testing/python/raises.py | 2 +- testing/test_compat.py | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 89aab6a077e..cf6e5adecf1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -145,7 +145,6 @@ ignore = [ "B009", # Do not call `getattr` with a constant attribute value "B010", # [*] Do not call `setattr` with a constant attribute value. "B011", # Do not `assert False` (`python -O` removes these calls) - "B017", # `pytest.raises(Exception)` should be considered evil "B023", # Function definition does not bind loop variable `warning` "B028", # No explicit `stacklevel` keyword argument found # pycodestyle ignore diff --git a/testing/python/raises.py b/testing/python/raises.py index ef6607d962a..929865e31a0 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -280,7 +280,7 @@ def __class__(self): def test_raises_context_manager_with_kwargs(self): with pytest.raises(TypeError) as excinfo: - with pytest.raises(Exception, foo="bar"): # type: ignore[call-overload] + with pytest.raises(OSError, foo="bar"): # type: ignore[call-overload] pass assert "Unexpected keyword arguments" in str(excinfo.value) diff --git a/testing/test_compat.py b/testing/test_compat.py index 9e66e9ecae8..c898af7c531 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -169,7 +169,7 @@ def raise_fail_outcome(self): def test_helper_failures() -> None: helper = ErrorsHelper() - with pytest.raises(Exception): + with pytest.raises(Exception): # noqa: B017 _ = helper.raise_exception with pytest.raises(OutcomeException): _ = helper.raise_fail_outcome @@ -179,7 +179,7 @@ def test_safe_getattr() -> None: helper = ErrorsHelper() assert safe_getattr(helper, "raise_exception", "default") == "default" assert safe_getattr(helper, "raise_fail_outcome", "default") == "default" - with pytest.raises(BaseException): + with pytest.raises(BaseException): # noqa: B017 assert safe_getattr(helper, "raise_baseexception", "default") From 4eb246d4e15de8e6d089d35c30d1102fb4f46032 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 21:26:49 +0100 Subject: [PATCH 0429/1271] [flake8-bugbear] noqa B023 not bound by design --- pyproject.toml | 1 - testing/test_recwarn.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cf6e5adecf1..8605e5bae56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -145,7 +145,6 @@ ignore = [ "B009", # Do not call `getattr` with a constant attribute value "B010", # [*] Do not call `setattr` with a constant attribute value. "B011", # Do not `assert False` (`python -O` removes these calls) - "B023", # Function definition does not bind loop variable `warning` "B028", # No explicit `stacklevel` keyword argument found # pycodestyle ignore # pytest can do weird low-level things, and we usually know diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index e2b2eb8a2d5..5045c781e1f 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -228,7 +228,7 @@ def test_deprecated_call_specificity(self) -> None: for warning in other_warnings: def f(): - warnings.warn(warning("hi")) + warnings.warn(warning("hi")) # noqa: B023 with pytest.warns(warning): with pytest.raises(pytest.fail.Exception): From e193a263c70549815377158dd0ddc9e325f6dfcf Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 2 Feb 2024 21:36:20 +0100 Subject: [PATCH 0430/1271] [flake8-pyi] Add checks for flake8-pyi and fix existing --- pyproject.toml | 1 + src/_pytest/capture.py | 3 ++- src/_pytest/compat.py | 5 ----- testing/test_assertion.py | 15 +++++++++++---- testing/test_terminal.py | 6 ++++-- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8605e5bae56..634b08cbd4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -133,6 +133,7 @@ select = [ "E", # pycodestyle "F", # pyflakes "I", # isort + "PYI", # flake8-pyi "UP", # pyupgrade "RUF", # ruff "W", # pycodestyle diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index b9e0950285b..dce431c3db4 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -598,7 +598,8 @@ class CaptureResult(NamedTuple, Generic[AnyStr]): else: class CaptureResult( - collections.namedtuple("CaptureResult", ["out", "err"]), Generic[AnyStr] + collections.namedtuple("CaptureResult", ["out", "err"]), # noqa: PYI024 + Generic[AnyStr], ): """The result of :method:`caplog.readouterr() `.""" diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 14717e94147..400b3864296 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -15,11 +15,6 @@ from typing import Callable from typing import Final from typing import NoReturn -from typing import TypeVar - - -_T = TypeVar("_T") -_S = TypeVar("_S") # fmt: off diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 2fa6fbe3793..2d92128fb82 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1,10 +1,10 @@ # mypy: allow-untyped-defs -import collections import sys import textwrap from typing import Any from typing import List from typing import MutableSequence +from typing import NamedTuple from typing import Optional import attr @@ -1179,7 +1179,9 @@ def __eq__(self, other): # pragma: no cover class TestAssert_reprcompare_namedtuple: def test_namedtuple(self) -> None: - NT = collections.namedtuple("NT", ["a", "b"]) + class NT(NamedTuple): + a: Any + b: Any left = NT(1, "b") right = NT(1, "c") @@ -1200,8 +1202,13 @@ def test_namedtuple(self) -> None: ] def test_comparing_two_different_namedtuple(self) -> None: - NT1 = collections.namedtuple("NT1", ["a", "b"]) - NT2 = collections.namedtuple("NT2", ["a", "b"]) + class NT1(NamedTuple): + a: Any + b: Any + + class NT2(NamedTuple): + a: Any + b: Any left = NT1(1, "b") right = NT2(2, "b") diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 22f041cedc8..bc457c39800 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1,6 +1,5 @@ # mypy: allow-untyped-defs """Terminal reporting of the full testing process.""" -import collections from io import StringIO import os from pathlib import Path @@ -10,6 +9,7 @@ from typing import cast from typing import Dict from typing import List +from typing import NamedTuple from typing import Tuple import pluggy @@ -34,7 +34,9 @@ import pytest -DistInfo = collections.namedtuple("DistInfo", ["project_name", "version"]) +class DistInfo(NamedTuple): + project_name: str + version: int TRANS_FNMATCH = str.maketrans({"[": "[[]", "]": "[]]"}) From 3101c026b96e15f155aa95e3e3321dbee586643c Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 4 Feb 2024 19:39:21 +0100 Subject: [PATCH 0431/1271] [flake8-bugbear] Remove hidden global state to import only once --- pyproject.toml | 1 - src/_pytest/unittest.py | 19 ++++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 634b08cbd4c..e3d64805d6f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -141,7 +141,6 @@ select = [ ignore = [ # bugbear ignore "B004", # Using `hasattr(x, "__call__")` to test if x is callable is unreliable. - "B006", # Do not use mutable data structures for argument defaults "B007", # Loop control variable `i` not used within loop body "B009", # Do not call `getattr` with a constant attribute value "B010", # [*] Do not call `setattr` with a constant attribute value. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index eccd7eca6c1..6598bdbc542 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -361,14 +361,21 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None: # Twisted trial support. +classImplements_has_run = False @hookimpl(wrapper=True) def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: if isinstance(item, TestCaseFunction) and "twisted.trial.unittest" in sys.modules: ut: Any = sys.modules["twisted.python.failure"] + global classImplements_has_run Failure__init__ = ut.Failure.__init__ - check_testcase_implements_trial_reporter() + if not classImplements_has_run: + from twisted.trial.itrial import IReporter + from zope.interface import classImplements + + classImplements(TestCaseFunction, IReporter) + classImplements_has_run = True def excstore( self, exc_value=None, exc_type=None, exc_tb=None, captureVars=None @@ -396,16 +403,6 @@ def excstore( return res -def check_testcase_implements_trial_reporter(done: List[int] = []) -> None: - if done: - return - from twisted.trial.itrial import IReporter - from zope.interface import classImplements - - classImplements(TestCaseFunction, IReporter) - done.append(1) - - def _is_skipped(obj) -> bool: """Return True if the given object has been marked with @unittest.skip.""" return bool(getattr(obj, "__unittest_skip__", False)) From 2e50788b6d749d3c30b3f32e828d7e2fd909117e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 03:39:23 +0000 Subject: [PATCH 0432/1271] build(deps): Bump pytest-django in /testing/plugins_integration Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.7.0 to 4.8.0. - [Release notes](https://github.com/pytest-dev/pytest-django/releases) - [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.7.0...v4.8.0) --- updated-dependencies: - dependency-name: pytest-django dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 0839b18c9fa..d43027d88ec 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -5,7 +5,7 @@ pytest-asyncio==0.23.3 # https://github.com/pytest-dev/pytest/pull/11785 # pytest-bdd==7.0.1 pytest-cov==4.1.0 -pytest-django==4.7.0 +pytest-django==4.8.0 pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.12.0 From 2d4e27daf2efa41328c51c833fa8f8b6e75b4b96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 03:39:30 +0000 Subject: [PATCH 0433/1271] build(deps): Bump pytest-sugar in /testing/plugins_integration Bumps [pytest-sugar](https://github.com/Teemu/pytest-sugar) from 0.9.7 to 1.0.0. - [Release notes](https://github.com/Teemu/pytest-sugar/releases) - [Changelog](https://github.com/Teemu/pytest-sugar/blob/main/CHANGES.rst) - [Commits](https://github.com/Teemu/pytest-sugar/compare/v0.9.7...v1.0.0) --- updated-dependencies: - dependency-name: pytest-sugar dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 0839b18c9fa..8f105fda6aa 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -10,7 +10,7 @@ pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.12.0 pytest-rerunfailures==13.0 -pytest-sugar==0.9.7 +pytest-sugar==1.0.0 pytest-trio==0.7.0 pytest-twisted==1.14.0 twisted==23.10.0 From 79de84941a50eda7a6f0511cb0ce7a63776e4563 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 5 Feb 2024 11:53:21 +0200 Subject: [PATCH 0434/1271] setup.cfg: move mypy configuration from setup.cfg to pyproject.toml TOML is a nicer format than the INI format setup.cfg uses. --- pyproject.toml | 14 ++++++++++++++ setup.cfg | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e3d64805d6f..15a855ce6f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -192,3 +192,17 @@ lines-after-imports = 2 "src/_pytest/_py/**/*.py" = ["B", "PYI"] "src/_pytest/_version.py" = ["I001"] "testing/python/approx.py" = ["B015"] + +[tool.mypy] +mypy_path = ["src"] +check_untyped_defs = true +disallow_any_generics = true +disallow_untyped_defs = true +ignore_missing_imports = true +show_error_codes = true +strict_equality = true +warn_redundant_casts = true +warn_return_any = true +warn_unreachable = true +warn_unused_configs = true +no_implicit_reexport = true diff --git a/setup.cfg b/setup.cfg index eebce8c7cfd..a9943cef1aa 100644 --- a/setup.cfg +++ b/setup.cfg @@ -89,17 +89,3 @@ ignore = [devpi:upload] formats = sdist.tgz,bdist_wheel - -[mypy] -mypy_path = src -check_untyped_defs = True -disallow_any_generics = True -disallow_untyped_defs = True -ignore_missing_imports = True -show_error_codes = True -strict_equality = True -warn_redundant_casts = True -warn_return_any = True -warn_unreachable = True -warn_unused_configs = True -no_implicit_reexport = True From 2fc7926bae8774f1a929752525b6ec1b95ea15e5 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 5 Feb 2024 11:55:38 +0200 Subject: [PATCH 0435/1271] setup.cfg: remove `[build_sphinx]` section Legacy thing that is no longer needed. --- setup.cfg | 5 ----- 1 file changed, 5 deletions(-) diff --git a/setup.cfg b/setup.cfg index a9943cef1aa..6ceb968f7c6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -78,11 +78,6 @@ testing = _pytest = py.typed pytest = py.typed -[build_sphinx] -source_dir = doc/en/ -build_dir = doc/build -all_files = 1 - [check-manifest] ignore = src/_pytest/_version.py From 5c67cb2cf57e50680ebdc5591b38dc2ab23834e4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 5 Feb 2024 11:58:56 +0200 Subject: [PATCH 0436/1271] setup.cfg: remove `[check-manifest]` section Not used since 731c35fcabef1e145e8049e1bf565a7c18ca328d. --- setup.cfg | 4 ---- 1 file changed, 4 deletions(-) diff --git a/setup.cfg b/setup.cfg index 6ceb968f7c6..df8e177cabb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -78,9 +78,5 @@ testing = _pytest = py.typed pytest = py.typed -[check-manifest] -ignore = - src/_pytest/_version.py - [devpi:upload] formats = sdist.tgz,bdist_wheel From cd9b2410472076652499512567ea40815f67654a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 5 Feb 2024 12:08:21 +0200 Subject: [PATCH 0437/1271] setup.cfg: remove `[devpi:upload]` section Not needed since bfe2cbe875f81bd8e333796d2594a9cd36806374. --- setup.cfg | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index df8e177cabb..ebc95634749 100644 --- a/setup.cfg +++ b/setup.cfg @@ -77,6 +77,3 @@ testing = [options.package_data] _pytest = py.typed pytest = py.typed - -[devpi:upload] -formats = sdist.tgz,bdist_wheel From ccbae95ad4fd69b0b006272aa3cc65090bdb674d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 5 Feb 2024 12:16:52 +0200 Subject: [PATCH 0438/1271] setup.cfg: remove redundant `packages`/`py_modules` The `package_dir` already achieves this. --- setup.cfg | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/setup.cfg b/setup.cfg index ebc95634749..354f9418c2b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -33,16 +33,6 @@ project_urls = Tracker=https://github.com/pytest-dev/pytest/issues [options] -packages = - _pytest - _pytest._code - _pytest._io - _pytest._py - _pytest.assertion - _pytest.config - _pytest.mark - pytest -py_modules = py install_requires = iniconfig packaging From 90634a6060a21e8e8209ed96dc032e4a4258eabe Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 5 Feb 2024 12:20:37 +0200 Subject: [PATCH 0439/1271] setup.cfg: remove `zip_safe` The setuptools docs say it's obsolete and no longer needed: https://setuptools.pypa.io/en/latest/deprecated/zip_safe.html#understanding-the-zip-safe-flag --- setup.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 354f9418c2b..a1a47e1baac 100644 --- a/setup.cfg +++ b/setup.cfg @@ -46,7 +46,6 @@ package_dir = setup_requires = setuptools setuptools-scm>=6.0 -zip_safe = no [options.entry_points] console_scripts = From a1d99e4bdd6effa2f2c9a50a2f4712e7fe1823d2 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 5 Feb 2024 13:56:07 +0100 Subject: [PATCH 0440/1271] [pyproject.toml] Move information from setup.cfg to pyproject.toml --- .pre-commit-config.yaml | 5 ----- pyproject.toml | 50 +++++++++++++++++++++++++++++++++++++++++ setup.cfg | 31 ------------------------- 3 files changed, 50 insertions(+), 36 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 032fe8c4d8b..ca3b41d58d2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,11 +21,6 @@ repos: hooks: - id: blacken-docs additional_dependencies: [black==24.1.1] -- repo: https://github.com/asottile/setup-cfg-fmt - rev: v2.5.0 - hooks: - - id: setup-cfg-fmt - args: ["--max-py-version=3.12", "--include-version-classifiers"] - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: diff --git a/pyproject.toml b/pyproject.toml index 15a855ce6f9..6e3d3612a0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,53 @@ +[project] + +name = "pytest" +dynamic = [ + "version", + "optional-dependencies", + "dependencies", + "scripts", + "requires-python" +] +description = "pytest: simple powerful testing with Python" +authors = [ + {name = "Holger Krekel"}, + {name = "Bruno Oliveira"}, + {name = "Ronny Pfannschmidt"}, + {name = "Floris Bruynooghe"}, + {name = "Brianna Laugher"}, + {name = "Florian Bruhin"}, + {name = "Others (See AUTHORS)"}, +] +readme = "README.rst" +license = {text = "MIT"} +keywords = ["test", "unittest"] +classifiers = [ + "Development Status :: 6 - Mature", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows", + "Operating System :: Unix", + "Operating System :: POSIX", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Testing", + "Topic :: Utilities", +] + +[project.urls] +Homepage = "https://docs.pytest.org/en/latest/" +Changelog = "https://docs.pytest.org/en/stable/changelog.html" +Twitter = "https://twitter.com/pytestdotorg" +Source = "https://github.com/pytest-dev/pytest" +Tracker = "https://github.com/pytest-dev/pytest/issues" + [build-system] requires = [ "setuptools>=45.0", diff --git a/setup.cfg b/setup.cfg index a1a47e1baac..bf981840bef 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,36 +1,5 @@ [metadata] -name = pytest -description = pytest: simple powerful testing with Python -long_description = file: README.rst -long_description_content_type = text/x-rst -url = https://docs.pytest.org/en/latest/ -author = Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin and others -license = MIT -license_files = LICENSE platforms = unix, linux, osx, cygwin, win32 -classifiers = - Development Status :: 6 - Mature - Intended Audience :: Developers - License :: OSI Approved :: MIT License - Operating System :: MacOS :: MacOS X - Operating System :: Microsoft :: Windows - Operating System :: POSIX - Programming Language :: Python :: 3 - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - Topic :: Software Development :: Libraries - Topic :: Software Development :: Testing - Topic :: Utilities -keywords = test, unittest -project_urls = - Changelog=https://docs.pytest.org/en/stable/changelog.html - Twitter=https://twitter.com/pytestdotorg - Source=https://github.com/pytest-dev/pytest - Tracker=https://github.com/pytest-dev/pytest/issues [options] install_requires = From c3583dee0b274af84b56e70f270d3a42d0ce2463 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 5 Feb 2024 14:02:06 +0100 Subject: [PATCH 0441/1271] [pyproject.toml] Translate 'metadata:platforms' to pyproject.toml --- setup.cfg | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index bf981840bef..8707c6180bb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,3 @@ -[metadata] -platforms = unix, linux, osx, cygwin, win32 - [options] install_requires = iniconfig From 411c2cbf9d8f1e18aa4b7e53ff3d60790beacf1d Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 5 Feb 2024 14:20:10 +0100 Subject: [PATCH 0442/1271] [pyproject.toml] Translate dynamic option to pyproject.toml --- pyproject.toml | 35 +++++++++++++++++++++++++++-------- setup.cfg | 24 ------------------------ 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6e3d3612a0a..38a9471e069 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,13 +1,6 @@ [project] - name = "pytest" -dynamic = [ - "version", - "optional-dependencies", - "dependencies", - "scripts", - "requires-python" -] +dynamic = ["version"] description = "pytest: simple powerful testing with Python" authors = [ {name = "Holger Krekel"}, @@ -41,6 +34,32 @@ classifiers = [ "Topic :: Utilities", ] +dependencies = [ + "colorama;sys_platform=='win32'", + "exceptiongroup>=1.0.0rc8;python_version<'3.11'", + "iniconfig", + "packaging", + "pluggy>=1.4.0,<2.0", + "tomli>=1.0.0;python_version<'3.11'", +] +requires-python = ">=3.8" + +[project.optional-dependencies] +testing = [ + "argcomplete", + "attrs>=19.2.0", + "hypothesis>=3.56", + "mock", + "pygments>=2.7.2", + "requests", + "setuptools", + "xmlschema", +] + +[project.scripts] +"py.test" = "pytest:console_main" +pytest = "pytest:console_main" + [project.urls] Homepage = "https://docs.pytest.org/en/latest/" Changelog = "https://docs.pytest.org/en/stable/changelog.html" diff --git a/setup.cfg b/setup.cfg index 8707c6180bb..364db8d7074 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,34 +1,10 @@ [options] -install_requires = - iniconfig - packaging - pluggy>=1.4.0,<2.0 - colorama;sys_platform=="win32" - exceptiongroup>=1.0.0rc8;python_version<"3.11" - tomli>=1.0.0;python_version<"3.11" -python_requires = >=3.8 package_dir = =src setup_requires = setuptools setuptools-scm>=6.0 -[options.entry_points] -console_scripts = - pytest=pytest:console_main - py.test=pytest:console_main - -[options.extras_require] -testing = - argcomplete - attrs>=19.2.0 - hypothesis>=3.56 - mock - pygments>=2.7.2 - requests - setuptools - xmlschema - [options.package_data] _pytest = py.typed pytest = py.typed From dab1583ce1ad9c08b64fefc632c9e3d900d4c3dd Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 5 Feb 2024 15:27:53 +0100 Subject: [PATCH 0443/1271] [pyproject.toml] Remove setup_requires / package_dir in setup.cfg already exists --- setup.cfg | 7 ------- 1 file changed, 7 deletions(-) diff --git a/setup.cfg b/setup.cfg index 364db8d7074..3e72c56d733 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,10 +1,3 @@ -[options] -package_dir = - =src -setup_requires = - setuptools - setuptools-scm>=6.0 - [options.package_data] _pytest = py.typed pytest = py.typed From c76ea72331f6c45e248b92be8233188ecd2347b7 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 5 Feb 2024 15:33:27 +0100 Subject: [PATCH 0444/1271] [pyproject.toml] Moving 'package_data' (py.typed) from setup.cfg --- pyproject.toml | 4 ++++ setup.cfg | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 setup.cfg diff --git a/pyproject.toml b/pyproject.toml index 38a9471e069..427de749a6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,6 +74,10 @@ requires = [ ] build-backend = "setuptools.build_meta" +[tool.setuptools.package-data] +"_pytest" = ["py.typed"] +"pytest" = ["py.typed"] + [tool.setuptools_scm] write_to = "src/_pytest/_version.py" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 3e72c56d733..00000000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[options.package_data] -_pytest = py.typed -pytest = py.typed From 835e8032f4b856c9e6d606dc909bde45281bdfb7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 20:29:38 +0000 Subject: [PATCH 0445/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.1.15 → v0.2.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.15...v0.2.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 032fe8c4d8b..b5f68ecfce5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.1.15" + rev: "v0.2.0" hooks: - id: ruff args: ["--fix"] From 757778f5f611a06ae5a8ac48c5c950cb1f8fceca Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 5 Feb 2024 20:20:31 +0100 Subject: [PATCH 0446/1271] [pyproject-fmt] Add pre-commit hook and autofix existing --- .pre-commit-config.yaml | 6 ++ pyproject.toml | 206 ++++++++++++++++++++-------------------- 2 files changed, 110 insertions(+), 102 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5c1ebb3c22f..22a9ec95f93 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,6 +42,12 @@ repos: # for mypy running on python>=3.11 since exceptiongroup is only a dependency # on <3.11 - exceptiongroup>=1.0.0rc8 +- repo: https://github.com/tox-dev/pyproject-fmt + rev: "1.7.0" + hooks: + - id: pyproject-fmt + # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version + additional_dependencies: ["tox>=4.9"] - repo: local hooks: - id: rst diff --git a/pyproject.toml b/pyproject.toml index 427de749a6a..98fa51c448e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,12 @@ [project] name = "pytest" -dynamic = ["version"] description = "pytest: simple powerful testing with Python" +readme = "README.rst" +keywords = [ + "test", + "unittest", +] +license = {text = "MIT"} authors = [ {name = "Holger Krekel"}, {name = "Bruno Oliveira"}, @@ -11,18 +16,15 @@ authors = [ {name = "Florian Bruhin"}, {name = "Others (See AUTHORS)"}, ] -readme = "README.rst" -license = {text = "MIT"} -keywords = ["test", "unittest"] +requires-python = ">=3.8" classifiers = [ "Development Status :: 6 - Mature", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: MacOS", "Operating System :: Microsoft :: Windows", - "Operating System :: Unix", "Operating System :: POSIX", - "Programming Language :: Python :: 3", + "Operating System :: Unix", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", @@ -33,21 +35,21 @@ classifiers = [ "Topic :: Software Development :: Testing", "Topic :: Utilities", ] - +dynamic = [ + "version", +] dependencies = [ - "colorama;sys_platform=='win32'", - "exceptiongroup>=1.0.0rc8;python_version<'3.11'", + 'colorama; sys_platform == "win32"', + 'exceptiongroup>=1.0.0rc8; python_version < "3.11"', "iniconfig", "packaging", - "pluggy>=1.4.0,<2.0", - "tomli>=1.0.0;python_version<'3.11'", + "pluggy<2.0,>=1.4", + 'tomli>=1; python_version < "3.11"', ] -requires-python = ">=3.8" - [project.optional-dependencies] testing = [ "argcomplete", - "attrs>=19.2.0", + "attrs>=19.2", "hypothesis>=3.56", "mock", "pygments>=2.7.2", @@ -55,24 +57,22 @@ testing = [ "setuptools", "xmlschema", ] - -[project.scripts] -"py.test" = "pytest:console_main" -pytest = "pytest:console_main" - [project.urls] -Homepage = "https://docs.pytest.org/en/latest/" Changelog = "https://docs.pytest.org/en/stable/changelog.html" -Twitter = "https://twitter.com/pytestdotorg" +Homepage = "https://docs.pytest.org/en/latest/" Source = "https://github.com/pytest-dev/pytest" Tracker = "https://github.com/pytest-dev/pytest/issues" +Twitter = "https://twitter.com/pytestdotorg" +[project.scripts] +"py.test" = "pytest:console_main" +pytest = "pytest:console_main" [build-system] +build-backend = "setuptools.build_meta" requires = [ - "setuptools>=45.0", - "setuptools-scm[toml]>=6.2.3", + "setuptools>=45", + "setuptools-scm[toml]>=6.2.3", ] -build-backend = "setuptools.build_meta" [tool.setuptools.package-data] "_pytest" = ["py.typed"] @@ -81,6 +81,86 @@ build-backend = "setuptools.build_meta" [tool.setuptools_scm] write_to = "src/_pytest/_version.py" +[tool.black] +target-version = ['py38'] + +[tool.ruff] +src = ["src"] +line-length = 88 +select = [ + "B", # bugbear + "D", # pydocstyle + "E", # pycodestyle + "F", # pyflakes + "I", # isort + "PYI", # flake8-pyi + "UP", # pyupgrade + "RUF", # ruff + "W", # pycodestyle +] +ignore = [ + # bugbear ignore + "B004", # Using `hasattr(x, "__call__")` to test if x is callable is unreliable. + "B007", # Loop control variable `i` not used within loop body + "B009", # Do not call `getattr` with a constant attribute value + "B010", # [*] Do not call `setattr` with a constant attribute value. + "B011", # Do not `assert False` (`python -O` removes these calls) + "B028", # No explicit `stacklevel` keyword argument found + # pycodestyle ignore + # pytest can do weird low-level things, and we usually know + # what we're doing when we use type(..) is ... + "E721", # Do not compare types, use `isinstance()` + # pydocstyle ignore + "D100", # Missing docstring in public module + "D101", # Missing docstring in public class + "D102", # Missing docstring in public method + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "D105", # Missing docstring in magic method + "D106", # Missing docstring in public nested class + "D107", # Missing docstring in `__init__` + "D209", # [*] Multi-line docstring closing quotes should be on a separate line + "D205", # 1 blank line required between summary line and description + "D400", # First line should end with a period + "D401", # First line of docstring should be in imperative mood + "D402", # First line should not be the function's signature + "D404", # First word of the docstring should not be "This" + "D415", # First line should end with a period, question mark, or exclamation point + # ruff ignore + "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` +] + +[tool.ruff.format] +docstring-code-format = true + +[tool.ruff.lint.pycodestyle] +# In order to be able to format for 88 char in ruff format +max-line-length = 120 + +[tool.ruff.lint.pydocstyle] +convention = "pep257" + +[tool.ruff.lint.isort] +force-single-line = true +combine-as-imports = true +force-sort-within-sections = true +order-by-type = false +known-local-folder = ["pytest", "_pytest"] +lines-after-imports = 2 + +[tool.ruff.lint.per-file-ignores] +"src/_pytest/_py/**/*.py" = ["B", "PYI"] +"src/_pytest/_version.py" = ["I001"] +"testing/python/approx.py" = ["B015"] + +[tool.check-wheel-contents] +# check-wheel-contents is executed by the build-and-inspect-python-package action. +# W009: Wheel contains multiple toplevel library entries +ignore = "W009" + +[tool.pyproject-fmt] +indent = 4 + [tool.pytest.ini_options] minversion = "2.0" addopts = "-rfEX -p pytester --strict-markers" @@ -140,7 +220,6 @@ markers = [ "uses_pexpect", ] - [tool.towncrier] package = "pytest" package_dir = "src" @@ -189,83 +268,6 @@ template = "changelog/_template.rst" name = "Trivial/Internal Changes" showcontent = true -[tool.black] -target-version = ['py38'] - -# check-wheel-contents is executed by the build-and-inspect-python-package action. -[tool.check-wheel-contents] -# W009: Wheel contains multiple toplevel library entries -ignore = "W009" - -[tool.ruff] -src = ["src"] -line-length = 88 -select = [ - "B", # bugbear - "D", # pydocstyle - "E", # pycodestyle - "F", # pyflakes - "I", # isort - "PYI", # flake8-pyi - "UP", # pyupgrade - "RUF", # ruff - "W", # pycodestyle -] -ignore = [ - # bugbear ignore - "B004", # Using `hasattr(x, "__call__")` to test if x is callable is unreliable. - "B007", # Loop control variable `i` not used within loop body - "B009", # Do not call `getattr` with a constant attribute value - "B010", # [*] Do not call `setattr` with a constant attribute value. - "B011", # Do not `assert False` (`python -O` removes these calls) - "B028", # No explicit `stacklevel` keyword argument found - # pycodestyle ignore - # pytest can do weird low-level things, and we usually know - # what we're doing when we use type(..) is ... - "E721", # Do not compare types, use `isinstance()` - # pydocstyle ignore - "D100", # Missing docstring in public module - "D101", # Missing docstring in public class - "D102", # Missing docstring in public method - "D103", # Missing docstring in public function - "D104", # Missing docstring in public package - "D105", # Missing docstring in magic method - "D106", # Missing docstring in public nested class - "D107", # Missing docstring in `__init__` - "D209", # [*] Multi-line docstring closing quotes should be on a separate line - "D205", # 1 blank line required between summary line and description - "D400", # First line should end with a period - "D401", # First line of docstring should be in imperative mood - "D402", # First line should not be the function's signature - "D404", # First word of the docstring should not be "This" - "D415", # First line should end with a period, question mark, or exclamation point - # ruff ignore - "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` -] - -[tool.ruff.format] -docstring-code-format = true - -[tool.ruff.lint.pycodestyle] -# In order to be able to format for 88 char in ruff format -max-line-length = 120 - -[tool.ruff.lint.pydocstyle] -convention = "pep257" - -[tool.ruff.lint.isort] -force-single-line = true -combine-as-imports = true -force-sort-within-sections = true -order-by-type = false -known-local-folder = ["pytest", "_pytest"] -lines-after-imports = 2 - -[tool.ruff.lint.per-file-ignores] -"src/_pytest/_py/**/*.py" = ["B", "PYI"] -"src/_pytest/_version.py" = ["I001"] -"testing/python/approx.py" = ["B015"] - [tool.mypy] mypy_path = ["src"] check_untyped_defs = true From d1095426c163c8a005d0c1c81612c4cedfe698b5 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 6 Feb 2024 14:38:52 +0100 Subject: [PATCH 0447/1271] Update setuptools version to the one that support pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 98fa51c448e..efbb9b6c2db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,7 +70,7 @@ pytest = "pytest:console_main" [build-system] build-backend = "setuptools.build_meta" requires = [ - "setuptools>=45", + "setuptools>=61", "setuptools-scm[toml]>=6.2.3", ] From 6e5008f19f3c8fffa1ea2b980d4214d9c338b481 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 6 Feb 2024 23:40:13 +0200 Subject: [PATCH 0448/1271] doctest: don't open code the module import Currently, `DoctestModule` does `import_path` on its own. This changes it to use `importtestmodule` as `Module` does. The behavioral changes are: - Much better error messages on import errors. - Handles a few more error cases (see `importtestmodule`). This technically expands the cover of `--doctest-ignore-import-errors` but I think it makes sense. - Considers `pytest_plugins` in the module. - Populates `self.obj` as properly (without double-imports) as is expected from a `PyCollector`. This is also needed for the next commit. --- src/_pytest/doctest.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index fdf84d3002c..e0fb7c1618d 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -40,7 +40,6 @@ from _pytest.outcomes import OutcomeException from _pytest.outcomes import skip from _pytest.pathlib import fnmatch_ex -from _pytest.pathlib import import_path from _pytest.python import Module from _pytest.python_api import approx from _pytest.warning_types import PytestWarning @@ -107,7 +106,7 @@ def pytest_addoption(parser: Parser) -> None: "--doctest-ignore-import-errors", action="store_true", default=False, - help="Ignore doctest ImportErrors", + help="Ignore doctest collection errors", dest="doctest_ignore_import_errors", ) group.addoption( @@ -561,12 +560,8 @@ def _from_module(self, module, object): pass try: - module = import_path( - self.path, - root=self.config.rootpath, - mode=self.config.getoption("importmode"), - ) - except ImportError: + module = self.obj + except Collector.CollectError: if self.config.getvalue("doctest_ignore_import_errors"): skip("unable to import module %r" % self.path) else: From 4c894f20a1df9229b871191972b48cac3d8a41d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Feb 2024 15:37:56 -0300 Subject: [PATCH 0449/1271] build(deps): Bump django in /testing/plugins_integration (#11946) Bumps [django](https://github.com/django/django) from 5.0 to 5.0.2. - [Commits](https://github.com/django/django/compare/5.0...5.0.2) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 9bb88556047..d7b06625164 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.2.0 -django==5.0 +django==5.0.2 pytest-asyncio==0.23.3 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 From 9cd14b4ffb1d96342a2e9d1f5cb92eab53bb5079 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 6 Feb 2024 23:09:00 +0200 Subject: [PATCH 0450/1271] doctest: fix autouse fixtures possibly not getting picked up Fix #11929. Figured out what's going on. We have the following collection tree: ``` ``` And the `test_main.py` contains an autouse fixture (`fake_game_ui`) that `doctest_main` needs in order to run properly. The fixture doesn't run! It doesn't run because nothing collects the fixtures from (calls `parsefactories()` on) the `test_main.py` `DoctestModule`. How come it only started happening with commit ab63ebb3dc07b89670b96ae97044f48406c44fa0? Turns out it mostly only worked accidentally. Each `DoctestModule` is also collected as a normal `Module`, with the `Module` collected after the `DoctestModule`. For example, if we add a non-doctest test to `test_main.py`, the collection tree looks like this: ``` ``` Now, `Module` *does* collect fixtures. When autouse fixtures are collected, they are added to the `_nodeid_autousenames` dict. Before ab63ebb3dc07b89670b96ae97044f48406c44fa0, `DoctestItem` consults `_nodeid_autousenames` at *setup* time. At this point, the `Module` has collected and so it ended up picking the autouse fixture (this relies on another "accident", that the `DoctestModule` and `Module` have the same node ID). After ab63ebb3dc07b89670b96ae97044f48406c44fa0, `DoctestItem` consults `_nodeid_autousenames` at *collection* time (= when it's created). At this point, the `Module` hasn't collected yet, so the autouse fixture is not picked out. The fix is simple -- have `DoctestModule.collect()` call `parsefactories`. From some testing I've done it shouldn't have negative consequences (I hope). --- changelog/11929.bugfix.rst | 1 + src/_pytest/doctest.py | 4 ++++ testing/test_doctest.py | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 changelog/11929.bugfix.rst diff --git a/changelog/11929.bugfix.rst b/changelog/11929.bugfix.rst new file mode 100644 index 00000000000..8ab50e6f451 --- /dev/null +++ b/changelog/11929.bugfix.rst @@ -0,0 +1 @@ +Fix a regression in pytest 8.0.0 whereby autouse fixtures defined in a module get ignored by the doctests in the module. diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index e0fb7c1618d..8fe992b6a12 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -567,6 +567,10 @@ def _from_module(self, module, object): else: raise + # While doctests currently don't support fixtures directly, we still + # need to pick up autouse fixtures. + self.session._fixturemanager.parsefactories(self) + # Uses internal doctest module parsing mechanism. finder = MockAwareDocTestFinder() optionflags = get_optionflags(self.config) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 3725284907a..c91ec31cd40 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1376,6 +1376,38 @@ def auto(request): str(result.stdout.no_fnmatch_line("*FAILURES*")) result.stdout.fnmatch_lines(["*=== 1 passed in *"]) + @pytest.mark.parametrize("scope", [*SCOPES, "package"]) + def test_auto_use_defined_in_same_module( + self, pytester: Pytester, scope: str + ) -> None: + """Autouse fixtures defined in the same module as the doctest get picked + up properly. + + Regression test for #11929. + """ + pytester.makepyfile( + f""" + import pytest + + AUTO = "the fixture did not run" + + @pytest.fixture(autouse=True, scope="{scope}") + def auto(request): + global AUTO + AUTO = "the fixture ran" + + def my_doctest(): + '''My doctest. + + >>> my_doctest() + 'the fixture ran' + ''' + return AUTO + """ + ) + result = pytester.runpytest("--doctest-modules") + result.assert_outcomes(passed=1) + class TestDoctestNamespaceFixture: SCOPES = ["module", "session", "class", "function"] From 42785cca442cb747aaec707626076ab23c23b4a1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 7 Feb 2024 22:13:23 +0200 Subject: [PATCH 0451/1271] Revert "testing: temporarily disable test due to hypothesis issue (#11836)" This reverts commit 5cd0535395541d8940035418b368331318002199. --- testing/python/metafunc.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index e132725e130..ed22c2b5a1c 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -14,6 +14,9 @@ from typing import Tuple from typing import Union +import hypothesis +from hypothesis import strategies + from _pytest import fixtures from _pytest import python from _pytest.compat import getfuncargnames @@ -26,10 +29,6 @@ import pytest -# import hypothesis -# from hypothesis import strategies - - class TestMetafunc: def Metafunc(self, func, config=None) -> python.Metafunc: # The unit tests of this class check if things work correctly @@ -294,15 +293,14 @@ class A: assert metafunc._calls[2].id == "x1-a" assert metafunc._calls[3].id == "x1-b" - # TODO: Uncomment - https://github.com/HypothesisWorks/hypothesis/pull/3849 - # @hypothesis.given(strategies.text() | strategies.binary()) - # @hypothesis.settings( - # deadline=400.0 - # ) # very close to std deadline and CI boxes are not reliable in CPU power - # def test_idval_hypothesis(self, value) -> None: - # escaped = IdMaker([], [], None, None, None, None, None)._idval(value, "a", 6) - # assert isinstance(escaped, str) - # escaped.encode("ascii") + @hypothesis.given(strategies.text() | strategies.binary()) + @hypothesis.settings( + deadline=400.0 + ) # very close to std deadline and CI boxes are not reliable in CPU power + def test_idval_hypothesis(self, value) -> None: + escaped = IdMaker([], [], None, None, None, None, None)._idval(value, "a", 6) + assert isinstance(escaped, str) + escaped.encode("ascii") def test_unicode_idval(self) -> None: """Test that Unicode strings outside the ASCII character set get From 9454fc38d3636b79ee657d6cacf7477eb8acee52 Mon Sep 17 00:00:00 2001 From: whysage <67018871+whysage@users.noreply.github.com> Date: Thu, 8 Feb 2024 02:47:56 +0200 Subject: [PATCH 0452/1271] closes: 10865 Fix muted exception (#11804) * feat: 10865 * feat: 10865 refactor code and tests * feat: 10865 add test skip for pypy * feat: 10865 add test with valid warning * feat: 10865 fix v2 for codecov * feat: 10865 fix conflict --- AUTHORS | 1 + changelog/10865.improvement.rst | 2 ++ src/_pytest/recwarn.py | 11 +++++++++++ testing/test_recwarn.py | 27 +++++++++++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 changelog/10865.improvement.rst diff --git a/AUTHORS b/AUTHORS index 87909762263..25159b8b07f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -416,6 +416,7 @@ Vivaan Verma Vlad Dragos Vlad Radziuk Vladyslav Rachek +Volodymyr Kochetkov Volodymyr Piskun Wei Lin Wil Cooley diff --git a/changelog/10865.improvement.rst b/changelog/10865.improvement.rst new file mode 100644 index 00000000000..2c2856dfe96 --- /dev/null +++ b/changelog/10865.improvement.rst @@ -0,0 +1,2 @@ +:func:`pytest.warns` now validates that warning object's ``message`` is of type `str` -- currently in Python it is possible to pass other types than `str` when creating `Warning` instances, however this causes an exception when :func:`warnings.filterwarnings` is used to filter those warnings. See `CPython #103577 `__ for a discussion. +While this can be considered a bug in CPython, we decided to put guards in pytest as the error message produced without this check in place is confusing. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index aa58d43b405..62df274bd37 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -329,3 +329,14 @@ def found_str(): module=w.__module__, source=w.source, ) + # Check warnings has valid argument type (#10865). + wrn: warnings.WarningMessage + for wrn in self: + self._validate_message(wrn) + + @staticmethod + def _validate_message(wrn: Any) -> None: + if not isinstance(msg := wrn.message.args[0], str): + raise TypeError( + f"Warning message must be str, got {msg!r} (type {type(msg).__name__})" + ) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 5045c781e1f..e269bd7ddc9 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -1,4 +1,5 @@ # mypy: allow-untyped-defs +import sys from typing import List from typing import Optional from typing import Type @@ -477,3 +478,29 @@ def test_catch_warning_within_raise(self) -> None: with pytest.raises(ValueError, match="some exception"): warnings.warn("some warning", category=FutureWarning) raise ValueError("some exception") + + +def test_raise_type_error_on_non_string_warning() -> None: + """Check pytest.warns validates warning messages are strings (#10865).""" + with pytest.raises(TypeError, match="Warning message must be str"): + with pytest.warns(UserWarning): + warnings.warn(1) # type: ignore + + +def test_no_raise_type_error_on_string_warning() -> None: + """Check pytest.warns validates warning messages are strings (#10865).""" + with pytest.warns(UserWarning): + warnings.warn("Warning") + + +@pytest.mark.skipif( + hasattr(sys, "pypy_version_info"), + reason="Not for pypy", +) +def test_raise_type_error_on_non_string_warning_cpython() -> None: + # Check that we get the same behavior with the stdlib, at least if filtering + # (see https://github.com/python/cpython/issues/103577 for details) + with pytest.raises(TypeError): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", "test") + warnings.warn(1) # type: ignore From d02618d173cc0229eb85befd3efbf6132135304a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 9 Feb 2024 10:48:05 +0200 Subject: [PATCH 0453/1271] Fix ruff deprecation warning warning: The top-level linter settings are deprecated in favour of their counterparts in the `lint` section. Please update the following options in `pyproject.toml`: - 'ignore' -> 'lint.ignore' - 'select' -> 'lint.select' --- pyproject.toml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index efbb9b6c2db..cf3265efec1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,6 +87,11 @@ target-version = ['py38'] [tool.ruff] src = ["src"] line-length = 88 + +[tool.ruff.format] +docstring-code-format = true + +[tool.ruff.lint] select = [ "B", # bugbear "D", # pydocstyle @@ -130,9 +135,6 @@ ignore = [ "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` ] -[tool.ruff.format] -docstring-code-format = true - [tool.ruff.lint.pycodestyle] # In order to be able to format for 88 char in ruff format max-line-length = 120 From d1ee6d154f0eef2c753ed6a123eec583d02ae00b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 9 Feb 2024 11:08:33 +0200 Subject: [PATCH 0454/1271] Enable flake8-pie --- pyproject.toml | 1 + src/_pytest/_py/path.py | 2 +- testing/test_assertion.py | 2 +- testing/test_config.py | 6 ++---- testing/test_skipping.py | 2 +- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cf3265efec1..e1769472390 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,7 @@ select = [ "UP", # pyupgrade "RUF", # ruff "W", # pycodestyle + "PIE", # flake8-pie ] ignore = [ # bugbear ignore diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 554cb4a67e8..7701561d90e 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -452,7 +452,7 @@ def relto(self, relpath): def ensure_dir(self, *args): """Ensure the path joined with args is a directory.""" - return self.ensure(*args, **{"dir": True}) + return self.ensure(*args, dir=True) def bestrelpath(self, dest): """Return a string which is a relative path from self diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 2d92128fb82..ef4e36644d9 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -601,7 +601,7 @@ def test_list_wrap_for_width_rewrap_same_length(self) -> None: def test_list_dont_wrap_strings(self) -> None: long_a = "a" * 10 - l1 = ["a"] + [long_a for _ in range(0, 7)] + l1 = ["a"] + [long_a for _ in range(7)] l2 = ["should not get wrapped"] diff = callequal(l1, l2, verbose=True) assert diff == [ diff --git a/testing/test_config.py b/testing/test_config.py index f2651dbeb53..ead693cf48b 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1231,8 +1231,7 @@ def test_terminal_plugin(request): import myplugin assert myplugin.terminal_plugin == [False, True] """, - **{ - "myplugin": """ + myplugin=""" terminal_plugin = [] def pytest_configure(config): @@ -1241,8 +1240,7 @@ def pytest_configure(config): def pytest_sessionstart(session): config = session.config terminal_plugin.append(bool(config.pluginmanager.get_plugin("terminalreporter"))) - """ - }, + """, ) pytester.syspathinsert() result = pytester.runpytest("-p", "myplugin", str(p1)) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 4391c06421b..3f1c83f5bbe 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -74,7 +74,7 @@ def test_marked_one_arg_twice(self, pytester: Pytester) -> None: """@pytest.mark.skipif("not hasattr(os, 'murks')")""", """@pytest.mark.skipif(condition="hasattr(os, 'murks')")""", ] - for i in range(0, 2): + for i in range(2): item = pytester.getitem( f""" import pytest From a182e10b06e0efd91d78f33db5c7424a2afef258 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 9 Feb 2024 11:14:36 +0200 Subject: [PATCH 0455/1271] Enable lint PGH004 - Use specific rule codes when using noqa --- bench/bench.py | 2 +- doc/en/example/assertion/failure_demo.py | 4 ++-- pyproject.toml | 1 + src/_pytest/assertion/rewrite.py | 2 +- testing/python/fixtures.py | 2 +- testing/test_assertrewrite.py | 2 +- testing/test_collection.py | 2 +- testing/test_warnings.py | 2 +- 8 files changed, 9 insertions(+), 8 deletions(-) diff --git a/bench/bench.py b/bench/bench.py index 91e380a80d7..437d3259d83 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -5,7 +5,7 @@ import cProfile import pstats - import pytest # NOQA + import pytest # noqa: F401 script = sys.argv[1:] if len(sys.argv) > 1 else ["empty.py"] cProfile.run("pytest.cmdline.main(%r)" % script, "prof") diff --git a/doc/en/example/assertion/failure_demo.py b/doc/en/example/assertion/failure_demo.py index abb9bce5097..f7a9c279426 100644 --- a/doc/en/example/assertion/failure_demo.py +++ b/doc/en/example/assertion/failure_demo.py @@ -172,7 +172,7 @@ def test_raise(self): raise ValueError("demo error") def test_tupleerror(self): - a, b = [1] # NOQA + a, b = [1] # noqa: F841 def test_reinterpret_fails_with_print_for_the_fun_of_it(self): items = [1, 2, 3] @@ -180,7 +180,7 @@ def test_reinterpret_fails_with_print_for_the_fun_of_it(self): a, b = items.pop() def test_some_error(self): - if namenotexi: # NOQA + if namenotexi: # noqa: F821 pass def func1(self): diff --git a/pyproject.toml b/pyproject.toml index e1769472390..0a83df1bb9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,6 +103,7 @@ select = [ "RUF", # ruff "W", # pycodestyle "PIE", # flake8-pie + "PGH004", # pygrep-hooks - Use specific rule codes when using noqa ] ignore = [ # bugbear ignore diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 9f3b65e8fc9..ddae34c7326 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -1006,7 +1006,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: if i: fail_inner: List[ast.stmt] = [] # cond is set in a prior loop iteration below - self.expl_stmts.append(ast.If(cond, fail_inner, [])) # noqa + self.expl_stmts.append(ast.If(cond, fail_inner, [])) # noqa: F821 self.expl_stmts = fail_inner # Check if the left operand is a ast.NamedExpr and the value has already been visited if ( diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index d0e8723cb87..35ed2efc5bf 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -712,7 +712,7 @@ def test_method(self, something): ) def test_request_garbage(self, pytester: Pytester) -> None: try: - import xdist # noqa + import xdist # noqa: F401 except ImportError: pass else: diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 6e1a9d54e77..b045b601e76 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -200,7 +200,7 @@ def f2() -> None: assert getmsg(f2) == "assert False" def f3() -> None: - assert a_global # type: ignore[name-defined] # noqa + assert a_global # type: ignore[name-defined] # noqa: F821 assert getmsg(f3, {"a_global": False}) == "assert False" diff --git a/testing/test_collection.py b/testing/test_collection.py index 8e41e0fae78..45a1ca9ae09 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -535,7 +535,7 @@ def test_collect_protocol_single_function(self, pytester: Pytester) -> None: newid = item.nodeid assert newid == id pprint.pprint(hookrec.calls) - topdir = pytester.path # noqa + topdir = pytester.path # noqa: F841 hookrec.assert_contains( [ ("pytest_collectstart", "collector.path == topdir"), diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 5b2f2713944..3ef0cd3b546 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -794,7 +794,7 @@ def test_resource_warning(pytester: Pytester, monkeypatch: pytest.MonkeyPatch) - # available, using `importorskip("tracemalloc")` for example, # because we want to ensure the same code path does not break in those platforms. try: - import tracemalloc # noqa + import tracemalloc # noqa: F401 has_tracemalloc = True except ImportError: From ea57c40c438b9bb9981518b36ce70e7e445cf674 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 9 Feb 2024 11:34:55 +0200 Subject: [PATCH 0456/1271] main: fix reversed collection order in Session Since we're working with a stack (last in first out), we need to append to it in reverse to preserve the order when popped. Fix #11937. --- changelog/11937.bugfix.rst | 1 + src/_pytest/main.py | 2 +- testing/acceptance_test.py | 2 +- testing/test_collection.py | 21 +++++++++++++++++++-- 4 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 changelog/11937.bugfix.rst diff --git a/changelog/11937.bugfix.rst b/changelog/11937.bugfix.rst new file mode 100644 index 00000000000..3b15fb528e9 --- /dev/null +++ b/changelog/11937.bugfix.rst @@ -0,0 +1 @@ +Fix a regression in pytest 8.0.0 whereby items would be collected in reverse order in some circumstances. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index c9ef877d72e..5c70ad74e40 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -897,7 +897,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: # Prune this level. any_matched_in_collector = False - for node in subnodes: + for node in reversed(subnodes): # Path part e.g. `/a/b/` in `/a/b/test_file.py::TestIt::test_it`. if isinstance(matchparts[0], Path): is_match = node.path == matchparts[0] diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 0264aa28856..e41d7a81fd9 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -241,7 +241,7 @@ def test_issue88_initial_file_multinodes(self, pytester: Pytester) -> None: pytester.copy_example("issue88_initial_file_multinodes") p = pytester.makepyfile("def test_hello(): pass") result = pytester.runpytest(p, "--collect-only") - result.stdout.fnmatch_lines(["*Module*test_issue88*", "*MyFile*test_issue88*"]) + result.stdout.fnmatch_lines(["*MyFile*test_issue88*", "*Module*test_issue88*"]) def test_issue93_initialnode_importing_capturing(self, pytester: Pytester) -> None: pytester.makeconftest( diff --git a/testing/test_collection.py b/testing/test_collection.py index 8e41e0fae78..ea8afc7c4de 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -592,12 +592,12 @@ def pytest_collect_file(file_path, parent): hookrec.assert_contains( [ ("pytest_collectstart", "collector.path == collector.session.path"), - ("pytest_collectstart", "collector.__class__.__name__ == 'Module'"), - ("pytest_pycollect_makeitem", "name == 'test_func'"), ( "pytest_collectstart", "collector.__class__.__name__ == 'SpecialFile'", ), + ("pytest_collectstart", "collector.__class__.__name__ == 'Module'"), + ("pytest_pycollect_makeitem", "name == 'test_func'"), ("pytest_collectreport", "report.nodeid.startswith(p.name)"), ] ) @@ -671,6 +671,23 @@ def test_method(self): # ensure we are reporting the collection of the single test item (#2464) assert [x.name for x in self.get_reported_items(hookrec)] == ["test_method"] + def test_collect_parametrized_order(self, pytester: Pytester) -> None: + p = pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize('i', [0, 1, 2]) + def test_param(i): ... + """ + ) + items, hookrec = pytester.inline_genitems(f"{p}::test_param") + assert len(items) == 3 + assert [item.nodeid for item in items] == [ + "test_collect_parametrized_order.py::test_param[0]", + "test_collect_parametrized_order.py::test_param[1]", + "test_collect_parametrized_order.py::test_param[2]", + ] + class Test_getinitialnodes: def test_global_file(self, pytester: Pytester) -> None: From 7690a0ddf15785f0af0e9a4cf8524379c53cd061 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 9 Feb 2024 14:59:04 +0100 Subject: [PATCH 0457/1271] Improve error message when using @pytest.fixture twice (#11670) * Improve error message when using @pytest.fixture twice While obvious in hindsight, this error message confused me. I thought my fixture function was used in a test function twice, since the wording is ambiguous. Also, the error does not tell me *which* function is the culprit. Finally, this adds a test, which wasn't done in cfd16d0dac1c935952b892bfbc225978c9b25de3 where this was originally implemented. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- src/_pytest/fixtures.py | 2 +- testing/python/fixtures.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index b0bbc0e0449..67eb0542574 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1188,7 +1188,7 @@ def __call__(self, function: FixtureFunction) -> FixtureFunction: if getattr(function, "_pytestfixturefunction", False): raise ValueError( - "fixture is being applied more than once to the same function" + f"@pytest.fixture is being applied more than once to the same function {function.__name__!r}" ) if hasattr(function, "pytestmark"): diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 35ed2efc5bf..0fb5aa45029 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4353,6 +4353,27 @@ def fix(): assert fix() == 1 +def test_fixture_double_decorator(pytester: Pytester) -> None: + """Check if an error is raised when using @pytest.fixture twice.""" + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + @pytest.fixture + def fixt(): + pass + """ + ) + result = pytester.runpytest() + result.assert_outcomes(errors=1) + result.stdout.fnmatch_lines( + [ + "E * ValueError: @pytest.fixture is being applied more than once to the same function 'fixt'" + ] + ) + + def test_fixture_param_shadowing(pytester: Pytester) -> None: """Parametrized arguments would be shadowed if a fixture with the same name also exists (#5036)""" pytester.makepyfile( From 1180348303599f835d37b2028288ce81b90b85c5 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 10 Feb 2024 15:46:45 +0100 Subject: [PATCH 0458/1271] [ruff] Add 'consider-using-in' from pylint See https://pylint.readthedocs.io/en/latest/user_guide/messages/refactor/consider-using-in.html An automated fix from ruff is available (but it's unsafe for now). --- pyproject.toml | 1 + src/_pytest/compat.py | 2 +- src/_pytest/junitxml.py | 2 +- src/_pytest/python.py | 2 +- src/_pytest/terminal.py | 2 +- testing/test_assertrewrite.py | 2 +- 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0a83df1bb9b..56b32b2101c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,6 +104,7 @@ select = [ "W", # pycodestyle "PIE", # flake8-pie "PGH004", # pygrep-hooks - Use specific rule codes when using noqa + "PLR1714", # Consider merging multiple comparisons ] ignore = [ # bugbear ignore diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 400b3864296..077fa65da2f 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -289,7 +289,7 @@ def get_user_id() -> int | None: # mypy follows the version and platform checking expectation of PEP 484: # https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks # Containment checks are too complex for mypy v1.5.0 and cause failure. - if sys.platform == "win32" or sys.platform == "emscripten": + if sys.platform in {"win32", "emscripten"}: # win32 does not have a getuid() function. # Emscripten has a return 0 stub. return None diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 51becf97b0f..4ca356f31f2 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -624,7 +624,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: def update_testcase_duration(self, report: TestReport) -> None: """Accumulate total duration for nodeid from given report and update the Junit.testcase with the new total if already created.""" - if self.report_duration == "total" or report.when == self.report_duration: + if self.report_duration in {"total", report.when}: reporter = self.node_reporter(report) reporter.duration += getattr(report, "duration", 0.0) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 10ca00890d4..cf3415d98b3 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1787,7 +1787,7 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: ntraceback = Traceback( ( entry - if i == 0 or i == len(ntraceback) - 1 + if i in {0, len(ntraceback) - 1} else entry.with_repr_style("short") ) for i, entry in enumerate(ntraceback) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 62dafe703ed..8909d95ef24 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -381,7 +381,7 @@ def _determine_show_progress_info(self) -> Literal["progress", "count", False]: if self.config.getoption("setupshow", False): return False cfg: str = self.config.getini("console_output_style") - if cfg == "progress" or cfg == "progress-even-when-capture-no": + if cfg in {"progress", "progress-even-when-capture-no"}: return "progress" elif cfg == "count": return "count" diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index b045b601e76..e676d562cf4 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -429,7 +429,7 @@ def f1() -> None: def f2() -> None: x = 1 - assert x == 1 or x == 2 + assert x == 1 or x == 2 # noqa: PLR1714 getmsg(f2, must_pass=True) From b922270ce7e6a7c0bd521f1eab3ea82b6041537d Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 10 Feb 2024 15:51:33 +0100 Subject: [PATCH 0459/1271] [performance] Micro-optimization in '_traceback_filter' Should be around 40% faster according to this simplified small benchmark: python -m timeit "a=[0, 1, 2, 3, 4];b=list((e if i in {0, len(a) -1} else str(e)) for i, e in enumerate(a))" 200000 loops, best of 5: 1.12 usec per loop python -m timeit "a=[0, 1, 2, 3, 4];b=list((a[0], *(str(e) for e in a[1:-1]), a[-1]))" 500000 loops, best of 5: 651 nsec per loop python -m timeit "a=[0, 1, 2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16];b=list((e if i in {0, len(a) -1} else str(e)) for i, e in enumerate(a))" 100000 loops, best of 5: 3.31 usec per loop python -m timeit "a=[0, 1, 2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16];b=list((a[0], *(str(e) for e in a[1:-1]), a[-1]))" 200000 loops, best of 5: 1.72 usec per loop --- src/_pytest/python.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index cf3415d98b3..91c48540dc7 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1786,11 +1786,10 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: if len(ntraceback) > 2: ntraceback = Traceback( ( - entry - if i in {0, len(ntraceback) - 1} - else entry.with_repr_style("short") + ntraceback[0], + *(t.with_repr_style("short") for t in ntraceback[1:-1]), + ntraceback[-1], ) - for i, entry in enumerate(ntraceback) ) return ntraceback From 7da04c963f7e134c86461b252828ebb7594151a5 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 10 Feb 2024 23:41:33 +0100 Subject: [PATCH 0460/1271] [ruff] Add unwanted pylint message to the ignore list --- pyproject.toml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 56b32b2101c..72988e23387 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,6 +104,8 @@ select = [ "W", # pycodestyle "PIE", # flake8-pie "PGH004", # pygrep-hooks - Use specific rule codes when using noqa + "PLE", # pylint error + "PLW", # pylint warning "PLR1714", # Consider merging multiple comparisons ] ignore = [ @@ -136,6 +138,11 @@ ignore = [ "D415", # First line should end with a period, question mark, or exclamation point # ruff ignore "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + # pylint ignore + "PLW0603", # Using the global statement + "PLW0120", # remove the else and dedent its contents + "PLW2901", # for loop variable overwritten by assignment target + "PLR5501", # Use `elif` instead of `else` then `if` ] [tool.ruff.lint.pycodestyle] From 23dfb52974af5d006a2dea3de5b9b6035cba6a65 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 10 Feb 2024 21:50:24 -0300 Subject: [PATCH 0461/1271] [automated] Update plugin list (#11964) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 158 +++++++++++++++---------------- 1 file changed, 79 insertions(+), 79 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 9ada47c7aff..ce1e4f6bd0a 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -67,7 +67,7 @@ This list contains 1367 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Dec 06, 2023 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Feb 06, 2024 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -86,7 +86,7 @@ This list contains 1367 plugins. :pypi:`pytest-appengine` AppEngine integration that works well with pytest-django Feb 27, 2017 N/A N/A :pypi:`pytest-appium` Pytest plugin for appium Dec 05, 2019 N/A N/A :pypi:`pytest-approvaltests` A plugin to use approvaltests with pytest May 08, 2022 4 - Beta pytest (>=7.0.1) - :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Dec 12, 2023 5 - Production/Stable pytest + :pypi:`pytest-approvaltests-geo` Extension for ApprovalTests.Python specific to geo data verification Feb 05, 2024 5 - Production/Stable pytest :pypi:`pytest-archon` Rule your architecture like a real developer Dec 18, 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 27, 2023 4 - Beta pytest >=4.6 @@ -105,7 +105,7 @@ This list contains 1367 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 Jan 28, 2024 4 - Beta pytest <8,>=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Feb 09, 2024 4 - Beta pytest <9,>=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) @@ -209,7 +209,7 @@ This list contains 1367 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 Dec 26, 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 Feb 04, 2024 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 @@ -320,7 +320,7 @@ This list contains 1367 plugins. :pypi:`pytest-dependency` Manage dependencies of tests Dec 31, 2023 4 - Beta N/A :pypi:`pytest-depends` Tests that depend on other tests Apr 05, 2020 5 - Production/Stable pytest (>=3) :pypi:`pytest-deprecate` Mark tests as testing a deprecated feature with a warning note. Jul 01, 2019 N/A N/A - :pypi:`pytest-describe` Describe-style plugin for pytest Apr 09, 2023 5 - Production/Stable pytest (<8,>=4.6) + :pypi:`pytest-describe` Describe-style plugin for pytest Feb 10, 2024 5 - Production/Stable pytest <9,>=4.6 :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest :pypi:`pytest-devpi-server` DevPI server fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-dhos` Common fixtures for pytest in DHOS services and libraries Sep 07, 2022 N/A N/A @@ -532,7 +532,7 @@ This list contains 1367 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 Dec 15, 2023 4 - Beta pytest >=6.0.0 + :pypi:`pytest-fzf` fzf-based test selector for pytest Feb 07, 2024 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 @@ -568,7 +568,7 @@ This list contains 1367 plugins. :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Jun 10, 2022 5 - Production/Stable N/A :pypi:`pytest-helm-chart` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Jun 15, 2020 4 - Beta pytest (>=5.4.2,<6.0.0) - :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Sep 13, 2023 4 - Beta pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Feb 07, 2024 4 - Beta pytest (>=8.0.0,<9.0.0) :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) @@ -579,12 +579,12 @@ This list contains 1367 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Feb 03, 2024 3 - Alpha pytest ==7.4.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 10, 2024 3 - Alpha pytest ==7.4.4 :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` Jan 06, 2024 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. Dec 25, 2023 N/A pytest + :pypi:`pytest-houdini` pytest plugin for testing code in Houdini. Feb 09, 2024 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) @@ -629,7 +629,7 @@ This list contains 1367 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 19, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Dec 13, 2023 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Jan 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package Feb 09, 2024 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 @@ -641,7 +641,7 @@ This list contains 1367 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. Jan 26, 2024 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Feb 09, 2024 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jan 29, 2024 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 @@ -690,7 +690,7 @@ This list contains 1367 plugins. :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Feb 01, 2024 N/A pytest (>=7) + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Feb 06, 2024 N/A pytest (>=7) :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A @@ -711,7 +711,7 @@ This list contains 1367 plugins. :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests Oct 14, 2023 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) - :pypi:`pytest-lock` pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. Jan 27, 2024 N/A pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-lock` pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. Feb 03, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-lockable` lockable resource plugin for pytest Jan 24, 2024 5 - Production/Stable pytest :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) :pypi:`pytest-log` print log Aug 15, 2021 N/A pytest (>=3.8) @@ -721,15 +721,15 @@ This list contains 1367 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Jan 27, 2024 5 - Production/Stable pytest ==7.4.4 + :pypi:`pytest-logikal` Common testing environment Feb 05, 2024 5 - Production/Stable pytest ==8.0.0 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Oct 04, 2023 5 - Production/Stable pytest :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) - :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 13, 2023 3 - Alpha pytest + :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Feb 07, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) - :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 09, 2023 N/A N/A + :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Feb 07, 2024 N/A pytest (>=7.0.0) :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A @@ -744,7 +744,7 @@ This list contains 1367 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Oct 08, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 + :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Feb 04, 2024 4 - Beta pytest !=6.0.0,<9,>=3.3.2 :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Jan 19, 2024 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A @@ -863,7 +863,7 @@ This list contains 1367 plugins. :pypi:`pytest-parallelize-tests` pytest plugin that parallelizes test execution across multiple hosts Jan 27, 2023 4 - Beta N/A :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) - :pypi:`pytest-parameterize-from-files` A pytest plugin that parameterizes tests from data files. Jan 27, 2024 4 - Beta pytest>=7.2.0 + :pypi:`pytest-parameterize-from-files` A pytest plugin that parameterizes tests from data files. Feb 09, 2024 4 - Beta pytest>=7.2.0 :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest @@ -901,7 +901,7 @@ This list contains 1367 plugins. :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Feb 02, 2024 N/A pytest (<9.0.0,>=6.2.4) - :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Jul 03, 2023 N/A N/A + :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Feb 06, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A @@ -960,7 +960,7 @@ This list contains 1367 plugins. :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Nov 03, 2023 N/A pytest + :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Feb 03, 2024 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Jan 26, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Jan 02, 2024 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 @@ -974,7 +974,7 @@ This list contains 1367 plugins. :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 Dec 22, 2023 5 - Production/Stable pytest >=3.0.0 + :pypi:`pytest-qt` pytest support for PyQt and PySide applications Feb 07, 2024 5 - Production/Stable pytest :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) @@ -1024,7 +1024,7 @@ This list contains 1367 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Dec 06, 2023 N/A pytest >=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Feb 05, 2024 N/A pytest <8.0.0,>=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) @@ -1036,7 +1036,7 @@ This list contains 1367 plugins. :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 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-reserial` Pytest fixture for recording and replaying serial port traffic. Feb 08, 2024 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jan 10, 2024 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) @@ -1049,7 +1049,7 @@ This list contains 1367 plugins. :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Jan 04, 2024 N/A pytest >=7.0.0 + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Feb 04, 2024 N/A pytest >=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest @@ -1157,7 +1157,7 @@ This list contains 1367 plugins. :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. 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-sphinx` Doctest plugin for pytest with support for Sphinx-specific doctest-directives Feb 03, 2024 4 - Beta pytest >=8.0.0 :pypi:`pytest-spiratest` Exports unit tests as test runs in Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Feb 01, 2024 6 - Mature pytest >=8.0.0 @@ -1185,11 +1185,11 @@ This list contains 1367 plugins. :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A - :pypi:`pytest-stf` pytest plugin for openSTF Oct 10, 2023 N/A pytest >=5.0 + :pypi:`pytest-stf` pytest plugin for openSTF Feb 08, 2024 N/A pytest >=5.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-structlog` Structured logging assertions Dec 18, 2022 N/A pytest + :pypi:`pytest-structlog` Structured logging assertions Feb 04, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) @@ -1255,7 +1255,7 @@ This list contains 1367 plugins. :pypi:`pytest-testreport-new` Oct 07, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) - :pypi:`pytest-test-utils` Jul 14, 2022 N/A pytest (>=5) + :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 :pypi:`pytest-tesults` Tesults plugin for pytest Jul 21, 2023 5 - Production/Stable pytest (>=3.5.0) :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A @@ -1274,8 +1274,8 @@ This list contains 1367 plugins. :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) - :pypi:`pytest-tipsi-django` Nov 17, 2021 4 - Beta pytest (>=6.0.0) - :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Nov 04, 2020 4 - Beta pytest (>=3.3.0) + :pypi:`pytest-tipsi-django` Better fixtures for django Feb 05, 2024 5 - Production/Stable pytest>=6.0.0 + :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Feb 04, 2024 5 - Production/Stable pytest>=3.3.0 :pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-tm4j-reporter` Cloud Jira Test Management (TM4J) PyTest reporter plugin Sep 01, 2020 N/A pytest :pypi:`pytest-tmnet` A small example package Mar 01, 2022 N/A N/A @@ -1336,7 +1336,7 @@ This list contains 1367 plugins. :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 Nov 23, 2023 4 - Beta pytest - :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Dec 19, 2023 4 - Beta pytest + :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Feb 07, 2024 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 @@ -1352,7 +1352,7 @@ This list contains 1367 plugins. :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-wake` Nov 07, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A - :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Jan 28, 2024 4 - Beta N/A + :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Feb 06, 2024 4 - Beta N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest @@ -1638,7 +1638,7 @@ This list contains 1367 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Dec 06, 2023, + *last release*: Feb 06, 2024, *status*: N/A, *requires*: pytest >=7.3.1 @@ -1771,7 +1771,7 @@ This list contains 1367 plugins. A plugin to use approvaltests with pytest :pypi:`pytest-approvaltests-geo` - *last release*: Dec 12, 2023, + *last release*: Feb 05, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -1904,9 +1904,9 @@ This list contains 1367 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jan 28, 2024, + *last release*: Feb 09, 2024, *status*: 4 - Beta, - *requires*: pytest <8,>=7.0.0 + *requires*: pytest <9,>=7.0.0 Pytest support for asyncio @@ -2632,7 +2632,7 @@ This list contains 1367 plugins. A pytest plugin to send a report and printing summary of tests. :pypi:`pytest-choose` - *last release*: Dec 26, 2023, + *last release*: Feb 04, 2024, *status*: N/A, *requires*: pytest >=7.0.0 @@ -3409,9 +3409,9 @@ This list contains 1367 plugins. Mark tests as testing a deprecated feature with a warning note. :pypi:`pytest-describe` - *last release*: Apr 09, 2023, + *last release*: Feb 10, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (<8,>=4.6) + *requires*: pytest <9,>=4.6 Describe-style plugin for pytest @@ -4893,7 +4893,7 @@ This list contains 1367 plugins. :pypi:`pytest-fzf` - *last release*: Dec 15, 2023, + *last release*: Feb 07, 2024, *status*: 4 - Beta, *requires*: pytest >=6.0.0 @@ -5145,9 +5145,9 @@ This list contains 1367 plugins. A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. :pypi:`pytest-helm-charts` - *last release*: Sep 13, 2023, + *last release*: Feb 07, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.1.2,<8.0.0) + *requires*: pytest (>=8.0.0,<9.0.0) A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. @@ -5222,7 +5222,7 @@ This list contains 1367 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 03, 2024, + *last release*: Feb 10, 2024, *status*: 3 - Alpha, *requires*: pytest ==7.4.4 @@ -5257,7 +5257,7 @@ This list contains 1367 plugins. A plugin that tracks test changes :pypi:`pytest-houdini` - *last release*: Dec 25, 2023, + *last release*: Feb 09, 2024, *status*: N/A, *requires*: pytest @@ -5572,7 +5572,7 @@ This list contains 1367 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Jan 04, 2024, + *last release*: Feb 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5656,7 +5656,7 @@ This list contains 1367 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Jan 26, 2024, + *last release*: Feb 09, 2024, *status*: 4 - Beta, *requires*: pytest @@ -5999,7 +5999,7 @@ This list contains 1367 plugins. It helps to use fixtures in pytest.mark.parametrize :pypi:`pytest-lazy-fixtures` - *last release*: Feb 01, 2024, + *last release*: Feb 06, 2024, *status*: N/A, *requires*: pytest (>=7) @@ -6146,7 +6146,7 @@ This list contains 1367 plugins. Pytest plugin for AWS integration tests :pypi:`pytest-lock` - *last release*: Jan 27, 2024, + *last release*: Feb 03, 2024, *status*: N/A, *requires*: pytest (>=7.4.3,<8.0.0) @@ -6216,9 +6216,9 @@ This list contains 1367 plugins. :pypi:`pytest-logikal` - *last release*: Jan 27, 2024, + *last release*: Feb 05, 2024, *status*: 5 - Production/Stable, - *requires*: pytest ==7.4.4 + *requires*: pytest ==8.0.0 Common testing environment @@ -6244,7 +6244,7 @@ This list contains 1367 plugins. pytest plugin for looping tests :pypi:`pytest-lsp` - *last release*: Nov 13, 2023, + *last release*: Feb 07, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -6272,9 +6272,9 @@ This list contains 1367 plugins. Test your markdown docs with pytest :pypi:`pytest-markdown-docs` - *last release*: Mar 09, 2023, + *last release*: Feb 07, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest (>=7.0.0) Run markdown code fences through pytest @@ -6377,9 +6377,9 @@ This list contains 1367 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: Oct 08, 2023, + *last release*: Feb 04, 2024, *status*: 4 - Beta, - *requires*: pytest !=6.0.0,<8,>=3.3.2 + *requires*: pytest !=6.0.0,<9,>=3.3.2 A pytest plugin to make a test results report with Markdown table format. @@ -7210,7 +7210,7 @@ This list contains 1367 plugins. Configure pytest fixtures using a combination of"parametrize" and markers :pypi:`pytest-parameterize-from-files` - *last release*: Jan 27, 2024, + *last release*: Feb 09, 2024, *status*: 4 - Beta, *requires*: pytest>=7.2.0 @@ -7476,7 +7476,7 @@ This list contains 1367 plugins. A pytest wrapper with fixtures for Playwright to automate web browsers :pypi:`pytest-playwright-async` - *last release*: Jul 03, 2023, + *last release*: Feb 06, 2024, *status*: N/A, *requires*: N/A @@ -7889,7 +7889,7 @@ This list contains 1367 plugins. Pyramid server fixture for py.test :pypi:`pytest-pyreport` - *last release*: Nov 03, 2023, + *last release*: Feb 03, 2024, *status*: N/A, *requires*: pytest @@ -7987,9 +7987,9 @@ This list contains 1367 plugins. pytest plugin to generate test result QR codes :pypi:`pytest-qt` - *last release*: Dec 22, 2023, + *last release*: Feb 07, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=3.0.0 + *requires*: pytest pytest support for PyQt and PySide applications @@ -8337,9 +8337,9 @@ This list contains 1367 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Dec 06, 2023, + *last release*: Feb 05, 2024, *status*: N/A, - *requires*: pytest >=3.8.0 + *requires*: pytest <8.0.0,>=3.8.0 Agent for Reporting results of tests to the Report Portal @@ -8421,7 +8421,7 @@ This list contains 1367 plugins. pytest plugin to re-run tests to eliminate flaky failures :pypi:`pytest-reserial` - *last release*: Aug 31, 2023, + *last release*: Feb 08, 2024, *status*: 4 - Beta, *requires*: pytest @@ -8512,7 +8512,7 @@ This list contains 1367 plugins. A RethinkDB plugin for pytest. :pypi:`pytest-retry` - *last release*: Jan 04, 2024, + *last release*: Feb 04, 2024, *status*: N/A, *requires*: pytest >=7.0.0 @@ -9268,9 +9268,9 @@ This list contains 1367 plugins. Modern benchmarking library for python with pytest integration. :pypi:`pytest-sphinx` - *last release*: Sep 06, 2022, + *last release*: Feb 03, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=8.0.0 Doctest plugin for pytest with support for Sphinx-specific doctest-directives @@ -9464,7 +9464,7 @@ This list contains 1367 plugins. Run a test suite one failing test at a time. :pypi:`pytest-stf` - *last release*: Oct 10, 2023, + *last release*: Feb 08, 2024, *status*: N/A, *requires*: pytest >=5.0 @@ -9492,7 +9492,7 @@ This list contains 1367 plugins. A Pytest plugin that allows you to loop tests for a user defined amount of time. :pypi:`pytest-structlog` - *last release*: Dec 18, 2022, + *last release*: Feb 04, 2024, *status*: N/A, *requires*: pytest @@ -9954,9 +9954,9 @@ This list contains 1367 plugins. Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply :pypi:`pytest-test-utils` - *last release*: Jul 14, 2022, + *last release*: Feb 08, 2024, *status*: N/A, - *requires*: pytest (>=5) + *requires*: pytest >=3.9 @@ -10087,16 +10087,16 @@ This list contains 1367 plugins. A pytest plugin to report test results to tinybird :pypi:`pytest-tipsi-django` - *last release*: Nov 17, 2021, - *status*: 4 - Beta, - *requires*: pytest (>=6.0.0) - + *last release*: Feb 05, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=6.0.0 + Better fixtures for django :pypi:`pytest-tipsi-testing` - *last release*: Nov 04, 2020, - *status*: 4 - Beta, - *requires*: pytest (>=3.3.0) + *last release*: Feb 04, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=3.3.0 Better fixtures management. Various helpers @@ -10521,7 +10521,7 @@ This list contains 1367 plugins. py.test fixture for creating a virtual environment :pypi:`pytest-ver` - *last release*: Dec 19, 2023, + *last release*: Feb 07, 2024, *status*: 4 - Beta, *requires*: pytest @@ -10633,7 +10633,7 @@ This list contains 1367 plugins. Local continuous test runner with pytest and watchdog. :pypi:`pytest-watcher` - *last release*: Jan 28, 2024, + *last release*: Feb 06, 2024, *status*: 4 - Beta, *requires*: N/A From 3b798e54221f1895a983000c7e5bc8afdacd5011 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:06:14 -0300 Subject: [PATCH 0462/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#11965) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.3 to 0.23.5. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.3...v0.23.5) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d7b06625164..61c423ce6ef 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.2.0 django==5.0.2 -pytest-asyncio==0.23.3 +pytest-asyncio==0.23.5 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 # pytest-bdd==7.0.1 From ca84327f158d869eb3d56e242314b3eeb906151d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 06:19:40 +0100 Subject: [PATCH 0463/1271] [pre-commit.ci] pre-commit autoupdate (#11967) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.2.0 → v0.2.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.2.0...v0.2.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 22a9ec95f93..e9cea8c60c3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.2.0" + rev: "v0.2.1" hooks: - id: ruff args: ["--fix"] From fe7907d78cd21a111542e8bf445526922bda9237 Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Wed, 14 Feb 2024 18:50:34 +0000 Subject: [PATCH 0464/1271] Add `logot` to plugin list (#11972) --- scripts/update-plugin-list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 2c57414c028..c215208199a 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -61,6 +61,7 @@ ) ADDITIONAL_PROJECTS = { # set of additional projects to consider as plugins "logassert", + "logot", "nuts", "flask_fixture", } From 46e6fb12c7d6d95750959964c1f59039dd51b579 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 14 Feb 2024 15:53:28 -0300 Subject: [PATCH 0465/1271] Consider paths and pathlists relative to cwd in case of an absent ini-file (#11963) Previously this would trigger an `AssertionError`. While it could be considered a bug-fix, but given it now can be relied upon, it is probably better to consider it an improvement. Fix #11311 --- changelog/11311.improvement.rst | 4 ++++ src/_pytest/config/__init__.py | 8 +++++--- src/_pytest/config/argparsing.py | 7 +++++++ testing/test_config.py | 12 ++++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 changelog/11311.improvement.rst diff --git a/changelog/11311.improvement.rst b/changelog/11311.improvement.rst new file mode 100644 index 00000000000..0072f39743a --- /dev/null +++ b/changelog/11311.improvement.rst @@ -0,0 +1,4 @@ +When using ``--override-ini`` for paths in invocations without a configuration file defined, the current working directory is used +as the relative directory. + +Previoulsy this would raise an :class:`AssertionError`. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index cada2aa0978..3d448214cbe 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1563,9 +1563,11 @@ def _getini(self, name: str): # in this case, we already have a list ready to use. # if type == "paths": - # TODO: This assert is probably not valid in all cases. - assert self.inipath is not None - dp = self.inipath.parent + dp = ( + self.inipath.parent + if self.inipath is not None + else self.invocation_params.dir + ) input_values = shlex.split(value) if isinstance(value, str) else value return [dp / x for x in input_values] elif type == "args": diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index da05acf398e..d98f1ae9a12 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -198,9 +198,16 @@ def addini( * ``paths``: a list of :class:`pathlib.Path`, separated as in a shell * ``pathlist``: a list of ``py.path``, separated as in a shell + For ``paths`` and ``pathlist`` types, they are considered relative to the ini-file. + In case the execution is happening without an ini-file defined, + they will be considered relative to the current working directory (for example with ``--override-ini``). + .. versionadded:: 7.0 The ``paths`` variable type. + .. versionadded:: 8.1 + Use the current working directory to resolve ``paths`` and ``pathlist`` in the absence of an ini-file. + Defaults to ``string`` if ``None`` or not passed. :param default: Default value if no ini-file option exists but is queried. diff --git a/testing/test_config.py b/testing/test_config.py index ead693cf48b..4377257b12e 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1874,6 +1874,18 @@ def test(): assert "ERROR:" not in result.stderr.str() result.stdout.fnmatch_lines(["collected 1 item", "*= 1 passed in *="]) + def test_override_ini_without_config_file(self, pytester: Pytester) -> None: + pytester.makepyfile(**{"src/override_ini_without_config_file.py": ""}) + pytester.makepyfile( + **{ + "tests/test_override_ini_without_config_file.py": ( + "import override_ini_without_config_file\ndef test(): pass" + ), + } + ) + result = pytester.runpytest("--override-ini", "pythonpath=src") + assert result.parseoutcomes() == {"passed": 1} + def test_help_via_addopts(pytester: Pytester) -> None: pytester.makeini( From acafd003aa643765abed144c618ab13cab24ecc1 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 14 Feb 2024 16:08:45 -0300 Subject: [PATCH 0466/1271] Consider pyproject.toml files for config if no other config files were found (#11962) Today `pyproject.toml` is the standard for declaring a Python project root, so seems reasonable to consider it for the ini configuration (and specially `rootdir`) in case we do not find other suitable candidates. Related to #11311 --- changelog/11962.improvement.rst | 1 + doc/en/reference/customize.rst | 13 +++++++++---- src/_pytest/config/findpaths.py | 5 +++++ testing/test_config.py | 32 +++++++++++++++++++++++++++++++- 4 files changed, 46 insertions(+), 5 deletions(-) create mode 100644 changelog/11962.improvement.rst diff --git a/changelog/11962.improvement.rst b/changelog/11962.improvement.rst new file mode 100644 index 00000000000..453b99d33d7 --- /dev/null +++ b/changelog/11962.improvement.rst @@ -0,0 +1 @@ +In case no other suitable candidates for configuration file are found, a ``pyproject.toml`` (even without a ``[tool.pytest.ini_options]`` table) will be considered as the configuration file and define the ``rootdir``. diff --git a/doc/en/reference/customize.rst b/doc/en/reference/customize.rst index 24c0ed21752..cab1117266f 100644 --- a/doc/en/reference/customize.rst +++ b/doc/en/reference/customize.rst @@ -177,13 +177,20 @@ Files will only be matched for configuration if: * ``tox.ini``: contains a ``[pytest]`` section. * ``setup.cfg``: contains a ``[tool:pytest]`` section. +Finally, a ``pyproject.toml`` file will be considered the ``configfile`` if no other match was found, in this case +even if it does not contain a ``[tool.pytest.ini_options]`` table (this was added in ``8.1``). + The files are considered in the order above. Options from multiple ``configfiles`` candidates are never merged - the first match wins. +The configuration file also determines the value of the ``rootpath``. + The :class:`Config ` object (accessible via hooks or through the :fixture:`pytestconfig` fixture) will subsequently carry these attributes: -- :attr:`config.rootpath `: the determined root directory, guaranteed to exist. +- :attr:`config.rootpath `: the determined root directory, guaranteed to exist. It is used as + a reference directory for constructing test addresses ("nodeids") and can be used also by plugins for storing + per-testrun information. - :attr:`config.inipath `: the determined ``configfile``, may be ``None`` (it is named ``inipath`` for historical reasons). @@ -193,9 +200,7 @@ will subsequently carry these attributes: versions of the older ``config.rootdir`` and ``config.inifile``, which have type ``py.path.local``, and still exist for backward compatibility. -The ``rootdir`` is used as a reference directory for constructing test -addresses ("nodeids") and can be used also by plugins for storing -per-testrun information. + Example: diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 96f3536514e..9909376de0f 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -101,15 +101,20 @@ def locate_config( args = [x for x in args if not str(x).startswith("-")] if not args: args = [invocation_dir] + found_pyproject_toml: Optional[Path] = None for arg in args: argpath = absolutepath(arg) for base in (argpath, *argpath.parents): for config_name in config_names: p = base / config_name if p.is_file(): + if p.name == "pyproject.toml" and found_pyproject_toml is None: + found_pyproject_toml = p ini_config = load_config_dict_from_file(p) if ini_config is not None: return base, p, ini_config + if found_pyproject_toml is not None: + return found_pyproject_toml.parent, found_pyproject_toml, {} return None, None, {} diff --git a/testing/test_config.py b/testing/test_config.py index 4377257b12e..88470ff2d49 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -135,15 +135,45 @@ def test_ini_names(self, pytester: Pytester, name, section) -> None: assert config.getini("minversion") == "3.36" def test_pyproject_toml(self, pytester: Pytester) -> None: - pytester.makepyprojecttoml( + pyproject_toml = pytester.makepyprojecttoml( """ [tool.pytest.ini_options] minversion = "1.0" """ ) config = pytester.parseconfig() + assert config.inipath == pyproject_toml assert config.getini("minversion") == "1.0" + def test_empty_pyproject_toml(self, pytester: Pytester) -> None: + """An empty pyproject.toml is considered as config if no other option is found.""" + pyproject_toml = pytester.makepyprojecttoml("") + config = pytester.parseconfig() + assert config.inipath == pyproject_toml + + def test_empty_pyproject_toml_found_many(self, pytester: Pytester) -> None: + """ + In case we find multiple pyproject.toml files in our search, without a [tool.pytest.ini_options] + table and without finding other candidates, the closest to where we started wins. + """ + pytester.makefile( + ".toml", + **{ + "pyproject": "", + "foo/pyproject": "", + "foo/bar/pyproject": "", + }, + ) + config = pytester.parseconfig(pytester.path / "foo/bar") + assert config.inipath == pytester.path / "foo/bar/pyproject.toml" + + def test_pytest_ini_trumps_pyproject_toml(self, pytester: Pytester) -> None: + """A pytest.ini always take precedence over a pyproject.toml file.""" + pytester.makepyprojecttoml("[tool.pytest.ini_options]") + pytest_ini = pytester.makefile(".ini", pytest="") + config = pytester.parseconfig() + assert config.inipath == pytest_ini + def test_toxini_before_lower_pytestini(self, pytester: Pytester) -> None: sub = pytester.mkdir("sub") sub.joinpath("tox.ini").write_text( From cbb5c82c3952b90178c7f3185f2267a0658528e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:11:20 -0300 Subject: [PATCH 0467/1271] build(deps): Bump peter-evans/create-pull-request from 5.0.2 to 6.0.0 (#11922) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 5.0.2 to 6.0.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/153407881ec5c347639a548ade7d8ad1d6740e38...b1ddad2c994a25fbc81a28b3ec0e368bb2021c50) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 214d734c974..55fb4dc6f01 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -46,7 +46,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request - uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 + uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 5d7a5a9343ec7d675a9599312f8055e2a81cc1db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Feb 2024 16:11:30 -0300 Subject: [PATCH 0468/1271] build(deps): Bump codecov/codecov-action from 3 to 4 (#11921) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3...v4) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 363cbe901fc..9fe01dc72cc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -205,7 +205,7 @@ jobs: - name: Upload coverage to Codecov if: "matrix.use_coverage" - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 continue-on-error: true with: fail_ci_if_error: true From c6313a06fbc837316bddda64e97b23ad6cc44afd Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 16 Feb 2024 12:03:38 +0200 Subject: [PATCH 0469/1271] scripts/update-plugin-list: include packages starting with "pytest_" (underscore) Fix #11985. --- scripts/update-plugin-list.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index c215208199a..6226bc8c928 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -29,7 +29,7 @@ ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. +It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, @@ -110,7 +110,10 @@ def pytest_plugin_projects_from_pypi(session: CachedSession) -> dict[str, int]: return { name: p["_last-serial"] for p in response.json()["projects"] - if (name := p["name"]).startswith("pytest-") or name in ADDITIONAL_PROJECTS + if ( + (name := p["name"]).startswith(("pytest-", "pytest_")) + or name in ADDITIONAL_PROJECTS + ) } From 288201b8f579efd3ebc4ca243966444f99686d9d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 4 Feb 2024 22:25:49 +0200 Subject: [PATCH 0470/1271] recwarn: let base exceptions propagate through `pytest.warns` again Fix #11907. --- changelog/11907.bugfix.rst | 1 + src/_pytest/recwarn.py | 12 +++++++ testing/test_recwarn.py | 70 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 changelog/11907.bugfix.rst diff --git a/changelog/11907.bugfix.rst b/changelog/11907.bugfix.rst new file mode 100644 index 00000000000..10aa39aeb0c --- /dev/null +++ b/changelog/11907.bugfix.rst @@ -0,0 +1 @@ +Fix a regression in pytest 8.0.0 whereby calling :func:`pytest.skip` and similar control-flow exceptions within a :func:`pytest.warns()` block would get suppressed instead of propagating. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 62df274bd37..ddb240eb2e7 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -20,6 +20,7 @@ from _pytest.deprecated import check_ispytest from _pytest.fixtures import fixture +from _pytest.outcomes import Exit from _pytest.outcomes import fail @@ -302,6 +303,17 @@ def __exit__( __tracebackhide__ = True + # BaseExceptions like pytest.{skip,fail,xfail,exit} or Ctrl-C within + # pytest.warns should *not* trigger "DID NOT WARN" and get suppressed + # when the warning doesn't happen. Control-flow exceptions should always + # propagate. + if exc_val is not None and ( + not isinstance(exc_val, Exception) + # Exit is an Exception, not a BaseException, for some reason. + or isinstance(exc_val, Exit) + ): + return + def found_str(): return pformat([record.message for record in self], indent=2) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index e269bd7ddc9..1feb3e654d4 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -5,9 +5,10 @@ from typing import Type import warnings -from _pytest.pytester import Pytester -from _pytest.recwarn import WarningsRecorder import pytest +from pytest import ExitCode +from pytest import Pytester +from pytest import WarningsRecorder def test_recwarn_stacklevel(recwarn: WarningsRecorder) -> None: @@ -479,6 +480,71 @@ def test_catch_warning_within_raise(self) -> None: warnings.warn("some warning", category=FutureWarning) raise ValueError("some exception") + def test_skip_within_warns(self, pytester: Pytester) -> None: + """Regression test for #11907.""" + pytester.makepyfile( + """ + import pytest + + def test_it(): + with pytest.warns(Warning): + pytest.skip("this is OK") + """, + ) + + result = pytester.runpytest() + assert result.ret == ExitCode.OK + result.assert_outcomes(skipped=1) + + def test_fail_within_warns(self, pytester: Pytester) -> None: + """Regression test for #11907.""" + pytester.makepyfile( + """ + import pytest + + def test_it(): + with pytest.warns(Warning): + pytest.fail("BOOM") + """, + ) + + result = pytester.runpytest() + assert result.ret == ExitCode.TESTS_FAILED + result.assert_outcomes(failed=1) + assert "DID NOT WARN" not in str(result.stdout) + + def test_exit_within_warns(self, pytester: Pytester) -> None: + """Regression test for #11907.""" + pytester.makepyfile( + """ + import pytest + + def test_it(): + with pytest.warns(Warning): + pytest.exit() + """, + ) + + result = pytester.runpytest() + assert result.ret == ExitCode.INTERRUPTED + result.assert_outcomes() + + def test_keyboard_interrupt_within_warns(self, pytester: Pytester) -> None: + """Regression test for #11907.""" + pytester.makepyfile( + """ + import pytest + + def test_it(): + with pytest.warns(Warning): + raise KeyboardInterrupt() + """, + ) + + result = pytester.runpytest_subprocess() + assert result.ret == ExitCode.INTERRUPTED + result.assert_outcomes() + def test_raise_type_error_on_non_string_warning() -> None: """Check pytest.warns validates warning messages are strings (#10865).""" From dcf9da92be44e5347fdb559c6717c031daae2b25 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 16 Feb 2024 13:38:55 +0200 Subject: [PATCH 0471/1271] recwarn: minor style improvements In preparation for next commit. --- src/_pytest/recwarn.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index ddb240eb2e7..5e1fea2a0b4 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -314,7 +314,7 @@ def __exit__( ): return - def found_str(): + def found_str() -> str: return pformat([record.message for record in self], indent=2) try: @@ -341,14 +341,19 @@ def found_str(): module=w.__module__, source=w.source, ) - # Check warnings has valid argument type (#10865). - wrn: warnings.WarningMessage - for wrn in self: - self._validate_message(wrn) - - @staticmethod - def _validate_message(wrn: Any) -> None: - if not isinstance(msg := wrn.message.args[0], str): - raise TypeError( - f"Warning message must be str, got {msg!r} (type {type(msg).__name__})" - ) + + # Currently in Python it is possible to pass other types than an + # `str` message when creating `Warning` instances, however this + # causes an exception when :func:`warnings.filterwarnings` is used + # to filter those warnings. See + # https://github.com/python/cpython/issues/103577 for a discussion. + # While this can be considered a bug in CPython, we put guards in + # pytest as the error message produced without this check in place + # is confusing (#10865). + for w in self: + msg = w.message.args[0] # type: ignore[union-attr] + if isinstance(msg, str): + continue + raise TypeError( + f"Warning message must be str, got {msg!r} (type {type(msg).__name__})" + ) From 0475b1c925d40930172d5e198861864905a2b15d Mon Sep 17 00:00:00 2001 From: Eero Vaher Date: Fri, 9 Feb 2024 21:13:41 +0100 Subject: [PATCH 0472/1271] Allow using `warnings.warn()` with Warnings Test: `warnings.warn()` expects that its first argument is a `str` or a `Warning`, but since 9454fc38d3636b79ee657d6cacf7477eb8acee52 `pytest.warns()` no longer allows `Warning` instances unless the first argument the `Warning` was initialized with is a `str`. Furthermore, if the `Warning` was created without arguments then `pytest.warns()` raises an unexpected `IndexError`. The new tests reveal the problem. Fix: `pytest.warns()` now allows using `warnings.warn()` with a `Warning` instance, as is required by Python, with one exception. If the warning used is a `UserWarning` that was created by passing it arguments and the first argument was not a `str` then `pytest.raises()` still considers that an error. This is because if an invalid type was used in `warnings.warn()` then Python creates a `UserWarning` anyways and it becomes impossible for `pytest` to figure out if that was done automatically or not. [ran: rebased on previous commit] --- AUTHORS | 1 + changelog/10865.improvement.rst | 3 ++- src/_pytest/recwarn.py | 15 +++++++++++++-- testing/test_recwarn.py | 27 +++++++++++++++++++-------- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/AUTHORS b/AUTHORS index 25159b8b07f..dce91c4fe0e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -127,6 +127,7 @@ Edison Gustavo Muenz Edoardo Batini Edson Tadeu M. Manoel Eduardo Schettino +Eero Vaher Eli Boyarski Elizaveta Shashkova Éloi Rivard diff --git a/changelog/10865.improvement.rst b/changelog/10865.improvement.rst index 2c2856dfe96..a5ced8e9ae3 100644 --- a/changelog/10865.improvement.rst +++ b/changelog/10865.improvement.rst @@ -1,2 +1,3 @@ -:func:`pytest.warns` now validates that warning object's ``message`` is of type `str` -- currently in Python it is possible to pass other types than `str` when creating `Warning` instances, however this causes an exception when :func:`warnings.filterwarnings` is used to filter those warnings. See `CPython #103577 `__ for a discussion. +:func:`pytest.warns` now validates that :func:`warnings.warn` was called with a `str` or a `Warning`. +Currently in Python it is possible to use other types, however this causes an exception when :func:`warnings.filterwarnings` is used to filter those warnings (see `CPython #103577 `__ for a discussion). While this can be considered a bug in CPython, we decided to put guards in pytest as the error message produced without this check in place is confusing. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 5e1fea2a0b4..9eced36ff53 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -351,9 +351,20 @@ def found_str() -> str: # pytest as the error message produced without this check in place # is confusing (#10865). for w in self: - msg = w.message.args[0] # type: ignore[union-attr] + if type(w.message) is not UserWarning: + # If the warning was of an incorrect type then `warnings.warn()` + # creates a UserWarning. Any other warning must have been specified + # explicitly. + continue + if not w.message.args: + # UserWarning() without arguments must have been specified explicitly. + continue + msg = w.message.args[0] if isinstance(msg, str): continue + # It's possible that UserWarning was explicitly specified, and + # its first argument was not a string. But that case can't be + # distinguished from an invalid type. raise TypeError( - f"Warning message must be str, got {msg!r} (type {type(msg).__name__})" + f"Warning must be str or Warning, got {msg!r} (type {type(msg).__name__})" ) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 1feb3e654d4..edd4f51b585 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -3,6 +3,7 @@ from typing import List from typing import Optional from typing import Type +from typing import Union import warnings import pytest @@ -546,24 +547,34 @@ def test_it(): result.assert_outcomes() -def test_raise_type_error_on_non_string_warning() -> None: - """Check pytest.warns validates warning messages are strings (#10865).""" - with pytest.raises(TypeError, match="Warning message must be str"): +def test_raise_type_error_on_invalid_warning() -> None: + """Check pytest.warns validates warning messages are strings (#10865) or + Warning instances (#11959).""" + with pytest.raises(TypeError, match="Warning must be str or Warning"): with pytest.warns(UserWarning): warnings.warn(1) # type: ignore -def test_no_raise_type_error_on_string_warning() -> None: - """Check pytest.warns validates warning messages are strings (#10865).""" - with pytest.warns(UserWarning): - warnings.warn("Warning") +@pytest.mark.parametrize( + "message", + [ + pytest.param("Warning", id="str"), + pytest.param(UserWarning(), id="UserWarning"), + pytest.param(Warning(), id="Warning"), + ], +) +def test_no_raise_type_error_on_valid_warning(message: Union[str, Warning]) -> None: + """Check pytest.warns validates warning messages are strings (#10865) or + Warning instances (#11959).""" + with pytest.warns(Warning): + warnings.warn(message) @pytest.mark.skipif( hasattr(sys, "pypy_version_info"), reason="Not for pypy", ) -def test_raise_type_error_on_non_string_warning_cpython() -> None: +def test_raise_type_error_on_invalid_warning_message_cpython() -> None: # Check that we get the same behavior with the stdlib, at least if filtering # (see https://github.com/python/cpython/issues/103577 for details) with pytest.raises(TypeError): From 9b838f491f895c8b46778c38953295364999aaee Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:01:41 +0200 Subject: [PATCH 0473/1271] recwarn: fix pytest.warns handling of Warnings with multiple arguments Fix #11906 --- changelog/11906.bugfix.rst | 1 + src/_pytest/recwarn.py | 8 ++++---- testing/test_recwarn.py | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 changelog/11906.bugfix.rst diff --git a/changelog/11906.bugfix.rst b/changelog/11906.bugfix.rst new file mode 100644 index 00000000000..68bede540a8 --- /dev/null +++ b/changelog/11906.bugfix.rst @@ -0,0 +1 @@ +Fix regression with :func:`pytest.warns` using custom warning subclasses which have more than one parameter in their `__init__`. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 9eced36ff53..bcf9f1466c5 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -334,10 +334,10 @@ def found_str() -> str: for w in self: if not self.matches(w): warnings.warn_explicit( - str(w.message), - w.message.__class__, # type: ignore[arg-type] - w.filename, - w.lineno, + message=w.message, + category=w.category, + filename=w.filename, + lineno=w.lineno, module=w.__module__, source=w.source, ) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index edd4f51b585..27ee9aa72f0 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -581,3 +581,17 @@ def test_raise_type_error_on_invalid_warning_message_cpython() -> None: with warnings.catch_warnings(): warnings.filterwarnings("ignore", "test") warnings.warn(1) # type: ignore + + +def test_multiple_arg_custom_warning() -> None: + """Test for issue #11906.""" + + class CustomWarning(UserWarning): + def __init__(self, a, b): + pass + + with pytest.warns(CustomWarning): + with pytest.raises(pytest.fail.Exception, match="DID NOT WARN"): + with pytest.warns(CustomWarning, match="not gonna match"): + a, b = 1, 2 + warnings.warn(CustomWarning(a, b)) From 22b541e4eb46d53370938da239c686eaecbbf8e4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 17 Feb 2024 00:09:47 +0200 Subject: [PATCH 0474/1271] Merge pull request #11993 from pytest-dev/release-8.0.1 Prepare release 8.0.1 (cherry picked from commit 68524d48586e7f8d070fc1146e5ff90e770d0382) --- changelog/11875.bugfix.rst | 1 - changelog/11879.bugfix.rst | 1 - changelog/11906.bugfix.rst | 1 - changelog/11907.bugfix.rst | 1 - changelog/11929.bugfix.rst | 1 - changelog/11937.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.0.1.rst | 21 +++++++++++++++++++ doc/en/builtin.rst | 34 ++++++++++++++----------------- doc/en/changelog.rst | 24 ++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/getting-started.rst | 2 +- doc/en/reference/reference.rst | 2 +- 13 files changed, 66 insertions(+), 30 deletions(-) delete mode 100644 changelog/11875.bugfix.rst delete mode 100644 changelog/11879.bugfix.rst delete mode 100644 changelog/11906.bugfix.rst delete mode 100644 changelog/11907.bugfix.rst delete mode 100644 changelog/11929.bugfix.rst delete mode 100644 changelog/11937.bugfix.rst create mode 100644 doc/en/announce/release-8.0.1.rst diff --git a/changelog/11875.bugfix.rst b/changelog/11875.bugfix.rst deleted file mode 100644 index d646be6314f..00000000000 --- a/changelog/11875.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Correctly handle errors from :func:`getpass.getuser` in Python 3.13. diff --git a/changelog/11879.bugfix.rst b/changelog/11879.bugfix.rst deleted file mode 100644 index 70b6cce72e7..00000000000 --- a/changelog/11879.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix an edge case where ``ExceptionInfo._stringify_exception`` could crash :func:`pytest.raises`. diff --git a/changelog/11906.bugfix.rst b/changelog/11906.bugfix.rst deleted file mode 100644 index 68bede540a8..00000000000 --- a/changelog/11906.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix regression with :func:`pytest.warns` using custom warning subclasses which have more than one parameter in their `__init__`. diff --git a/changelog/11907.bugfix.rst b/changelog/11907.bugfix.rst deleted file mode 100644 index 10aa39aeb0c..00000000000 --- a/changelog/11907.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.0.0 whereby calling :func:`pytest.skip` and similar control-flow exceptions within a :func:`pytest.warns()` block would get suppressed instead of propagating. diff --git a/changelog/11929.bugfix.rst b/changelog/11929.bugfix.rst deleted file mode 100644 index 8ab50e6f451..00000000000 --- a/changelog/11929.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.0.0 whereby autouse fixtures defined in a module get ignored by the doctests in the module. diff --git a/changelog/11937.bugfix.rst b/changelog/11937.bugfix.rst deleted file mode 100644 index 3b15fb528e9..00000000000 --- a/changelog/11937.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.0.0 whereby items would be collected in reverse order in some circumstances. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 120aae6626e..78045114667 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.0.1 release-8.0.0 release-8.0.0rc2 release-8.0.0rc1 diff --git a/doc/en/announce/release-8.0.1.rst b/doc/en/announce/release-8.0.1.rst new file mode 100644 index 00000000000..7d828e55bd9 --- /dev/null +++ b/doc/en/announce/release-8.0.1.rst @@ -0,0 +1,21 @@ +pytest-8.0.1 +======================================= + +pytest 8.0.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Clément Robert +* Pierre Sassoulas +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index c565a87c469..e9e42b9e8ca 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:526 + cache -- .../_pytest/cacheprovider.py:527 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1008 + capsysbinary -- .../_pytest/capture.py:1007 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -43,7 +43,6 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[bytes] `. Example: - .. code-block:: python def test_output(capsysbinary): @@ -51,7 +50,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1036 + capfd -- .../_pytest/capture.py:1034 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -61,7 +60,6 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[str] `. Example: - .. code-block:: python def test_system_echo(capfd): @@ -69,7 +67,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1064 + capfdbinary -- .../_pytest/capture.py:1061 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -79,7 +77,6 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[bytes] `. Example: - .. code-block:: python def test_system_echo(capfdbinary): @@ -97,7 +94,6 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[str] `. Example: - .. code-block:: python def test_output(capsys): @@ -105,7 +101,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:743 + doctest_namespace [session scope] -- .../_pytest/doctest.py:745 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -119,7 +115,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1365 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1354 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -129,7 +125,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a if pytestconfig.getoption("verbose") > 0: ... - record_property -- .../_pytest/junitxml.py:284 + record_property -- .../_pytest/junitxml.py:283 Add extra properties to the calling test. User properties become part of the test report and are available to the @@ -143,13 +139,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a def test_function(record_property): record_property("example_key", 1) - record_xml_attribute -- .../_pytest/junitxml.py:307 + record_xml_attribute -- .../_pytest/junitxml.py:306 Add extra xml attributes to the tag for the calling test. The fixture is callable with ``name, value``. The value is automatically XML-encoded. - record_testsuite_property [session scope] -- .../_pytest/junitxml.py:345 + record_testsuite_property [session scope] -- .../_pytest/junitxml.py:344 Record a new ```` tag as child of the root ````. This is suitable to writing global information regarding the entire test @@ -174,10 +170,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a `pytest-xdist `__ plugin. See :issue:`7767` for details. - tmpdir_factory [session scope] -- .../_pytest/legacypath.py:300 + tmpdir_factory [session scope] -- .../_pytest/legacypath.py:302 Return a :class:`pytest.TempdirFactory` instance for the test session. - tmpdir -- .../_pytest/legacypath.py:307 + tmpdir -- .../_pytest/legacypath.py:309 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. @@ -207,7 +203,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a * caplog.record_tuples -> list of (logger_name, level, message) tuples * caplog.clear() -> clear captured records and formatted log output string - monkeypatch -- .../_pytest/monkeypatch.py:30 + monkeypatch -- .../_pytest/monkeypatch.py:32 A convenient fixture for monkey-patching. The fixture provides these methods to modify objects, dictionaries, or @@ -231,16 +227,16 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a To undo modifications done by the fixture in a contained scope, use :meth:`context() `. - recwarn -- .../_pytest/recwarn.py:30 + recwarn -- .../_pytest/recwarn.py:32 Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information on warning categories. - tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:239 + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:241 Return a :class:`pytest.TempPathFactory` instance for the test session. - tmp_path -- .../_pytest/tmpdir.py:254 + tmp_path -- .../_pytest/tmpdir.py:256 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 6f67b7ba16c..6ed764207e6 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,30 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.0.1 (2024-02-16) +========================= + +Bug Fixes +--------- + +- `#11875 `_: Correctly handle errors from :func:`getpass.getuser` in Python 3.13. + + +- `#11879 `_: Fix an edge case where ``ExceptionInfo._stringify_exception`` could crash :func:`pytest.raises`. + + +- `#11906 `_: Fix regression with :func:`pytest.warns` using custom warning subclasses which have more than one parameter in their `__init__`. + + +- `#11907 `_: Fix a regression in pytest 8.0.0 whereby calling :func:`pytest.skip` and similar control-flow exceptions within a :func:`pytest.warns()` block would get suppressed instead of propagating. + + +- `#11929 `_: Fix a regression in pytest 8.0.0 whereby autouse fixtures defined in a module get ignored by the doctests in the module. + + +- `#11937 `_: Fix a regression in pytest 8.0.0 whereby items would be collected in reverse order in some circumstances. + + pytest 8.0.0 (2024-01-27) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 207aa145bc6..99afaded84c 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -503,10 +503,10 @@ Running it results in some skips if we don't have all the python interpreters in .. code-block:: pytest . $ pytest -rs -q multipython.py - ssssssssssssssssssssssss... [100%] + ssssssssssss...ssssssssssss [100%] ========================= short test summary info ========================== - SKIPPED [12] multipython.py:68: 'python3.9' not found - SKIPPED [12] multipython.py:68: 'python3.10' not found + SKIPPED [12] multipython.py:65: 'python3.9' not found + SKIPPED [12] multipython.py:65: 'python3.11' not found 3 passed, 24 skipped in 0.12s Parametrization of optional implementations/imports diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 48af9d9754e..114d69328c2 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.0.0 + pytest 8.0.1 .. _`simpletest`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 4f0b1835b4d..1076026c205 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2028,7 +2028,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: failure --doctest-glob=pat Doctests file matching pattern, default: test*.txt --doctest-ignore-import-errors - Ignore doctest ImportErrors + Ignore doctest collection errors --doctest-continue-on-failure For a given doctest, continue to run after the first failure From 9f13d41d7bf773d9a64ff84f7c26fec7fbd431cf Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 17 Feb 2024 12:13:57 +0200 Subject: [PATCH 0475/1271] code: fix `IndexError` crash in `getstatementrange_ast` Fix #11953. --- changelog/11953.bugfix.rst | 1 + src/_pytest/_code/source.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelog/11953.bugfix.rst diff --git a/changelog/11953.bugfix.rst b/changelog/11953.bugfix.rst new file mode 100644 index 00000000000..5aff5f7fdb7 --- /dev/null +++ b/changelog/11953.bugfix.rst @@ -0,0 +1 @@ +Fix an ``IndexError`` crash raising from ``getstatementrange_ast``. diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index 69f580e2055..dac3c3867d8 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -197,7 +197,9 @@ def getstatementrange_ast( # by using the BlockFinder helper used which inspect.getsource() uses itself. block_finder = inspect.BlockFinder() # If we start with an indented line, put blockfinder to "started" mode. - block_finder.started = source.lines[start][0].isspace() + block_finder.started = ( + bool(source.lines[start]) and source.lines[start][0].isspace() + ) it = ((x + "\n") for x in source.lines[start:end]) try: for tok in tokenize.generate_tokens(lambda: next(it)): From 5f241f388be3aaf4faa5e5e0029548863413014f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 17 Feb 2024 16:10:21 -0300 Subject: [PATCH 0476/1271] Revert sys.platform verification to simple comparison (#11998) As the comment above it states, we need to keep the comparison simple so mypy can understand it, otherwise it will fail to properly handle this on Windows and will flag ``os.getuid()`` missing. --- src/_pytest/compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 077fa65da2f..fa387f6db12 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -289,7 +289,7 @@ def get_user_id() -> int | None: # mypy follows the version and platform checking expectation of PEP 484: # https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks # Containment checks are too complex for mypy v1.5.0 and cause failure. - if sys.platform in {"win32", "emscripten"}: + if sys.platform == "win32" or sys.platform == "emscripten": # noqa: PLR1714 # win32 does not have a getuid() function. # Emscripten has a return 0 stub. return None From cefb3e2277b6ea24acc7b1088f80ef0f9e9f3858 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 17 Feb 2024 17:46:58 -0300 Subject: [PATCH 0477/1271] Disallow Sphinx 6 and 7 (#12000) Using Sphinx 6.x and 7.x the search bar disappears. Restrict to Sphinx 5.x for now until we find a solution. Reverts #11568 Fixes #11988 --- doc/en/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 36801746aae..3369bd10b76 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -2,7 +2,8 @@ pallets-sphinx-themes pluggy>=1.2.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 -sphinx>=5,<8 +# In Sphinx 6 and 7, the search bar disappears; restrict this for now until we find a solution. +sphinx>=5,<6 sphinxcontrib-trio sphinxcontrib-svg2pdfconverter # Pin packaging because it no longer handles 'latest' version, which From 52da8dd66c9eaba3c8557f80fc9a5b87a4ea03b1 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 18 Feb 2024 00:19:26 +0000 Subject: [PATCH 0478/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 408 +++++++++++++++++++++++-------- 1 file changed, 312 insertions(+), 96 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index ce1e4f6bd0a..f9d3d02f059 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -7,7 +7,7 @@ Pytest Plugin List ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with "pytest-" and a handful of manually selected projects. +It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, @@ -27,7 +27,7 @@ please refer to `the update script =7,<9) ; extra == "pytest" :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A - :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 21, 2022 N/A pytest (>=6,<8) + :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Feb 10, 2024 N/A pytest (>=6) :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Nov 08, 2023 N/A pytest >=5.4.0 :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) @@ -67,7 +68,7 @@ This list contains 1367 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Feb 06, 2024 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Feb 12, 2024 N/A pytest >=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -104,9 +105,10 @@ This list contains 1367 plugins. :pypi:`pytest-astropy` Meta-package containing dependencies for testing Sep 26, 2023 5 - Production/Stable pytest >=4.6 :pypi:`pytest-astropy-header` pytest plugin to add diagnostic information to the header of the test output Sep 06, 2022 3 - Alpha pytest (>=4.6) :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest + :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Feb 09, 2024 4 - Beta pytest <9,>=7.0.0 - :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Nov 30, 2023 N/A N/A + :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 12, 2024 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) @@ -144,12 +146,14 @@ This list contains 1367 plugins. :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A + :pypi:`pytest-behave` A powerful test automation framework designed to provide a comprehensive solution for testing user interfaces and APIs Feb 15, 2024 N/A N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) + :pypi:`pytest-bisect-tests` Find tests leaking state and affecting other Feb 17, 2024 N/A N/A :pypi:`pytest-black` A pytest plugin to enable format checking with black Oct 05, 2020 4 - Beta N/A :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) @@ -169,6 +173,7 @@ This list contains 1367 plugins. :pypi:`pytest-briefcase` A pytest plugin for running tests on a Briefcase project. Jun 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-browser` A pytest plugin for console based browser test selection just after the collection phase Dec 10, 2016 3 - Alpha N/A :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A + :pypi:`pytest_browserstack` Py.test plugin for BrowserStack Jan 27, 2016 4 - Beta N/A :pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Sep 23, 2023 5 - Production/Stable pytest >=7.1.0 @@ -192,7 +197,7 @@ This list contains 1367 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Jan 14, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Feb 12, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A @@ -211,12 +216,14 @@ This list contains 1367 plugins. :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 Feb 04, 2024 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_cid` Compare data structures containing matching CIDs of different versions and encoding Sep 01, 2023 4 - Beta pytest >= 5.0, < 7.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 :pypi:`pytest-circleci-parallelized-rjp` Parallelize pytest across CircleCI workers. Jun 21, 2022 N/A pytest :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) + :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 25, 2023 4 - Beta N/A :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) @@ -227,6 +234,7 @@ This list contains 1367 plugins. :pypi:`pytest-cmake` Provide CMake module for Pytest Jul 19, 2023 N/A pytest<8,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) + :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Nov 29, 2022 4 - Beta pytest (>=4.6.0) @@ -263,6 +271,7 @@ This list contains 1367 plugins. :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' + :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 26, 2023 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) @@ -297,7 +306,7 @@ This list contains 1367 plugins. :pypi:`pytest-datafixtures` Data fixtures for pytest made simple Dec 05, 2020 5 - Production/Stable N/A :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A - :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jan 31, 2024 5 - Production/Stable pytest + :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Feb 15, 2024 5 - Production/Stable pytest :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A :pypi:`pytest-data-suites` Class-based pytest parametrization Jul 24, 2022 N/A pytest (>=6.0,<8.0) :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) @@ -401,7 +410,7 @@ This list contains 1367 plugins. :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Jun 12, 2023 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A - :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Jan 27, 2024 N/A N/A + :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Feb 16, 2024 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A :pypi:`pytest-easyread` pytest plugin that makes terminal printouts of the reports easier to read Nov 17, 2017 N/A N/A :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" @@ -414,14 +423,14 @@ This list contains 1367 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. Jan 22, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Feb 14, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 14, 2024 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) @@ -438,13 +447,16 @@ This list contains 1367 plugins. :pypi:`pytest-envvars` Pytest plugin to validate use of envvars on your tests Jun 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-env-yaml` Apr 02, 2019 N/A N/A :pypi:`pytest-eradicate` pytest plugin to check for commented out code Sep 08, 2020 N/A pytest (>=2.4.2) + :pypi:`pytest_erp` py.test plugin to send test info to report portal dynamically Jan 13, 2015 N/A N/A :pypi:`pytest-error-for-skips` Pytest plugin to treat skipped tests a test failure Dec 19, 2019 4 - Beta pytest (>=4.6) :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Jan 24, 2024 4 - Beta pytest (>=7.4.3,<8.0.0) + :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 + :pypi:`pytest-exasol-itde` Feb 15, 2024 N/A pytest (>=7,<9) :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -461,6 +473,7 @@ This list contains 1367 plugins. :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest + :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A @@ -472,7 +485,7 @@ This list contains 1367 plugins. :pypi:`pytest-failed-screen-record` Create a video of the screen when pytest fails Jan 05, 2023 4 - Beta pytest (>=7.1.2d,<8.0.0) :pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A :pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0) - :pypi:`pytest-fail-slow` Fail tests that take too long to run Oct 21, 2023 N/A pytest >=6.0 + :pypi:`pytest-fail-slow` Fail tests that take too long to run Feb 11, 2024 N/A pytest>=7.0 :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A :pypi:`pytest-falcon-client` Pytest \`client\` fixture for the Falcon Framework Mar 19, 2019 N/A N/A @@ -500,6 +513,7 @@ This list contains 1367 plugins. :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A :pypi:`pytest-fixture-order` pytest plugin to control fixture evaluation order May 16, 2022 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-fixture-ref` Lets users reference fixtures without name matching magic. Nov 17, 2022 4 - Beta N/A + :pypi:`pytest-fixture-remover` A LibCST codemod to remove pytest fixtures applied via the usefixtures decorator, as well as its parametrizations. Feb 14, 2024 5 - Production/Stable N/A :pypi:`pytest-fixture-rtttg` Warn or fail on fixture name clash Feb 23, 2022 N/A pytest (>=7.0.1,<8.0.0) :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest @@ -533,15 +547,16 @@ This list contains 1367 plugins. :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 Feb 07, 2024 4 - Beta pytest >=6.0.0 + :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A :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. Dec 18, 2023 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Feb 15, 2024 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-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. Jan 29, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Feb 15, 2024 N/A pytest>=3.6 :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 @@ -564,6 +579,7 @@ This list contains 1367 plugins. :pypi:`pytest-growl` Growl notifications for pytest results. Jan 13, 2014 5 - Production/Stable N/A :pypi:`pytest-grpc` pytest plugin for grpc May 01, 2020 N/A pytest (>=3.6.0) :pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Feb 05, 2023 N/A N/A + :pypi:`pytest_gui_status` Show pytest status in gui Jan 23, 2016 N/A pytest :pypi:`pytest-hammertime` Display "🔨 " instead of "." for passed pytest tests. Jul 28, 2018 N/A pytest :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Jun 10, 2022 5 - Production/Stable N/A @@ -579,7 +595,7 @@ This list contains 1367 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Feb 10, 2024 3 - Alpha pytest ==7.4.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 17, 2024 3 - Alpha pytest ==7.4.4 :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` Jan 06, 2024 N/A N/A @@ -602,7 +618,7 @@ This list contains 1367 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest-httpserver` pytest-httpserver is a httpserver for pytest May 22, 2023 3 - Alpha N/A + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 13, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Jan 29, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -651,6 +667,7 @@ This list contains 1367 plugins. :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A + :pypi:`pytest_jar_yuan` A allure and pytest used package Dec 12, 2022 N/A N/A :pypi:`pytest-jasmine` Run jasmine tests from your pytest test suite Nov 04, 2017 1 - Planning N/A :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) @@ -718,7 +735,7 @@ This list contains 1367 plugins. :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) :pypi:`pytest-logdog` Pytest plugin to test logging Jun 15, 2021 1 - Planning pytest (>=6.2.0) :pypi:`pytest-logfest` Pytest plugin providing three logger fixtures with basic or full writing to log files Jul 21, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Jul 25, 2019 4 - Beta pytest (>=3.2) + :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Feb 12, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logikal` Common testing environment Feb 05, 2024 5 - Production/Stable pytest ==8.0.0 @@ -745,7 +762,7 @@ This list contains 1367 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Feb 04, 2024 4 - Beta pytest !=6.0.0,<9,>=3.3.2 - :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Jan 19, 2024 N/A pytest (>=7.4.3) + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Feb 15, 2024 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 @@ -754,9 +771,9 @@ This list contains 1367 plugins. :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A - :pypi:`pytest-metadata` pytest plugin for test session metadata Feb 01, 2024 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-metadata` pytest plugin for test session metadata Feb 12, 2024 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 Jan 16, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Feb 15, 2024 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) @@ -789,7 +806,7 @@ This list contains 1367 plugins. :pypi:`pytest-mp` A test batcher for multiprocessed Pytest runs May 23, 2018 4 - Beta pytest :pypi:`pytest-mpi` pytest plugin to collect information from tests Jan 08, 2022 3 - Alpha pytest :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest - :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Jul 23, 2022 4 - Beta pytest + :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Feb 14, 2024 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Aug 03, 2023 4 - Beta pytest (<8) ; extra == 'test' :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A @@ -815,7 +832,7 @@ This list contains 1367 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jan 11, 2024 N/A pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Feb 16, 2024 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A @@ -823,12 +840,14 @@ This list contains 1367 plugins. :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A + :pypi:`pytest_notebook` A pytest plugin for testing Jupyter Notebooks. Nov 28, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-notice` Send pytest execution result email Nov 05, 2020 N/A N/A :pypi:`pytest-notification` A pytest plugin for sending a desktop notification and playing a sound upon completion of tests Jun 19, 2020 N/A pytest (>=4) :pypi:`pytest-notifier` A pytest plugin to notify test result Jun 12, 2020 3 - Alpha pytest + :pypi:`pytest_notify` Get notifications when your tests ends Jul 05, 2017 N/A pytest>=3.0.0 :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A - :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Oct 11, 2023 5 - Production/Stable N/A + :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Feb 13, 2024 5 - Production/Stable N/A :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A @@ -853,7 +872,7 @@ This list contains 1367 plugins. :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 - :pypi:`pytest-otel` pytest-otel report OpenTelemetry traces about test executed Jan 18, 2023 N/A N/A + :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Feb 16, 2024 N/A pytest==7.1.3 :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A :pypi:`pytest-owner` Add owner mark for tests Apr 25, 2022 N/A N/A :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A @@ -863,11 +882,12 @@ This list contains 1367 plugins. :pypi:`pytest-parallelize-tests` pytest plugin that parallelizes test execution across multiple hosts Jan 27, 2023 4 - Beta N/A :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) - :pypi:`pytest-parameterize-from-files` A pytest plugin that parameterizes tests from data files. Feb 09, 2024 4 - Beta pytest>=7.2.0 + :pypi:`pytest-parameterize-from-files` A pytest plugin that parameterizes tests from data files. Feb 15, 2024 4 - Beta pytest>=7.2.0 :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest + :pypi:`pytest_param_files` Create pytest parametrize decorators from external files. Jul 29, 2023 N/A pytest :pypi:`pytest-param-scope` pytest parametrize scope fixture workaround Oct 18, 2023 N/A pytest :pypi:`pytest-parawtf` Finally spell paramete?ri[sz]e correctly Dec 03, 2018 4 - Beta pytest (>=3.6.0) :pypi:`pytest-pass` Check out https://github.com/elilutsky/pytest-pass Dec 04, 2019 N/A N/A @@ -881,6 +901,7 @@ This list contains 1367 plugins. :pypi:`pytest-pep257` py.test plugin for pep257 Jul 09, 2016 N/A N/A :pypi:`pytest-pep8` pytest plugin to check PEP8 requirements Apr 27, 2014 N/A N/A :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) + :pypi:`pytest-percents` Feb 10, 2024 N/A N/A :pypi:`pytest-perf` Run performance tests against the mainline code. Jan 28, 2024 5 - Production/Stable pytest >=6 ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A @@ -919,7 +940,7 @@ This list contains 1367 plugins. :pypi:`pytest-ponyorm` PonyORM in Pytest Oct 31, 2018 N/A pytest (>=3.1.1) :pypi:`pytest-poo` Visualize your crappy tests Mar 25, 2021 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A - :pypi:`pytest-pook` Pytest plugin for pook Dec 23, 2023 4 - Beta pytest + :pypi:`pytest-pook` Pytest plugin for pook Feb 15, 2024 4 - Beta pytest :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) @@ -978,6 +999,7 @@ This list contains 1367 plugins. :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) + :pypi:`pytest_quickify` Run test suites with pytest-quickify. Jun 14, 2019 N/A pytest :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Jul 05, 2023 5 - Production/Stable pytest (>=6.2) :pypi:`pytest-race` Race conditions tester for pytest Jun 07, 2022 4 - Beta N/A :pypi:`pytest-rage` pytest plugin to implement PEP712 Oct 21, 2011 3 - Alpha N/A @@ -991,6 +1013,7 @@ This list contains 1367 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Feb 17, 2024 4 - Beta pytest >=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable 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 @@ -1013,6 +1036,7 @@ This list contains 1367 plugins. :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest + :pypi:`pytest_repeater` py.test plugin for repeating single test multiple times. Feb 09, 2018 1 - Planning N/A :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jan 11, 2024 5 - Production/Stable pytest :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A @@ -1037,7 +1061,7 @@ This list contains 1367 plugins. :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. Feb 08, 2024 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jan 10, 2024 N/A pytest ~=4.6 ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Feb 14, 2024 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 @@ -1061,6 +1085,7 @@ This list contains 1367 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Feb 08, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1083,16 +1108,17 @@ This list contains 1367 plugins. :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 29, 2024 5 - Production/Stable N/A + :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 17, 2024 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-schema` 👍 Validate return values against a schema-like object in testing Feb 16, 2024 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 Feb 01, 2024 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. Jan 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Feb 17, 2024 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 @@ -1100,7 +1126,7 @@ This list contains 1367 plugins. :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Dec 19, 2023 3 - Alpha pytest >=6.2 + :pypi:`pytest-servers` pytest servers Feb 14, 2024 3 - Alpha pytest >=6.2 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1167,7 +1193,7 @@ This list contains 1367 plugins. :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 Jan 12, 2024 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-addon-ui-smartx` Library to support testing Splunk Add-on UX Feb 13, 2024 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 @@ -1208,6 +1234,7 @@ This list contains 1367 plugins. :pypi:`pytest-synodic` Synodic Pytest utilities Jan 12, 2024 N/A pytest>=7.4.4 :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A + :pypi:`pytest_tagging` a pytest plugin to tag tests Feb 15, 2024 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) @@ -1215,7 +1242,6 @@ This list contains 1367 plugins. :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) - :pypi:`pytest-tcp` A Pytest plugin for test prioritization Dec 10, 2023 4 - Beta pytest >=7.4.3 :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A @@ -1231,7 +1257,7 @@ This list contains 1367 plugins. :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A - :pypi:`pytest-testinfra` Test infrastructures Nov 13, 2023 5 - Production/Stable pytest !=3.0.2 + :pypi:`pytest-testinfra` Test infrastructures Feb 15, 2024 5 - Production/Stable pytest >=6 :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) @@ -1256,7 +1282,7 @@ This list contains 1367 plugins. :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 - :pypi:`pytest-tesults` Tesults plugin for pytest Jul 21, 2023 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A @@ -1332,7 +1358,7 @@ This list contains 1367 plugins. :pypi:`pytest-variables` pytest plugin for providing variables to tests/fixtures Feb 01, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-variant` Variant support for Pytest Jun 06, 2022 N/A N/A :pypi:`pytest-vcr` Plugin for managing VCR.py cassettes Apr 26, 2019 5 - Production/Stable pytest (>=3.6.0) - :pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Jun 20, 2022 5 - Production/Stable pytest (>=6.2.2) + :pypi:`pytest-vcr-delete-on-fail` A pytest plugin that automates vcrpy cassettes deletion on test failure. Feb 16, 2024 5 - Production/Stable pytest (>=8.0.0,<9.0.0) :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 Nov 23, 2023 4 - Beta pytest @@ -1353,6 +1379,7 @@ This list contains 1367 plugins. :pypi:`pytest-wake` Nov 07, 2023 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Feb 06, 2024 4 - Beta N/A + :pypi:`pytest_wdb` Trace pytest tests with wdb to halt on error with --wdb. Jul 04, 2016 N/A N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest @@ -1413,6 +1440,13 @@ This list contains 1367 plugins. Simple but powerful assertion and verification of logged lines. + :pypi:`logot` + *last release*: Feb 17, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest (>=7,<9) ; extra == "pytest" + + Test whether your code is logging correctly 🪵 + :pypi:`nuts` *last release*: Aug 11, 2023, *status*: N/A, @@ -1435,9 +1469,9 @@ This list contains 1367 plugins. A contextmanager pytest fixture for handling multiple mock abstracts :pypi:`pytest-accept` - *last release*: Dec 21, 2022, + *last release*: Feb 10, 2024, *status*: N/A, - *requires*: pytest (>=6,<8) + *requires*: pytest (>=6) A pytest-plugin for updating doctest outputs @@ -1638,7 +1672,7 @@ This list contains 1367 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Feb 06, 2024, + *last release*: Feb 12, 2024, *status*: N/A, *requires*: pytest >=7.3.1 @@ -1896,6 +1930,13 @@ This list contains 1367 plugins. + :pypi:`pytest_async` + *last release*: Feb 26, 2020, + *status*: N/A, + *requires*: N/A + + pytest-async - Run your coroutine in event loop without decorator + :pypi:`pytest-async-generators` *last release*: Jul 05, 2023, *status*: N/A, @@ -1911,7 +1952,7 @@ This list contains 1367 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-cooperative` - *last release*: Nov 30, 2023, + *last release*: Feb 12, 2024, *status*: N/A, *requires*: N/A @@ -2176,6 +2217,13 @@ This list contains 1367 plugins. use icdiff for better error messages in pytest assertions + :pypi:`pytest-behave` + *last release*: Feb 15, 2024, + *status*: N/A, + *requires*: N/A + + A powerful test automation framework designed to provide a comprehensive solution for testing user interfaces and APIs + :pypi:`pytest-bench` *last release*: Jul 21, 2014, *status*: 3 - Alpha, @@ -2218,6 +2266,13 @@ This list contains 1367 plugins. Provides a mock fixture for python bigquery client + :pypi:`pytest-bisect-tests` + *last release*: Feb 17, 2024, + *status*: N/A, + *requires*: N/A + + Find tests leaking state and affecting other + :pypi:`pytest-black` *last release*: Oct 05, 2020, *status*: 4 - Beta, @@ -2351,6 +2406,13 @@ This list contains 1367 plugins. BrowserMob proxy plugin for py.test. + :pypi:`pytest_browserstack` + *last release*: Jan 27, 2016, + *status*: 4 - Beta, + *requires*: N/A + + Py.test plugin for BrowserStack + :pypi:`pytest-browserstack-local` *last release*: Feb 09, 2018, *status*: N/A, @@ -2513,7 +2575,7 @@ This list contains 1367 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Jan 14, 2024, + *last release*: Feb 12, 2024, *status*: N/A, *requires*: N/A @@ -2645,6 +2707,13 @@ This list contains 1367 plugins. Run only a chunk of your test suite + :pypi:`pytest_cid` + *last release*: Sep 01, 2023, + *status*: 4 - Beta, + *requires*: pytest >= 5.0, < 7.0 + + Compare data structures containing matching CIDs of different versions and encoding + :pypi:`pytest-circleci` *last release*: May 03, 2019, *status*: N/A, @@ -2687,6 +2756,13 @@ This list contains 1367 plugins. Easy quality control for CLDF datasets using pytest + :pypi:`pytest_cleanup` + *last release*: Jan 28, 2020, + *status*: N/A, + *requires*: N/A + + Automated, comprehensive and well-organised pytest test cases. + :pypi:`pytest-cleanuptotal` *last release*: Sep 25, 2023, *status*: 4 - Beta, @@ -2757,6 +2833,13 @@ This list contains 1367 plugins. PyTest plugin for testing Smart Contracts for Ethereum blockchain. + :pypi:`pytest_codeblocks` + *last release*: Sep 17, 2023, + *status*: 5 - Production/Stable, + *requires*: pytest >= 7.0.0 + + Test code blocks in your READMEs + :pypi:`pytest-codecarbon` *last release*: Jun 15, 2022, *status*: N/A, @@ -3009,6 +3092,13 @@ This list contains 1367 plugins. Pytest plugin for excluding tests based on coverage data + :pypi:`pytest_covid` + *last release*: Jun 24, 2020, + *status*: N/A, + *requires*: N/A + + Too many faillure, less tests. + :pypi:`pytest-cpp` *last release*: Nov 01, 2023, *status*: 5 - Production/Stable, @@ -3248,7 +3338,7 @@ This list contains 1367 plugins. A pytest plugin for managing an archive of test data. :pypi:`pytest-datarecorder` - *last release*: Jan 31, 2024, + *last release*: Feb 15, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -3976,7 +4066,7 @@ This list contains 1367 plugins. pytest-easy-addoption: Easy way to work with pytest addoption :pypi:`pytest-easy-api` - *last release*: Jan 27, 2024, + *last release*: Feb 16, 2024, *status*: N/A, *requires*: N/A @@ -4067,56 +4157,56 @@ This list contains 1367 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Jan 22, 2024, + *last release*: Feb 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4234,6 +4324,13 @@ This list contains 1367 plugins. pytest plugin to check for commented out code + :pypi:`pytest_erp` + *last release*: Jan 13, 2015, + *status*: N/A, + *requires*: N/A + + py.test plugin to send test info to report portal dynamically + :pypi:`pytest-error-for-skips` *last release*: Dec 19, 2019, *status*: 4 - Beta, @@ -4276,6 +4373,13 @@ This list contains 1367 plugins. The testing package containing tools to test Web3-based projects + :pypi:`pytest_exact_fixtures` + *last release*: Feb 04, 2019, + *status*: N/A, + *requires*: N/A + + Parse queries in Lucene and Elasticsearch syntaxes + :pypi:`pytest-examples` *last release*: Jul 11, 2023, *status*: 4 - Beta, @@ -4283,6 +4387,13 @@ This list contains 1367 plugins. Pytest plugin for testing examples in docstrings and markdown files. + :pypi:`pytest-exasol-itde` + *last release*: Feb 15, 2024, + *status*: N/A, + *requires*: pytest (>=7,<9) + + + :pypi:`pytest-excel` *last release*: Sep 14, 2023, *status*: 5 - Production/Stable, @@ -4395,6 +4506,13 @@ This list contains 1367 plugins. a special outcome for tests that are blocked for external reasons + :pypi:`pytest_extra` + *last release*: Aug 14, 2014, + *status*: N/A, + *requires*: N/A + + Some helpers for writing tests with pytest. + :pypi:`pytest-extra-durations` *last release*: Apr 21, 2020, *status*: 4 - Beta, @@ -4473,9 +4591,9 @@ This list contains 1367 plugins. A pytest plugin that helps better distinguishing real test failures from setup flakiness. :pypi:`pytest-fail-slow` - *last release*: Oct 21, 2023, + *last release*: Feb 11, 2024, *status*: N/A, - *requires*: pytest >=6.0 + *requires*: pytest>=7.0 Fail tests that take too long to run @@ -4668,6 +4786,13 @@ This list contains 1367 plugins. Lets users reference fixtures without name matching magic. + :pypi:`pytest-fixture-remover` + *last release*: Feb 14, 2024, + *status*: 5 - Production/Stable, + *requires*: N/A + + A LibCST codemod to remove pytest fixtures applied via the usefixtures decorator, as well as its parametrizations. + :pypi:`pytest-fixture-rtttg` *last release*: Feb 23, 2022, *status*: N/A, @@ -4899,6 +5024,13 @@ This list contains 1367 plugins. fzf-based test selector for pytest + :pypi:`pytest_gae` + *last release*: Aug 03, 2016, + *status*: 3 - Alpha, + *requires*: N/A + + pytest plugin for apps written with Google's AppEngine + :pypi:`pytest-gather-fixtures` *last release*: Apr 12, 2022, *status*: N/A, @@ -4921,7 +5053,7 @@ This list contains 1367 plugins. Uses gcov to measure test coverage of a C library :pypi:`pytest-gee` - *last release*: Dec 18, 2023, + *last release*: Feb 15, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -4956,7 +5088,7 @@ This list contains 1367 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jan 29, 2024, + *last release*: Feb 15, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5116,6 +5248,13 @@ This list contains 1367 plugins. Py.Test plugin for Grunnur-based packages. + :pypi:`pytest_gui_status` + *last release*: Jan 23, 2016, + *status*: N/A, + *requires*: pytest + + Show pytest status in gui + :pypi:`pytest-hammertime` *last release*: Jul 28, 2018, *status*: N/A, @@ -5222,7 +5361,7 @@ This list contains 1367 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 10, 2024, + *last release*: Feb 17, 2024, *status*: 3 - Alpha, *requires*: pytest ==7.4.4 @@ -5382,8 +5521,8 @@ This list contains 1367 plugins. A thin wrapper of HTTPretty for pytest - :pypi:`pytest-httpserver` - *last release*: May 22, 2023, + :pypi:`pytest_httpserver` + *last release*: Feb 13, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -5725,6 +5864,13 @@ This list contains 1367 plugins. A contextmanager pytest fixture for handling multiple mock iters + :pypi:`pytest_jar_yuan` + *last release*: Dec 12, 2022, + *status*: N/A, + *requires*: N/A + + A allure and pytest used package + :pypi:`pytest-jasmine` *last release*: Nov 04, 2017, *status*: 1 - Planning, @@ -6195,8 +6341,8 @@ This list contains 1367 plugins. Pytest plugin providing three logger fixtures with basic or full writing to log files :pypi:`pytest-logger` - *last release*: Jul 25, 2019, - *status*: 4 - Beta, + *last release*: Feb 12, 2024, + *status*: 5 - Production/Stable, *requires*: pytest (>=3.2) Plugin configuring handlers for loggers from Python logging module. @@ -6384,7 +6530,7 @@ This list contains 1367 plugins. A pytest plugin to make a test results report with Markdown table format. :pypi:`pytest-meilisearch` - *last release*: Jan 19, 2024, + *last release*: Feb 15, 2024, *status*: N/A, *requires*: pytest (>=7.4.3) @@ -6447,7 +6593,7 @@ This list contains 1367 plugins. Pytest to Slack reporting plugin :pypi:`pytest-metadata` - *last release*: Feb 01, 2024, + *last release*: Feb 12, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -6461,7 +6607,7 @@ This list contains 1367 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Jan 16, 2024, + *last release*: Feb 15, 2024, *status*: N/A, *requires*: pytest @@ -6692,7 +6838,7 @@ This list contains 1367 plugins. pytest plugin for running individual tests with mpiexec :pypi:`pytest-mpl` - *last release*: Jul 23, 2022, + *last release*: Feb 14, 2024, *status*: 4 - Beta, *requires*: pytest @@ -6874,7 +7020,7 @@ This list contains 1367 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Jan 11, 2024, + *last release*: Feb 16, 2024, *status*: N/A, *requires*: pytest (>=6.2.5,<7.0.0) @@ -6929,6 +7075,13 @@ This list contains 1367 plugins. pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach + :pypi:`pytest_notebook` + *last release*: Nov 28, 2023, + *status*: 4 - Beta, + *requires*: pytest>=3.5.0 + + A pytest plugin for testing Jupyter Notebooks. + :pypi:`pytest-notice` *last release*: Nov 05, 2020, *status*: N/A, @@ -6950,6 +7103,13 @@ This list contains 1367 plugins. A pytest plugin to notify test result + :pypi:`pytest_notify` + *last release*: Jul 05, 2017, + *status*: N/A, + *requires*: pytest>=3.0.0 + + Get notifications when your tests ends + :pypi:`pytest-notimplemented` *last release*: Aug 27, 2019, *status*: N/A, @@ -6965,7 +7125,7 @@ This list contains 1367 plugins. A PyTest Reporter to send test runs to Notion.so :pypi:`pytest-nunit` - *last release*: Oct 11, 2023, + *last release*: Feb 13, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -7140,11 +7300,11 @@ This list contains 1367 plugins. OS X notifications for py.test results. :pypi:`pytest-otel` - *last release*: Jan 18, 2023, + *last release*: Feb 16, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest==7.1.3 - pytest-otel report OpenTelemetry traces about test executed + OpenTelemetry plugin for Pytest :pypi:`pytest-override-env-var` *last release*: Feb 25, 2023, @@ -7210,7 +7370,7 @@ This list contains 1367 plugins. Configure pytest fixtures using a combination of"parametrize" and markers :pypi:`pytest-parameterize-from-files` - *last release*: Feb 09, 2024, + *last release*: Feb 15, 2024, *status*: 4 - Beta, *requires*: pytest>=7.2.0 @@ -7244,6 +7404,13 @@ This list contains 1367 plugins. A simple pytest extension for creating a named test suite. + :pypi:`pytest_param_files` + *last release*: Jul 29, 2023, + *status*: N/A, + *requires*: pytest + + Create pytest parametrize decorators from external files. + :pypi:`pytest-param-scope` *last release*: Oct 18, 2023, *status*: N/A, @@ -7335,6 +7502,13 @@ This list contains 1367 plugins. Change the exit code of pytest test sessions when a required percent of tests pass. + :pypi:`pytest-percents` + *last release*: Feb 10, 2024, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-perf` *last release*: Jan 28, 2024, *status*: 5 - Production/Stable, @@ -7602,7 +7776,7 @@ This list contains 1367 plugins. Visualize your failed tests with poo :pypi:`pytest-pook` - *last release*: Dec 23, 2023, + *last release*: Feb 15, 2024, *status*: 4 - Beta, *requires*: pytest @@ -8014,6 +8188,13 @@ This list contains 1367 plugins. pytest plugin to generate random data inspired by QuickCheck + :pypi:`pytest_quickify` + *last release*: Jun 14, 2019, + *status*: N/A, + *requires*: pytest + + Run test suites with pytest-quickify. + :pypi:`pytest-rabbitmq` *last release*: Jul 05, 2023, *status*: 5 - Production/Stable, @@ -8105,6 +8286,13 @@ This list contains 1367 plugins. Randomise the order in which pytest tests are run with some control over the randomness + :pypi:`pytest-ranking` + *last release*: Feb 17, 2024, + *status*: 4 - Beta, + *requires*: pytest >=7.4.3 + + A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection + :pypi:`pytest-readme` *last release*: Sep 02, 2022, *status*: 5 - Production/Stable, @@ -8259,6 +8447,13 @@ This list contains 1367 plugins. pytest plugin for repeating tests + :pypi:`pytest_repeater` + *last release*: Feb 09, 2018, + *status*: 1 - Planning, + *requires*: N/A + + py.test plugin for repeating single test multiple times. + :pypi:`pytest-replay` *last release*: Jan 11, 2024, *status*: 5 - Production/Stable, @@ -8428,7 +8623,7 @@ This list contains 1367 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Jan 10, 2024, + *last release*: Feb 14, 2024, *status*: N/A, *requires*: pytest ~=4.6 ; python_version == "2.7" @@ -8595,6 +8790,13 @@ This list contains 1367 plugins. pytest plugin for ROAST configuration override and fixtures + :pypi:`pytest_robotframework` + *last release*: Feb 08, 2024, + *status*: N/A, + *requires*: pytest<9,>=7 + + a pytest plugin that can run both python and robotframework tests while generating robot reports for them + :pypi:`pytest-rocketchat` *last release*: Apr 18, 2021, *status*: 5 - Production/Stable, @@ -8749,8 +8951,15 @@ This list contains 1367 plugins. + :pypi:`pytest_sauce` + *last release*: Jul 14, 2014, + *status*: 3 - Alpha, + *requires*: N/A + + pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs + :pypi:`pytest-sbase` - *last release*: Jan 29, 2024, + *last release*: Feb 17, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8771,9 +8980,9 @@ This list contains 1367 plugins. The job of test scheduling for humans. :pypi:`pytest-schema` - *last release*: Mar 14, 2022, + *last release*: Feb 16, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.5.0) + *requires*: pytest >=3.5.0 👍 Validate return values against a schema-like object in testing @@ -8813,7 +9022,7 @@ This list contains 1367 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jan 29, 2024, + *last release*: Feb 17, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -8869,7 +9078,7 @@ This list contains 1367 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Dec 19, 2023, + *last release*: Feb 14, 2024, *status*: 3 - Alpha, *requires*: pytest >=6.2 @@ -9338,7 +9547,7 @@ This list contains 1367 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Dec 01, 2023, + *last release*: Feb 13, 2024, *status*: N/A, *requires*: N/A @@ -9624,6 +9833,13 @@ This list contains 1367 plugins. Pyst - Pytest System-Test Plugin + :pypi:`pytest_tagging` + *last release*: Feb 15, 2024, + *status*: N/A, + *requires*: pytest (>=7.1.3,<8.0.0) + + a pytest plugin to tag tests + :pypi:`pytest-takeltest` *last release*: Feb 15, 2023, *status*: N/A, @@ -9673,13 +9889,6 @@ This list contains 1367 plugins. tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used - :pypi:`pytest-tcp` - *last release*: Dec 10, 2023, - *status*: 4 - Beta, - *requires*: pytest >=7.4.3 - - A Pytest plugin for test prioritization - :pypi:`pytest-tcpclient` *last release*: Nov 16, 2022, *status*: N/A, @@ -9786,9 +9995,9 @@ This list contains 1367 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-testinfra` - *last release*: Nov 13, 2023, + *last release*: Feb 15, 2024, *status*: 5 - Production/Stable, - *requires*: pytest !=3.0.2 + *requires*: pytest >=6 Test infrastructures @@ -9961,9 +10170,9 @@ This list contains 1367 plugins. :pypi:`pytest-tesults` - *last release*: Jul 21, 2023, + *last release*: Feb 15, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.5.0) + *requires*: pytest >=3.5.0 Tesults plugin for pytest @@ -10493,9 +10702,9 @@ This list contains 1367 plugins. Plugin for managing VCR.py cassettes :pypi:`pytest-vcr-delete-on-fail` - *last release*: Jun 20, 2022, + *last release*: Feb 16, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2.2) + *requires*: pytest (>=8.0.0,<9.0.0) A pytest plugin that automates vcrpy cassettes deletion on test failure. @@ -10639,6 +10848,13 @@ This list contains 1367 plugins. Automatically rerun your tests on file modifications + :pypi:`pytest_wdb` + *last release*: Jul 04, 2016, + *status*: N/A, + *requires*: N/A + + Trace pytest tests with wdb to halt on error with --wdb. + :pypi:`pytest-wdl` *last release*: Nov 17, 2020, *status*: 5 - Production/Stable, From abf6a60567c118e52de92f881b8b4210dd1ceafa Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 17 Feb 2024 22:21:30 -0300 Subject: [PATCH 0479/1271] Fix 'pytest_' mention: it was being considered a rst reference --- doc/en/reference/plugin_list.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index f9d3d02f059..b89a9b05fa2 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -7,7 +7,7 @@ Pytest Plugin List ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. +It includes PyPI projects whose names begin with ``"pytest-"`` or ``"pytest_"`` and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, From 40011b838b67691c76302f3cd8d18862f37b9370 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 18 Feb 2024 07:21:05 -0300 Subject: [PATCH 0480/1271] Allow Sphinx 7.x (#12002) Thanks to https://github.com/pytest-dev/pytest/issues/11988#issuecomment-1950318888, the problem was our custom template. The solution was to copy the template from Sphinx 7 and remove the header. --- doc/en/_templates/slim_searchbox.html | 5 ++--- doc/en/requirements.txt | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/en/_templates/slim_searchbox.html b/doc/en/_templates/slim_searchbox.html index e98ad4ed905..f088ff8d312 100644 --- a/doc/en/_templates/slim_searchbox.html +++ b/doc/en/_templates/slim_searchbox.html @@ -5,11 +5,10 @@ - + {%- endif %} diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 3369bd10b76..52415740470 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -2,8 +2,7 @@ pallets-sphinx-themes pluggy>=1.2.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 -# In Sphinx 6 and 7, the search bar disappears; restrict this for now until we find a solution. -sphinx>=5,<6 +sphinx>=7 sphinxcontrib-trio sphinxcontrib-svg2pdfconverter # Pin packaging because it no longer handles 'latest' version, which From 998fee1679892f62cc9bd727e9e17911d746ed64 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 18 Feb 2024 17:27:47 -0300 Subject: [PATCH 0481/1271] Clarify PytestPluginManager._is_in_confcutdir (#12007) Follow up to #12006, let's put some comments clarifying `is_in_confcutdir` semantics, as this is not the first time someone misunderstands it. Also removed an obsolete comment in `_loadconftestmodules`: we already set the `confcutdir` based on `rootdir`/`initfile` if not explicitly given. Co-authored-by: Ran Benita --- src/_pytest/config/__init__.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 3d448214cbe..f8eea936aa6 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -578,12 +578,18 @@ def _set_initial_conftests( self._try_load_conftest(invocation_dir, importmode, rootpath) def _is_in_confcutdir(self, path: Path) -> bool: - """Whether a path is within the confcutdir. - - When false, should not load conftest. - """ + """Whether to consider the given path to load conftests from.""" if self._confcutdir is None: return True + # The semantics here are literally: + # Do not load a conftest if it is found upwards from confcut dir. + # But this is *not* the same as: + # Load only conftests from confcutdir or below. + # At first glance they might seem the same thing, however we do support use cases where + # we want to load conftests that are not found in confcutdir or below, but are found + # in completely different directory hierarchies like packages installed + # in out-of-source trees. + # (see #9767 for a regression where the logic was inverted). return path not in self._confcutdir.parents def _try_load_conftest( @@ -609,9 +615,6 @@ def _loadconftestmodules( if directory in self._dirpath2confmods: return - # XXX these days we may rather want to use config.rootpath - # and allow users to opt into looking into the rootdir parent - # directories instead of requiring to specify confcutdir. clist = [] for parent in reversed((directory, *directory.parents)): if self._is_in_confcutdir(parent): From 95f21f96cc2252d9a3162f63ac9c26d4ab97abf5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 21:36:03 -0300 Subject: [PATCH 0482/1271] [pre-commit.ci] pre-commit autoupdate (#12012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.2.1 → v0.2.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.2.1...v0.2.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e9cea8c60c3..78cf36bae4c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.2.1" + rev: "v0.2.2" hooks: - id: ruff args: ["--fix"] From a37cff3ca8be06dc1154a54bbc32c32e82eef4ee Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 19 Feb 2024 20:54:49 +0200 Subject: [PATCH 0483/1271] testing: add a regression test for `setup_module` + `--doctest-modules` Refs #12011 (only fails on 8.0.1, not main). --- changelog/12011.bugfix.rst | 1 + testing/test_doctest.py | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 changelog/12011.bugfix.rst diff --git a/changelog/12011.bugfix.rst b/changelog/12011.bugfix.rst new file mode 100644 index 00000000000..5b755ade335 --- /dev/null +++ b/changelog/12011.bugfix.rst @@ -0,0 +1 @@ +Fixed a regression in 8.0.1 whereby ``setup_module`` xunit-style fixtures are not executed when ``--doctest-modules`` is passed. diff --git a/testing/test_doctest.py b/testing/test_doctest.py index c91ec31cd40..32897a916fe 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -878,6 +878,25 @@ def test_foo(): result = pytester.runpytest(p, "--doctest-modules") result.stdout.fnmatch_lines(["*collected 1 item*"]) + def test_setup_module(self, pytester: Pytester) -> None: + """Regression test for #12011 - setup_module not executed when running + with `--doctest-modules`.""" + pytester.makepyfile( + """ + CONSTANT = 0 + + def setup_module(): + global CONSTANT + CONSTANT = 1 + + def test(): + assert CONSTANT == 1 + """ + ) + result = pytester.runpytest("--doctest-modules") + assert result.ret == 0 + result.assert_outcomes(passed=1) + class TestLiterals: @pytest.mark.parametrize("config_mode", ["ini", "comment"]) From 79def57cc65e18bae0f5a6ad84c433e210e97126 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 21 Feb 2024 09:35:25 +0200 Subject: [PATCH 0484/1271] python: small code cleanup --- src/_pytest/python.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 91c48540dc7..a060b17e57a 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1267,7 +1267,6 @@ def parametrize( # Add funcargs as fixturedefs to fixtureinfo.arg2fixturedefs by registering # artificial "pseudo" FixtureDef's so that later at test execution time we can # rely on a proper FixtureDef to exist for fixture setup. - arg2fixturedefs = self._arg2fixturedefs node = None # If we have a scope that is higher than function, we need # to make sure we only ever create an according fixturedef on @@ -1281,7 +1280,7 @@ def parametrize( # If used class scope and there is no class, use module-level # collector (for now). if scope_ is Scope.Class: - assert isinstance(collector, _pytest.python.Module) + assert isinstance(collector, Module) node = collector # If used package scope and there is no package, use session # (for now). @@ -1316,7 +1315,7 @@ def parametrize( ) if name2pseudofixturedef is not None: name2pseudofixturedef[argname] = fixturedef - arg2fixturedefs[argname] = [fixturedef] + self._arg2fixturedefs[argname] = [fixturedef] # Create the new calls: if we are parametrize() multiple times (by applying the decorator # more than once) then we accumulate those calls generating the cartesian product From 2007cf629663055931947e60f630fa1f8f0bef5a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 21 Feb 2024 09:58:59 +0200 Subject: [PATCH 0485/1271] fixtures: remove a level of indentation A bit easier to follow. --- src/_pytest/fixtures.py | 48 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 67eb0542574..b13d9e70399 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -169,33 +169,31 @@ def get_parametrized_fixture_keys( the specified scope.""" assert scope is not Scope.Function try: - callspec = item.callspec # type: ignore[attr-defined] + callspec: CallSpec2 = item.callspec # type: ignore[attr-defined] except AttributeError: - pass - else: - cs: CallSpec2 = callspec - # cs.indices is random order of argnames. Need to - # sort this so that different calls to - # get_parametrized_fixture_keys will be deterministic. - for argname in sorted(cs.indices): - if cs._arg2scope[argname] != scope: - continue - - item_cls = None - if scope is Scope.Session: - scoped_item_path = None - elif scope is Scope.Package: - scoped_item_path = item.path - elif scope is Scope.Module: - scoped_item_path = item.path - elif scope is Scope.Class: - scoped_item_path = item.path - item_cls = item.cls # type: ignore[attr-defined] - else: - assert_never(scope) + return + # cs.indices is random order of argnames. Need to + # sort this so that different calls to + # get_parametrized_fixture_keys will be deterministic. + for argname in sorted(callspec.indices): + if callspec._arg2scope[argname] != scope: + continue + + item_cls = None + if scope is Scope.Session: + scoped_item_path = None + elif scope is Scope.Package: + scoped_item_path = item.path + elif scope is Scope.Module: + scoped_item_path = item.path + elif scope is Scope.Class: + scoped_item_path = item.path + item_cls = item.cls # type: ignore[attr-defined] + else: + assert_never(scope) - param_index = cs.indices[argname] - yield FixtureArgKey(argname, param_index, scoped_item_path, item_cls) + param_index = callspec.indices[argname] + yield FixtureArgKey(argname, param_index, scoped_item_path, item_cls) # Algorithm for sorting on a per-parametrized resource setup basis. From 9bea1be2157e8467712aa1de46312ed0827741d8 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 21 Feb 2024 10:00:16 +0200 Subject: [PATCH 0486/1271] fixtures: remove a no longer needed sort Dicts these days preserve order, so the sort is no longer needed to achieve determinism. As shown by the `test_dynamic_parametrized_ordering` test, this can change the ordering of items, but only in equivalent ways (same number of setups/teardowns per scope), it will just respect the user's given ordering better (hence `vxlan` items now ordered before `vlan` items compared to the previous ordering). --- src/_pytest/fixtures.py | 5 +---- testing/python/fixtures.py | 8 ++++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index b13d9e70399..935d2b9a0eb 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -172,10 +172,7 @@ def get_parametrized_fixture_keys( callspec: CallSpec2 = item.callspec # type: ignore[attr-defined] except AttributeError: return - # cs.indices is random order of argnames. Need to - # sort this so that different calls to - # get_parametrized_fixture_keys will be deterministic. - for argname in sorted(callspec.indices): + for argname in callspec.indices: if callspec._arg2scope[argname] != scope: continue diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 0fb5aa45029..299e411a695 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2730,12 +2730,12 @@ def test2(reprovision): """ test_dynamic_parametrized_ordering.py::test[flavor1-vxlan] PASSED test_dynamic_parametrized_ordering.py::test2[flavor1-vxlan] PASSED - test_dynamic_parametrized_ordering.py::test[flavor2-vxlan] PASSED - test_dynamic_parametrized_ordering.py::test2[flavor2-vxlan] PASSED - test_dynamic_parametrized_ordering.py::test[flavor2-vlan] PASSED - test_dynamic_parametrized_ordering.py::test2[flavor2-vlan] PASSED test_dynamic_parametrized_ordering.py::test[flavor1-vlan] PASSED test_dynamic_parametrized_ordering.py::test2[flavor1-vlan] PASSED + test_dynamic_parametrized_ordering.py::test[flavor2-vlan] PASSED + test_dynamic_parametrized_ordering.py::test2[flavor2-vlan] PASSED + test_dynamic_parametrized_ordering.py::test[flavor2-vxlan] PASSED + test_dynamic_parametrized_ordering.py::test2[flavor2-vxlan] PASSED """ ) From c5c729e27aa1e866af37f2ee97b1c68e9463070c Mon Sep 17 00:00:00 2001 From: Ben Leith Date: Wed, 21 Feb 2024 23:02:19 +1100 Subject: [PATCH 0487/1271] Add --log-file-mode option to the logging plugin, enabling appending to log-files (#11979) Previously, the mode was hard-coded to be "w" which truncates the file before logging. Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/11978.improvement.rst | 3 + doc/en/how-to/logging.rst | 6 +- src/_pytest/logging.py | 14 ++- testing/logging/test_reporting.py | 168 ++++++++++++++++++++++++++++++ 5 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 changelog/11978.improvement.rst diff --git a/AUTHORS b/AUTHORS index dce91c4fe0e..bb27dd1d7c2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -56,6 +56,7 @@ Babak Keyvani Barney Gale Ben Brown Ben Gartner +Ben Leith Ben Webb Benjamin Peterson Benjamin Schubert diff --git a/changelog/11978.improvement.rst b/changelog/11978.improvement.rst new file mode 100644 index 00000000000..1f1143dacf0 --- /dev/null +++ b/changelog/11978.improvement.rst @@ -0,0 +1,3 @@ +Add ``--log-file-mode`` option to the logging plugin, enabling appending to log-files. This option accepts either ``"w"`` or ``"a"`` and defaults to ``"w"``. + +Previously, the mode was hard-coded to be ``"w"`` which truncates the file before logging. diff --git a/doc/en/how-to/logging.rst b/doc/en/how-to/logging.rst index bdcfbe34fa2..300e9f6e6c2 100644 --- a/doc/en/how-to/logging.rst +++ b/doc/en/how-to/logging.rst @@ -206,8 +206,9 @@ option names are: * ``log_cli_date_format`` If you need to record the whole test suite logging calls to a file, you can pass -``--log-file=/path/to/log/file``. This log file is opened in write mode which +``--log-file=/path/to/log/file``. This log file is opened in write mode by default which means that it will be overwritten at each run tests session. +If you'd like the file opened in append mode instead, then you can pass ``--log-file-mode=a``. Note that relative paths for the log-file location, whether passed on the CLI or declared in a config file, are always resolved relative to the current working directory. @@ -223,12 +224,13 @@ All of the log file options can also be set in the configuration INI file. The option names are: * ``log_file`` +* ``log_file_mode`` * ``log_file_level`` * ``log_file_format`` * ``log_file_date_format`` You can call ``set_log_path()`` to customize the log_file path dynamically. This functionality -is considered **experimental**. +is considered **experimental**. Note that ``set_log_path()`` respects the ``log_file_mode`` option. .. _log_colors: diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index aa3a33e6377..e9a3234fdec 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -298,6 +298,13 @@ def add_option_ini(option, dest, default=None, type=None, **kwargs): default=None, help="Path to a file when logging will be written to", ) + add_option_ini( + "--log-file-mode", + dest="log_file_mode", + default="w", + choices=["w", "a"], + help="Log file open mode", + ) add_option_ini( "--log-file-level", dest="log_file_level", @@ -669,7 +676,10 @@ def __init__(self, config: Config) -> None: if not os.path.isdir(directory): os.makedirs(directory) - self.log_file_handler = _FileHandler(log_file, mode="w", encoding="UTF-8") + self.log_file_mode = get_option_ini(config, "log_file_mode") or "w" + self.log_file_handler = _FileHandler( + log_file, mode=self.log_file_mode, encoding="UTF-8" + ) log_file_format = get_option_ini(config, "log_file_format", "log_format") log_file_date_format = get_option_ini( config, "log_file_date_format", "log_date_format" @@ -746,7 +756,7 @@ def set_log_path(self, fname: str) -> None: fpath.parent.mkdir(exist_ok=True, parents=True) # https://github.com/python/mypy/issues/11193 - stream: io.TextIOWrapper = fpath.open(mode="w", encoding="UTF-8") # type: ignore[assignment] + stream: io.TextIOWrapper = fpath.open(mode=self.log_file_mode, encoding="UTF-8") # type: ignore[assignment] old_stream = self.log_file_handler.setStream(stream) if old_stream: old_stream.close() diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 24eae19b7ba..7e592febf56 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -661,6 +661,73 @@ def test_log_file(request): assert "This log message won't be shown" not in contents +def test_log_file_mode_cli(pytester: Pytester) -> None: + # Default log file level + pytester.makepyfile( + """ + import pytest + import logging + def test_log_file(request): + plugin = request.config.pluginmanager.getplugin('logging-plugin') + assert plugin.log_file_handler.level == logging.WARNING + logging.getLogger('catchlog').info("This log message won't be shown") + logging.getLogger('catchlog').warning("This log message will be shown") + print('PASSED') + """ + ) + + log_file = str(pytester.path.joinpath("pytest.log")) + + with open(log_file, mode="w", encoding="utf-8") as wfh: + wfh.write("A custom header\n") + + result = pytester.runpytest( + "-s", + f"--log-file={log_file}", + "--log-file-mode=a", + "--log-file-level=WARNING", + ) + + # fnmatch_lines does an assertion internally + result.stdout.fnmatch_lines(["test_log_file_mode_cli.py PASSED"]) + + # make sure that we get a '0' exit code for the testsuite + assert result.ret == 0 + assert os.path.isfile(log_file) + with open(log_file, encoding="utf-8") as rfh: + contents = rfh.read() + assert "A custom header" in contents + assert "This log message will be shown" in contents + assert "This log message won't be shown" not in contents + + +def test_log_file_mode_cli_invalid(pytester: Pytester) -> None: + # Default log file level + pytester.makepyfile( + """ + import pytest + import logging + def test_log_file(request): + plugin = request.config.pluginmanager.getplugin('logging-plugin') + assert plugin.log_file_handler.level == logging.WARNING + logging.getLogger('catchlog').info("This log message won't be shown") + logging.getLogger('catchlog').warning("This log message will be shown") + """ + ) + + log_file = str(pytester.path.joinpath("pytest.log")) + + result = pytester.runpytest( + "-s", + f"--log-file={log_file}", + "--log-file-mode=b", + "--log-file-level=WARNING", + ) + + # make sure that we get a '4' exit code for the testsuite + assert result.ret == ExitCode.USAGE_ERROR + + def test_log_file_cli_level(pytester: Pytester) -> None: # Default log file level pytester.makepyfile( @@ -741,6 +808,47 @@ def test_log_file(request): assert "This log message won't be shown" not in contents +def test_log_file_mode_ini(pytester: Pytester) -> None: + log_file = str(pytester.path.joinpath("pytest.log")) + + pytester.makeini( + f""" + [pytest] + log_file={log_file} + log_file_mode=a + log_file_level=WARNING + """ + ) + pytester.makepyfile( + """ + import pytest + import logging + def test_log_file(request): + plugin = request.config.pluginmanager.getplugin('logging-plugin') + assert plugin.log_file_handler.level == logging.WARNING + logging.getLogger('catchlog').info("This log message won't be shown") + logging.getLogger('catchlog').warning("This log message will be shown") + print('PASSED') + """ + ) + + with open(log_file, mode="w", encoding="utf-8") as wfh: + wfh.write("A custom header\n") + + result = pytester.runpytest("-s") + + # fnmatch_lines does an assertion internally + result.stdout.fnmatch_lines(["test_log_file_mode_ini.py PASSED"]) + + assert result.ret == ExitCode.OK + assert os.path.isfile(log_file) + with open(log_file, encoding="utf-8") as rfh: + contents = rfh.read() + assert "A custom header" in contents + assert "This log message will be shown" in contents + assert "This log message won't be shown" not in contents + + def test_log_file_ini_level(pytester: Pytester) -> None: log_file = str(pytester.path.joinpath("pytest.log")) @@ -1060,6 +1168,66 @@ def test_second(): assert "message from test 2" in content +def test_log_set_path_with_log_file_mode(pytester: Pytester) -> None: + report_dir_base = str(pytester.path) + + pytester.makeini( + """ + [pytest] + log_file_level = DEBUG + log_cli=true + log_file_mode=a + """ + ) + pytester.makeconftest( + f""" + import os + import pytest + @pytest.hookimpl(wrapper=True, tryfirst=True) + def pytest_runtest_setup(item): + config = item.config + logging_plugin = config.pluginmanager.get_plugin("logging-plugin") + report_file = os.path.join({report_dir_base!r}, item._request.node.name) + logging_plugin.set_log_path(report_file) + return (yield) + """ + ) + pytester.makepyfile( + """ + import logging + logger = logging.getLogger("testcase-logger") + def test_first(): + logger.info("message from test 1") + assert True + + def test_second(): + logger.debug("message from test 2") + assert True + """ + ) + + test_first_log_file = os.path.join(report_dir_base, "test_first") + test_second_log_file = os.path.join(report_dir_base, "test_second") + with open(test_first_log_file, mode="w", encoding="utf-8") as wfh: + wfh.write("A custom header for test 1\n") + + with open(test_second_log_file, mode="w", encoding="utf-8") as wfh: + wfh.write("A custom header for test 2\n") + + result = pytester.runpytest() + assert result.ret == ExitCode.OK + + with open(test_first_log_file, encoding="utf-8") as rfh: + content = rfh.read() + assert "A custom header for test 1" in content + assert "message from test 1" in content + + with open(test_second_log_file, encoding="utf-8") as rfh: + content = rfh.read() + assert "A custom header for test 2" in content + assert "message from test 2" in content + + def test_colored_captured_log(pytester: Pytester) -> None: """Test that the level names of captured log messages of a failing test are colored.""" From 59e9a58cc9c97386f949e909716e8abde7fc31b2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 22 Feb 2024 21:04:11 -0300 Subject: [PATCH 0488/1271] Remove Anthony from Tidelift participants (#12020) As discussed in the core development channels, @asottile asked to no longer be a Tidelift participant, at least for the time being. --- TIDELIFT.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/TIDELIFT.rst b/TIDELIFT.rst index 2fe25841c3a..6c7ad917745 100644 --- a/TIDELIFT.rst +++ b/TIDELIFT.rst @@ -23,7 +23,6 @@ members of the `contributors team`_ interested in receiving funding. The current list of contributors receiving funding are: -* `@asottile`_ * `@nicoddemus`_ * `@The-Compiler`_ @@ -55,6 +54,5 @@ funds. Just drop a line to one of the `@pytest-dev/tidelift-admins`_ or use the .. _`@pytest-dev/tidelift-admins`: https://github.com/orgs/pytest-dev/teams/tidelift-admins/members .. _`agreement`: https://tidelift.com/docs/lifting/agreement -.. _`@asottile`: https://github.com/asottile .. _`@nicoddemus`: https://github.com/nicoddemus .. _`@The-Compiler`: https://github.com/The-Compiler From 1640f2e4544e63da6bf7c6587040897ca0810770 Mon Sep 17 00:00:00 2001 From: Eric Larson Date: Fri, 23 Feb 2024 01:11:05 -0500 Subject: [PATCH 0489/1271] ENH: Improve warning stacklevel (#12014) * ENH: Improve warning stacklevel * TST: Add test * TST: Ping * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * MAINT: Changelog --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/12014.bugfix.rst | 1 + src/_pytest/mark/structures.py | 6 +++--- testing/deprecated_test.py | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 changelog/12014.bugfix.rst diff --git a/changelog/12014.bugfix.rst b/changelog/12014.bugfix.rst new file mode 100644 index 00000000000..344bf8b7e03 --- /dev/null +++ b/changelog/12014.bugfix.rst @@ -0,0 +1 @@ +Fix the ``stacklevel`` used when warning about marks used on fixtures. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 5a7f9b20240..1da300c8213 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -355,7 +355,7 @@ def __call__(self, *args: object, **kwargs: object): func = args[0] is_class = inspect.isclass(func) if len(args) == 1 and (istestfunc(func) or is_class): - store_mark(func, self.mark) + store_mark(func, self.mark, stacklevel=3) return func return self.with_args(*args, **kwargs) @@ -410,7 +410,7 @@ def normalize_mark_list( yield mark_obj -def store_mark(obj, mark: Mark) -> None: +def store_mark(obj, mark: Mark, *, stacklevel: int = 2) -> None: """Store a Mark on an object. This is used to implement the Mark declarations/decorators correctly. @@ -420,7 +420,7 @@ def store_mark(obj, mark: Mark) -> None: from ..fixtures import getfixturemarker if getfixturemarker(obj) is not None: - warnings.warn(MARKED_FIXTURE, stacklevel=2) + warnings.warn(MARKED_FIXTURE, stacklevel=stacklevel) # Always reassign name to avoid updating pytestmark in a reference that # was only borrowed. diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 52752d4e8e9..a5f51306358 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -118,6 +118,8 @@ def foo(): raise NotImplementedError() assert len(record) == 2 # one for each mark decorator + # should point to this file + assert all(rec.filename == __file__ for rec in record) def test_fixture_disallowed_between_marks(): From 010ce2ab0f6d2e90f295d4e3f9e725d31dd5721d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 23 Feb 2024 09:35:57 +0200 Subject: [PATCH 0490/1271] Add typing to `from_parent` return values (#11916) Up to now the return values of `from_parent` were untyped, this is an attempt to make it work with `typing.Self`. --- src/_pytest/doctest.py | 11 +++++------ src/_pytest/main.py | 11 ++++++++--- src/_pytest/nodes.py | 22 +++++++++++++--------- src/_pytest/python.py | 25 +++++++++++++------------ src/_pytest/unittest.py | 3 +-- testing/test_collection.py | 2 +- 6 files changed, 41 insertions(+), 33 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 8fe992b6a12..ced3b82f5ea 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -47,6 +47,7 @@ if TYPE_CHECKING: import doctest + from typing import Self DOCTEST_REPORT_CHOICE_NONE = "none" DOCTEST_REPORT_CHOICE_CDIFF = "cdiff" @@ -133,11 +134,9 @@ def pytest_collect_file( if config.option.doctestmodules and not any( (_is_setup_py(file_path), _is_main_py(file_path)) ): - mod: DoctestModule = DoctestModule.from_parent(parent, path=file_path) - return mod + return DoctestModule.from_parent(parent, path=file_path) elif _is_doctest(config, file_path, parent): - txt: DoctestTextfile = DoctestTextfile.from_parent(parent, path=file_path) - return txt + return DoctestTextfile.from_parent(parent, path=file_path) return None @@ -272,14 +271,14 @@ def __init__( self._initrequest() @classmethod - def from_parent( # type: ignore + def from_parent( # type: ignore[override] cls, parent: "Union[DoctestTextfile, DoctestModule]", *, name: str, runner: "doctest.DocTestRunner", dtest: "doctest.DocTest", - ): + ) -> "Self": # incompatible signature due to imposed limits on subclass """The public named constructor.""" return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 5c70ad74e40..672ad67b9e5 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -21,6 +21,7 @@ from typing import overload from typing import Sequence from typing import Tuple +from typing import TYPE_CHECKING from typing import Union import warnings @@ -49,6 +50,10 @@ from _pytest.warning_types import PytestWarning +if TYPE_CHECKING: + from typing import Self + + def pytest_addoption(parser: Parser) -> None: parser.addini( "norecursedirs", @@ -491,16 +496,16 @@ class Dir(nodes.Directory): @classmethod def from_parent( # type: ignore[override] cls, - parent: nodes.Collector, # type: ignore[override] + parent: nodes.Collector, *, path: Path, - ) -> "Dir": + ) -> "Self": """The public constructor. :param parent: The parent collector of this Dir. :param path: The directory's path. """ - return super().from_parent(parent=parent, path=path) # type: ignore[no-any-return] + return super().from_parent(parent=parent, path=path) def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: config = self.config diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 48f7d584168..2381b65eaf9 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -11,6 +11,7 @@ from typing import Iterator from typing import List from typing import MutableMapping +from typing import NoReturn from typing import Optional from typing import overload from typing import Set @@ -41,6 +42,8 @@ if TYPE_CHECKING: + from typing import Self + # Imported here due to circular import. from _pytest._code.code import _TracebackStyle from _pytest.main import Session @@ -51,6 +54,7 @@ tracebackcutdir = Path(_pytest.__file__).parent +_T = TypeVar("_T") _NodeType = TypeVar("_NodeType", bound="Node") @@ -69,33 +73,33 @@ class NodeMeta(abc.ABCMeta): progress on detangling the :class:`Node` classes. """ - def __call__(self, *k, **kw): + def __call__(cls, *k, **kw) -> NoReturn: msg = ( "Direct construction of {name} has been deprecated, please use {name}.from_parent.\n" "See " "https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent" " for more details." - ).format(name=f"{self.__module__}.{self.__name__}") + ).format(name=f"{cls.__module__}.{cls.__name__}") fail(msg, pytrace=False) - def _create(self, *k, **kw): + def _create(cls: Type[_T], *k, **kw) -> _T: try: - return super().__call__(*k, **kw) + return super().__call__(*k, **kw) # type: ignore[no-any-return,misc] except TypeError: - sig = signature(getattr(self, "__init__")) + sig = signature(getattr(cls, "__init__")) known_kw = {k: v for k, v in kw.items() if k in sig.parameters} from .warning_types import PytestDeprecationWarning warnings.warn( PytestDeprecationWarning( - f"{self} is not using a cooperative constructor and only takes {set(known_kw)}.\n" + f"{cls} is not using a cooperative constructor and only takes {set(known_kw)}.\n" "See https://docs.pytest.org/en/stable/deprecations.html" "#constructors-of-custom-pytest-node-subclasses-should-take-kwargs " "for more details." ) ) - return super().__call__(*k, **known_kw) + return super().__call__(*k, **known_kw) # type: ignore[no-any-return,misc] class Node(abc.ABC, metaclass=NodeMeta): @@ -181,7 +185,7 @@ def __init__( self._store = self.stash @classmethod - def from_parent(cls, parent: "Node", **kw): + def from_parent(cls, parent: "Node", **kw) -> "Self": """Public constructor for Nodes. This indirection got introduced in order to enable removing @@ -583,7 +587,7 @@ def from_parent( *, path: Optional[Path] = None, **kw, - ): + ) -> "Self": """The public constructor.""" return super().from_parent(parent=parent, path=path, **kw) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index a060b17e57a..ca64a877d42 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -27,6 +27,7 @@ from typing import Sequence from typing import Set from typing import Tuple +from typing import TYPE_CHECKING from typing import Union import warnings @@ -81,6 +82,10 @@ from _pytest.warning_types import PytestUnhandledCoroutineWarning +if TYPE_CHECKING: + from typing import Self + + _PYTEST_DIR = Path(_pytest.__file__).parent @@ -204,8 +209,7 @@ def pytest_collect_directory( ) -> Optional[nodes.Collector]: pkginit = path / "__init__.py" if pkginit.is_file(): - pkg: Package = Package.from_parent(parent, path=path) - return pkg + return Package.from_parent(parent, path=path) return None @@ -230,8 +234,7 @@ def path_matches_patterns(path: Path, patterns: Iterable[str]) -> bool: def pytest_pycollect_makemodule(module_path: Path, parent) -> "Module": - mod: Module = Module.from_parent(parent, path=module_path) - return mod + return Module.from_parent(parent, path=module_path) @hookimpl(trylast=True) @@ -242,8 +245,7 @@ def pytest_pycollect_makeitem( # Nothing was collected elsewhere, let's do it here. if safe_isclass(obj): if collector.istestclass(obj, name): - klass: Class = Class.from_parent(collector, name=name, obj=obj) - return klass + return Class.from_parent(collector, name=name, obj=obj) elif collector.istestfunction(obj, name): # mock seems to store unbound methods (issue473), normalize it. obj = getattr(obj, "__func__", obj) @@ -262,7 +264,7 @@ def pytest_pycollect_makeitem( ) elif getattr(obj, "__test__", True): if is_generator(obj): - res: Function = Function.from_parent(collector, name=name) + res = Function.from_parent(collector, name=name) reason = ( f"yield tests were removed in pytest 4.0 - {name} will be ignored" ) @@ -465,9 +467,7 @@ def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]: clscol = self.getparent(Class) cls = clscol and clscol.obj or None - definition: FunctionDefinition = FunctionDefinition.from_parent( - self, name=name, callobj=funcobj - ) + definition = FunctionDefinition.from_parent(self, name=name, callobj=funcobj) fixtureinfo = definition._fixtureinfo # pytest_generate_tests impls call metafunc.parametrize() which fills @@ -751,7 +751,7 @@ class Class(PyCollector): """Collector for test methods (and nested classes) in a Python class.""" @classmethod - def from_parent(cls, parent, *, name, obj=None, **kw): + def from_parent(cls, parent, *, name, obj=None, **kw) -> "Self": # type: ignore[override] """The public constructor.""" return super().from_parent(name=name, parent=parent, **kw) @@ -1730,8 +1730,9 @@ def __init__( self.fixturenames = fixtureinfo.names_closure self._initrequest() + # todo: determine sound type limitations @classmethod - def from_parent(cls, parent, **kw): # todo: determine sound type limitations + def from_parent(cls, parent, **kw) -> "Self": """The public constructor.""" return super().from_parent(parent=parent, **kw) diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 6598bdbc542..2b7966531c1 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -55,8 +55,7 @@ def pytest_pycollect_makeitem( except Exception: return None # Yes, so let's collect it. - item: UnitTestCase = UnitTestCase.from_parent(collector, name=name, obj=obj) - return item + return UnitTestCase.from_parent(collector, name=name, obj=obj) class UnitTestCase(Class): diff --git a/testing/test_collection.py b/testing/test_collection.py index 98cff8fe9a1..de8cacb8ffb 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1613,7 +1613,7 @@ def collect(self): assert collector.x == 10 -def test_class_from_parent(pytester: Pytester, request: FixtureRequest) -> None: +def test_class_from_parent(request: FixtureRequest) -> None: """Ensure Class.from_parent can forward custom arguments to the constructor.""" class MyCollector(pytest.Class): From 00d9640abc783e714881a2380af22ed77462ab21 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 23 Feb 2024 11:29:00 +0200 Subject: [PATCH 0491/1271] Revert "Fix teardown error reporting when `--maxfail=1` (#11721)" Fix #12021. Reopens #11706. This reverts commit 12b9bd580198edf88a795b692cbd6a1a05fe408a. This change caused a bad regression in pytest-xdist: https://github.com/pytest-dev/pytest-xdist/issues/1024 pytest-xdist necessarily has special handling of `--maxfail` and session fixture teardown get executed multiple times with the change. Since I'm not sure how to adapt pytest-xdist myself, revert for now. I kept the sticky `shouldstop`/`shouldfail` changes as they are good ideas regardless I think. --- changelog/12021.bugfix.rst | 1 + doc/en/changelog.rst | 2 ++ src/_pytest/runner.py | 4 --- testing/test_runner.py | 50 -------------------------------------- 4 files changed, 3 insertions(+), 54 deletions(-) create mode 100644 changelog/12021.bugfix.rst diff --git a/changelog/12021.bugfix.rst b/changelog/12021.bugfix.rst new file mode 100644 index 00000000000..eb8771ad720 --- /dev/null +++ b/changelog/12021.bugfix.rst @@ -0,0 +1 @@ +Reverted a fix to `--maxfail` handling in pytest 8.0.0 because it caused a regression in pytest-xdist whereby session fixture teardowns may get executed multiple times when the max-fails is reached. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 6ed764207e6..88f67635565 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -85,6 +85,8 @@ Bug Fixes - `#11706 `_: Fix reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`. + NOTE: This change was reverted in pytest 8.0.2 to fix a `regression `_ it caused in pytest-xdist. + - `#11758 `_: Fixed ``IndexError: string index out of range`` crash in ``if highlighted[-1] == "\n" and source[-1] != "\n"``. This bug was introduced in pytest 8.0.0rc1. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index d25fdb73836..7ed8f09bdbe 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -132,10 +132,6 @@ def runtestprotocol( show_test_item(item) if not item.config.getoption("setuponly", False): reports.append(call_and_report(item, "call", log)) - # If the session is about to fail or stop, teardown everything - this is - # necessary to correctly report fixture teardown errors (see #11706) - if item.session.shouldfail or item.session.shouldstop: - nextitem = None reports.append(call_and_report(item, "teardown", log, nextitem=nextitem)) # After all teardown hooks have been called # want funcargs and request info to go away. diff --git a/testing/test_runner.py b/testing/test_runner.py index 6b2b3105b0c..322e6dc0462 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1089,53 +1089,3 @@ def func() -> None: with pytest.raises(TypeError) as excinfo: OutcomeException(func) # type: ignore assert str(excinfo.value) == expected - - -def test_teardown_session_failed(pytester: Pytester) -> None: - """Test that higher-scoped fixture teardowns run in the context of the last - item after the test session bails early due to --maxfail. - - Regression test for #11706. - """ - pytester.makepyfile( - """ - import pytest - - @pytest.fixture(scope="module") - def baz(): - yield - pytest.fail("This is a failing teardown") - - def test_foo(baz): - pytest.fail("This is a failing test") - - def test_bar(): pass - """ - ) - result = pytester.runpytest("--maxfail=1") - result.assert_outcomes(failed=1, errors=1) - - -def test_teardown_session_stopped(pytester: Pytester) -> None: - """Test that higher-scoped fixture teardowns run in the context of the last - item after the test session bails early due to --stepwise. - - Regression test for #11706. - """ - pytester.makepyfile( - """ - import pytest - - @pytest.fixture(scope="module") - def baz(): - yield - pytest.fail("This is a failing teardown") - - def test_foo(baz): - pytest.fail("This is a failing test") - - def test_bar(): pass - """ - ) - result = pytester.runpytest("--stepwise") - result.assert_outcomes(failed=1, errors=1) From ad651ddfce7b618d3238683aa64c46df35648664 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 22 Feb 2024 22:16:46 +0200 Subject: [PATCH 0492/1271] fixtures: remove an unneeded suppress In `CallSpec2.setmulti` the `params` and `_arg2scope` dicts are always set together. Further, the `get_parametrized_fixture_keys` accesses `_arg2scope` for all argnames without a check, which I think rules out that the code protects against plugin shenanigans. After removing the suppress, adjust the comment and code to make more sense. --- src/_pytest/fixtures.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 935d2b9a0eb..99de03fe849 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -2,7 +2,6 @@ import abc from collections import defaultdict from collections import deque -from contextlib import suppress import dataclasses import functools import inspect @@ -578,7 +577,6 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: # (latter managed by fixturedef) argname = fixturedef.argname funcitem = self._pyfuncitem - scope = fixturedef._scope try: callspec = funcitem.callspec except AttributeError: @@ -586,13 +584,13 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: if callspec is not None and argname in callspec.params: param = callspec.params[argname] param_index = callspec.indices[argname] - # If a parametrize invocation set a scope it will override - # the static scope defined with the fixture function. - with suppress(KeyError): - scope = callspec._arg2scope[argname] + # The parametrize invocation scope overrides the fixture's scope. + scope = callspec._arg2scope[argname] else: param = NOTSET param_index = 0 + scope = fixturedef._scope + has_params = fixturedef.params is not None fixtures_not_supported = getattr(funcitem, "nofuncargs", False) if has_params and fixtures_not_supported: From 8d9b95dcdb131716b72b300abe969d4bf5209bd9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 23 Feb 2024 07:51:15 -0300 Subject: [PATCH 0493/1271] Fix collection of short paths on Windows (#11936) Passing a short path in the command line was causing the matchparts check to fail, because ``Path(short_path) != Path(long_path)``. Using ``os.path.samefile`` as fallback ensures the comparsion works on Windows when comparing short/long paths. Fix #11895 --- changelog/11895.bugfix.rst | 1 + src/_pytest/main.py | 4 ++++ testing/test_collection.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 changelog/11895.bugfix.rst diff --git a/changelog/11895.bugfix.rst b/changelog/11895.bugfix.rst new file mode 100644 index 00000000000..4211213c1e5 --- /dev/null +++ b/changelog/11895.bugfix.rst @@ -0,0 +1 @@ +Fix collection on Windows where initial paths contain the short version of a path (for example ``c:\PROGRA~1\tests``). diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 672ad67b9e5..639bf26c1cc 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -906,6 +906,10 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: # Path part e.g. `/a/b/` in `/a/b/test_file.py::TestIt::test_it`. if isinstance(matchparts[0], Path): is_match = node.path == matchparts[0] + if sys.platform == "win32" and not is_match: + # In case the file paths do not match, fallback to samefile() to + # account for short-paths on Windows (#11895). + is_match = os.path.samefile(node.path, matchparts[0]) # Name part e.g. `TestIt` in `/a/b/test_file.py::TestIt::test_it`. else: # TODO: Remove parametrized workaround once collection structure contains diff --git a/testing/test_collection.py b/testing/test_collection.py index de8cacb8ffb..0507400455c 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -4,9 +4,11 @@ import pprint import shutil import sys +import tempfile import textwrap from typing import List +from _pytest.assertion.util import running_on_ci from _pytest.config import ExitCode from _pytest.fixtures import FixtureRequest from _pytest.main import _in_venv @@ -1759,3 +1761,29 @@ def test_foo(): assert True assert result.ret == ExitCode.OK assert result.parseoutcomes() == {"passed": 1} + + +@pytest.mark.skipif(not sys.platform.startswith("win"), reason="Windows only") +def test_collect_short_file_windows(pytester: Pytester) -> None: + """Reproducer for #11895: short paths not colleced on Windows.""" + short_path = tempfile.mkdtemp() + if "~" not in short_path: # pragma: no cover + if running_on_ci(): + # On CI, we are expecting that under the current GitHub actions configuration, + # tempfile.mkdtemp() is producing short paths, so we want to fail to prevent + # this from silently changing without us noticing. + pytest.fail( + f"tempfile.mkdtemp() failed to produce a short path on CI: {short_path}" + ) + else: + # We want to skip failing this test locally in this situation because + # depending on the local configuration tempfile.mkdtemp() might not produce a short path: + # For example, user might have configured %TEMP% exactly to avoid generating short paths. + pytest.skip( + f"tempfile.mkdtemp() failed to produce a short path: {short_path}, skipping" + ) + + test_file = Path(short_path).joinpath("test_collect_short_file_windows.py") + test_file.write_text("def test(): pass", encoding="UTF-8") + result = pytester.runpytest(short_path) + assert result.parseoutcomes() == {"passed": 1} From c09f74619b4126d16706d2a35d860838d1756d49 Mon Sep 17 00:00:00 2001 From: robotherapist Date: Mon, 5 Feb 2024 21:09:28 +0100 Subject: [PATCH 0494/1271] runner: add support for `sys.last_exc` for post-mortem debugging on Python>=3.12 Fix #11850 --- AUTHORS | 1 + changelog/11850.improvement.rst | 1 + src/_pytest/runner.py | 4 ++++ testing/test_runner.py | 5 +++++ 4 files changed, 11 insertions(+) create mode 100644 changelog/11850.improvement.rst diff --git a/AUTHORS b/AUTHORS index bb27dd1d7c2..f78c4b3f94b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -128,6 +128,7 @@ Edison Gustavo Muenz Edoardo Batini Edson Tadeu M. Manoel Eduardo Schettino +Edward Haigh Eero Vaher Eli Boyarski Elizaveta Shashkova diff --git a/changelog/11850.improvement.rst b/changelog/11850.improvement.rst new file mode 100644 index 00000000000..87fc0953c19 --- /dev/null +++ b/changelog/11850.improvement.rst @@ -0,0 +1 @@ +Added support for :data:`sys.last_exc` for post-mortem debugging on Python>=3.12. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 7ed8f09bdbe..b60af9dd3fb 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -164,6 +164,8 @@ def pytest_runtest_call(item: Item) -> None: del sys.last_type del sys.last_value del sys.last_traceback + if sys.version_info >= (3, 12, 0): + del sys.last_exc # type: ignore[attr-defined] except AttributeError: pass try: @@ -172,6 +174,8 @@ def pytest_runtest_call(item: Item) -> None: # Store trace info to allow postmortem debugging sys.last_type = type(e) sys.last_value = e + if sys.version_info >= (3, 12, 0): + sys.last_exc = e # type: ignore[attr-defined] assert e.__traceback__ is not None # Skip *this* frame sys.last_traceback = e.__traceback__.tb_next diff --git a/testing/test_runner.py b/testing/test_runner.py index 322e6dc0462..8cc496f7064 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -926,6 +926,9 @@ def runtest(self): # Check that exception info is stored on sys assert sys.last_type is IndexError assert isinstance(sys.last_value, IndexError) + if sys.version_info >= (3, 12, 0): + assert isinstance(sys.last_exc, IndexError) # type: ignore[attr-defined] + assert sys.last_value.args[0] == "TEST" assert sys.last_traceback @@ -934,6 +937,8 @@ def runtest(self): runner.pytest_runtest_call(ItemMightRaise()) # type: ignore[arg-type] assert not hasattr(sys, "last_type") assert not hasattr(sys, "last_value") + if sys.version_info >= (3, 12, 0): + assert not hasattr(sys, "last_exc") assert not hasattr(sys, "last_traceback") From 84bd31de649eea0f7ea1cb5d9269fa184dc59a97 Mon Sep 17 00:00:00 2001 From: Patrick Lannigan Date: Sat, 24 Feb 2024 14:27:54 -0500 Subject: [PATCH 0495/1271] New verbosity_test_case ini option (#11653) Allow for the output of test case execution to be controlled independently from the application verbosity level. `verbosity_test_case` is the new ini setting to adjust this functionality. Fix #11639 --- changelog/11653.feature.rst | 2 + doc/en/how-to/output.rst | 4 +- doc/en/reference/reference.rst | 13 ++ src/_pytest/config/__init__.py | 2 + src/_pytest/terminal.py | 28 ++-- testing/test_terminal.py | 233 +++++++++++++++++++++++++++++++++ 6 files changed, 273 insertions(+), 9 deletions(-) create mode 100644 changelog/11653.feature.rst diff --git a/changelog/11653.feature.rst b/changelog/11653.feature.rst new file mode 100644 index 00000000000..f165c3f8e20 --- /dev/null +++ b/changelog/11653.feature.rst @@ -0,0 +1,2 @@ +Added the new :confval:`verbosity_test_cases` configuration option for fine-grained control of test execution verbosity. +See :ref:`Fine-grained verbosity ` for more details. diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index 76b2a53dd18..5b47a5c7776 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -325,7 +325,9 @@ This is done by setting a verbosity level in the configuration file for the spec ``pytest --no-header`` with a value of ``2`` would have the same output as the previous example, but each test inside the file is shown by a single character in the output. -(Note: currently this is the only option available, but more might be added in the future). +:confval:`verbosity_test_cases`: Controls how verbose the test execution output should be when pytest is executed. +Running ``pytest --no-header`` with a value of ``2`` would have the same output as the first verbosity example, but each +test inside the file gets its own line in the output. .. _`pytest.detailed_failed_tests_usage`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 1076026c205..bba4a399c72 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1865,6 +1865,19 @@ passed multiple times. The expected format is ``name=value``. For example:: "auto" can be used to explicitly use the global verbosity level. +.. confval:: verbosity_test_cases + + Set a verbosity level specifically for test case execution related output, overriding the application wide level. + + .. code-block:: ini + + [pytest] + verbosity_test_cases = 2 + + Defaults to application wide verbosity level (via the ``-v`` command-line option). A special value of + "auto" can be used to explicitly use the global verbosity level. + + .. confval:: xfail_strict If set to ``True``, tests marked with ``@pytest.mark.xfail`` that actually succeed will by default fail the diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index f8eea936aa6..069e2196d25 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1657,6 +1657,8 @@ def getvalueorskip(self, name: str, path=None): #: Verbosity type for failed assertions (see :confval:`verbosity_assertions`). VERBOSITY_ASSERTIONS: Final = "assertions" + #: Verbosity type for test case execution (see :confval:`verbosity_test_cases`). + VERBOSITY_TEST_CASES: Final = "test_cases" _VERBOSITY_INI_DEFAULT: Final = "auto" def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 8909d95ef24..75d57197aac 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -255,6 +255,14 @@ def pytest_addoption(parser: Parser) -> None: "progress even when capture=no)", default="progress", ) + Config._add_verbosity_ini( + parser, + Config.VERBOSITY_TEST_CASES, + help=( + "Specify a verbosity level for test case execution, overriding the main level. " + "Higher levels will provide more detailed information about each test case executed." + ), + ) def pytest_configure(config: Config) -> None: @@ -408,7 +416,7 @@ def no_summary(self) -> bool: @property def showfspath(self) -> bool: if self._showfspath is None: - return self.verbosity >= 0 + return self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) >= 0 return self._showfspath @showfspath.setter @@ -417,7 +425,7 @@ def showfspath(self, value: Optional[bool]) -> None: @property def showlongtestinfo(self) -> bool: - return self.verbosity > 0 + return self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) > 0 def hasopt(self, char: str) -> bool: char = {"xfailed": "x", "skipped": "s"}.get(char, char) @@ -595,7 +603,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: markup = {"yellow": True} else: markup = {} - if self.verbosity <= 0: + if self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) <= 0: self._tw.write(letter, **markup) else: self._progress_nodeids_reported.add(rep.nodeid) @@ -604,7 +612,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: self.write_ensure_prefix(line, word, **markup) if rep.skipped or hasattr(report, "wasxfail"): reason = _get_raw_skip_reason(rep) - if self.config.option.verbose < 2: + if self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) < 2: available_width = ( (self._tw.fullwidth - self._tw.width_of_current_line) - len(" [100%]") @@ -641,7 +649,10 @@ def _is_last_item(self) -> bool: def pytest_runtest_logfinish(self, nodeid: str) -> None: assert self._session - if self.verbosity <= 0 and self._show_progress_info: + if ( + self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) <= 0 + and self._show_progress_info + ): if self._show_progress_info == "count": num_tests = self._session.testscollected progress_length = len(f" [{num_tests}/{num_tests}]") @@ -819,8 +830,9 @@ def pytest_collection_finish(self, session: "Session") -> None: rep.toterminal(self._tw) def _printcollecteditems(self, items: Sequence[Item]) -> None: - if self.config.option.verbose < 0: - if self.config.option.verbose < -1: + test_cases_verbosity = self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) + if test_cases_verbosity < 0: + if test_cases_verbosity < -1: counts = Counter(item.nodeid.split("::", 1)[0] for item in items) for name, count in sorted(counts.items()): self._tw.line("%s: %d" % (name, count)) @@ -840,7 +852,7 @@ def _printcollecteditems(self, items: Sequence[Item]) -> None: stack.append(col) indent = (len(stack) - 1) * " " self._tw.line(f"{indent}{col}") - if self.config.option.verbose >= 1: + if test_cases_verbosity >= 1: obj = getattr(col, "obj", None) doc = inspect.getdoc(obj) if obj else None if doc: diff --git a/testing/test_terminal.py b/testing/test_terminal.py index bc457c39800..b311d6c9b14 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2611,6 +2611,239 @@ def test_format_trimmed() -> None: assert _format_trimmed(" ({}) ", msg, len(msg) + 3) == " (unconditional ...) " +class TestFineGrainedTestCase: + DEFAULT_FILE_CONTENTS = """ + import pytest + + @pytest.mark.parametrize("i", range(4)) + def test_ok(i): + ''' + some docstring + ''' + pass + + def test_fail(): + assert False + """ + LONG_SKIP_FILE_CONTENTS = """ + import pytest + + @pytest.mark.skip( + "some long skip reason that will not fit on a single line with other content that goes" + " on and on and on and on and on" + ) + def test_skip(): + pass + """ + + @pytest.mark.parametrize("verbosity", [1, 2]) + def test_execute_positive(self, verbosity, pytester: Pytester) -> None: + # expected: one test case per line (with file name), word describing result + p = TestFineGrainedTestCase._initialize_files(pytester, verbosity=verbosity) + result = pytester.runpytest(p) + + result.stdout.fnmatch_lines( + [ + "collected 5 items", + "", + f"{p.name}::test_ok[0] PASSED [ 20%]", + f"{p.name}::test_ok[1] PASSED [ 40%]", + f"{p.name}::test_ok[2] PASSED [ 60%]", + f"{p.name}::test_ok[3] PASSED [ 80%]", + f"{p.name}::test_fail FAILED [100%]", + ], + consecutive=True, + ) + + def test_execute_0_global_1(self, pytester: Pytester) -> None: + # expected: one file name per line, single character describing result + p = TestFineGrainedTestCase._initialize_files(pytester, verbosity=0) + result = pytester.runpytest("-v", p) + + result.stdout.fnmatch_lines( + [ + "collecting ... collected 5 items", + "", + f"{p.name} ....F [100%]", + ], + consecutive=True, + ) + + @pytest.mark.parametrize("verbosity", [-1, -2]) + def test_execute_negative(self, verbosity, pytester: Pytester) -> None: + # expected: single character describing result + p = TestFineGrainedTestCase._initialize_files(pytester, verbosity=verbosity) + result = pytester.runpytest(p) + + result.stdout.fnmatch_lines( + [ + "collected 5 items", + "....F [100%]", + ], + consecutive=True, + ) + + def test_execute_skipped_positive_2(self, pytester: Pytester) -> None: + # expected: one test case per line (with file name), word describing result, full reason + p = TestFineGrainedTestCase._initialize_files( + pytester, + verbosity=2, + file_contents=TestFineGrainedTestCase.LONG_SKIP_FILE_CONTENTS, + ) + result = pytester.runpytest(p) + + result.stdout.fnmatch_lines( + [ + "collected 1 item", + "", + f"{p.name}::test_skip SKIPPED (some long skip", + "reason that will not fit on a single line with other content that goes", + "on and on and on and on and on) [100%]", + ], + consecutive=True, + ) + + def test_execute_skipped_positive_1(self, pytester: Pytester) -> None: + # expected: one test case per line (with file name), word describing result, reason truncated + p = TestFineGrainedTestCase._initialize_files( + pytester, + verbosity=1, + file_contents=TestFineGrainedTestCase.LONG_SKIP_FILE_CONTENTS, + ) + result = pytester.runpytest(p) + + result.stdout.fnmatch_lines( + [ + "collected 1 item", + "", + f"{p.name}::test_skip SKIPPED (some long ski...) [100%]", + ], + consecutive=True, + ) + + def test_execute_skipped__0_global_1(self, pytester: Pytester) -> None: + # expected: one file name per line, single character describing result (no reason) + p = TestFineGrainedTestCase._initialize_files( + pytester, + verbosity=0, + file_contents=TestFineGrainedTestCase.LONG_SKIP_FILE_CONTENTS, + ) + result = pytester.runpytest("-v", p) + + result.stdout.fnmatch_lines( + [ + "collecting ... collected 1 item", + "", + f"{p.name} s [100%]", + ], + consecutive=True, + ) + + @pytest.mark.parametrize("verbosity", [-1, -2]) + def test_execute_skipped_negative(self, verbosity, pytester: Pytester) -> None: + # expected: single character describing result (no reason) + p = TestFineGrainedTestCase._initialize_files( + pytester, + verbosity=verbosity, + file_contents=TestFineGrainedTestCase.LONG_SKIP_FILE_CONTENTS, + ) + result = pytester.runpytest(p) + + result.stdout.fnmatch_lines( + [ + "collected 1 item", + "s [100%]", + ], + consecutive=True, + ) + + @pytest.mark.parametrize("verbosity", [1, 2]) + def test__collect_only_positive(self, verbosity, pytester: Pytester) -> None: + p = TestFineGrainedTestCase._initialize_files(pytester, verbosity=verbosity) + result = pytester.runpytest("--collect-only", p) + + result.stdout.fnmatch_lines( + [ + "collected 5 items", + "", + f"", + f" ", + " ", + " some docstring", + " ", + " some docstring", + " ", + " some docstring", + " ", + " some docstring", + " ", + ], + consecutive=True, + ) + + def test_collect_only_0_global_1(self, pytester: Pytester) -> None: + p = TestFineGrainedTestCase._initialize_files(pytester, verbosity=0) + result = pytester.runpytest("-v", "--collect-only", p) + + result.stdout.fnmatch_lines( + [ + "collecting ... collected 5 items", + "", + f"", + f" ", + " ", + " ", + " ", + " ", + " ", + ], + consecutive=True, + ) + + def test_collect_only_negative_1(self, pytester: Pytester) -> None: + p = TestFineGrainedTestCase._initialize_files(pytester, verbosity=-1) + result = pytester.runpytest("--collect-only", p) + + result.stdout.fnmatch_lines( + [ + "collected 5 items", + "", + f"{p.name}::test_ok[0]", + f"{p.name}::test_ok[1]", + f"{p.name}::test_ok[2]", + f"{p.name}::test_ok[3]", + f"{p.name}::test_fail", + ], + consecutive=True, + ) + + def test_collect_only_negative_2(self, pytester: Pytester) -> None: + p = TestFineGrainedTestCase._initialize_files(pytester, verbosity=-2) + result = pytester.runpytest("--collect-only", p) + + result.stdout.fnmatch_lines( + [ + "collected 5 items", + "", + f"{p.name}: 5", + ], + consecutive=True, + ) + + @staticmethod + def _initialize_files( + pytester: Pytester, verbosity: int, file_contents: str = DEFAULT_FILE_CONTENTS + ) -> Path: + p = pytester.makepyfile(file_contents) + pytester.makeini( + f""" + [pytest] + verbosity_test_cases = {verbosity} + """ + ) + return p + + def test_summary_xfail_reason(pytester: Pytester) -> None: pytester.makepyfile( """ From 7460b1aa3132d3ecfd47e399ec248f4097986aa5 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 25 Feb 2024 00:24:32 +0200 Subject: [PATCH 0496/1271] Cherry pick 8.0.2 release notes (cherry picked from commit e53f79893212391c0bada5f1628b977371a09434) --- changelog/11895.bugfix.rst | 1 - changelog/11953.bugfix.rst | 1 - changelog/12021.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.0.2.rst | 18 ++++++++++++++++++ doc/en/changelog.rst | 15 +++++++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 10 files changed, 41 insertions(+), 10 deletions(-) delete mode 100644 changelog/11895.bugfix.rst delete mode 100644 changelog/11953.bugfix.rst delete mode 100644 changelog/12021.bugfix.rst create mode 100644 doc/en/announce/release-8.0.2.rst diff --git a/changelog/11895.bugfix.rst b/changelog/11895.bugfix.rst deleted file mode 100644 index 4211213c1e5..00000000000 --- a/changelog/11895.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix collection on Windows where initial paths contain the short version of a path (for example ``c:\PROGRA~1\tests``). diff --git a/changelog/11953.bugfix.rst b/changelog/11953.bugfix.rst deleted file mode 100644 index 5aff5f7fdb7..00000000000 --- a/changelog/11953.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix an ``IndexError`` crash raising from ``getstatementrange_ast``. diff --git a/changelog/12021.bugfix.rst b/changelog/12021.bugfix.rst deleted file mode 100644 index eb8771ad720..00000000000 --- a/changelog/12021.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Reverted a fix to `--maxfail` handling in pytest 8.0.0 because it caused a regression in pytest-xdist whereby session fixture teardowns may get executed multiple times when the max-fails is reached. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 78045114667..5374e8c7596 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.0.2 release-8.0.1 release-8.0.0 release-8.0.0rc2 diff --git a/doc/en/announce/release-8.0.2.rst b/doc/en/announce/release-8.0.2.rst new file mode 100644 index 00000000000..c42159c57cf --- /dev/null +++ b/doc/en/announce/release-8.0.2.rst @@ -0,0 +1,18 @@ +pytest-8.0.2 +======================================= + +pytest 8.0.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 88f67635565..bdf5a155031 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,21 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.0.2 (2024-02-24) +========================= + +Bug Fixes +--------- + +- `#11895 `_: Fix collection on Windows where initial paths contain the short version of a path (for example ``c:\PROGRA~1\tests``). + + +- `#11953 `_: Fix an ``IndexError`` crash raising from ``getstatementrange_ast``. + + +- `#12021 `_: Reverted a fix to `--maxfail` handling in pytest 8.0.0 because it caused a regression in pytest-xdist whereby session fixture teardowns may get executed multiple times when the max-fails is reached. + + pytest 8.0.1 (2024-02-16) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 99afaded84c..c6ac6489979 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 89acb7d3b65..7207ca2ae63 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 114d69328c2..f1919886495 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.0.1 + pytest 8.0.2 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index bc45c3a29bf..329c568c00b 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From b6eb985d558e626f4820d7681c72120848b5dc60 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 25 Feb 2024 00:19:33 +0000 Subject: [PATCH 0497/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 190 +++++++++++++++++-------------- 1 file changed, 107 insertions(+), 83 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index b89a9b05fa2..6e5c2c15cbc 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -7,7 +7,7 @@ Pytest Plugin List ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with ``"pytest-"`` or ``"pytest_"`` and a handful of manually selected projects. +It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, @@ -27,7 +27,7 @@ please refer to `the update script =7,<9) ; extra == "pytest" + :pypi:`logot` Test whether your code is logging correctly 🪵 Feb 19, 2024 5 - Production/Stable pytest (>=7,<9) ; extra == "pytest" :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A @@ -68,7 +68,7 @@ This list contains 1394 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) - :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Feb 12, 2024 N/A pytest >=7.3.1 + :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Feb 21, 2024 N/A pytest <8.0.0,>=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) @@ -138,7 +138,7 @@ This list contains 1394 plugins. :pypi:`pytest-bdd` BDD for pytest Dec 02, 2023 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 - :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 15, 2023 N/A pytest >=7.1.3 + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Feb 19, 2024 N/A pytest >=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A @@ -146,7 +146,6 @@ This list contains 1394 plugins. :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A - :pypi:`pytest-behave` A powerful test automation framework designed to provide a comprehensive solution for testing user interfaces and APIs Feb 15, 2024 N/A N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A @@ -212,7 +211,7 @@ This list contains 1394 plugins. :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest>=7.0 :pypi:`pytest-check-mk` pytest plugin to test Check_MK checks Nov 19, 2015 4 - Beta pytest - :pypi:`pytest-check-requirements` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-check-requirements` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 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 Feb 04, 2024 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) @@ -292,7 +291,7 @@ This list contains 1394 plugins. :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A :pypi:`pytest-cython` A plugin for testing Cython extension modules Feb 16, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest - :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Aug 16, 2020 N/A pytest (>=6.0.1) ; extra == 'test' + :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 24, 2024 N/A pytest <8,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest @@ -337,7 +336,7 @@ This list contains 1394 plugins. :pypi:`pytest-dicom` pytest plugin to provide DICOM fixtures Dec 19, 2018 3 - Alpha pytest :pypi:`pytest-dictsdiff` Jul 26, 2019 N/A N/A :pypi:`pytest-diff` A simple plugin to use with pytest Mar 30, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all' :pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0) :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 11, 2023 4 - Beta pytest>=7.3.2 @@ -423,14 +422,14 @@ This list contains 1394 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. Feb 14, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Feb 23, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 23, 2024 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) @@ -462,6 +461,7 @@ This list contains 1394 plugins. :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest :pypi:`pytest-executable` pytest plugin for testing executables Oct 07, 2023 N/A pytest <8,>=5 :pypi:`pytest-execution-timer` A timer for the phases of Pytest's execution. Dec 24, 2021 4 - Beta N/A + :pypi:`pytest-exit-code` A pytest plugin that overrides the built-in exit codes to retain more information about the test results. Feb 23, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-expect` py.test plugin to store test expectations and mark tests based on them Apr 21, 2016 4 - Beta N/A :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-expecter` Better testing with expecter and pytest. Sep 18, 2022 5 - Production/Stable N/A @@ -477,7 +477,7 @@ This list contains 1394 plugins. :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A - :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) :pypi:`pytest-factoryboy` Factory Boy support for pytest. Oct 10, 2023 6 - Mature pytest (>=6.2) :pypi:`pytest-factoryboy-fixtures` Generates pytest fixtures that allow the use of type hinting Jun 25, 2020 N/A N/A @@ -488,7 +488,7 @@ This list contains 1394 plugins. :pypi:`pytest-fail-slow` Fail tests that take too long to run Feb 11, 2024 N/A pytest>=7.0 :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A - :pypi:`pytest-falcon-client` Pytest \`client\` fixture for the Falcon Framework Mar 19, 2019 N/A N/A + :pypi:`pytest-falcon-client` A package to prevent Dependency Confusion attacks against Yandex. Feb 21, 2024 N/A N/A :pypi:`pytest-fantasy` Pytest plugin for Flask Fantasy Framework Mar 14, 2019 N/A N/A :pypi:`pytest-fastapi` Dec 27, 2020 N/A N/A :pypi:`pytest-fastapi-deps` A fixture which allows easy replacement of fastapi dependencies for testing Jul 20, 2022 5 - Production/Stable pytest @@ -507,7 +507,7 @@ This list contains 1394 plugins. :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest - :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Nov 09, 2023 4 - Beta pytest >=3.5.0 + :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Feb 22, 2024 4 - Beta pytest >=3.5.0 :pypi:`pytest-fixture-config` Fixture configuration utils for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-fixture-maker` Pytest plugin to load fixtures from YAML files Sep 21, 2021 N/A N/A :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A @@ -551,6 +551,7 @@ This list contains 1394 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Feb 18, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-gee` The Python plugin for your GEE based packages. Feb 15, 2024 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) @@ -595,7 +596,7 @@ This list contains 1394 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Feb 17, 2024 3 - Alpha pytest ==7.4.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 24, 2024 3 - Alpha pytest ==7.4.4 :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` Jan 06, 2024 N/A N/A @@ -620,7 +621,7 @@ This list contains 1394 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 13, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-httpx` Send responses to httpx. Jan 29, 2024 5 - Production/Stable pytest <9,>=7 + :pypi:`pytest-httpx` Send responses to httpx. Feb 21, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -646,11 +647,11 @@ This list contains 1394 plugins. :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. Dec 13, 2023 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Feb 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Nov 29, 2023 5 - Production/Stable N/A - :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Jun 16, 2022 4 - Beta N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Feb 20, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-insper` Pytest plugin for courses at Insper Feb 01, 2024 N/A pytest - :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Nov 02, 2022 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Feb 19, 2024 N/A pytest (>=7.2.0,<9.0.0) :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) :pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0) :pypi:`pytest-integration` Organizing pytests by integration or not Nov 17, 2022 N/A N/A @@ -684,7 +685,7 @@ This list contains 1394 plugins. :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Dec 05, 2023 4 - Beta pytest + :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Feb 21, 2024 4 - Beta pytest :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest @@ -735,7 +736,7 @@ This list contains 1394 plugins. :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) :pypi:`pytest-logdog` Pytest plugin to test logging Jun 15, 2021 1 - Planning pytest (>=6.2.0) :pypi:`pytest-logfest` Pytest plugin providing three logger fixtures with basic or full writing to log files Jul 21, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Feb 12, 2024 5 - Production/Stable pytest (>=3.2) + :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Feb 21, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logikal` Common testing environment Feb 05, 2024 5 - Production/Stable pytest ==8.0.0 @@ -773,7 +774,7 @@ This list contains 1394 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 Feb 12, 2024 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 Feb 15, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Feb 21, 2024 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) @@ -872,7 +873,7 @@ This list contains 1394 plugins. :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 - :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Feb 16, 2024 N/A pytest==7.1.3 + :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Feb 19, 2024 N/A pytest==8.0.1 :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A :pypi:`pytest-owner` Add owner mark for tests Apr 25, 2022 N/A N/A :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A @@ -924,6 +925,7 @@ This list contains 1394 plugins. :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Feb 02, 2024 N/A pytest (<9.0.0,>=6.2.4) :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Feb 06, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A + :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Feb 24, 2024 N/A pytest (>=8.0.0,<9.0.0) :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A @@ -986,6 +988,7 @@ This list contains 1394 plugins. :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Jan 02, 2024 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) + :pypi:`pytest-pythonhashseed` Pytest plugin to set PYTHONHASHSEED env var. Feb 18, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 @@ -1085,7 +1088,7 @@ This list contains 1394 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Feb 08, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Feb 22, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1109,7 +1112,7 @@ This list contains 1394 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 17, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 23, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1118,7 +1121,7 @@ This list contains 1394 plugins. :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 Feb 01, 2024 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. Feb 17, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Feb 23, 2024 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 @@ -1137,7 +1140,7 @@ This list contains 1394 plugins. :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A - :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Jul 02, 2023 5 - Production/Stable pytest (>=7.1.0) + :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Feb 23, 2024 5 - Production/Stable pytest >=7.4.0 :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) @@ -1193,7 +1196,7 @@ This list contains 1394 plugins. :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 Jan 12, 2024 N/A pytest (>5.4.0,<8) - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Feb 13, 2024 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Feb 23, 2024 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 @@ -1205,7 +1208,7 @@ This list contains 1394 plugins. :pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A pytest>=6.2.0 :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A - :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-static` pytest-static Jan 15, 2024 1 - Planning pytest (>=7.4.3,<8.0.0) :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest @@ -1408,7 +1411,7 @@ This list contains 1394 plugins. :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) - :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 10, 2023 N/A N/A + :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :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 @@ -1441,7 +1444,7 @@ This list contains 1394 plugins. Simple but powerful assertion and verification of logged lines. :pypi:`logot` - *last release*: Feb 17, 2024, + *last release*: Feb 19, 2024, *status*: 5 - Production/Stable, *requires*: pytest (>=7,<9) ; extra == "pytest" @@ -1672,9 +1675,9 @@ This list contains 1394 plugins. Static code checks used at Alphamoon :pypi:`pytest-analyzer` - *last release*: Feb 12, 2024, + *last release*: Feb 21, 2024, *status*: N/A, - *requires*: pytest >=7.3.1 + *requires*: pytest <8.0.0,>=7.3.1 this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system @@ -2162,7 +2165,7 @@ This list contains 1394 plugins. BDD for pytest :pypi:`pytest-bdd-report` - *last release*: Nov 15, 2023, + *last release*: Feb 19, 2024, *status*: N/A, *requires*: pytest >=7.1.3 @@ -2217,13 +2220,6 @@ This list contains 1394 plugins. use icdiff for better error messages in pytest assertions - :pypi:`pytest-behave` - *last release*: Feb 15, 2024, - *status*: N/A, - *requires*: N/A - - A powerful test automation framework designed to provide a comprehensive solution for testing user interfaces and APIs - :pypi:`pytest-bench` *last release*: Jul 21, 2014, *status*: 3 - Alpha, @@ -2680,7 +2676,7 @@ This list contains 1394 plugins. pytest plugin to test Check_MK checks :pypi:`pytest-check-requirements` - *last release*: Feb 10, 2023, + *last release*: Feb 20, 2024, *status*: N/A, *requires*: N/A @@ -3240,9 +3236,9 @@ This list contains 1394 plugins. :pypi:`pytest-darker` - *last release*: Aug 16, 2020, + *last release*: Feb 24, 2024, *status*: N/A, - *requires*: pytest (>=6.0.1) ; extra == 'test' + *requires*: pytest <8,>=6.0.1 A pytest plugin for checking of modified code using Darker @@ -3555,7 +3551,7 @@ This list contains 1394 plugins. A simple plugin to use with pytest :pypi:`pytest-diffeo` - *last release*: Feb 10, 2023, + *last release*: Feb 20, 2024, *status*: N/A, *requires*: N/A @@ -4157,56 +4153,56 @@ This list contains 1394 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Feb 14, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Feb 14, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Feb 14, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Feb 14, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Feb 14, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Feb 14, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Feb 14, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Feb 14, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4429,6 +4425,13 @@ This list contains 1394 plugins. A timer for the phases of Pytest's execution. + :pypi:`pytest-exit-code` + *last release*: Feb 23, 2024, + *status*: 4 - Beta, + *requires*: pytest >=6.2.0 + + A pytest plugin that overrides the built-in exit codes to retain more information about the test results. + :pypi:`pytest-expect` *last release*: Apr 21, 2016, *status*: 4 - Beta, @@ -4535,7 +4538,7 @@ This list contains 1394 plugins. Provides test utilities to run fabric task tests by using docker containers :pypi:`pytest-factor` - *last release*: Feb 10, 2023, + *last release*: Feb 20, 2024, *status*: N/A, *requires*: N/A @@ -4612,11 +4615,11 @@ This list contains 1394 plugins. Pytest helpers for Falcon. :pypi:`pytest-falcon-client` - *last release*: Mar 19, 2019, + *last release*: Feb 21, 2024, *status*: N/A, *requires*: N/A - Pytest \`client\` fixture for the Falcon Framework + A package to prevent Dependency Confusion attacks against Yandex. :pypi:`pytest-fantasy` *last release*: Mar 14, 2019, @@ -4745,7 +4748,7 @@ This list contains 1394 plugins. Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers :pypi:`pytest-fixturecollection` - *last release*: Nov 09, 2023, + *last release*: Feb 22, 2024, *status*: 4 - Beta, *requires*: pytest >=3.5.0 @@ -5052,6 +5055,13 @@ This list contains 1394 plugins. Uses gcov to measure test coverage of a C library + :pypi:`pytest-gcs` + *last release*: Feb 18, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest >=6.2 + + GCS fixtures and fixture factories for Pytest. + :pypi:`pytest-gee` *last release*: Feb 15, 2024, *status*: 3 - Alpha, @@ -5361,7 +5371,7 @@ This list contains 1394 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 17, 2024, + *last release*: Feb 24, 2024, *status*: 3 - Alpha, *requires*: pytest ==7.4.4 @@ -5536,7 +5546,7 @@ This list contains 1394 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Jan 29, 2024, + *last release*: Feb 21, 2024, *status*: 5 - Production/Stable, *requires*: pytest <9,>=7 @@ -5718,16 +5728,16 @@ This list contains 1394 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Nov 29, 2023, + *last release*: Feb 20, 2024, *status*: 5 - Production/Stable, *requires*: N/A Common fixtures for inmanta LSM related modules :pypi:`pytest-inmanta-yang` - *last release*: Jun 16, 2022, + *last release*: Feb 22, 2024, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest Common fixtures used in inmanta yang related modules @@ -5746,9 +5756,9 @@ This list contains 1394 plugins. Pytest plugin for courses at Insper :pypi:`pytest-insta` - *last release*: Nov 02, 2022, + *last release*: Feb 19, 2024, *status*: N/A, - *requires*: pytest (>=7.2.0,<8.0.0) + *requires*: pytest (>=7.2.0,<9.0.0) A practical snapshot testing plugin for pytest @@ -5984,7 +5994,7 @@ This list contains 1394 plugins. pytest plugin supporting json test report output :pypi:`pytest-jupyter` - *last release*: Dec 05, 2023, + *last release*: Feb 21, 2024, *status*: 4 - Beta, *requires*: pytest @@ -6341,7 +6351,7 @@ This list contains 1394 plugins. Pytest plugin providing three logger fixtures with basic or full writing to log files :pypi:`pytest-logger` - *last release*: Feb 12, 2024, + *last release*: Feb 21, 2024, *status*: 5 - Production/Stable, *requires*: pytest (>=3.2) @@ -6607,7 +6617,7 @@ This list contains 1394 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Feb 15, 2024, + *last release*: Feb 21, 2024, *status*: N/A, *requires*: pytest @@ -7300,9 +7310,9 @@ This list contains 1394 plugins. OS X notifications for py.test results. :pypi:`pytest-otel` - *last release*: Feb 16, 2024, + *last release*: Feb 19, 2024, *status*: N/A, - *requires*: pytest==7.1.3 + *requires*: pytest==8.0.1 OpenTelemetry plugin for Pytest @@ -7663,6 +7673,13 @@ This list contains 1394 plugins. + :pypi:`pytest-playwright-enhanced` + *last release*: Feb 24, 2024, + *status*: N/A, + *requires*: pytest (>=8.0.0,<9.0.0) + + A pytest plugin for playwright python + :pypi:`pytest-playwrights` *last release*: Dec 02, 2021, *status*: N/A, @@ -8097,6 +8114,13 @@ This list contains 1394 plugins. Pytest plugin for interaction with TestRail + :pypi:`pytest-pythonhashseed` + *last release*: Feb 18, 2024, + *status*: 4 - Beta, + *requires*: pytest>=3.0.0 + + Pytest plugin to set PYTHONHASHSEED env var. + :pypi:`pytest-pythonpath` *last release*: Feb 10, 2022, *status*: 5 - Production/Stable, @@ -8791,7 +8815,7 @@ This list contains 1394 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Feb 08, 2024, + *last release*: Feb 22, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -8959,7 +8983,7 @@ This list contains 1394 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Feb 17, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9022,7 +9046,7 @@ This list contains 1394 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Feb 17, 2024, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9155,9 +9179,9 @@ This list contains 1394 plugins. A pytest plugin to help with testing shell scripts / black box commands :pypi:`pytest-shell-utilities` - *last release*: Jul 02, 2023, + *last release*: Feb 23, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.1.0) + *requires*: pytest >=7.4.0 Pytest plugin to simplify running shell commands against the system @@ -9547,7 +9571,7 @@ This list contains 1394 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Feb 13, 2024, + *last release*: Feb 23, 2024, *status*: N/A, *requires*: N/A @@ -9631,7 +9655,7 @@ This list contains 1394 plugins. Start pytest run from a given point :pypi:`pytest-star-track-issue` - *last release*: Feb 10, 2023, + *last release*: Feb 20, 2024, *status*: N/A, *requires*: N/A @@ -11052,7 +11076,7 @@ This list contains 1394 plugins. :pypi:`pytest-xskynet` - *last release*: Feb 10, 2023, + *last release*: Feb 20, 2024, *status*: N/A, *requires*: N/A From ffd727e9d60a638f915f49b25f89b9a38b8b9700 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 24 Feb 2024 21:35:51 -0300 Subject: [PATCH 0498/1271] Fix mention of the prefix for pytest plugins in `plugin_list` --- doc/en/reference/plugin_list.rst | 2 +- scripts/update-plugin-list.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6e5c2c15cbc..e02080eb262 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -7,7 +7,7 @@ Pytest Plugin List ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. +It includes PyPI projects whose names begin with ``pytest-`` or ``pytest_`` and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 6226bc8c928..6831fc984dd 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -29,7 +29,7 @@ ================== Below is an automated compilation of ``pytest``` plugins available on `PyPI `_. -It includes PyPI projects whose names begin with "pytest-" or "pytest_" and a handful of manually selected projects. +It includes PyPI projects whose names begin with ``pytest-`` or ``pytest_`` and a handful of manually selected projects. Packages classified as inactive are excluded. For detailed insights into how this list is generated, From 98b008ff6ca663723767f807cb730cc6833c9034 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 10:51:07 -0300 Subject: [PATCH 0499/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#12033) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.2.0...4.3.0) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 61c423ce6ef..42ab2af997b 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==4.2.0 +anyio[curio,trio]==4.3.0 django==5.0.2 pytest-asyncio==0.23.5 # Temporarily not installed until pytest-bdd is fixed: From 686f9e0720da7d50ea94fe54dbea85da50e300af Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 27 Feb 2024 17:49:35 +0200 Subject: [PATCH 0500/1271] fixtures: remove unneeded optimization from `_getnextfixturedef` According to my understanding, this code, which handles obtaining the relevant fixturedefs when a dynamic `getfixturevalue` is used, has an optimization where it only grabs fixturedefs that are visible to the *parent* of the item, instead of the item itself, under the assumption that a fixturedef can't be visible to a single item, only to a collector. Remove this optimization for the following reasons: - It doesn't save much (one loop iteration in `matchfactories`) - It slightly complicates the complex fixtures code - If some plugin wants to make a fixture visible only to a single item, why not let it? - In the static case (`getfixtureclosure`), this optimization is not done (despite the confusing name `parentnode`, it is *not* the parent node). This is inconsistent. --- src/_pytest/fixtures.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 99de03fe849..0a505d65ad0 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -413,9 +413,7 @@ def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": # We arrive here because of a dynamic call to # getfixturevalue(argname) usage which was naturally # not known at parsing/collection time. - parent = self._pyfuncitem.parent - assert parent is not None - fixturedefs = self._fixturemanager.getfixturedefs(argname, parent) + fixturedefs = self._fixturemanager.getfixturedefs(argname, self._pyfuncitem) if fixturedefs is not None: self._arg2fixturedefs[argname] = fixturedefs # No fixtures defined with this name. From c83c1c4bda7e92bcda00dad29798b8fc73028997 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 27 Feb 2024 10:51:31 +0200 Subject: [PATCH 0501/1271] fixtures: add `_iter_chain` helper method Will be reused in the next commit. --- src/_pytest/fixtures.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 99de03fe849..86a8eef0452 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -540,6 +540,16 @@ def getfixturevalue(self, argname: str) -> Any: ) return fixturedef.cached_result[0] + def _iter_chain(self) -> Iterator["SubRequest"]: + """Yield all SubRequests in the chain, from self up. + + Note: does *not* yield the TopRequest. + """ + current = self + while isinstance(current, SubRequest): + yield current + current = current._parent_request + def _get_active_fixturedef( self, argname: str ) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]: @@ -557,11 +567,7 @@ def _get_active_fixturedef( return fixturedef def _get_fixturestack(self) -> List["FixtureDef[Any]"]: - current = self - values: List[FixtureDef[Any]] = [] - while isinstance(current, SubRequest): - values.append(current._fixturedef) # type: ignore[has-type] - current = current._parent_request + values = [request._fixturedef for request in self._iter_chain()] values.reverse() return values @@ -705,7 +711,7 @@ def __init__( ) self._parent_request: Final[FixtureRequest] = request self._scope_field: Final = scope - self._fixturedef: Final = fixturedef + self._fixturedef: Final[FixtureDef[object]] = fixturedef if param is not NOTSET: self.param = param self.param_index: Final = param_index From bd45ccd2ca399121fa91baa3fa0d25c2c36b6671 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 27 Feb 2024 10:37:40 +0200 Subject: [PATCH 0502/1271] fixtures: avoid mutable `arg2index` state in favor of looking up the request chain pytest allows a fixture to request its own name (directly or indirectly), in which case the fixture with the same name but one level up is used. To know which fixture should be used next, pytest keeps a mutable item-global dict `_arg2index` which maintains this state. This is not great: - Mutable state like this is hard to understand and reason about. - It is conceptually buggy; the indexing is global (e.g. if requesting `fix1` and `fix2`, the indexing is shared between them), but actually different branches of the subrequest tree should not affect each other. This is not an issue in practice because pytest keeps a cache of the fixturedefs it resolved anyway (`_fixture_defs`), but if the cache is removed it becomes evident. Instead of the `_arg2index` state, count how many `argname`s deep we are in the subrequest tree ("the fixture stack") and use that for the index. This way, no global mutable state and the logic is very localized and easier to understand. This is slower, however fixture stacks should not be so deep that this matters much, I hope. --- src/_pytest/fixtures.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 86a8eef0452..fff95521865 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -343,7 +343,6 @@ def __init__( pyfuncitem: "Function", fixturename: Optional[str], arg2fixturedefs: Dict[str, Sequence["FixtureDef[Any]"]], - arg2index: Dict[str, int], fixture_defs: Dict[str, "FixtureDef[Any]"], *, _ispytest: bool = False, @@ -357,16 +356,6 @@ def __init__( # collection. Dynamically requested fixtures (using # `request.getfixturevalue("foo")`) are added dynamically. self._arg2fixturedefs: Final = arg2fixturedefs - # A fixture may override another fixture with the same name, e.g. a fixture - # in a module can override a fixture in a conftest, a fixture in a class can - # override a fixture in the module, and so on. - # An overriding fixture can request its own name; in this case it gets - # the value of the fixture it overrides, one level up. - # The _arg2index state keeps the current depth in the overriding chain. - # The fixturedefs list in _arg2fixturedefs for a given name is ordered from - # furthest to closest, so we use negative indexing -1, -2, ... to go from - # last to first. - self._arg2index: Final = arg2index # The evaluated argnames so far, mapping to the FixtureDef they resolved # to. self._fixture_defs: Final = fixture_defs @@ -424,11 +413,24 @@ def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": # The are no fixtures with this name applicable for the function. if not fixturedefs: raise FixtureLookupError(argname, self) - index = self._arg2index.get(argname, 0) - 1 - # The fixture requested its own name, but no remaining to override. + + # A fixture may override another fixture with the same name, e.g. a + # fixture in a module can override a fixture in a conftest, a fixture in + # a class can override a fixture in the module, and so on. + # An overriding fixture can request its own name (possibly indirectly); + # in this case it gets the value of the fixture it overrides, one level + # up. + # Check how many `argname`s deep we are, and take the next one. + # `fixturedefs` is sorted from furthest to closest, so use negative + # indexing to go in reverse. + index = -1 + for request in self._iter_chain(): + if request.fixturename == argname: + index -= 1 + # If already consumed all of the available levels, fail. if -index > len(fixturedefs): raise FixtureLookupError(argname, self) - self._arg2index[argname] = index + return fixturedefs[index] @property @@ -660,7 +662,6 @@ def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: fixturename=None, pyfuncitem=pyfuncitem, arg2fixturedefs=pyfuncitem._fixtureinfo.name2fixturedefs.copy(), - arg2index={}, fixture_defs={}, _ispytest=_ispytest, ) @@ -706,7 +707,6 @@ def __init__( fixturename=fixturedef.argname, fixture_defs=request._fixture_defs, arg2fixturedefs=request._arg2fixturedefs, - arg2index=request._arg2index, _ispytest=_ispytest, ) self._parent_request: Final[FixtureRequest] = request From 4db5e537091567b1a9a98707c0b8e244d01f3db5 Mon Sep 17 00:00:00 2001 From: donghui <977675308@qq.com> Date: Fri, 1 Mar 2024 05:43:57 +0800 Subject: [PATCH 0503/1271] docs: update plugins number --- README.rst | 2 +- doc/en/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index fba23872ec8..a81e082cdd7 100644 --- a/README.rst +++ b/README.rst @@ -99,7 +99,7 @@ Features - Python 3.8+ or PyPy3 -- Rich plugin architecture, with over 850+ `external plugins `_ and thriving community +- Rich plugin architecture, with over 1300+ `external plugins `_ and thriving community Documentation diff --git a/doc/en/index.rst b/doc/en/index.rst index bc0bd56bf45..9d97dfaa680 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -81,7 +81,7 @@ Features - Python 3.8+ or PyPy 3 -- Rich plugin architecture, with over 800+ :ref:`external plugins ` and thriving community +- Rich plugin architecture, with over 1300+ :ref:`external plugins ` and thriving community Documentation From ff4c3b2873296ee5bfffbcc86e728de830d5d409 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Mar 2024 13:26:08 +0200 Subject: [PATCH 0504/1271] main: add missing `import importlib.util` Used in `resolve_collection_argument`. It's implicitly imported by some other import, but some type checkers don't recognize this. --- src/_pytest/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 639bf26c1cc..a5d8475150b 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -5,6 +5,7 @@ import fnmatch import functools import importlib +import importlib.util import os from pathlib import Path import sys From 5e0d11746ce696af1ac754f102c1399aed846554 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Mar 2024 11:47:30 +0200 Subject: [PATCH 0505/1271] main: model the result of `resolve_collection_arguments` as a dataclass In preparation of adding more info to it. --- src/_pytest/main.py | 50 +++++++++++++++++++++--------- testing/test_main.py | 72 ++++++++++++++++++++++++++++++-------------- 2 files changed, 86 insertions(+), 36 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index a5d8475150b..8aa1d584aa5 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -564,7 +564,7 @@ def __init__(self, config: Config) -> None: self._initialpaths: FrozenSet[Path] = frozenset() self._initialpaths_with_parents: FrozenSet[Path] = frozenset() self._notfound: List[Tuple[str, Sequence[nodes.Collector]]] = [] - self._initial_parts: List[Tuple[Path, List[str]]] = [] + self._initial_parts: List[CollectionArgument] = [] self._collection_cache: Dict[nodes.Collector, CollectReport] = {} self.items: List[nodes.Item] = [] @@ -770,15 +770,15 @@ def perform_collect( initialpaths: List[Path] = [] initialpaths_with_parents: List[Path] = [] for arg in args: - fspath, parts = resolve_collection_argument( + collection_argument = resolve_collection_argument( self.config.invocation_params.dir, arg, as_pypath=self.config.option.pyargs, ) - self._initial_parts.append((fspath, parts)) - initialpaths.append(fspath) - initialpaths_with_parents.append(fspath) - initialpaths_with_parents.extend(fspath.parents) + self._initial_parts.append(collection_argument) + initialpaths.append(collection_argument.path) + initialpaths_with_parents.append(collection_argument.path) + initialpaths_with_parents.extend(collection_argument.path.parents) self._initialpaths = frozenset(initialpaths) self._initialpaths_with_parents = frozenset(initialpaths_with_parents) @@ -840,10 +840,13 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: pm = self.config.pluginmanager - for argpath, names in self._initial_parts: - self.trace("processing argument", (argpath, names)) + for collection_argument in self._initial_parts: + self.trace("processing argument", collection_argument) self.trace.root.indent += 1 + argpath = collection_argument.path + names = collection_argument.parts + # resolve_collection_argument() ensures this. if argpath.is_dir(): assert not names, f"invalid arg {(argpath, names)!r}" @@ -862,7 +865,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: notfound_collectors = [] work: List[ Tuple[Union[nodes.Collector, nodes.Item], List[Union[Path, str]]] - ] = [(self, paths + names)] + ] = [(self, [*paths, *names])] while work: matchnode, matchparts = work.pop() @@ -971,9 +974,17 @@ def search_pypath(module_name: str) -> str: return spec.origin +@dataclasses.dataclass(frozen=True) +class CollectionArgument: + """A resolved collection argument.""" + + path: Path + parts: Sequence[str] + + def resolve_collection_argument( invocation_path: Path, arg: str, *, as_pypath: bool = False -) -> Tuple[Path, List[str]]: +) -> CollectionArgument: """Parse path arguments optionally containing selection parts and return (fspath, names). Command-line arguments can point to files and/or directories, and optionally contain @@ -981,9 +992,12 @@ def resolve_collection_argument( "pkg/tests/test_foo.py::TestClass::test_foo" - This function ensures the path exists, and returns a tuple: + This function ensures the path exists, and returns a resolved `CollectionArgument`: - (Path("/full/path/to/pkg/tests/test_foo.py"), ["TestClass", "test_foo"]) + CollectionArgument( + path=Path("/full/path/to/pkg/tests/test_foo.py"), + parts=["TestClass", "test_foo"], + ) When as_pypath is True, expects that the command-line argument actually contains module paths instead of file-system paths: @@ -991,7 +1005,12 @@ def resolve_collection_argument( "pkg.tests.test_foo::TestClass::test_foo" In which case we search sys.path for a matching module, and then return the *path* to the - found module. + found module, which may look like this: + + CollectionArgument( + path=Path("/home/u/myvenv/lib/site-packages/pkg/tests/test_foo.py"), + parts=["TestClass", "test_foo"], + ) If the path doesn't exist, raise UsageError. If the path is a directory and selection parts are present, raise UsageError. @@ -1018,4 +1037,7 @@ def resolve_collection_argument( else "directory argument cannot contain :: selection parts: {arg}" ) raise UsageError(msg.format(arg=arg)) - return fspath, parts + return CollectionArgument( + path=fspath, + parts=parts, + ) diff --git a/testing/test_main.py b/testing/test_main.py index d92fa21d365..d940dc51829 100644 --- a/testing/test_main.py +++ b/testing/test_main.py @@ -8,6 +8,7 @@ from _pytest.config import ExitCode from _pytest.config import UsageError +from _pytest.main import CollectionArgument from _pytest.main import resolve_collection_argument from _pytest.main import validate_basetemp from _pytest.pytester import Pytester @@ -133,26 +134,38 @@ def invocation_path(self, pytester: Pytester) -> Path: def test_file(self, invocation_path: Path) -> None: """File and parts.""" - assert resolve_collection_argument(invocation_path, "src/pkg/test.py") == ( - invocation_path / "src/pkg/test.py", - [], + assert resolve_collection_argument( + invocation_path, "src/pkg/test.py" + ) == CollectionArgument( + path=invocation_path / "src/pkg/test.py", + parts=[], ) - assert resolve_collection_argument(invocation_path, "src/pkg/test.py::") == ( - invocation_path / "src/pkg/test.py", - [""], + assert resolve_collection_argument( + invocation_path, "src/pkg/test.py::" + ) == CollectionArgument( + path=invocation_path / "src/pkg/test.py", + parts=[""], ) assert resolve_collection_argument( invocation_path, "src/pkg/test.py::foo::bar" - ) == (invocation_path / "src/pkg/test.py", ["foo", "bar"]) + ) == CollectionArgument( + path=invocation_path / "src/pkg/test.py", + parts=["foo", "bar"], + ) assert resolve_collection_argument( invocation_path, "src/pkg/test.py::foo::bar::" - ) == (invocation_path / "src/pkg/test.py", ["foo", "bar", ""]) + ) == CollectionArgument( + path=invocation_path / "src/pkg/test.py", + parts=["foo", "bar", ""], + ) def test_dir(self, invocation_path: Path) -> None: """Directory and parts.""" - assert resolve_collection_argument(invocation_path, "src/pkg") == ( - invocation_path / "src/pkg", - [], + assert resolve_collection_argument( + invocation_path, "src/pkg" + ) == CollectionArgument( + path=invocation_path / "src/pkg", + parts=[], ) with pytest.raises( @@ -169,13 +182,21 @@ def test_pypath(self, invocation_path: Path) -> None: """Dotted name and parts.""" assert resolve_collection_argument( invocation_path, "pkg.test", as_pypath=True - ) == (invocation_path / "src/pkg/test.py", []) + ) == CollectionArgument( + path=invocation_path / "src/pkg/test.py", + parts=[], + ) assert resolve_collection_argument( invocation_path, "pkg.test::foo::bar", as_pypath=True - ) == (invocation_path / "src/pkg/test.py", ["foo", "bar"]) - assert resolve_collection_argument(invocation_path, "pkg", as_pypath=True) == ( - invocation_path / "src/pkg", - [], + ) == CollectionArgument( + path=invocation_path / "src/pkg/test.py", + parts=["foo", "bar"], + ) + assert resolve_collection_argument( + invocation_path, "pkg", as_pypath=True + ) == CollectionArgument( + path=invocation_path / "src/pkg", + parts=[], ) with pytest.raises( @@ -186,10 +207,12 @@ def test_pypath(self, invocation_path: Path) -> None: ) def test_parametrized_name_with_colons(self, invocation_path: Path) -> None: - ret = resolve_collection_argument( + assert resolve_collection_argument( invocation_path, "src/pkg/test.py::test[a::b]" + ) == CollectionArgument( + path=invocation_path / "src/pkg/test.py", + parts=["test[a::b]"], ) - assert ret == (invocation_path / "src/pkg/test.py", ["test[a::b]"]) def test_does_not_exist(self, invocation_path: Path) -> None: """Given a file/module that does not exist raises UsageError.""" @@ -209,9 +232,11 @@ def test_does_not_exist(self, invocation_path: Path) -> None: def test_absolute_paths_are_resolved_correctly(self, invocation_path: Path) -> None: """Absolute paths resolve back to absolute paths.""" full_path = str(invocation_path / "src") - assert resolve_collection_argument(invocation_path, full_path) == ( - Path(os.path.abspath("src")), - [], + assert resolve_collection_argument( + invocation_path, full_path + ) == CollectionArgument( + path=Path(os.path.abspath("src")), + parts=[], ) # ensure full paths given in the command-line without the drive letter resolve @@ -219,7 +244,10 @@ def test_absolute_paths_are_resolved_correctly(self, invocation_path: Path) -> N drive, full_path_without_drive = os.path.splitdrive(full_path) assert resolve_collection_argument( invocation_path, full_path_without_drive - ) == (Path(os.path.abspath("src")), []) + ) == CollectionArgument( + path=Path(os.path.abspath("src")), + parts=[], + ) def test_module_full_path_without_drive(pytester: Pytester) -> None: From 1612d4e393db42406a67430f848321999e0241b6 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Mar 2024 11:59:26 +0200 Subject: [PATCH 0506/1271] main: add `module_name` to `CollectionArgument` This is available when the argument is a `--pyargs` argument (resolved from a python module path). Will be used in an upcoming commit. --- src/_pytest/main.py | 19 ++++++++++++++----- testing/test_main.py | 11 +++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 8aa1d584aa5..55bbf5b3984 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -957,17 +957,18 @@ def genitems( node.ihook.pytest_collectreport(report=rep) -def search_pypath(module_name: str) -> str: - """Search sys.path for the given a dotted module name, and return its file system path.""" +def search_pypath(module_name: str) -> Optional[str]: + """Search sys.path for the given a dotted module name, and return its file + system path if found.""" try: spec = importlib.util.find_spec(module_name) # AttributeError: looks like package module, but actually filename # ImportError: module does not exist # ValueError: not a module name except (AttributeError, ImportError, ValueError): - return module_name + return None if spec is None or spec.origin is None or spec.origin == "namespace": - return module_name + return None elif spec.submodule_search_locations: return os.path.dirname(spec.origin) else: @@ -980,6 +981,7 @@ class CollectionArgument: path: Path parts: Sequence[str] + module_name: Optional[str] def resolve_collection_argument( @@ -997,6 +999,7 @@ def resolve_collection_argument( CollectionArgument( path=Path("/full/path/to/pkg/tests/test_foo.py"), parts=["TestClass", "test_foo"], + module_name=None, ) When as_pypath is True, expects that the command-line argument actually contains @@ -1010,6 +1013,7 @@ def resolve_collection_argument( CollectionArgument( path=Path("/home/u/myvenv/lib/site-packages/pkg/tests/test_foo.py"), parts=["TestClass", "test_foo"], + module_name="pkg.tests.test_foo", ) If the path doesn't exist, raise UsageError. @@ -1019,8 +1023,12 @@ def resolve_collection_argument( strpath, *parts = base.split("::") if parts: parts[-1] = f"{parts[-1]}{squacket}{rest}" + module_name = None if as_pypath: - strpath = search_pypath(strpath) + pyarg_strpath = search_pypath(strpath) + if pyarg_strpath is not None: + module_name = strpath + strpath = pyarg_strpath fspath = invocation_path / strpath fspath = absolutepath(fspath) if not safe_exists(fspath): @@ -1040,4 +1048,5 @@ def resolve_collection_argument( return CollectionArgument( path=fspath, parts=parts, + module_name=module_name, ) diff --git a/testing/test_main.py b/testing/test_main.py index d940dc51829..345aa1e62cf 100644 --- a/testing/test_main.py +++ b/testing/test_main.py @@ -139,24 +139,28 @@ def test_file(self, invocation_path: Path) -> None: ) == CollectionArgument( path=invocation_path / "src/pkg/test.py", parts=[], + module_name=None, ) assert resolve_collection_argument( invocation_path, "src/pkg/test.py::" ) == CollectionArgument( path=invocation_path / "src/pkg/test.py", parts=[""], + module_name=None, ) assert resolve_collection_argument( invocation_path, "src/pkg/test.py::foo::bar" ) == CollectionArgument( path=invocation_path / "src/pkg/test.py", parts=["foo", "bar"], + module_name=None, ) assert resolve_collection_argument( invocation_path, "src/pkg/test.py::foo::bar::" ) == CollectionArgument( path=invocation_path / "src/pkg/test.py", parts=["foo", "bar", ""], + module_name=None, ) def test_dir(self, invocation_path: Path) -> None: @@ -166,6 +170,7 @@ def test_dir(self, invocation_path: Path) -> None: ) == CollectionArgument( path=invocation_path / "src/pkg", parts=[], + module_name=None, ) with pytest.raises( @@ -185,18 +190,21 @@ def test_pypath(self, invocation_path: Path) -> None: ) == CollectionArgument( path=invocation_path / "src/pkg/test.py", parts=[], + module_name="pkg.test", ) assert resolve_collection_argument( invocation_path, "pkg.test::foo::bar", as_pypath=True ) == CollectionArgument( path=invocation_path / "src/pkg/test.py", parts=["foo", "bar"], + module_name="pkg.test", ) assert resolve_collection_argument( invocation_path, "pkg", as_pypath=True ) == CollectionArgument( path=invocation_path / "src/pkg", parts=[], + module_name="pkg", ) with pytest.raises( @@ -212,6 +220,7 @@ def test_parametrized_name_with_colons(self, invocation_path: Path) -> None: ) == CollectionArgument( path=invocation_path / "src/pkg/test.py", parts=["test[a::b]"], + module_name=None, ) def test_does_not_exist(self, invocation_path: Path) -> None: @@ -237,6 +246,7 @@ def test_absolute_paths_are_resolved_correctly(self, invocation_path: Path) -> N ) == CollectionArgument( path=Path(os.path.abspath("src")), parts=[], + module_name=None, ) # ensure full paths given in the command-line without the drive letter resolve @@ -247,6 +257,7 @@ def test_absolute_paths_are_resolved_correctly(self, invocation_path: Path) -> N ) == CollectionArgument( path=Path(os.path.abspath("src")), parts=[], + module_name=None, ) From f20e32c98221c6d4cc22013f365e2e4eea475015 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Mar 2024 14:17:03 +0200 Subject: [PATCH 0507/1271] main: slight refactor to collection argument parents logic No logical change, preparation for the next commit. --- src/_pytest/main.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 55bbf5b3984..faba6786de5 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -851,13 +851,14 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: if argpath.is_dir(): assert not names, f"invalid arg {(argpath, names)!r}" - # Match the argpath from the root, e.g. + paths = [argpath] + # Add relevant parents of the path, from the root, e.g. # /a/b/c.py -> [/, /a, /a/b, /a/b/c.py] - paths = [*reversed(argpath.parents), argpath] - # Paths outside of the confcutdir should not be considered, unless - # it's the argpath itself. - while len(paths) > 1 and not pm._is_in_confcutdir(paths[0]): - paths = paths[1:] + # Paths outside of the confcutdir should not be considered. + for path in argpath.parents: + if not pm._is_in_confcutdir(path): + break + paths.insert(0, path) # Start going over the parts from the root, collecting each level # and discarding all nodes which don't match the level's part. From 31026a2df2f05228887f99e902f5e6d861710451 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 1 Mar 2024 12:19:30 +0200 Subject: [PATCH 0508/1271] main: only include package parents in collection tree for --pyargs collection arguments (diff better viewed ignoring whitespace) In pytest<8, the collection tree for `pyargs` arguments in an invocation like this: pytest --collect-only --pyargs pyflakes.test.test_undefined_names looked like this: ``` ... snipped ... ``` The pytest 8 collection improvements changed it to this: ``` ... snipped ... ``` Besides being egregious (and potentially even worse than the above, going all the way to the root, for system-installed packages, as is apparently common in CI), this also caused permission errors when trying to probe some of those intermediate directories. This change makes `--pyargs` arguments no longer try to add parent directories to the collection tree according to the `--confcutdir` like they're regular arguments. Instead, only add the parents that are in the import path. This now looks like this: ``` ... snipped ... ``` Fix #11904. --- changelog/11904.bugfix.rst | 3 +++ src/_pytest/main.py | 20 ++++++++++++----- testing/test_collection.py | 45 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 changelog/11904.bugfix.rst diff --git a/changelog/11904.bugfix.rst b/changelog/11904.bugfix.rst new file mode 100644 index 00000000000..2aed9bcb059 --- /dev/null +++ b/changelog/11904.bugfix.rst @@ -0,0 +1,3 @@ +Fixed a regression in pytest 8.0.0 that would cause test collection to fail due to permission errors when using ``--pyargs``. + +This change improves the collection tree for tests specified using ``--pyargs``, see :pull:`12043` for a comparison with pytest 8.0 and <8. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index faba6786de5..b7ed72ddc3b 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -846,6 +846,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: argpath = collection_argument.path names = collection_argument.parts + module_name = collection_argument.module_name # resolve_collection_argument() ensures this. if argpath.is_dir(): @@ -854,11 +855,20 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: paths = [argpath] # Add relevant parents of the path, from the root, e.g. # /a/b/c.py -> [/, /a, /a/b, /a/b/c.py] - # Paths outside of the confcutdir should not be considered. - for path in argpath.parents: - if not pm._is_in_confcutdir(path): - break - paths.insert(0, path) + if module_name is None: + # Paths outside of the confcutdir should not be considered. + for path in argpath.parents: + if not pm._is_in_confcutdir(path): + break + paths.insert(0, path) + else: + # For --pyargs arguments, only consider paths matching the module + # name. Paths beyond the package hierarchy are not included. + module_name_parts = module_name.split(".") + for i, path in enumerate(argpath.parents, 2): + if i > len(module_name_parts) or path.stem != module_name_parts[-i]: + break + paths.insert(0, path) # Start going over the parts from the root, collecting each level # and discarding all nodes which don't match the level's part. diff --git a/testing/test_collection.py b/testing/test_collection.py index 0507400455c..fbc8543e9c4 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1787,3 +1787,48 @@ def test_collect_short_file_windows(pytester: Pytester) -> None: test_file.write_text("def test(): pass", encoding="UTF-8") result = pytester.runpytest(short_path) assert result.parseoutcomes() == {"passed": 1} + + +def test_pyargs_collection_tree(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: + """When using `--pyargs`, the collection tree of a pyargs collection + argument should only include parents in the import path, not up to confcutdir. + + Regression test for #11904. + """ + site_packages = pytester.path / "venv/lib/site-packages" + site_packages.mkdir(parents=True) + monkeypatch.syspath_prepend(site_packages) + pytester.makepyfile( + **{ + "venv/lib/site-packages/pkg/__init__.py": "", + "venv/lib/site-packages/pkg/sub/__init__.py": "", + "venv/lib/site-packages/pkg/sub/test_it.py": "def test(): pass", + } + ) + + result = pytester.runpytest("--pyargs", "--collect-only", "pkg.sub.test_it") + assert result.ret == ExitCode.OK + result.stdout.fnmatch_lines( + [ + "", + " ", + " ", + " ", + ], + consecutive=True, + ) + + # Now with an unrelated rootdir with unrelated files. + monkeypatch.chdir(tempfile.gettempdir()) + + result = pytester.runpytest("--pyargs", "--collect-only", "pkg.sub.test_it") + assert result.ret == ExitCode.OK + result.stdout.fnmatch_lines( + [ + "", + " ", + " ", + " ", + ], + consecutive=True, + ) From 887e251abbea9d59be41972b3642ffd5748a587f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Feb 2024 21:35:01 +0200 Subject: [PATCH 0509/1271] testing/test_pathlib: remove `test_issue131_on__init__` The test seems wrong, and we haven't been able to figure out what it's trying to test (the original issue is lost in time). --- testing/test_pathlib.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 075259009de..b99b3e78fbc 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -259,20 +259,6 @@ def test_check_filepath_consistency( assert orig == p assert issubclass(ImportPathMismatchError, ImportError) - def test_issue131_on__init__(self, tmp_path: Path) -> None: - # __init__.py files may be namespace packages, and thus the - # __file__ of an imported module may not be ourselves - # see issue - tmp_path.joinpath("proja").mkdir() - p1 = tmp_path.joinpath("proja", "__init__.py") - p1.touch() - tmp_path.joinpath("sub", "proja").mkdir(parents=True) - p2 = tmp_path.joinpath("sub", "proja", "__init__.py") - p2.touch() - m1 = import_path(p1, root=tmp_path) - m2 = import_path(p2, root=tmp_path) - assert m1 == m2 - def test_ensuresyspath_append(self, tmp_path: Path) -> None: root1 = tmp_path / "root1" root1.mkdir() From 300ceb435e9c5dc3f03698a281eb879eee610842 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Feb 2024 21:33:42 +0200 Subject: [PATCH 0510/1271] testing/test_doctest: make `test_importmode` more realistic --- testing/test_doctest.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 32897a916fe..58fce244f45 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -117,12 +117,12 @@ def test_simple_doctestfile(self, pytester: Pytester): def test_importmode(self, pytester: Pytester): pytester.makepyfile( **{ - "namespacepkg/innerpkg/__init__.py": "", - "namespacepkg/innerpkg/a.py": """ + "src/namespacepkg/innerpkg/__init__.py": "", + "src/namespacepkg/innerpkg/a.py": """ def some_func(): return 42 """, - "namespacepkg/innerpkg/b.py": """ + "src/namespacepkg/innerpkg/b.py": """ from namespacepkg.innerpkg.a import some_func def my_func(): ''' @@ -133,6 +133,10 @@ def my_func(): """, } ) + # For 'namespacepkg' to be considered a namespace package, its containing directory + # needs to be reachable from sys.path: + # https://packaging.python.org/en/latest/guides/packaging-namespace-packages + pytester.syspathinsert(pytester.path / "src") reprec = pytester.inline_run("--doctest-modules", "--import-mode=importlib") reprec.assertoutcome(passed=1) From dcf01fd39ada7c6834467dde64fcab00910a4489 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Feb 2024 21:59:02 +0200 Subject: [PATCH 0511/1271] testing/test_pathlib: add an importlib test Ensure the implementation isn't changed to trigger such a bug. --- testing/test_pathlib.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index b99b3e78fbc..d3ae0024870 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -671,6 +671,36 @@ def test_my_test(): result = pytester.runpytest("--import-mode=importlib") result.stdout.fnmatch_lines("* 1 passed *") + def test_import_path_imports_correct_file(self, pytester: Pytester) -> None: + """ + Import the module by the given path, even if other module with the same name + is reachable from sys.path. + """ + pytester.syspathinsert() + # Create a 'x.py' module reachable from sys.path that raises AssertionError + # if imported. + x_at_root = pytester.path / "x.py" + x_at_root.write_text("raise AssertionError('x at root')", encoding="ascii") + + # Create another x.py module, but in some subdirectories to ensure it is not + # accessible from sys.path. + x_in_sub_folder = pytester.path / "a/b/x.py" + x_in_sub_folder.parent.mkdir(parents=True) + x_in_sub_folder.write_text("X = 'a/b/x'", encoding="ascii") + + # Import our x.py module from the subdirectories. + # The 'x.py' module from sys.path was not imported for sure because + # otherwise we would get an AssertionError. + mod = import_path( + x_in_sub_folder, mode=ImportMode.importlib, root=pytester.path + ) + assert mod.__file__ and Path(mod.__file__) == x_in_sub_folder + assert mod.X == "a/b/x" + + # Attempt to import root 'x.py'. + with pytest.raises(AssertionError, match="x at root"): + _ = import_path(x_at_root, mode=ImportMode.importlib, root=pytester.path) + def test_safe_exists(tmp_path: Path) -> None: d = tmp_path.joinpath("some_dir") From 7524e60d8f96f74deb6160a15beb0d20712cb901 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Feb 2024 20:03:08 +0200 Subject: [PATCH 0512/1271] pathlib: extract a function `resolve_pkg_root_and_module_name` Will be reused. --- src/_pytest/pathlib.py | 46 +++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 1e0891153e5..d64705154a2 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -541,16 +541,10 @@ def import_path( insert_missing_modules(sys.modules, module_name) return mod - pkg_path = resolve_package_path(path) - if pkg_path is not None: - pkg_root = pkg_path.parent - names = list(path.with_suffix("").relative_to(pkg_root).parts) - if names[-1] == "__init__": - names.pop() - module_name = ".".join(names) - else: - pkg_root = path.parent - module_name = path.stem + try: + pkg_root, module_name = resolve_pkg_root_and_module_name(path) + except CouldNotResolvePathError: + pkg_root, module_name = path.parent, path.stem # Change sys.path permanently: restoring it at the end of this function would cause surprising # problems because of delayed imports: for example, a conftest.py file imported by this function @@ -689,6 +683,38 @@ def resolve_package_path(path: Path) -> Optional[Path]: return result +def resolve_pkg_root_and_module_name(path: Path) -> Tuple[Path, str]: + """ + Return the path to the directory of the root package that contains the + given Python file, and its module name: + + src/ + app/ + __init__.py + core/ + __init__.py + models.py + + Passing the full path to `models.py` will yield Path("src") and "app.core.models". + + Raises CouldNotResolvePathError if the given path does not belong to a package (missing any __init__.py files). + """ + pkg_path = resolve_package_path(path) + if pkg_path is not None: + pkg_root = pkg_path.parent + names = list(path.with_suffix("").relative_to(pkg_root).parts) + if names[-1] == "__init__": + names.pop() + module_name = ".".join(names) + return pkg_root, module_name + + raise CouldNotResolvePathError(f"Could not resolve for {path}") + + +class CouldNotResolvePathError(Exception): + """Custom exception raised by resolve_pkg_root_and_module_name.""" + + def scandir( path: Union[str, "os.PathLike[str]"], sort_key: Callable[["os.DirEntry[str]"], object] = lambda entry: entry.name, From 4dea18308bafafb0be0b2d07e02328051c3095d5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Feb 2024 21:08:50 +0200 Subject: [PATCH 0513/1271] pathlib: extract a function `_import_module_using_spec` Will be reused. --- src/_pytest/pathlib.py | 50 ++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index d64705154a2..7e61a561d77 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -526,19 +526,11 @@ def import_path( with contextlib.suppress(KeyError): return sys.modules[module_name] - for meta_importer in sys.meta_path: - spec = meta_importer.find_spec(module_name, [str(path.parent)]) - if spec is not None: - break - else: - spec = importlib.util.spec_from_file_location(module_name, str(path)) - - if spec is None: + mod = _import_module_using_spec( + module_name, path, path.parent, insert_modules=True + ) + if mod is None: raise ImportError(f"Can't find module {module_name} at location {path}") - mod = importlib.util.module_from_spec(spec) - sys.modules[module_name] = mod - spec.loader.exec_module(mod) # type: ignore[union-attr] - insert_missing_modules(sys.modules, module_name) return mod try: @@ -586,6 +578,40 @@ def import_path( return mod +def _import_module_using_spec( + module_name: str, module_path: Path, module_location: Path, *, insert_modules: bool +) -> Optional[ModuleType]: + """ + Tries to import a module by its canonical name, path to the .py file, and its + parent location. + + :param insert_modules: + If True, will call insert_missing_modules to create empty intermediate modules + for made-up module names (when importing test files not reachable from sys.path). + Note: we can probably drop insert_missing_modules altogether: instead of + generating module names such as "src.tests.test_foo", which require intermediate + empty modules, we might just as well generate unique module names like + "src_tests_test_foo". + """ + # Checking with sys.meta_path first in case one of its hooks can import this module, + # such as our own assertion-rewrite hook. + for meta_importer in sys.meta_path: + spec = meta_importer.find_spec(module_name, [str(module_location)]) + if spec is not None: + break + else: + spec = importlib.util.spec_from_file_location(module_name, str(module_path)) + if spec is not None: + mod = importlib.util.module_from_spec(spec) + sys.modules[module_name] = mod + spec.loader.exec_module(mod) # type: ignore[union-attr] + if insert_modules: + insert_missing_modules(sys.modules, module_name) + return mod + + return None + + # Implement a special _is_same function on Windows which returns True if the two filenames # compare equal, to circumvent os.path.samefile returning False for mounts in UNC (#7678). if sys.platform.startswith("win"): From 58674264553392e1d2c2e88ea7de5460e01cd6df Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Feb 2024 20:08:15 +0200 Subject: [PATCH 0514/1271] pathlib: handle filenames starting with `.` in `module_name_from_path` --- src/_pytest/pathlib.py | 5 +++++ testing/test_pathlib.py | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 7e61a561d77..e2fa4db1260 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -648,6 +648,11 @@ def module_name_from_path(path: Path, root: Path) -> str: if len(path_parts) >= 2 and path_parts[-1] == "__init__": path_parts = path_parts[:-1] + # Module names cannot contain ".", normalize them to "_". This prevents + # a directory having a "." in the name (".env.310" for example) causing extra intermediate modules. + # Also, important to replace "." at the start of paths, as those are considered relative imports. + path_parts = [x.replace(".", "_") for x in path_parts] + return ".".join(path_parts) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index d3ae0024870..0870900716e 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -584,6 +584,18 @@ def test_module_name_from_path(self, tmp_path: Path) -> None: result = module_name_from_path(tmp_path / "__init__.py", tmp_path) assert result == "__init__" + # Modules which start with "." are considered relative and will not be imported + # unless part of a package, so we replace it with a "_" when generating the fake module name. + result = module_name_from_path(tmp_path / ".env/tests/test_foo.py", tmp_path) + assert result == "_env.tests.test_foo" + + # We want to avoid generating extra intermediate modules if some directory just happens + # to contain a "." in the name. + result = module_name_from_path( + tmp_path / ".env.310/tests/test_foo.py", tmp_path + ) + assert result == "_env_310.tests.test_foo" + def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> None: From 067daf9f7d7072a4e199dd51b738193be370a1c7 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Feb 2024 20:13:28 +0200 Subject: [PATCH 0515/1271] pathlib: consider namespace packages in `resolve_pkg_root_and_module_name` This applies to `append` and `prepend` import modes; support for `importlib` mode will be added in a separate change. --- changelog/11475.feature.rst | 3 + src/_pytest/pathlib.py | 28 ++++++- testing/test_pathlib.py | 143 ++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 changelog/11475.feature.rst diff --git a/changelog/11475.feature.rst b/changelog/11475.feature.rst new file mode 100644 index 00000000000..6b73c81586a --- /dev/null +++ b/changelog/11475.feature.rst @@ -0,0 +1,3 @@ +pytest now correctly identifies modules that are part of `namespace packages `__, for example when importing user-level modules for doctesting. + +Previously pytest was not aware of namespace packages, so running a doctest from a subpackage that is part of a namespace package would import just the subpackage (for example ``app.models``) instead of its full path (for example ``com.company.app.models``). diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index e2fa4db1260..8097adb22e1 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -534,7 +534,9 @@ def import_path( return mod try: - pkg_root, module_name = resolve_pkg_root_and_module_name(path) + pkg_root, module_name = resolve_pkg_root_and_module_name( + path, consider_ns_packages=True + ) except CouldNotResolvePathError: pkg_root, module_name = path.parent, path.stem @@ -714,7 +716,9 @@ def resolve_package_path(path: Path) -> Optional[Path]: return result -def resolve_pkg_root_and_module_name(path: Path) -> Tuple[Path, str]: +def resolve_pkg_root_and_module_name( + path: Path, *, consider_ns_packages: bool = False +) -> Tuple[Path, str]: """ Return the path to the directory of the root package that contains the given Python file, and its module name: @@ -728,11 +732,31 @@ def resolve_pkg_root_and_module_name(path: Path) -> Tuple[Path, str]: Passing the full path to `models.py` will yield Path("src") and "app.core.models". + If consider_ns_packages is True, then we additionally check upwards in the hierarchy + until we find a directory that is reachable from sys.path, which marks it as a namespace package: + + https://packaging.python.org/en/latest/guides/packaging-namespace-packages + Raises CouldNotResolvePathError if the given path does not belong to a package (missing any __init__.py files). """ pkg_path = resolve_package_path(path) if pkg_path is not None: pkg_root = pkg_path.parent + # https://packaging.python.org/en/latest/guides/packaging-namespace-packages/ + if consider_ns_packages: + # Go upwards in the hierarchy, if we find a parent path included + # in sys.path, it means the package found by resolve_package_path() + # actually belongs to a namespace package. + for parent in pkg_root.parents: + # If any of the parent paths has a __init__.py, it means it is not + # a namespace package (see the docs linked above). + if (parent / "__init__.py").is_file(): + break + if str(parent) in sys.path: + # Point the pkg_root to the root of the namespace package. + pkg_root = parent + break + names = list(path.with_suffix("").relative_to(pkg_root).parts) if names[-1] == "__init__": names.pop() diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 0870900716e..d515cb5bd1a 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -9,11 +9,13 @@ from typing import Any from typing import Generator from typing import Iterator +from typing import Tuple import unittest.mock from _pytest.monkeypatch import MonkeyPatch from _pytest.pathlib import bestrelpath from _pytest.pathlib import commonpath +from _pytest.pathlib import CouldNotResolvePathError from _pytest.pathlib import ensure_deletable from _pytest.pathlib import fnmatch_ex from _pytest.pathlib import get_extended_length_path_str @@ -25,6 +27,7 @@ from _pytest.pathlib import maybe_delete_a_numbered_dir from _pytest.pathlib import module_name_from_path from _pytest.pathlib import resolve_package_path +from _pytest.pathlib import resolve_pkg_root_and_module_name from _pytest.pathlib import safe_exists from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit @@ -33,6 +36,20 @@ import pytest +@pytest.fixture(autouse=True) +def autouse_pytester(pytester: Pytester) -> None: + """ + Fixture to make pytester() being autouse for all tests in this module. + + pytester makes sure to restore sys.path to its previous state, and many tests in this module + import modules and change sys.path because of that, so common module names such as "test" or "test.conftest" + end up leaking to tests in other modules. + + Note: we might consider extracting the sys.path restoration aspect into its own fixture, and apply it + to the entire test suite always. + """ + + class TestFNMatcherPort: """Test our port of py.common.FNMatcher (fnmatch_ex).""" @@ -596,6 +613,33 @@ def test_module_name_from_path(self, tmp_path: Path) -> None: ) assert result == "_env_310.tests.test_foo" + def test_resolve_pkg_root_and_module_name( + self, tmp_path: Path, monkeypatch: MonkeyPatch + ) -> None: + # Create a directory structure first without __init__.py files. + (tmp_path / "src/app/core").mkdir(parents=True) + models_py = tmp_path / "src/app/core/models.py" + models_py.touch() + with pytest.raises(CouldNotResolvePathError): + _ = resolve_pkg_root_and_module_name(models_py) + + # Create the __init__.py files, it should now resolve to a proper module name. + (tmp_path / "src/app/__init__.py").touch() + (tmp_path / "src/app/core/__init__.py").touch() + assert resolve_pkg_root_and_module_name(models_py) == ( + tmp_path / "src", + "app.core.models", + ) + + # If we add tmp_path to sys.path, src becomes a namespace package. + monkeypatch.syspath_prepend(tmp_path) + assert resolve_pkg_root_and_module_name( + models_py, consider_ns_packages=True + ) == ( + tmp_path, + "src.app.core.models", + ) + def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path ) -> None: @@ -741,3 +785,102 @@ def test_safe_exists(tmp_path: Path) -> None: side_effect=ValueError("name too long"), ): assert safe_exists(p) is False + + +class TestNamespacePackages: + """Test import_path support when importing from properly namespace packages.""" + + def setup_directories( + self, tmp_path: Path, monkeypatch: MonkeyPatch, pytester: Pytester + ) -> Tuple[Path, Path]: + # Set up a namespace package "com.company", containing + # two subpackages, "app" and "calc". + (tmp_path / "src/dist1/com/company/app/core").mkdir(parents=True) + (tmp_path / "src/dist1/com/company/app/__init__.py").touch() + (tmp_path / "src/dist1/com/company/app/core/__init__.py").touch() + models_py = tmp_path / "src/dist1/com/company/app/core/models.py" + models_py.touch() + + (tmp_path / "src/dist2/com/company/calc/algo").mkdir(parents=True) + (tmp_path / "src/dist2/com/company/calc/__init__.py").touch() + (tmp_path / "src/dist2/com/company/calc/algo/__init__.py").touch() + algorithms_py = tmp_path / "src/dist2/com/company/calc/algo/algorithms.py" + algorithms_py.touch() + + # Validate the namespace package by importing it in a Python subprocess. + r = pytester.runpython_c( + dedent( + f""" + import sys + sys.path.append(r{str(tmp_path / "src/dist1")!r}) + sys.path.append(r{str(tmp_path / "src/dist2")!r}) + import com.company.app.core.models + import com.company.calc.algo.algorithms + """ + ) + ) + assert r.ret == 0 + + monkeypatch.syspath_prepend(tmp_path / "src/dist1") + monkeypatch.syspath_prepend(tmp_path / "src/dist2") + return models_py, algorithms_py + + @pytest.mark.parametrize("import_mode", ["prepend", "append"]) + def test_resolve_pkg_root_and_module_name_ns_multiple_levels( + self, + tmp_path: Path, + monkeypatch: MonkeyPatch, + pytester: Pytester, + import_mode: str, + ) -> None: + models_py, algorithms_py = self.setup_directories( + tmp_path, monkeypatch, pytester + ) + + pkg_root, module_name = resolve_pkg_root_and_module_name( + models_py, consider_ns_packages=True + ) + assert (pkg_root, module_name) == ( + tmp_path / "src/dist1", + "com.company.app.core.models", + ) + + mod = import_path(models_py, mode=import_mode, root=tmp_path) + assert mod.__name__ == "com.company.app.core.models" + assert mod.__file__ == str(models_py) + + pkg_root, module_name = resolve_pkg_root_and_module_name( + algorithms_py, consider_ns_packages=True + ) + assert (pkg_root, module_name) == ( + tmp_path / "src/dist2", + "com.company.calc.algo.algorithms", + ) + + mod = import_path(algorithms_py, mode=import_mode, root=tmp_path) + assert mod.__name__ == "com.company.calc.algo.algorithms" + assert mod.__file__ == str(algorithms_py) + + @pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"]) + def test_incorrect_namespace_package( + self, + tmp_path: Path, + monkeypatch: MonkeyPatch, + pytester: Pytester, + import_mode: str, + ) -> None: + models_py, algorithms_py = self.setup_directories( + tmp_path, monkeypatch, pytester + ) + # Namespace packages must not have an __init__.py at any of its + # directories; if it does, we then fall back to importing just the + # part of the package containing the __init__.py files. + (tmp_path / "src/dist1/com/__init__.py").touch() + + pkg_root, module_name = resolve_pkg_root_and_module_name( + models_py, consider_ns_packages=True + ) + assert (pkg_root, module_name) == ( + tmp_path / "src/dist1/com/company", + "app.core.models", + ) From c85fce39b60a6cc3537e9da3e7a4f4946cfe4d49 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 17 Feb 2024 10:39:15 -0300 Subject: [PATCH 0516/1271] Change importlib to first try to import modules using the standard mechanism As detailed in https://github.com/pytest-dev/pytest/issues/11475#issuecomment-1937043670, currently with `--import-mode=importlib` pytest will try to import every file by using a unique module name, regardless if that module could be imported using the normal import mechanism without touching `sys.path`. This has the consequence that non-test modules available in `sys.path` (via other mechanism, such as being installed into a virtualenv, PYTHONPATH, etc) would end up being imported as standalone modules, instead of imported with their expected module names. To illustrate: ``` .env/ lib/ site-packages/ anndata/ core.py ``` Given `anndata` is installed into the virtual environment, `python -c "import anndata.core"` works, but pytest with `importlib` mode would import that module as a standalone module named `".env.lib.site-packages.anndata.core"`, because importlib module was designed to import test files which are not reachable from `sys.path`, but now it is clear that normal modules should be imported using the standard mechanisms if possible. Now `imporlib` mode will first try to import the module normally, without changing `sys.path`, and if that fails it falls back to importing the module as a standalone module. This also makes `importlib` respect namespace packages. This supersedes #11931. Fix #11475 Close #11931 --- changelog/11475.improvement.rst | 1 + src/_pytest/pathlib.py | 17 ++++ testing/test_pathlib.py | 143 +++++++++++++++++++++++++++++++- 3 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 changelog/11475.improvement.rst diff --git a/changelog/11475.improvement.rst b/changelog/11475.improvement.rst new file mode 100644 index 00000000000..fc6e8be3a3a --- /dev/null +++ b/changelog/11475.improvement.rst @@ -0,0 +1 @@ +:ref:`--import-mode=importlib ` now tries to import modules using the standard import mechanism (but still without changing :py:data:`sys.path`), falling back to importing modules directly only if that fails. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 8097adb22e1..8c4e2fd87aa 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -522,6 +522,23 @@ def import_path( raise ImportError(path) if mode is ImportMode.importlib: + # Try to import this module using the standard import mechanisms, but + # without touching sys.path. + try: + pkg_root, module_name = resolve_pkg_root_and_module_name( + path, consider_ns_packages=True + ) + except CouldNotResolvePathError: + pass + else: + mod = _import_module_using_spec( + module_name, path, pkg_root, insert_modules=False + ) + if mod is not None: + return mod + + # Could not import the module with the current sys.path, so we fall back + # to importing the file as a single module, not being a part of a package. module_name = module_name_from_path(path, root) with contextlib.suppress(KeyError): return sys.modules[module_name] diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index d515cb5bd1a..13c22b8007a 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -3,6 +3,7 @@ import os.path from pathlib import Path import pickle +import shutil import sys from textwrap import dedent from types import ModuleType @@ -727,6 +728,146 @@ def test_my_test(): result = pytester.runpytest("--import-mode=importlib") result.stdout.fnmatch_lines("* 1 passed *") + def create_installed_doctests_and_tests_dir( + self, path: Path, monkeypatch: MonkeyPatch + ) -> Tuple[Path, Path, Path]: + """ + Create a directory structure where the application code is installed in a virtual environment, + and the tests are in an outside ".tests" directory. + + Return the paths to the core module (installed in the virtualenv), and the test modules. + """ + app = path / "src/app" + app.mkdir(parents=True) + (app / "__init__.py").touch() + core_py = app / "core.py" + core_py.write_text( + dedent( + """ + def foo(): + ''' + >>> 1 + 1 + 2 + ''' + """ + ), + encoding="ascii", + ) + + # Install it into a site-packages directory, and add it to sys.path, mimicking what + # happens when installing into a virtualenv. + site_packages = path / ".env/lib/site-packages" + site_packages.mkdir(parents=True) + shutil.copytree(app, site_packages / "app") + assert (site_packages / "app/core.py").is_file() + + monkeypatch.syspath_prepend(site_packages) + + # Create the tests files, outside 'src' and the virtualenv. + # We use the same test name on purpose, but in different directories, to ensure + # this works as advertised. + conftest_path1 = path / ".tests/a/conftest.py" + conftest_path1.parent.mkdir(parents=True) + conftest_path1.write_text( + dedent( + """ + import pytest + @pytest.fixture + def a_fix(): return "a" + """ + ), + encoding="ascii", + ) + test_path1 = path / ".tests/a/test_core.py" + test_path1.write_text( + dedent( + """ + import app.core + def test(a_fix): + assert a_fix == "a" + """, + ), + encoding="ascii", + ) + + conftest_path2 = path / ".tests/b/conftest.py" + conftest_path2.parent.mkdir(parents=True) + conftest_path2.write_text( + dedent( + """ + import pytest + @pytest.fixture + def b_fix(): return "b" + """ + ), + encoding="ascii", + ) + + test_path2 = path / ".tests/b/test_core.py" + test_path2.write_text( + dedent( + """ + import app.core + def test(b_fix): + assert b_fix == "b" + """, + ), + encoding="ascii", + ) + return (site_packages / "app/core.py"), test_path1, test_path2 + + def test_import_using_normal_mechanism_first( + self, monkeypatch: MonkeyPatch, pytester: Pytester + ) -> None: + """ + Test import_path imports from the canonical location when possible first, only + falling back to its normal flow when the module being imported is not reachable via sys.path (#11475). + """ + core_py, test_path1, test_path2 = self.create_installed_doctests_and_tests_dir( + pytester.path, monkeypatch + ) + + # core_py is reached from sys.path, so should be imported normally. + mod = import_path(core_py, mode="importlib", root=pytester.path) + assert mod.__name__ == "app.core" + assert mod.__file__ and Path(mod.__file__) == core_py + + # tests are not reachable from sys.path, so they are imported as a standalone modules. + # Instead of '.tests.a.test_core', we import as "_tests.a.test_core" because + # importlib considers module names starting with '.' to be local imports. + mod = import_path(test_path1, mode="importlib", root=pytester.path) + assert mod.__name__ == "_tests.a.test_core" + mod = import_path(test_path2, mode="importlib", root=pytester.path) + assert mod.__name__ == "_tests.b.test_core" + + def test_import_using_normal_mechanism_first_integration( + self, monkeypatch: MonkeyPatch, pytester: Pytester + ) -> None: + """ + Same test as above, but verify the behavior calling pytest. + + We should not make this call in the same test as above, as the modules have already + been imported by separate import_path() calls. + """ + core_py, test_path1, test_path2 = self.create_installed_doctests_and_tests_dir( + pytester.path, monkeypatch + ) + result = pytester.runpytest( + "--import-mode=importlib", + "--doctest-modules", + "--pyargs", + "app", + "./.tests", + ) + result.stdout.fnmatch_lines( + [ + f"{core_py.relative_to(pytester.path)} . *", + f"{test_path1.relative_to(pytester.path)} . *", + f"{test_path2.relative_to(pytester.path)} . *", + "* 3 passed*", + ] + ) + def test_import_path_imports_correct_file(self, pytester: Pytester) -> None: """ Import the module by the given path, even if other module with the same name @@ -825,7 +966,7 @@ def setup_directories( monkeypatch.syspath_prepend(tmp_path / "src/dist2") return models_py, algorithms_py - @pytest.mark.parametrize("import_mode", ["prepend", "append"]) + @pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"]) def test_resolve_pkg_root_and_module_name_ns_multiple_levels( self, tmp_path: Path, From 5746b8e69620e39d69a04383cff2ca9d54a7e41f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 27 Feb 2024 21:29:59 +0200 Subject: [PATCH 0517/1271] doc: update and improve import mode docs --- doc/en/explanation/goodpractices.rst | 6 ++- doc/en/explanation/pythonpath.rst | 80 ++++++++++++++++++++++------ 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst index efde420cd8f..1390ba4e8fe 100644 --- a/doc/en/explanation/goodpractices.rst +++ b/doc/en/explanation/goodpractices.rst @@ -60,8 +60,10 @@ Within Python modules, ``pytest`` also discovers tests using the standard :ref:`unittest.TestCase ` subclassing technique. -Choosing a test layout / import rules -------------------------------------- +.. _`test layout`: + +Choosing a test layout +---------------------- ``pytest`` supports two common test layouts: diff --git a/doc/en/explanation/pythonpath.rst b/doc/en/explanation/pythonpath.rst index 5b533f47fdc..6b1d3ae2cbc 100644 --- a/doc/en/explanation/pythonpath.rst +++ b/doc/en/explanation/pythonpath.rst @@ -15,14 +15,23 @@ changing :data:`sys.path`. Some aspects of the import process can be controlled through the ``--import-mode`` command-line flag, which can assume these values: +.. _`import-mode-prepend`: + * ``prepend`` (default): the directory path containing each module will be inserted into the *beginning* - of :py:data:`sys.path` if not already there, and then imported with the :func:`importlib.import_module ` function. + of :py:data:`sys.path` if not already there, and then imported with + the :func:`importlib.import_module ` function. + + It is highly recommended to arrange your test modules as packages by adding ``__init__.py`` files to your directories + containing tests. This will make the tests part of a proper Python package, allowing pytest to resolve their full + name (for example ``tests.core.test_core`` for ``test_core.py`` inside the ``tests.core`` package). - This requires test module names to be unique when the test directory tree is not arranged in - packages, because the modules will put in :py:data:`sys.modules` after importing. + If the test directory tree is not arranged as packages, then each test file needs to have a unique name + compared to the other test files, otherwise pytest will raise an error if it finds two tests with the same name. This is the classic mechanism, dating back from the time Python 2 was still supported. +.. _`import-mode-append`: + * ``append``: the directory containing each module is appended to the end of :py:data:`sys.path` if not already there, and imported with :func:`importlib.import_module `. @@ -38,32 +47,71 @@ these values: the tests will run against the installed version of ``pkg_under_test`` when ``--import-mode=append`` is used whereas with ``prepend`` they would pick up the local version. This kind of confusion is why - we advocate for using :ref:`src ` layouts. + we advocate for using :ref:`src-layouts `. Same as ``prepend``, requires test module names to be unique when the test directory tree is not arranged in packages, because the modules will put in :py:data:`sys.modules` after importing. -* ``importlib``: new in pytest-6.0, this mode uses more fine control mechanisms provided by :mod:`importlib` to import test modules. This gives full control over the import process, and doesn't require changing :py:data:`sys.path`. +.. _`import-mode-importlib`: + +* ``importlib``: this mode uses more fine control mechanisms provided by :mod:`importlib` to import test modules, without changing :py:data:`sys.path`. + + Advantages of this mode: + + * pytest will not change :py:data:`sys.path` at all. + * Test module names do not need to be unique -- pytest will generate a unique name automatically based on the ``rootdir``. + + Disadvantages: + + * Test modules can't import each other. + * Testing utility modules in the tests directories (for example a ``tests.helpers`` module containing test-related functions/classes) + are not importable. The recommendation in this case it to place testing utility modules together with the application/library + code, for example ``app.testing.helpers``. + + Important: by "test utility modules" we mean functions/classes which are imported by + other tests directly; this does not include fixtures, which should be placed in ``conftest.py`` files, along + with the test modules, and are discovered automatically by pytest. - For this reason this doesn't require test module names to be unique. + It works like this: - One drawback however is that test modules are non-importable by each other. Also, utility - modules in the tests directories are not automatically importable because the tests directory is no longer - added to :py:data:`sys.path`. + 1. Given a certain module path, for example ``tests/core/test_models.py``, derives a canonical name + like ``tests.core.test_models`` and tries to import it. - Initially we intended to make ``importlib`` the default in future releases, however it is clear now that - it has its own set of drawbacks so the default will remain ``prepend`` for the foreseeable future. + For non-test modules this will work if they are accessible via :py:data:`sys.path`, so + for example ``.env/lib/site-packages/app/core.py`` will be importable as ``app.core``. + This is happens when plugins import non-test modules (for example doctesting). + + If this step succeeds, the module is returned. + + For test modules, unless they are reachable from :py:data:`sys.path`, this step will fail. + + 2. If the previous step fails, we import the module directly using ``importlib`` facilities, which lets us import it without + changing :py:data:`sys.path`. + + Because Python requires the module to also be available in :py:data:`sys.modules`, pytest derives a unique name for it based + on its relative location from the ``rootdir``, and adds the module to :py:data:`sys.modules`. + + For example, ``tests/core/test_models.py`` will end up being imported as the module ``tests.core.test_models``. + + .. versionadded:: 6.0 + +.. note:: + + Initially we intended to make ``importlib`` the default in future releases, however it is clear now that + it has its own set of drawbacks so the default will remain ``prepend`` for the foreseeable future. .. seealso:: The :confval:`pythonpath` configuration variable. + :ref:`test layout`. + ``prepend`` and ``append`` import modes scenarios ------------------------------------------------- Here's a list of scenarios when using ``prepend`` or ``append`` import modes where pytest needs to -change ``sys.path`` in order to import test modules or ``conftest.py`` files, and the issues users +change :py:data:`sys.path` in order to import test modules or ``conftest.py`` files, and the issues users might encounter because of that. Test modules / ``conftest.py`` files inside packages @@ -92,7 +140,7 @@ pytest will find ``foo/bar/tests/test_foo.py`` and realize it is part of a packa there's an ``__init__.py`` file in the same folder. It will then search upwards until it can find the last folder which still contains an ``__init__.py`` file in order to find the package *root* (in this case ``foo/``). To load the module, it will insert ``root/`` to the front of -``sys.path`` (if not there already) in order to load +:py:data:`sys.path` (if not there already) in order to load ``test_foo.py`` as the *module* ``foo.bar.tests.test_foo``. The same logic applies to the ``conftest.py`` file: it will be imported as ``foo.conftest`` module. @@ -122,8 +170,8 @@ When executing: pytest will find ``foo/bar/tests/test_foo.py`` and realize it is NOT part of a package given that there's no ``__init__.py`` file in the same folder. It will then add ``root/foo/bar/tests`` to -``sys.path`` in order to import ``test_foo.py`` as the *module* ``test_foo``. The same is done -with the ``conftest.py`` file by adding ``root/foo`` to ``sys.path`` to import it as ``conftest``. +:py:data:`sys.path` in order to import ``test_foo.py`` as the *module* ``test_foo``. The same is done +with the ``conftest.py`` file by adding ``root/foo`` to :py:data:`sys.path` to import it as ``conftest``. For this reason this layout cannot have test modules with the same name, as they all will be imported in the global import namespace. @@ -136,7 +184,7 @@ Invoking ``pytest`` versus ``python -m pytest`` ----------------------------------------------- Running pytest with ``pytest [...]`` instead of ``python -m pytest [...]`` yields nearly -equivalent behaviour, except that the latter will add the current directory to ``sys.path``, which +equivalent behaviour, except that the latter will add the current directory to :py:data:`sys.path`, which is standard ``python`` behavior. See also :ref:`invoke-python`. From 199d4e2b7387cb38f54fc578c1521b5b1eea5db2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 2 Mar 2024 11:19:57 -0300 Subject: [PATCH 0518/1271] pathlib: import signature and docs for import_path --- src/_pytest/pathlib.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 8c4e2fd87aa..b4a0ceb2277 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -484,26 +484,31 @@ class ImportPathMismatchError(ImportError): def import_path( - p: Union[str, "os.PathLike[str]"], + path: Union[str, "os.PathLike[str]"], *, mode: Union[str, ImportMode] = ImportMode.prepend, root: Path, ) -> ModuleType: - """Import and return a module from the given path, which can be a file (a module) or + """ + Import and return a module from the given path, which can be a file (a module) or a directory (a package). - The import mechanism used is controlled by the `mode` parameter: + :param path: + Path to the file to import. - * `mode == ImportMode.prepend`: the directory containing the module (or package, taking - `__init__.py` files into account) will be put at the *start* of `sys.path` before - being imported with `importlib.import_module`. + :param mode: + Controls the underlying import mechanism that will be used: - * `mode == ImportMode.append`: same as `prepend`, but the directory will be appended - to the end of `sys.path`, if not already in `sys.path`. + * ImportMode.prepend: the directory containing the module (or package, taking + `__init__.py` files into account) will be put at the *start* of `sys.path` before + being imported with `importlib.import_module`. - * `mode == ImportMode.importlib`: uses more fine control mechanisms provided by `importlib` - to import the module, which avoids having to muck with `sys.path` at all. It effectively - allows having same-named test modules in different places. + * ImportMode.append: same as `prepend`, but the directory will be appended + to the end of `sys.path`, if not already in `sys.path`. + + * ImportMode.importlib: uses more fine control mechanisms provided by `importlib` + to import the module, which avoids having to muck with `sys.path` at all. It effectively + allows having same-named test modules in different places. :param root: Used as an anchor when mode == ImportMode.importlib to obtain @@ -514,10 +519,9 @@ def import_path( If after importing the given `path` and the module `__file__` are different. Only raised in `prepend` and `append` modes. """ + path = Path(path) mode = ImportMode(mode) - path = Path(p) - if not path.exists(): raise ImportError(path) From 111c0d910e15afb9e1ed1f6862e1637594eaa076 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 2 Mar 2024 11:46:54 -0300 Subject: [PATCH 0519/1271] Add consider_namespace_packages ini option Fix #11475 --- src/_pytest/config/__init__.py | 68 ++++++++++-- src/_pytest/main.py | 6 ++ src/_pytest/pathlib.py | 16 +-- src/_pytest/python.py | 7 +- src/_pytest/runner.py | 3 + testing/code/test_excinfo.py | 6 +- testing/code/test_source.py | 2 +- testing/test_conftest.py | 76 +++++++++++--- testing/test_pathlib.py | 182 +++++++++++++++++++++++++-------- testing/test_pluginmanager.py | 26 ++++- 10 files changed, 315 insertions(+), 77 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 069e2196d25..7ed79483c4e 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -547,6 +547,8 @@ def _set_initial_conftests( confcutdir: Optional[Path], invocation_dir: Path, importmode: Union[ImportMode, str], + *, + consider_namespace_packages: bool, ) -> None: """Load initial conftest files given a preparsed "namespace". @@ -572,10 +574,20 @@ def _set_initial_conftests( # Ensure we do not break if what appears to be an anchor # is in fact a very long option (#10169, #11394). if safe_exists(anchor): - self._try_load_conftest(anchor, importmode, rootpath) + self._try_load_conftest( + anchor, + importmode, + rootpath, + consider_namespace_packages=consider_namespace_packages, + ) foundanchor = True if not foundanchor: - self._try_load_conftest(invocation_dir, importmode, rootpath) + self._try_load_conftest( + invocation_dir, + importmode, + rootpath, + consider_namespace_packages=consider_namespace_packages, + ) def _is_in_confcutdir(self, path: Path) -> bool: """Whether to consider the given path to load conftests from.""" @@ -593,17 +605,37 @@ def _is_in_confcutdir(self, path: Path) -> bool: return path not in self._confcutdir.parents def _try_load_conftest( - self, anchor: Path, importmode: Union[str, ImportMode], rootpath: Path + self, + anchor: Path, + importmode: Union[str, ImportMode], + rootpath: Path, + *, + consider_namespace_packages: bool, ) -> None: - self._loadconftestmodules(anchor, importmode, rootpath) + self._loadconftestmodules( + anchor, + importmode, + rootpath, + consider_namespace_packages=consider_namespace_packages, + ) # let's also consider test* subdirs if anchor.is_dir(): for x in anchor.glob("test*"): if x.is_dir(): - self._loadconftestmodules(x, importmode, rootpath) + self._loadconftestmodules( + x, + importmode, + rootpath, + consider_namespace_packages=consider_namespace_packages, + ) def _loadconftestmodules( - self, path: Path, importmode: Union[str, ImportMode], rootpath: Path + self, + path: Path, + importmode: Union[str, ImportMode], + rootpath: Path, + *, + consider_namespace_packages: bool, ) -> None: if self._noconftest: return @@ -620,7 +652,12 @@ def _loadconftestmodules( if self._is_in_confcutdir(parent): conftestpath = parent / "conftest.py" if conftestpath.is_file(): - mod = self._importconftest(conftestpath, importmode, rootpath) + mod = self._importconftest( + conftestpath, + importmode, + rootpath, + consider_namespace_packages=consider_namespace_packages, + ) clist.append(mod) self._dirpath2confmods[directory] = clist @@ -642,7 +679,12 @@ def _rget_with_confmod( raise KeyError(name) def _importconftest( - self, conftestpath: Path, importmode: Union[str, ImportMode], rootpath: Path + self, + conftestpath: Path, + importmode: Union[str, ImportMode], + rootpath: Path, + *, + consider_namespace_packages: bool, ) -> types.ModuleType: conftestpath_plugin_name = str(conftestpath) existing = self.get_plugin(conftestpath_plugin_name) @@ -661,7 +703,12 @@ def _importconftest( pass try: - mod = import_path(conftestpath, mode=importmode, root=rootpath) + mod = import_path( + conftestpath, + mode=importmode, + root=rootpath, + consider_namespace_packages=consider_namespace_packages, + ) except Exception as e: assert e.__traceback__ is not None raise ConftestImportFailure(conftestpath, cause=e) from e @@ -1177,6 +1224,9 @@ def pytest_load_initial_conftests(self, early_config: "Config") -> None: confcutdir=early_config.known_args_namespace.confcutdir, invocation_dir=early_config.invocation_params.dir, importmode=early_config.known_args_namespace.importmode, + consider_namespace_packages=early_config.getini( + "consider_namespace_packages" + ), ) def _initini(self, args: Sequence[str]) -> None: diff --git a/src/_pytest/main.py b/src/_pytest/main.py index b7ed72ddc3b..8e8d238acbb 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -222,6 +222,12 @@ def pytest_addoption(parser: Parser) -> None: help="Prepend/append to sys.path when importing test modules and conftest " "files. Default: prepend.", ) + parser.addini( + "consider_namespace_packages", + type="bool", + default=False, + help="Consider namespace packages when resolving module names during import", + ) group = parser.getgroup("debugconfig", "test session debugging and configuration") group.addoption( diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index b4a0ceb2277..a19e89aa116 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -488,6 +488,7 @@ def import_path( *, mode: Union[str, ImportMode] = ImportMode.prepend, root: Path, + consider_namespace_packages: bool, ) -> ModuleType: """ Import and return a module from the given path, which can be a file (a module) or @@ -515,6 +516,9 @@ def import_path( a unique name for the module being imported so it can safely be stored into ``sys.modules``. + :param consider_namespace_packages: + If True, consider namespace packages when resolving module names. + :raises ImportPathMismatchError: If after importing the given `path` and the module `__file__` are different. Only raised in `prepend` and `append` modes. @@ -530,7 +534,7 @@ def import_path( # without touching sys.path. try: pkg_root, module_name = resolve_pkg_root_and_module_name( - path, consider_ns_packages=True + path, consider_namespace_packages=consider_namespace_packages ) except CouldNotResolvePathError: pass @@ -556,7 +560,7 @@ def import_path( try: pkg_root, module_name = resolve_pkg_root_and_module_name( - path, consider_ns_packages=True + path, consider_namespace_packages=consider_namespace_packages ) except CouldNotResolvePathError: pkg_root, module_name = path.parent, path.stem @@ -674,7 +678,7 @@ def module_name_from_path(path: Path, root: Path) -> str: # Module names cannot contain ".", normalize them to "_". This prevents # a directory having a "." in the name (".env.310" for example) causing extra intermediate modules. # Also, important to replace "." at the start of paths, as those are considered relative imports. - path_parts = [x.replace(".", "_") for x in path_parts] + path_parts = tuple(x.replace(".", "_") for x in path_parts) return ".".join(path_parts) @@ -738,7 +742,7 @@ def resolve_package_path(path: Path) -> Optional[Path]: def resolve_pkg_root_and_module_name( - path: Path, *, consider_ns_packages: bool = False + path: Path, *, consider_namespace_packages: bool = False ) -> Tuple[Path, str]: """ Return the path to the directory of the root package that contains the @@ -753,7 +757,7 @@ def resolve_pkg_root_and_module_name( Passing the full path to `models.py` will yield Path("src") and "app.core.models". - If consider_ns_packages is True, then we additionally check upwards in the hierarchy + If consider_namespace_packages is True, then we additionally check upwards in the hierarchy until we find a directory that is reachable from sys.path, which marks it as a namespace package: https://packaging.python.org/en/latest/guides/packaging-namespace-packages @@ -764,7 +768,7 @@ def resolve_pkg_root_and_module_name( if pkg_path is not None: pkg_root = pkg_path.parent # https://packaging.python.org/en/latest/guides/packaging-namespace-packages/ - if consider_ns_packages: + if consider_namespace_packages: # Go upwards in the hierarchy, if we find a parent path included # in sys.path, it means the package found by resolve_package_path() # actually belongs to a namespace package. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index ca64a877d42..e1730b1a7e0 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -516,7 +516,12 @@ def importtestmodule( # We assume we are only called once per module. importmode = config.getoption("--import-mode") try: - mod = import_path(path, mode=importmode, root=config.rootpath) + mod = import_path( + path, + mode=importmode, + root=config.rootpath, + consider_namespace_packages=config.getini("consider_namespace_packages"), + ) except SyntaxError as e: raise nodes.Collector.CollectError( ExceptionInfo.from_current().getrepr(style="short") diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index b60af9dd3fb..16abb895d58 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -380,6 +380,9 @@ def collect() -> List[Union[Item, Collector]]: collector.path, collector.config.getoption("importmode"), rootpath=collector.config.rootpath, + consider_namespace_packages=collector.config.getini( + "consider_namespace_packages" + ), ) return list(collector.collect()) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index cce23bf87d4..49c5dd3715b 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -180,7 +180,7 @@ def test_traceback_cut(self) -> None: def test_traceback_cut_excludepath(self, pytester: Pytester) -> None: p = pytester.makepyfile("def f(): raise ValueError") with pytest.raises(ValueError) as excinfo: - import_path(p, root=pytester.path).f() # type: ignore[attr-defined] + import_path(p, root=pytester.path, consider_namespace_packages=False).f() # type: ignore[attr-defined] basedir = Path(pytest.__file__).parent newtraceback = excinfo.traceback.cut(excludepath=basedir) for x in newtraceback: @@ -543,7 +543,9 @@ def importasmod(source): tmp_path.joinpath("__init__.py").touch() modpath.write_text(source, encoding="utf-8") importlib.invalidate_caches() - return import_path(modpath, root=tmp_path) + return import_path( + modpath, root=tmp_path, consider_namespace_packages=False + ) return importasmod diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 9d0565380e4..12ea27b3517 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -296,7 +296,7 @@ def method(self): ) path = tmp_path.joinpath("a.py") path.write_text(str(source), encoding="utf-8") - mod: Any = import_path(path, root=tmp_path) + mod: Any = import_path(path, root=tmp_path, consider_namespace_packages=False) s2 = Source(mod.A) assert str(source).strip() == str(s2).strip() diff --git a/testing/test_conftest.py b/testing/test_conftest.py index bb74fa75d61..3116dfe2584 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -38,6 +38,7 @@ def conftest_setinitial( confcutdir=confcutdir, invocation_dir=Path.cwd(), importmode="prepend", + consider_namespace_packages=False, ) @@ -64,7 +65,9 @@ def basedir( def test_basic_init(self, basedir: Path) -> None: conftest = PytestPluginManager() p = basedir / "adir" - conftest._loadconftestmodules(p, importmode="prepend", rootpath=basedir) + conftest._loadconftestmodules( + p, importmode="prepend", rootpath=basedir, consider_namespace_packages=False + ) assert conftest._rget_with_confmod("a", p)[1] == 1 def test_immediate_initialiation_and_incremental_are_the_same( @@ -72,15 +75,26 @@ def test_immediate_initialiation_and_incremental_are_the_same( ) -> None: conftest = PytestPluginManager() assert not len(conftest._dirpath2confmods) - conftest._loadconftestmodules(basedir, importmode="prepend", rootpath=basedir) + conftest._loadconftestmodules( + basedir, + importmode="prepend", + rootpath=basedir, + consider_namespace_packages=False, + ) snap1 = len(conftest._dirpath2confmods) assert snap1 == 1 conftest._loadconftestmodules( - basedir / "adir", importmode="prepend", rootpath=basedir + basedir / "adir", + importmode="prepend", + rootpath=basedir, + consider_namespace_packages=False, ) assert len(conftest._dirpath2confmods) == snap1 + 1 conftest._loadconftestmodules( - basedir / "b", importmode="prepend", rootpath=basedir + basedir / "b", + importmode="prepend", + rootpath=basedir, + consider_namespace_packages=False, ) assert len(conftest._dirpath2confmods) == snap1 + 2 @@ -92,10 +106,18 @@ def test_value_access_not_existing(self, basedir: Path) -> None: def test_value_access_by_path(self, basedir: Path) -> None: conftest = ConftestWithSetinitial(basedir) adir = basedir / "adir" - conftest._loadconftestmodules(adir, importmode="prepend", rootpath=basedir) + conftest._loadconftestmodules( + adir, + importmode="prepend", + rootpath=basedir, + consider_namespace_packages=False, + ) assert conftest._rget_with_confmod("a", adir)[1] == 1 conftest._loadconftestmodules( - adir / "b", importmode="prepend", rootpath=basedir + adir / "b", + importmode="prepend", + rootpath=basedir, + consider_namespace_packages=False, ) assert conftest._rget_with_confmod("a", adir / "b")[1] == 1.5 @@ -152,7 +174,12 @@ def test_conftest_global_import(pytester: Pytester) -> None: import pytest from _pytest.config import PytestPluginManager conf = PytestPluginManager() - mod = conf._importconftest(Path("conftest.py"), importmode="prepend", rootpath=Path.cwd()) + mod = conf._importconftest( + Path("conftest.py"), + importmode="prepend", + rootpath=Path.cwd(), + consider_namespace_packages=False, + ) assert mod.x == 3 import conftest assert conftest is mod, (conftest, mod) @@ -160,7 +187,12 @@ def test_conftest_global_import(pytester: Pytester) -> None: sub.mkdir() subconf = sub / "conftest.py" subconf.write_text("y=4", encoding="utf-8") - mod2 = conf._importconftest(subconf, importmode="prepend", rootpath=Path.cwd()) + mod2 = conf._importconftest( + subconf, + importmode="prepend", + rootpath=Path.cwd(), + consider_namespace_packages=False, + ) assert mod != mod2 assert mod2.y == 4 import conftest @@ -176,17 +208,30 @@ def test_conftestcutdir(pytester: Pytester) -> None: p = pytester.mkdir("x") conftest = PytestPluginManager() conftest_setinitial(conftest, [pytester.path], confcutdir=p) - conftest._loadconftestmodules(p, importmode="prepend", rootpath=pytester.path) + conftest._loadconftestmodules( + p, + importmode="prepend", + rootpath=pytester.path, + consider_namespace_packages=False, + ) values = conftest._getconftestmodules(p) assert len(values) == 0 conftest._loadconftestmodules( - conf.parent, importmode="prepend", rootpath=pytester.path + conf.parent, + importmode="prepend", + rootpath=pytester.path, + consider_namespace_packages=False, ) values = conftest._getconftestmodules(conf.parent) assert len(values) == 0 assert not conftest.has_plugin(str(conf)) # but we can still import a conftest directly - conftest._importconftest(conf, importmode="prepend", rootpath=pytester.path) + conftest._importconftest( + conf, + importmode="prepend", + rootpath=pytester.path, + consider_namespace_packages=False, + ) values = conftest._getconftestmodules(conf.parent) assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf)) @@ -405,13 +450,18 @@ def test_conftest_import_order(pytester: Pytester, monkeypatch: MonkeyPatch) -> ct2 = sub / "conftest.py" ct2.write_text("", encoding="utf-8") - def impct(p, importmode, root): + def impct(p, importmode, root, consider_namespace_packages): return p conftest = PytestPluginManager() conftest._confcutdir = pytester.path monkeypatch.setattr(conftest, "_importconftest", impct) - conftest._loadconftestmodules(sub, importmode="prepend", rootpath=pytester.path) + conftest._loadconftestmodules( + sub, + importmode="prepend", + rootpath=pytester.path, + consider_namespace_packages=False, + ) mods = cast(List[Path], conftest._getconftestmodules(sub)) expected = [ct1, ct2] assert mods == expected diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 13c22b8007a..a5d582bc4bd 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -171,13 +171,17 @@ def setuptestfs(self, path: Path) -> None: ) def test_smoke_test(self, path1: Path) -> None: - obj = import_path(path1 / "execfile.py", root=path1) + obj = import_path( + path1 / "execfile.py", root=path1, consider_namespace_packages=False + ) assert obj.x == 42 # type: ignore[attr-defined] assert obj.__name__ == "execfile" def test_import_path_missing_file(self, path1: Path) -> None: with pytest.raises(ImportPathMismatchError): - import_path(path1 / "sampledir", root=path1) + import_path( + path1 / "sampledir", root=path1, consider_namespace_packages=False + ) def test_renamed_dir_creates_mismatch( self, tmp_path: Path, monkeypatch: MonkeyPatch @@ -185,25 +189,37 @@ def test_renamed_dir_creates_mismatch( tmp_path.joinpath("a").mkdir() p = tmp_path.joinpath("a", "test_x123.py") p.touch() - import_path(p, root=tmp_path) + import_path(p, root=tmp_path, consider_namespace_packages=False) tmp_path.joinpath("a").rename(tmp_path.joinpath("b")) with pytest.raises(ImportPathMismatchError): - import_path(tmp_path.joinpath("b", "test_x123.py"), root=tmp_path) + import_path( + tmp_path.joinpath("b", "test_x123.py"), + root=tmp_path, + consider_namespace_packages=False, + ) # Errors can be ignored. monkeypatch.setenv("PY_IGNORE_IMPORTMISMATCH", "1") - import_path(tmp_path.joinpath("b", "test_x123.py"), root=tmp_path) + import_path( + tmp_path.joinpath("b", "test_x123.py"), + root=tmp_path, + consider_namespace_packages=False, + ) # PY_IGNORE_IMPORTMISMATCH=0 does not ignore error. monkeypatch.setenv("PY_IGNORE_IMPORTMISMATCH", "0") with pytest.raises(ImportPathMismatchError): - import_path(tmp_path.joinpath("b", "test_x123.py"), root=tmp_path) + import_path( + tmp_path.joinpath("b", "test_x123.py"), + root=tmp_path, + consider_namespace_packages=False, + ) def test_messy_name(self, tmp_path: Path) -> None: # https://bitbucket.org/hpk42/py-trunk/issue/129 path = tmp_path / "foo__init__.py" path.touch() - module = import_path(path, root=tmp_path) + module = import_path(path, root=tmp_path, consider_namespace_packages=False) assert module.__name__ == "foo__init__" def test_dir(self, tmp_path: Path) -> None: @@ -211,31 +227,39 @@ def test_dir(self, tmp_path: Path) -> None: p.mkdir() p_init = p / "__init__.py" p_init.touch() - m = import_path(p, root=tmp_path) + m = import_path(p, root=tmp_path, consider_namespace_packages=False) assert m.__name__ == "hello_123" - m = import_path(p_init, root=tmp_path) + m = import_path(p_init, root=tmp_path, consider_namespace_packages=False) assert m.__name__ == "hello_123" def test_a(self, path1: Path) -> None: otherdir = path1 / "otherdir" - mod = import_path(otherdir / "a.py", root=path1) + mod = import_path( + otherdir / "a.py", root=path1, consider_namespace_packages=False + ) assert mod.result == "got it" # type: ignore[attr-defined] assert mod.__name__ == "otherdir.a" def test_b(self, path1: Path) -> None: otherdir = path1 / "otherdir" - mod = import_path(otherdir / "b.py", root=path1) + mod = import_path( + otherdir / "b.py", root=path1, consider_namespace_packages=False + ) assert mod.stuff == "got it" # type: ignore[attr-defined] assert mod.__name__ == "otherdir.b" def test_c(self, path1: Path) -> None: otherdir = path1 / "otherdir" - mod = import_path(otherdir / "c.py", root=path1) + mod = import_path( + otherdir / "c.py", root=path1, consider_namespace_packages=False + ) assert mod.value == "got it" # type: ignore[attr-defined] def test_d(self, path1: Path) -> None: otherdir = path1 / "otherdir" - mod = import_path(otherdir / "d.py", root=path1) + mod = import_path( + otherdir / "d.py", root=path1, consider_namespace_packages=False + ) assert mod.value2 == "got it" # type: ignore[attr-defined] def test_import_after(self, tmp_path: Path) -> None: @@ -243,7 +267,7 @@ def test_import_after(self, tmp_path: Path) -> None: tmp_path.joinpath("xxxpackage", "__init__.py").touch() mod1path = tmp_path.joinpath("xxxpackage", "module1.py") mod1path.touch() - mod1 = import_path(mod1path, root=tmp_path) + mod1 = import_path(mod1path, root=tmp_path, consider_namespace_packages=False) assert mod1.__name__ == "xxxpackage.module1" from xxxpackage import module1 @@ -262,7 +286,9 @@ def test_check_filepath_consistency( pseudopath.touch() mod.__file__ = str(pseudopath) mp.setitem(sys.modules, name, mod) - newmod = import_path(p, root=tmp_path) + newmod = import_path( + p, root=tmp_path, consider_namespace_packages=False + ) assert mod == newmod mod = ModuleType(name) pseudopath = tmp_path.joinpath(name + "123.py") @@ -270,7 +296,7 @@ def test_check_filepath_consistency( mod.__file__ = str(pseudopath) monkeypatch.setitem(sys.modules, name, mod) with pytest.raises(ImportPathMismatchError) as excinfo: - import_path(p, root=tmp_path) + import_path(p, root=tmp_path, consider_namespace_packages=False) modname, modfile, orig = excinfo.value.args assert modname == name assert modfile == str(pseudopath) @@ -283,13 +309,19 @@ def test_ensuresyspath_append(self, tmp_path: Path) -> None: file1 = root1 / "x123.py" file1.touch() assert str(root1) not in sys.path - import_path(file1, mode="append", root=tmp_path) + import_path( + file1, mode="append", root=tmp_path, consider_namespace_packages=False + ) assert str(root1) == sys.path[-1] assert str(root1) not in sys.path[:-1] def test_invalid_path(self, tmp_path: Path) -> None: with pytest.raises(ImportError): - import_path(tmp_path / "invalid.py", root=tmp_path) + import_path( + tmp_path / "invalid.py", + root=tmp_path, + consider_namespace_packages=False, + ) @pytest.fixture def simple_module( @@ -307,7 +339,12 @@ def test_importmode_importlib( self, simple_module: Path, tmp_path: Path, request: pytest.FixtureRequest ) -> None: """`importlib` mode does not change sys.path.""" - module = import_path(simple_module, mode="importlib", root=tmp_path) + module = import_path( + simple_module, + mode="importlib", + root=tmp_path, + consider_namespace_packages=False, + ) assert module.foo(2) == 42 # type: ignore[attr-defined] assert str(simple_module.parent) not in sys.path assert module.__name__ in sys.modules @@ -319,8 +356,18 @@ def test_remembers_previous_imports( self, simple_module: Path, tmp_path: Path ) -> None: """`importlib` mode called remembers previous module (#10341, #10811).""" - module1 = import_path(simple_module, mode="importlib", root=tmp_path) - module2 = import_path(simple_module, mode="importlib", root=tmp_path) + module1 = import_path( + simple_module, + mode="importlib", + root=tmp_path, + consider_namespace_packages=False, + ) + module2 = import_path( + simple_module, + mode="importlib", + root=tmp_path, + consider_namespace_packages=False, + ) assert module1 is module2 def test_no_meta_path_found( @@ -328,7 +375,12 @@ def test_no_meta_path_found( ) -> None: """Even without any meta_path should still import module.""" monkeypatch.setattr(sys, "meta_path", []) - module = import_path(simple_module, mode="importlib", root=tmp_path) + module = import_path( + simple_module, + mode="importlib", + root=tmp_path, + consider_namespace_packages=False, + ) assert module.foo(2) == 42 # type: ignore[attr-defined] # mode='importlib' fails if no spec is found to load the module @@ -341,7 +393,12 @@ def test_no_meta_path_found( importlib.util, "spec_from_file_location", lambda *args: None ) with pytest.raises(ImportError): - import_path(simple_module, mode="importlib", root=tmp_path) + import_path( + simple_module, + mode="importlib", + root=tmp_path, + consider_namespace_packages=False, + ) def test_resolve_package_path(tmp_path: Path) -> None: @@ -477,7 +534,9 @@ def test_samefile_false_negatives(tmp_path: Path, monkeypatch: MonkeyPatch) -> N # the paths too. Using a context to narrow the patch as much as possible given # this is an important system function. mp.setattr(os.path, "samefile", lambda x, y: False) - module = import_path(module_path, root=tmp_path) + module = import_path( + module_path, root=tmp_path, consider_namespace_packages=False + ) assert getattr(module, "foo")() == 42 @@ -499,7 +558,9 @@ class Data: encoding="utf-8", ) - module = import_path(fn, mode="importlib", root=tmp_path) + module = import_path( + fn, mode="importlib", root=tmp_path, consider_namespace_packages=False + ) Data: Any = getattr(module, "Data") data = Data(value="foo") assert data.value == "foo" @@ -525,7 +586,9 @@ def round_trip(): encoding="utf-8", ) - module = import_path(fn, mode="importlib", root=tmp_path) + module = import_path( + fn, mode="importlib", root=tmp_path, consider_namespace_packages=False + ) round_trip = getattr(module, "round_trip") action = round_trip() assert action() == 42 @@ -575,10 +638,14 @@ def round_trip(obj): s = pickle.dumps(obj) return pickle.loads(s) - module = import_path(fn1, mode="importlib", root=tmp_path) + module = import_path( + fn1, mode="importlib", root=tmp_path, consider_namespace_packages=False + ) Data1 = getattr(module, "Data") - module = import_path(fn2, mode="importlib", root=tmp_path) + module = import_path( + fn2, mode="importlib", root=tmp_path, consider_namespace_packages=False + ) Data2 = getattr(module, "Data") assert round_trip(Data1(20)) == Data1(20) @@ -635,7 +702,7 @@ def test_resolve_pkg_root_and_module_name( # If we add tmp_path to sys.path, src becomes a namespace package. monkeypatch.syspath_prepend(tmp_path) assert resolve_pkg_root_and_module_name( - models_py, consider_ns_packages=True + models_py, consider_namespace_packages=True ) == ( tmp_path, "src.app.core.models", @@ -709,7 +776,12 @@ def __init__(self) -> None: encoding="ascii", ) - mod = import_path(init, root=tmp_path, mode=ImportMode.importlib) + mod = import_path( + init, + root=tmp_path, + mode=ImportMode.importlib, + consider_namespace_packages=False, + ) assert len(mod.instance.INSTANCES) == 1 def test_importlib_root_is_package(self, pytester: Pytester) -> None: @@ -828,16 +900,31 @@ def test_import_using_normal_mechanism_first( ) # core_py is reached from sys.path, so should be imported normally. - mod = import_path(core_py, mode="importlib", root=pytester.path) + mod = import_path( + core_py, + mode="importlib", + root=pytester.path, + consider_namespace_packages=False, + ) assert mod.__name__ == "app.core" assert mod.__file__ and Path(mod.__file__) == core_py # tests are not reachable from sys.path, so they are imported as a standalone modules. # Instead of '.tests.a.test_core', we import as "_tests.a.test_core" because # importlib considers module names starting with '.' to be local imports. - mod = import_path(test_path1, mode="importlib", root=pytester.path) + mod = import_path( + test_path1, + mode="importlib", + root=pytester.path, + consider_namespace_packages=False, + ) assert mod.__name__ == "_tests.a.test_core" - mod = import_path(test_path2, mode="importlib", root=pytester.path) + mod = import_path( + test_path2, + mode="importlib", + root=pytester.path, + consider_namespace_packages=False, + ) assert mod.__name__ == "_tests.b.test_core" def test_import_using_normal_mechanism_first_integration( @@ -889,14 +976,22 @@ def test_import_path_imports_correct_file(self, pytester: Pytester) -> None: # The 'x.py' module from sys.path was not imported for sure because # otherwise we would get an AssertionError. mod = import_path( - x_in_sub_folder, mode=ImportMode.importlib, root=pytester.path + x_in_sub_folder, + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=False, ) assert mod.__file__ and Path(mod.__file__) == x_in_sub_folder assert mod.X == "a/b/x" # Attempt to import root 'x.py'. with pytest.raises(AssertionError, match="x at root"): - _ = import_path(x_at_root, mode=ImportMode.importlib, root=pytester.path) + _ = import_path( + x_at_root, + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=False, + ) def test_safe_exists(tmp_path: Path) -> None: @@ -979,26 +1074,33 @@ def test_resolve_pkg_root_and_module_name_ns_multiple_levels( ) pkg_root, module_name = resolve_pkg_root_and_module_name( - models_py, consider_ns_packages=True + models_py, consider_namespace_packages=True ) assert (pkg_root, module_name) == ( tmp_path / "src/dist1", "com.company.app.core.models", ) - mod = import_path(models_py, mode=import_mode, root=tmp_path) + mod = import_path( + models_py, mode=import_mode, root=tmp_path, consider_namespace_packages=True + ) assert mod.__name__ == "com.company.app.core.models" assert mod.__file__ == str(models_py) pkg_root, module_name = resolve_pkg_root_and_module_name( - algorithms_py, consider_ns_packages=True + algorithms_py, consider_namespace_packages=True ) assert (pkg_root, module_name) == ( tmp_path / "src/dist2", "com.company.calc.algo.algorithms", ) - mod = import_path(algorithms_py, mode=import_mode, root=tmp_path) + mod = import_path( + algorithms_py, + mode=import_mode, + root=tmp_path, + consider_namespace_packages=True, + ) assert mod.__name__ == "com.company.calc.algo.algorithms" assert mod.__file__ == str(algorithms_py) @@ -1019,7 +1121,7 @@ def test_incorrect_namespace_package( (tmp_path / "src/dist1/com/__init__.py").touch() pkg_root, module_name = resolve_pkg_root_and_module_name( - models_py, consider_ns_packages=True + models_py, consider_namespace_packages=True ) assert (pkg_root, module_name) == ( tmp_path / "src/dist1/com/company", diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index f68f143f433..da43364f643 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -46,7 +46,10 @@ def pytest_myhook(xyz): kwargs=dict(pluginmanager=config.pluginmanager) ) config.pluginmanager._importconftest( - conf, importmode="prepend", rootpath=pytester.path + conf, + importmode="prepend", + rootpath=pytester.path, + consider_namespace_packages=False, ) # print(config.pluginmanager.get_plugins()) res = config.hook.pytest_myhook(xyz=10) @@ -75,7 +78,10 @@ def pytest_addoption(parser): """ ) config.pluginmanager._importconftest( - p, importmode="prepend", rootpath=pytester.path + p, + importmode="prepend", + rootpath=pytester.path, + consider_namespace_packages=False, ) assert config.option.test123 @@ -115,6 +121,7 @@ def test_conftestpath_case_sensitivity(self, pytester: Pytester) -> None: conftest, importmode="prepend", rootpath=pytester.path, + consider_namespace_packages=False, ) plugin = config.pluginmanager.get_plugin(str(conftest)) assert plugin is mod @@ -123,6 +130,7 @@ def test_conftestpath_case_sensitivity(self, pytester: Pytester) -> None: conftest_upper_case, importmode="prepend", rootpath=pytester.path, + consider_namespace_packages=False, ) plugin_uppercase = config.pluginmanager.get_plugin(str(conftest_upper_case)) assert plugin_uppercase is mod_uppercase @@ -174,12 +182,18 @@ def test_hook_proxy(self, pytester: Pytester) -> None: conftest2 = pytester.path.joinpath("tests/subdir/conftest.py") config.pluginmanager._importconftest( - conftest1, importmode="prepend", rootpath=pytester.path + conftest1, + importmode="prepend", + rootpath=pytester.path, + consider_namespace_packages=False, ) ihook_a = session.gethookproxy(pytester.path / "tests") assert ihook_a is not None config.pluginmanager._importconftest( - conftest2, importmode="prepend", rootpath=pytester.path + conftest2, + importmode="prepend", + rootpath=pytester.path, + consider_namespace_packages=False, ) ihook_b = session.gethookproxy(pytester.path / "tests") assert ihook_a is not ihook_b @@ -398,7 +412,9 @@ def test_consider_conftest_deps( pytestpm: PytestPluginManager, ) -> None: mod = import_path( - pytester.makepyfile("pytest_plugins='xyz'"), root=pytester.path + pytester.makepyfile("pytest_plugins='xyz'"), + root=pytester.path, + consider_namespace_packages=False, ) with pytest.raises(ImportError): pytestpm.consider_conftest(mod, registration_name="unused") From aac720abc900631ebd3d1807dcaf0c297d578113 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 2 Mar 2024 12:03:08 -0300 Subject: [PATCH 0520/1271] testing/test_pathlib: parametrize namespace package option Test with namespace packages support even when it will not find namespace packages to ensure it will at least not give weird results or crashes. --- testing/test_pathlib.py | 149 +++++++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 56 deletions(-) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index a5d582bc4bd..357860563a8 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -100,6 +100,15 @@ def test_not_matching(self, pattern: str, path: str) -> None: assert not fnmatch_ex(pattern, path) +@pytest.fixture(params=[True, False]) +def ns_param(request: pytest.FixtureRequest) -> bool: + """ + Simple parametrized fixture for tests which call import_path() with consider_namespace_packages + using True and False. + """ + return bool(request.param) + + class TestImportPath: """ @@ -170,32 +179,32 @@ def setuptestfs(self, path: Path) -> None: encoding="utf-8", ) - def test_smoke_test(self, path1: Path) -> None: + def test_smoke_test(self, path1: Path, ns_param: bool) -> None: obj = import_path( - path1 / "execfile.py", root=path1, consider_namespace_packages=False + path1 / "execfile.py", root=path1, consider_namespace_packages=ns_param ) assert obj.x == 42 # type: ignore[attr-defined] assert obj.__name__ == "execfile" - def test_import_path_missing_file(self, path1: Path) -> None: + def test_import_path_missing_file(self, path1: Path, ns_param: bool) -> None: with pytest.raises(ImportPathMismatchError): import_path( - path1 / "sampledir", root=path1, consider_namespace_packages=False + path1 / "sampledir", root=path1, consider_namespace_packages=ns_param ) def test_renamed_dir_creates_mismatch( - self, tmp_path: Path, monkeypatch: MonkeyPatch + self, tmp_path: Path, monkeypatch: MonkeyPatch, ns_param: bool ) -> None: tmp_path.joinpath("a").mkdir() p = tmp_path.joinpath("a", "test_x123.py") p.touch() - import_path(p, root=tmp_path, consider_namespace_packages=False) + import_path(p, root=tmp_path, consider_namespace_packages=ns_param) tmp_path.joinpath("a").rename(tmp_path.joinpath("b")) with pytest.raises(ImportPathMismatchError): import_path( tmp_path.joinpath("b", "test_x123.py"), root=tmp_path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) # Errors can be ignored. @@ -203,7 +212,7 @@ def test_renamed_dir_creates_mismatch( import_path( tmp_path.joinpath("b", "test_x123.py"), root=tmp_path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) # PY_IGNORE_IMPORTMISMATCH=0 does not ignore error. @@ -212,69 +221,71 @@ def test_renamed_dir_creates_mismatch( import_path( tmp_path.joinpath("b", "test_x123.py"), root=tmp_path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) - def test_messy_name(self, tmp_path: Path) -> None: + def test_messy_name(self, tmp_path: Path, ns_param: bool) -> None: # https://bitbucket.org/hpk42/py-trunk/issue/129 path = tmp_path / "foo__init__.py" path.touch() - module = import_path(path, root=tmp_path, consider_namespace_packages=False) + module = import_path(path, root=tmp_path, consider_namespace_packages=ns_param) assert module.__name__ == "foo__init__" - def test_dir(self, tmp_path: Path) -> None: + def test_dir(self, tmp_path: Path, ns_param: bool) -> None: p = tmp_path / "hello_123" p.mkdir() p_init = p / "__init__.py" p_init.touch() - m = import_path(p, root=tmp_path, consider_namespace_packages=False) + m = import_path(p, root=tmp_path, consider_namespace_packages=ns_param) assert m.__name__ == "hello_123" - m = import_path(p_init, root=tmp_path, consider_namespace_packages=False) + m = import_path(p_init, root=tmp_path, consider_namespace_packages=ns_param) assert m.__name__ == "hello_123" - def test_a(self, path1: Path) -> None: + def test_a(self, path1: Path, ns_param: bool) -> None: otherdir = path1 / "otherdir" mod = import_path( - otherdir / "a.py", root=path1, consider_namespace_packages=False + otherdir / "a.py", root=path1, consider_namespace_packages=ns_param ) assert mod.result == "got it" # type: ignore[attr-defined] assert mod.__name__ == "otherdir.a" - def test_b(self, path1: Path) -> None: + def test_b(self, path1: Path, ns_param: bool) -> None: otherdir = path1 / "otherdir" mod = import_path( - otherdir / "b.py", root=path1, consider_namespace_packages=False + otherdir / "b.py", root=path1, consider_namespace_packages=ns_param ) assert mod.stuff == "got it" # type: ignore[attr-defined] assert mod.__name__ == "otherdir.b" - def test_c(self, path1: Path) -> None: + def test_c(self, path1: Path, ns_param: bool) -> None: otherdir = path1 / "otherdir" mod = import_path( - otherdir / "c.py", root=path1, consider_namespace_packages=False + otherdir / "c.py", root=path1, consider_namespace_packages=ns_param ) assert mod.value == "got it" # type: ignore[attr-defined] - def test_d(self, path1: Path) -> None: + def test_d(self, path1: Path, ns_param: bool) -> None: otherdir = path1 / "otherdir" mod = import_path( - otherdir / "d.py", root=path1, consider_namespace_packages=False + otherdir / "d.py", root=path1, consider_namespace_packages=ns_param ) assert mod.value2 == "got it" # type: ignore[attr-defined] - def test_import_after(self, tmp_path: Path) -> None: + def test_import_after(self, tmp_path: Path, ns_param: bool) -> None: tmp_path.joinpath("xxxpackage").mkdir() tmp_path.joinpath("xxxpackage", "__init__.py").touch() mod1path = tmp_path.joinpath("xxxpackage", "module1.py") mod1path.touch() - mod1 = import_path(mod1path, root=tmp_path, consider_namespace_packages=False) + mod1 = import_path( + mod1path, root=tmp_path, consider_namespace_packages=ns_param + ) assert mod1.__name__ == "xxxpackage.module1" from xxxpackage import module1 assert module1 is mod1 def test_check_filepath_consistency( - self, monkeypatch: MonkeyPatch, tmp_path: Path + self, monkeypatch: MonkeyPatch, tmp_path: Path, ns_param: bool ) -> None: name = "pointsback123" p = tmp_path.joinpath(name + ".py") @@ -287,7 +298,7 @@ def test_check_filepath_consistency( mod.__file__ = str(pseudopath) mp.setitem(sys.modules, name, mod) newmod = import_path( - p, root=tmp_path, consider_namespace_packages=False + p, root=tmp_path, consider_namespace_packages=ns_param ) assert mod == newmod mod = ModuleType(name) @@ -296,31 +307,31 @@ def test_check_filepath_consistency( mod.__file__ = str(pseudopath) monkeypatch.setitem(sys.modules, name, mod) with pytest.raises(ImportPathMismatchError) as excinfo: - import_path(p, root=tmp_path, consider_namespace_packages=False) + import_path(p, root=tmp_path, consider_namespace_packages=ns_param) modname, modfile, orig = excinfo.value.args assert modname == name assert modfile == str(pseudopath) assert orig == p assert issubclass(ImportPathMismatchError, ImportError) - def test_ensuresyspath_append(self, tmp_path: Path) -> None: + def test_ensuresyspath_append(self, tmp_path: Path, ns_param: bool) -> None: root1 = tmp_path / "root1" root1.mkdir() file1 = root1 / "x123.py" file1.touch() assert str(root1) not in sys.path import_path( - file1, mode="append", root=tmp_path, consider_namespace_packages=False + file1, mode="append", root=tmp_path, consider_namespace_packages=ns_param ) assert str(root1) == sys.path[-1] assert str(root1) not in sys.path[:-1] - def test_invalid_path(self, tmp_path: Path) -> None: + def test_invalid_path(self, tmp_path: Path, ns_param: bool) -> None: with pytest.raises(ImportError): import_path( tmp_path / "invalid.py", root=tmp_path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) @pytest.fixture @@ -336,14 +347,18 @@ def simple_module( sys.modules.pop(module_name, None) def test_importmode_importlib( - self, simple_module: Path, tmp_path: Path, request: pytest.FixtureRequest + self, + simple_module: Path, + tmp_path: Path, + request: pytest.FixtureRequest, + ns_param: bool, ) -> None: """`importlib` mode does not change sys.path.""" module = import_path( simple_module, mode="importlib", root=tmp_path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) assert module.foo(2) == 42 # type: ignore[attr-defined] assert str(simple_module.parent) not in sys.path @@ -353,25 +368,29 @@ def test_importmode_importlib( assert "_src.tests" in sys.modules def test_remembers_previous_imports( - self, simple_module: Path, tmp_path: Path + self, simple_module: Path, tmp_path: Path, ns_param: bool ) -> None: """`importlib` mode called remembers previous module (#10341, #10811).""" module1 = import_path( simple_module, mode="importlib", root=tmp_path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) module2 = import_path( simple_module, mode="importlib", root=tmp_path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) assert module1 is module2 def test_no_meta_path_found( - self, simple_module: Path, monkeypatch: MonkeyPatch, tmp_path: Path + self, + simple_module: Path, + monkeypatch: MonkeyPatch, + tmp_path: Path, + ns_param: bool, ) -> None: """Even without any meta_path should still import module.""" monkeypatch.setattr(sys, "meta_path", []) @@ -379,7 +398,7 @@ def test_no_meta_path_found( simple_module, mode="importlib", root=tmp_path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) assert module.foo(2) == 42 # type: ignore[attr-defined] @@ -541,7 +560,9 @@ def test_samefile_false_negatives(tmp_path: Path, monkeypatch: MonkeyPatch) -> N class TestImportLibMode: - def test_importmode_importlib_with_dataclass(self, tmp_path: Path) -> None: + def test_importmode_importlib_with_dataclass( + self, tmp_path: Path, ns_param: bool + ) -> None: """Ensure that importlib mode works with a module containing dataclasses (#7856).""" fn = tmp_path.joinpath("_src/tests/test_dataclass.py") fn.parent.mkdir(parents=True) @@ -559,14 +580,16 @@ class Data: ) module = import_path( - fn, mode="importlib", root=tmp_path, consider_namespace_packages=False + fn, mode="importlib", root=tmp_path, consider_namespace_packages=ns_param ) Data: Any = getattr(module, "Data") data = Data(value="foo") assert data.value == "foo" assert data.__module__ == "_src.tests.test_dataclass" - def test_importmode_importlib_with_pickle(self, tmp_path: Path) -> None: + def test_importmode_importlib_with_pickle( + self, tmp_path: Path, ns_param: bool + ) -> None: """Ensure that importlib mode works with pickle (#7859).""" fn = tmp_path.joinpath("_src/tests/test_pickle.py") fn.parent.mkdir(parents=True) @@ -587,14 +610,14 @@ def round_trip(): ) module = import_path( - fn, mode="importlib", root=tmp_path, consider_namespace_packages=False + fn, mode="importlib", root=tmp_path, consider_namespace_packages=ns_param ) round_trip = getattr(module, "round_trip") action = round_trip() assert action() == 42 def test_importmode_importlib_with_pickle_separate_modules( - self, tmp_path: Path + self, tmp_path: Path, ns_param: bool ) -> None: """ Ensure that importlib mode works can load pickles that look similar but are @@ -639,12 +662,12 @@ def round_trip(obj): return pickle.loads(s) module = import_path( - fn1, mode="importlib", root=tmp_path, consider_namespace_packages=False + fn1, mode="importlib", root=tmp_path, consider_namespace_packages=ns_param ) Data1 = getattr(module, "Data") module = import_path( - fn2, mode="importlib", root=tmp_path, consider_namespace_packages=False + fn2, mode="importlib", root=tmp_path, consider_namespace_packages=ns_param ) Data2 = getattr(module, "Data") @@ -694,7 +717,9 @@ def test_resolve_pkg_root_and_module_name( # Create the __init__.py files, it should now resolve to a proper module name. (tmp_path / "src/app/__init__.py").touch() (tmp_path / "src/app/core/__init__.py").touch() - assert resolve_pkg_root_and_module_name(models_py) == ( + assert resolve_pkg_root_and_module_name( + models_py, consider_namespace_packages=True + ) == ( tmp_path / "src", "app.core.models", ) @@ -707,6 +732,12 @@ def test_resolve_pkg_root_and_module_name( tmp_path, "src.app.core.models", ) + assert resolve_pkg_root_and_module_name( + models_py, consider_namespace_packages=False + ) == ( + tmp_path / "src", + "app.core.models", + ) def test_insert_missing_modules( self, monkeypatch: MonkeyPatch, tmp_path: Path @@ -739,7 +770,9 @@ def test_parent_contains_child_module_attribute( assert modules["xxx"].tests is modules["xxx.tests"] assert modules["xxx.tests"].foo is modules["xxx.tests.foo"] - def test_importlib_package(self, monkeypatch: MonkeyPatch, tmp_path: Path): + def test_importlib_package( + self, monkeypatch: MonkeyPatch, tmp_path: Path, ns_param: bool + ): """ Importing a package using --importmode=importlib should not import the package's __init__.py file more than once (#11306). @@ -780,7 +813,7 @@ def __init__(self) -> None: init, root=tmp_path, mode=ImportMode.importlib, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) assert len(mod.instance.INSTANCES) == 1 @@ -889,7 +922,7 @@ def test(b_fix): return (site_packages / "app/core.py"), test_path1, test_path2 def test_import_using_normal_mechanism_first( - self, monkeypatch: MonkeyPatch, pytester: Pytester + self, monkeypatch: MonkeyPatch, pytester: Pytester, ns_param: bool ) -> None: """ Test import_path imports from the canonical location when possible first, only @@ -904,7 +937,7 @@ def test_import_using_normal_mechanism_first( core_py, mode="importlib", root=pytester.path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) assert mod.__name__ == "app.core" assert mod.__file__ and Path(mod.__file__) == core_py @@ -916,19 +949,19 @@ def test_import_using_normal_mechanism_first( test_path1, mode="importlib", root=pytester.path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) assert mod.__name__ == "_tests.a.test_core" mod = import_path( test_path2, mode="importlib", root=pytester.path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) assert mod.__name__ == "_tests.b.test_core" def test_import_using_normal_mechanism_first_integration( - self, monkeypatch: MonkeyPatch, pytester: Pytester + self, monkeypatch: MonkeyPatch, pytester: Pytester, ns_param: bool ) -> None: """ Same test as above, but verify the behavior calling pytest. @@ -941,6 +974,8 @@ def test_import_using_normal_mechanism_first_integration( ) result = pytester.runpytest( "--import-mode=importlib", + "-o", + f"consider_namespace_packages={ns_param}", "--doctest-modules", "--pyargs", "app", @@ -955,7 +990,9 @@ def test_import_using_normal_mechanism_first_integration( ] ) - def test_import_path_imports_correct_file(self, pytester: Pytester) -> None: + def test_import_path_imports_correct_file( + self, pytester: Pytester, ns_param: bool + ) -> None: """ Import the module by the given path, even if other module with the same name is reachable from sys.path. @@ -979,7 +1016,7 @@ def test_import_path_imports_correct_file(self, pytester: Pytester) -> None: x_in_sub_folder, mode=ImportMode.importlib, root=pytester.path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) assert mod.__file__ and Path(mod.__file__) == x_in_sub_folder assert mod.X == "a/b/x" @@ -990,7 +1027,7 @@ def test_import_path_imports_correct_file(self, pytester: Pytester) -> None: x_at_root, mode=ImportMode.importlib, root=pytester.path, - consider_namespace_packages=False, + consider_namespace_packages=ns_param, ) From d6134bc21e27efee7a2e264bd089e6c223515904 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 2 Mar 2024 12:16:12 -0300 Subject: [PATCH 0521/1271] doc: document consider_namespace_packages option --- changelog/11475.feature.rst | 4 ++-- changelog/11475.improvement.rst | 2 ++ doc/en/explanation/pythonpath.rst | 10 ++++++++-- doc/en/reference/reference.rst | 13 +++++++++++++ 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/changelog/11475.feature.rst b/changelog/11475.feature.rst index 6b73c81586a..42550235d80 100644 --- a/changelog/11475.feature.rst +++ b/changelog/11475.feature.rst @@ -1,3 +1,3 @@ -pytest now correctly identifies modules that are part of `namespace packages `__, for example when importing user-level modules for doctesting. +Added the new :confval:`consider_namespace_packages` configuration option, defaulting to ``False``. -Previously pytest was not aware of namespace packages, so running a doctest from a subpackage that is part of a namespace package would import just the subpackage (for example ``app.models``) instead of its full path (for example ``com.company.app.models``). +If set to ``True``, pytest will attempt to identify modules that are part of `namespace packages `__ when importing modules. diff --git a/changelog/11475.improvement.rst b/changelog/11475.improvement.rst index fc6e8be3a3a..4f6a4bffaad 100644 --- a/changelog/11475.improvement.rst +++ b/changelog/11475.improvement.rst @@ -1 +1,3 @@ :ref:`--import-mode=importlib ` now tries to import modules using the standard import mechanism (but still without changing :py:data:`sys.path`), falling back to importing modules directly only if that fails. + +This means that installed packages will be imported under their canonical name if possible first, for example ``app.core.models``, instead of having the module name always be derived from their path (for example ``.env310.lib.site_packages.app.core.models``). diff --git a/doc/en/explanation/pythonpath.rst b/doc/en/explanation/pythonpath.rst index 6b1d3ae2cbc..33eba86b57a 100644 --- a/doc/en/explanation/pythonpath.rst +++ b/doc/en/explanation/pythonpath.rst @@ -10,8 +10,7 @@ Import modes pytest as a testing framework needs to import test modules and ``conftest.py`` files for execution. -Importing files in Python (at least until recently) is a non-trivial processes, often requiring -changing :data:`sys.path`. Some aspects of the +Importing files in Python is a non-trivial processes, so aspects of the import process can be controlled through the ``--import-mode`` command-line flag, which can assume these values: @@ -100,10 +99,17 @@ these values: Initially we intended to make ``importlib`` the default in future releases, however it is clear now that it has its own set of drawbacks so the default will remain ``prepend`` for the foreseeable future. +.. note:: + + By default, pytest will not attempt to resolve namespace packages automatically, but that can + be changed via the :confval:`consider_namespace_packages` configuration variable. + .. seealso:: The :confval:`pythonpath` configuration variable. + The :confval:`consider_namespace_packages` configuration variable. + :ref:`test layout`. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index bba4a399c72..f84b7ea4847 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1274,6 +1274,19 @@ passed multiple times. The expected format is ``name=value``. For example:: variables, that will be expanded. For more information about cache plugin please refer to :ref:`cache_provider`. +.. confval:: consider_namespace_packages + + Controls if pytest should attempt to identify `namespace packages `__ + when collecting Python modules. Default is ``False``. + + Set to ``True`` if you are testing namespace packages installed into a virtual environment and it is important for + your packages to be imported using their full namespace package name. + + Only `native namespace packages `__ + are supported, with no plans to support `legacy namespace packages `__. + + .. versionadded:: 8.1 + .. confval:: console_output_style Sets the console output style while running tests: From 434282e17f5f1f4fcc1464a0a0921cf19804bdd7 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 2 Mar 2024 22:43:56 +0200 Subject: [PATCH 0522/1271] fixtures: use exception group when multiple finalizers raise in fixture teardown Previously, if more than one fixture finalizer raised, only the first was reported, and the other errors were lost. Use an exception group to report them all. This is similar to the change we made in node teardowns (in `SetupState`). --- changelog/12047.improvement.rst | 2 ++ src/_pytest/fixtures.py | 45 ++++++++++++++++++--------------- testing/python/fixtures.py | 15 ++++++++--- 3 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 changelog/12047.improvement.rst diff --git a/changelog/12047.improvement.rst b/changelog/12047.improvement.rst new file mode 100644 index 00000000000..e9ad5eddcab --- /dev/null +++ b/changelog/12047.improvement.rst @@ -0,0 +1,2 @@ +When multiple finalizers of a fixture raise an exception, now all exceptions are reported as an exception group. +Previously, only the first exception was reported. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 0a505d65ad0..b619dc358e1 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -7,6 +7,7 @@ import inspect import os from pathlib import Path +import sys from typing import AbstractSet from typing import Any from typing import Callable @@ -67,6 +68,10 @@ from _pytest.scope import Scope +if sys.version_info[:2] < (3, 11): + from exceptiongroup import BaseExceptionGroup + + if TYPE_CHECKING: from typing import Deque @@ -1017,27 +1022,25 @@ def addfinalizer(self, finalizer: Callable[[], object]) -> None: self._finalizers.append(finalizer) def finish(self, request: SubRequest) -> None: - exc = None - try: - while self._finalizers: - try: - func = self._finalizers.pop() - func() - except BaseException as e: - # XXX Only first exception will be seen by user, - # ideally all should be reported. - if exc is None: - exc = e - if exc: - raise exc - finally: - ihook = request.node.ihook - ihook.pytest_fixture_post_finalizer(fixturedef=self, request=request) - # Even if finalization fails, we invalidate the cached fixture - # value and remove all finalizers because they may be bound methods - # which will keep instances alive. - self.cached_result = None - self._finalizers.clear() + exceptions: List[BaseException] = [] + while self._finalizers: + fin = self._finalizers.pop() + try: + fin() + except BaseException as e: + exceptions.append(e) + node = request.node + node.ihook.pytest_fixture_post_finalizer(fixturedef=self, request=request) + # Even if finalization fails, we invalidate the cached fixture + # value and remove all finalizers because they may be bound methods + # which will keep instances alive. + self.cached_result = None + self._finalizers.clear() + if len(exceptions) == 1: + raise exceptions[0] + elif len(exceptions) > 1: + msg = f'errors while tearing down fixture "{self.argname}" of {node}' + raise BaseExceptionGroup(msg, exceptions[::-1]) def execute(self, request: SubRequest) -> FixtureValue: # Get required arguments and register our own finish() diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 299e411a695..6edff6ecd43 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -932,8 +932,9 @@ def test_request_subrequest_addfinalizer_exceptions( self, pytester: Pytester ) -> None: """ - Ensure exceptions raised during teardown by a finalizer are suppressed - until all finalizers are called, re-raising the first exception (#2440) + Ensure exceptions raised during teardown by finalizers are suppressed + until all finalizers are called, then re-reaised together in an + exception group (#2440) """ pytester.makepyfile( """ @@ -960,8 +961,16 @@ def test_second(): """ ) result = pytester.runpytest() + result.assert_outcomes(passed=2, errors=1) result.stdout.fnmatch_lines( - ["*Exception: Error in excepts fixture", "* 2 passed, 1 error in *"] + [ + ' | *ExceptionGroup: errors while tearing down fixture "subrequest" of (2 sub-exceptions)', # noqa: E501 + " +-+---------------- 1 ----------------", + " | Exception: Error in something fixture", + " +---------------- 2 ----------------", + " | Exception: Error in excepts fixture", + " +------------------------------------", + ], ) def test_request_getmodulepath(self, pytester: Pytester) -> None: From 8248946a552635f5751a58c7a6dfd24e98db7404 Mon Sep 17 00:00:00 2001 From: mrbean-bremen Date: Sun, 3 Mar 2024 13:41:31 +0100 Subject: [PATCH 0523/1271] Do not collect symlinked tests under Windows (#12050) The check for short paths under Windows via os.path.samefile, introduced in #11936, also found similar tests in symlinked tests in the GH Actions CI. Fixes #12039. Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/12039.bugfix.rst | 1 + src/_pytest/main.py | 9 ++++++++- testing/test_collection.py | 27 ++++++++++++++++++++++++++- 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 changelog/12039.bugfix.rst diff --git a/AUTHORS b/AUTHORS index f78c4b3f94b..4c4d68df147 100644 --- a/AUTHORS +++ b/AUTHORS @@ -283,6 +283,7 @@ Mike Hoyle (hoylemd) Mike Lundy Milan Lesnek Miro Hrončok +mrbean-bremen Nathaniel Compton Nathaniel Waisbrot Ned Batchelder diff --git a/changelog/12039.bugfix.rst b/changelog/12039.bugfix.rst new file mode 100644 index 00000000000..267eae6b8b2 --- /dev/null +++ b/changelog/12039.bugfix.rst @@ -0,0 +1 @@ +Fixed a regression in ``8.0.2`` where tests created using :fixture:`tmp_path` have been collected multiple times in CI under Windows. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index b7ed72ddc3b..d8cd023cc6e 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -924,7 +924,14 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: if sys.platform == "win32" and not is_match: # In case the file paths do not match, fallback to samefile() to # account for short-paths on Windows (#11895). - is_match = os.path.samefile(node.path, matchparts[0]) + same_file = os.path.samefile(node.path, matchparts[0]) + # We don't want to match links to the current node, + # otherwise we would match the same file more than once (#12039). + is_match = same_file and ( + os.path.islink(node.path) + == os.path.islink(matchparts[0]) + ) + # Name part e.g. `TestIt` in `/a/b/test_file.py::TestIt::test_it`. else: # TODO: Remove parametrized workaround once collection structure contains diff --git a/testing/test_collection.py b/testing/test_collection.py index fbc8543e9c4..1491ec85990 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1765,7 +1765,7 @@ def test_foo(): assert True @pytest.mark.skipif(not sys.platform.startswith("win"), reason="Windows only") def test_collect_short_file_windows(pytester: Pytester) -> None: - """Reproducer for #11895: short paths not colleced on Windows.""" + """Reproducer for #11895: short paths not collected on Windows.""" short_path = tempfile.mkdtemp() if "~" not in short_path: # pragma: no cover if running_on_ci(): @@ -1832,3 +1832,28 @@ def test_pyargs_collection_tree(pytester: Pytester, monkeypatch: MonkeyPatch) -> ], consecutive=True, ) + + +def test_do_not_collect_symlink_siblings( + pytester: Pytester, tmp_path: Path, request: pytest.FixtureRequest +) -> None: + """ + Regression test for #12039: Do not collect from directories that are symlinks to other directories in the same path. + + The check for short paths under Windows via os.path.samefile, introduced in #11936, also finds the symlinked + directory created by tmp_path/tmpdir. + """ + # Use tmp_path because it creates a symlink with the name "current" next to the directory it creates. + symlink_path = tmp_path.parent / (tmp_path.name[:-1] + "current") + assert symlink_path.is_symlink() is True + + # Create test file. + tmp_path.joinpath("test_foo.py").write_text("def test(): pass", encoding="UTF-8") + + # Ensure we collect it only once if we pass the tmp_path. + result = pytester.runpytest(tmp_path, "-sv") + result.assert_outcomes(passed=1) + + # Ensure we collect it only once if we pass the symlinked directory. + result = pytester.runpytest(symlink_path, "-sv") + result.assert_outcomes(passed=1) From 5e2ee7175c145f84ff9882be9496abb56e6e56f2 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Sun, 3 Mar 2024 13:48:29 +0100 Subject: [PATCH 0524/1271] monkeypatch.delenv PYTHONBREAKPOINT in two tests that previously failed/skipped --- testing/test_debugging.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 02ad700a609..91a0be48108 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -1,5 +1,4 @@ # mypy: allow-untyped-defs -import os import sys from typing import List @@ -10,9 +9,6 @@ import pytest -_ENVIRON_PYTHONBREAKPOINT = os.environ.get("PYTHONBREAKPOINT", "") - - @pytest.fixture(autouse=True) def pdb_env(request): if "pytester" in request.fixturenames: @@ -959,7 +955,10 @@ def test_nothing(): pass result = pytester.runpytest_subprocess(*args) result.stdout.fnmatch_lines(["*1 passed in *"]) - def test_pdb_custom_cls(self, pytester: Pytester, custom_debugger_hook) -> None: + def test_pdb_custom_cls( + self, pytester: Pytester, custom_debugger_hook, monkeypatch: MonkeyPatch + ) -> None: + monkeypatch.delenv("PYTHONBREAKPOINT", raising=False) p1 = pytester.makepyfile( """ def test_nothing(): @@ -1003,11 +1002,10 @@ def test_nothing(): pass result = pytester.runpytest_subprocess(*args) result.stdout.fnmatch_lines(["*1 passed in *"]) - @pytest.mark.skipif( - not _ENVIRON_PYTHONBREAKPOINT == "", - reason="Requires breakpoint() default value", - ) - def test_sys_breakpoint_interception(self, pytester: Pytester) -> None: + def test_sys_breakpoint_interception( + self, pytester: Pytester, monkeypatch: MonkeyPatch + ) -> None: + monkeypatch.delenv("PYTHONBREAKPOINT", raising=False) p1 = pytester.makepyfile( """ def test_1(): From 82fe28dae4eec900123175cee87245f37b964e5c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:50:42 +0000 Subject: [PATCH 0525/1271] [automated] Update plugin list (#12049) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 238 +++++++++++++++++++++---------- 1 file changed, 163 insertions(+), 75 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index e02080eb262..fb3ff912cd7 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7,<9) ; extra == "pytest" + :pypi:`logot` Test whether your code is logging correctly 🪵 Feb 29, 2024 5 - Production/Stable pytest (>=7,<9) ; extra == "pytest" :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A @@ -108,7 +108,7 @@ This list contains 1397 plugins. :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Feb 09, 2024 4 - Beta pytest <9,>=7.0.0 - :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 12, 2024 N/A N/A + :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 25, 2024 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) @@ -149,6 +149,7 @@ This list contains 1397 plugins. :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A + :pypi:`pytest-better-parametrize` Better description of parametrized test cases Feb 26, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) @@ -181,7 +182,7 @@ This list contains 1397 plugins. :pypi:`pytest-bugzilla-notifier` A plugin that allows you to execute create, update, and read information from BugZilla bugs Jun 15, 2018 4 - Beta pytest (>=2.9.2) :pypi:`pytest-buildkite` Plugin for pytest that automatically publishes coverage and pytest report annotations to Buildkite. Jul 13, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-builtin-types` Nov 17, 2021 N/A pytest - :pypi:`pytest-bwrap` Run your tests in Bubblewrap sandboxes Oct 26, 2018 3 - Alpha N/A + :pypi:`pytest-bwrap` Run your tests in Bubblewrap sandboxes Feb 25, 2024 3 - Alpha N/A :pypi:`pytest-cache` pytest plugin with mechanisms for caching across test runs Jun 04, 2013 3 - Alpha N/A :pypi:`pytest-cache-assert` Cache assertion data to simplify regression testing of complex serializable data Aug 14, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-cagoule` Pytest plugin to only run tests affected by changes Jan 01, 2020 3 - Alpha N/A @@ -197,6 +198,7 @@ This list contains 1397 plugins. :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Feb 12, 2024 N/A N/A + :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A :pypi:`pytest-change-assert` 修改报错中文为英文 Oct 19, 2022 N/A N/A @@ -291,7 +293,7 @@ This list contains 1397 plugins. :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A :pypi:`pytest-cython` A plugin for testing Cython extension modules Feb 16, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest - :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 24, 2024 N/A pytest <8,>=6.0.1 + :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest @@ -373,6 +375,7 @@ This list contains 1397 plugins. :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) + :pypi:`pytest-docker-compose-v2` Manages Docker containers during your integration tests Feb 28, 2024 4 - Beta pytest<8,>=7.2.2 :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) :pypi:`pytest-docker-fixtures` pytest docker fixtures Nov 17, 2023 3 - Alpha N/A :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Feb 09, 2022 4 - Beta pytest @@ -389,6 +392,7 @@ This list contains 1397 plugins. :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) + :pypi:`pytest-doctest-mkdocstrings` Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) Mar 02, 2024 N/A pytest :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Dec 13, 2023 5 - Production/Stable 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 Dec 14, 2023 N/A N/A @@ -422,14 +426,14 @@ This list contains 1397 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. Feb 23, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Mar 01, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Mar 01, 2024 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) @@ -551,7 +555,7 @@ This list contains 1397 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Feb 18, 2024 5 - Production/Stable pytest >=6.2 + :pypi:`pytest-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-gee` The Python plugin for your GEE based packages. Feb 15, 2024 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) @@ -596,7 +600,7 @@ This list contains 1397 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Feb 24, 2024 3 - Alpha pytest ==7.4.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 01, 2024 3 - Alpha pytest ==8.0.2 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jan 06, 2024 N/A N/A @@ -619,7 +623,7 @@ This list contains 1397 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 13, 2024 3 - Alpha N/A + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 24, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-httpx` Send responses to httpx. Feb 21, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -650,6 +654,7 @@ This list contains 1397 plugins. :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Feb 20, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A + :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest :pypi:`pytest-insper` Pytest plugin for courses at Insper Feb 01, 2024 N/A pytest :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Feb 19, 2024 N/A pytest (>=7.2.0,<9.0.0) :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) @@ -659,7 +664,7 @@ This list contains 1397 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Feb 09, 2024 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jan 29, 2024 5 - Production/Stable pytest <7.2.0,>=6 + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Feb 28, 2024 5 - Production/Stable pytest <7.2.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A @@ -700,6 +705,7 @@ This list contains 1397 plugins. :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-kuunda` pytest plugin to help with test data setup for PySpark tests Feb 25, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-kwparametrize` Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks Jan 22, 2021 N/A pytest (>=6) :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. Aug 20, 2022 3 - Alpha pytest (>=3.6,<8) :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A @@ -712,6 +718,7 @@ This list contains 1397 plugins. :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A + :pypi:`pytest-leaping` Coming soon! Mar 02, 2024 N/A N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A @@ -753,7 +760,7 @@ This list contains 1397 plugins. :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A - :pypi:`pytest-matcher` Keep a ChangeLog Jan 15, 2024 5 - Production/Stable pytest + :pypi:`pytest-matcher` Keep a ChangeLog Feb 29, 2024 5 - Production/Stable pytest :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -780,6 +787,7 @@ This list contains 1397 plugins. :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Jan 04, 2024 N/A pytest >=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Feb 28, 2024 N/A pytest >=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Oct 19, 2023 5 - Production/Stable pytest >=5.0 @@ -792,6 +800,7 @@ This list contains 1397 plugins. :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest + :pypi:`pytest-modalt` Massively distributed pytest runs using modal.com Feb 27, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-modified-env` Pytest plugin to fail a test if it leaves modified \`os.environ\` afterwards. Jan 29, 2022 4 - Beta N/A :pypi:`pytest-modifyjunit` Utility for adding additional properties to junit xml for IDM QE Jan 10, 2019 N/A N/A :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest @@ -818,9 +827,9 @@ This list contains 1397 plugins. :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Jul 25, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Feb 29, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 - :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 25, 2023 N/A pytest>=7,<8 + :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 26, 2024 N/A pytest>=7,<9 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) @@ -848,7 +857,7 @@ This list contains 1397 plugins. :pypi:`pytest_notify` Get notifications when your tests ends Jul 05, 2017 N/A pytest>=3.0.0 :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A - :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Feb 13, 2024 5 - Production/Stable N/A + :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Feb 26, 2024 5 - Production/Stable N/A :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A @@ -923,9 +932,9 @@ This list contains 1397 plugins. :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Feb 02, 2024 N/A pytest (<9.0.0,>=6.2.4) - :pypi:`pytest-playwright-async` ASYNC Pytest plugin for Playwright Feb 06, 2024 N/A N/A + :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Feb 25, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A - :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Feb 24, 2024 N/A pytest (>=8.0.0,<9.0.0) + :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 02, 2024 N/A pytest (>=8.0.0,<9.0.0) :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A @@ -988,9 +997,10 @@ This list contains 1397 plugins. :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Jan 02, 2024 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) - :pypi:`pytest-pythonhashseed` Pytest plugin to set PYTHONHASHSEED env var. Feb 18, 2024 4 - Beta pytest>=3.0.0 + :pypi:`pytest-pythonhashseed` Pytest plugin to set PYTHONHASHSEED env var. Feb 25, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest + :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) :pypi:`pytest-qasync` Pytest support for qasync. Jul 12, 2021 4 - Beta pytest (>=5.4.0) @@ -1016,7 +1026,7 @@ This list contains 1397 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Feb 17, 2024 4 - Beta pytest >=7.4.3 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Mar 01, 2024 4 - Beta pytest >=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable 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 @@ -1030,7 +1040,7 @@ This list contains 1397 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 - :pypi:`pytest-regtest` "pytest plugin for snapshot regression testing" Jan 22, 2024 N/A pytest>7.2 + :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Feb 26, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A @@ -1043,15 +1053,15 @@ This list contains 1397 plugins. :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jan 11, 2024 5 - Production/Stable pytest :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A - :pypi:`pytest-reporter` Generate Pytest reports with templates Jul 22, 2021 4 - Beta pytest - :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Jun 05, 2023 4 - Beta N/A + :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest + :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Feb 28, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Feb 05, 2024 N/A pytest <8.0.0,>=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Mar 01, 2024 N/A pytest >=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) @@ -1072,7 +1082,7 @@ This list contains 1397 plugins. :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jul 10, 2023 5 - Production/Stable pytest - :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 + :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Feb 27, 2024 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A @@ -1088,7 +1098,7 @@ This list contains 1397 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Feb 22, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Feb 27, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1112,7 +1122,7 @@ This list contains 1397 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 01, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1121,7 +1131,7 @@ This list contains 1397 plugins. :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 Feb 01, 2024 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. Feb 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 01, 2024 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 @@ -1264,7 +1274,7 @@ This list contains 1397 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 23, 2023 4 - Beta pytest <8,>=5 + :pypi:`pytest-testmon` selects tests affected by changed files and methods Feb 27, 2024 4 - Beta pytest <9,>=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) @@ -1280,6 +1290,7 @@ This list contains 1397 plugins. :pypi:`pytest-testrail-ns` pytest plugin for creating TestRail runs and adding results Aug 12, 2022 N/A N/A :pypi:`pytest-testrail-plugin` PyTest plugin for TestRail Apr 21, 2020 3 - Alpha pytest :pypi:`pytest-testrail-reporter` Sep 10, 2018 N/A N/A + :pypi:`pytest-testrail-results` A pytest plugin to upload results to TestRail. Mar 01, 2024 N/A pytest >=7.2.0 :pypi:`pytest-testreport` Dec 01, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-testreport-new` Oct 07, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) @@ -1444,7 +1455,7 @@ This list contains 1397 plugins. Simple but powerful assertion and verification of logged lines. :pypi:`logot` - *last release*: Feb 19, 2024, + *last release*: Feb 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest (>=7,<9) ; extra == "pytest" @@ -1955,7 +1966,7 @@ This list contains 1397 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-cooperative` - *last release*: Feb 12, 2024, + *last release*: Feb 25, 2024, *status*: N/A, *requires*: N/A @@ -2241,6 +2252,13 @@ This list contains 1397 plugins. A small example package + :pypi:`pytest-better-parametrize` + *last release*: Feb 26, 2024, + *status*: 4 - Beta, + *requires*: pytest >=6.2.0 + + Better description of parametrized test cases + :pypi:`pytest-bg-process` *last release*: Jan 24, 2022, *status*: 4 - Beta, @@ -2466,7 +2484,7 @@ This list contains 1397 plugins. :pypi:`pytest-bwrap` - *last release*: Oct 26, 2018, + *last release*: Feb 25, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -2577,6 +2595,13 @@ This list contains 1397 plugins. pytest-celery a shim pytest plugin to enable celery.contrib.pytest + :pypi:`pytest-cfg-fetcher` + *last release*: Feb 26, 2024, + *status*: N/A, + *requires*: N/A + + Pass config options to your unit tests. + :pypi:`pytest-chainmaker` *last release*: Oct 15, 2021, *status*: N/A, @@ -3236,9 +3261,9 @@ This list contains 1397 plugins. :pypi:`pytest-darker` - *last release*: Feb 24, 2024, + *last release*: Feb 25, 2024, *status*: N/A, - *requires*: pytest <8,>=6.0.1 + *requires*: pytest <7,>=6.0.1 A pytest plugin for checking of modified code using Darker @@ -3809,6 +3834,13 @@ This list contains 1397 plugins. Manages Docker containers during your integration tests + :pypi:`pytest-docker-compose-v2` + *last release*: Feb 28, 2024, + *status*: 4 - Beta, + *requires*: pytest<8,>=7.2.2 + + Manages Docker containers during your integration tests + :pypi:`pytest-docker-db` *last release*: Mar 20, 2021, *status*: 5 - Production/Stable, @@ -3921,6 +3953,13 @@ This list contains 1397 plugins. A simple pytest plugin to import names and add them to the doctest namespace. + :pypi:`pytest-doctest-mkdocstrings` + *last release*: Mar 02, 2024, + *status*: N/A, + *requires*: pytest + + Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) + :pypi:`pytest-doctestplus` *last release*: Dec 13, 2023, *status*: 5 - Production/Stable, @@ -4153,56 +4192,56 @@ This list contains 1397 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5056,7 +5095,7 @@ This list contains 1397 plugins. Uses gcov to measure test coverage of a C library :pypi:`pytest-gcs` - *last release*: Feb 18, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=6.2 @@ -5371,9 +5410,9 @@ This list contains 1397 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 24, 2024, + *last release*: Mar 01, 2024, *status*: 3 - Alpha, - *requires*: pytest ==7.4.4 + *requires*: pytest ==8.0.2 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -5532,7 +5571,7 @@ This list contains 1397 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest_httpserver` - *last release*: Feb 13, 2024, + *last release*: Feb 24, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -5748,6 +5787,13 @@ This list contains 1397 plugins. A simple image diff plugin for pytest + :pypi:`pytest-in-robotframework` + *last release*: Mar 02, 2024, + *status*: N/A, + *requires*: pytest + + The extension enables easy execution of pytest tests within the Robot Framework environment. + :pypi:`pytest-insper` *last release*: Feb 01, 2024, *status*: N/A, @@ -5812,7 +5858,7 @@ This list contains 1397 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Jan 29, 2024, + *last release*: Feb 28, 2024, *status*: 5 - Production/Stable, *requires*: pytest <7.2.0,>=6 @@ -6098,6 +6144,13 @@ This list contains 1397 plugins. + :pypi:`pytest-kuunda` + *last release*: Feb 25, 2024, + *status*: 4 - Beta, + *requires*: pytest >=6.2.0 + + pytest plugin to help with test data setup for PySpark tests + :pypi:`pytest-kwparametrize` *last release*: Jan 22, 2021, *status*: N/A, @@ -6182,6 +6235,13 @@ This list contains 1397 plugins. A pytest plugin to trace resource leaks. + :pypi:`pytest-leaping` + *last release*: Mar 02, 2024, + *status*: N/A, + *requires*: N/A + + Coming soon! + :pypi:`pytest-level` *last release*: Oct 21, 2019, *status*: N/A, @@ -6470,7 +6530,7 @@ This list contains 1397 plugins. UNKNOWN :pypi:`pytest-matcher` - *last release*: Jan 15, 2024, + *last release*: Feb 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -6658,6 +6718,13 @@ This list contains 1397 plugins. Pytest plugin that creates missing fixtures + :pypi:`pytest-mitmproxy` + *last release*: Feb 28, 2024, + *status*: N/A, + *requires*: pytest >=7.0 + + pytest plugin for mitmproxy tests + :pypi:`pytest-ml` *last release*: May 04, 2019, *status*: 4 - Beta, @@ -6742,6 +6809,13 @@ This list contains 1397 plugins. A pytest plugin for testing TCP clients + :pypi:`pytest-modalt` + *last release*: Feb 27, 2024, + *status*: 4 - Beta, + *requires*: pytest >=6.2.0 + + Massively distributed pytest runs using modal.com + :pypi:`pytest-modified-env` *last release*: Jan 29, 2022, *status*: 4 - Beta, @@ -6925,9 +6999,9 @@ This list contains 1397 plugins. Mypy static type checker plugin for Pytest :pypi:`pytest-mypy-plugins` - *last release*: Jul 25, 2023, + *last release*: Feb 29, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 pytest plugin for writing tests for mypy plugins @@ -6939,9 +7013,9 @@ This list contains 1397 plugins. Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. :pypi:`pytest-mypy-testing` - *last release*: Feb 25, 2023, + *last release*: Feb 26, 2024, *status*: N/A, - *requires*: pytest>=7,<8 + *requires*: pytest>=7,<9 Pytest plugin to check mypy output. @@ -7135,7 +7209,7 @@ This list contains 1397 plugins. A PyTest Reporter to send test runs to Notion.so :pypi:`pytest-nunit` - *last release*: Feb 13, 2024, + *last release*: Feb 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -7659,8 +7733,8 @@ This list contains 1397 plugins. A pytest wrapper with fixtures for Playwright to automate web browsers - :pypi:`pytest-playwright-async` - *last release*: Feb 06, 2024, + :pypi:`pytest_playwright_async` + *last release*: Feb 25, 2024, *status*: N/A, *requires*: N/A @@ -7674,7 +7748,7 @@ This list contains 1397 plugins. :pypi:`pytest-playwright-enhanced` - *last release*: Feb 24, 2024, + *last release*: Mar 02, 2024, *status*: N/A, *requires*: pytest (>=8.0.0,<9.0.0) @@ -8115,7 +8189,7 @@ This list contains 1397 plugins. Pytest plugin for interaction with TestRail :pypi:`pytest-pythonhashseed` - *last release*: Feb 18, 2024, + *last release*: Feb 25, 2024, *status*: 4 - Beta, *requires*: pytest>=3.0.0 @@ -8135,6 +8209,13 @@ This list contains 1397 plugins. pytest plugin for a better developer experience when working with the PyTorch test suite + :pypi:`pytest-pyvenv` + *last release*: Feb 27, 2024, + *status*: N/A, + *requires*: pytest ; extra == 'test' + + A package for create venv in tests + :pypi:`pytest-pyvista` *last release*: Sep 29, 2023, *status*: 4 - Beta, @@ -8311,7 +8392,7 @@ This list contains 1397 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-ranking` - *last release*: Feb 17, 2024, + *last release*: Mar 01, 2024, *status*: 4 - Beta, *requires*: pytest >=7.4.3 @@ -8409,11 +8490,11 @@ This list contains 1397 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Jan 22, 2024, + *last release*: Feb 26, 2024, *status*: N/A, *requires*: pytest>7.2 - "pytest plugin for snapshot regression testing" + pytest plugin for snapshot regression testing :pypi:`pytest-relative-order` *last release*: May 17, 2021, @@ -8500,14 +8581,14 @@ This list contains 1397 plugins. Creates json report that is compatible with atom.io's linter message format :pypi:`pytest-reporter` - *last release*: Jul 22, 2021, + *last release*: Feb 28, 2024, *status*: 4 - Beta, *requires*: pytest Generate Pytest reports with templates :pypi:`pytest-reporter-html1` - *last release*: Jun 05, 2023, + *last release*: Feb 28, 2024, *status*: 4 - Beta, *requires*: N/A @@ -8556,9 +8637,9 @@ This list contains 1397 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Feb 05, 2024, + *last release*: Mar 01, 2024, *status*: N/A, - *requires*: pytest <8.0.0,>=3.8.0 + *requires*: pytest >=3.8.0 Agent for Reporting results of tests to the Report Portal @@ -8703,7 +8784,7 @@ This list contains 1397 plugins. Pytest plugin to restrict the test types allowed :pypi:`pytest-result-log` - *last release*: Jan 10, 2024, + *last release*: Feb 27, 2024, *status*: N/A, *requires*: pytest>=7.2.0 @@ -8815,7 +8896,7 @@ This list contains 1397 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Feb 22, 2024, + *last release*: Feb 27, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -8983,7 +9064,7 @@ This list contains 1397 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9046,7 +9127,7 @@ This list contains 1397 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Feb 23, 2024, + *last release*: Mar 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10047,9 +10128,9 @@ This list contains 1397 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: Nov 23, 2023, + *last release*: Feb 27, 2024, *status*: 4 - Beta, - *requires*: pytest <8,>=5 + *requires*: pytest <9,>=5 selects tests affected by changed files and methods @@ -10158,6 +10239,13 @@ This list contains 1397 plugins. + :pypi:`pytest-testrail-results` + *last release*: Mar 01, 2024, + *status*: N/A, + *requires*: pytest >=7.2.0 + + A pytest plugin to upload results to TestRail. + :pypi:`pytest-testreport` *last release*: Dec 01, 2022, *status*: 4 - Beta, From e410705561673380d535a2ae32a4be42e115cf2c Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 3 Mar 2024 23:25:09 +0200 Subject: [PATCH 0526/1271] Cherry-pick 8.1.0 release notes (cherry picked from commit 0a536810dc5f51dac99bdb90dde06704b5aa034e) --- changelog/10865.improvement.rst | 3 - changelog/11311.improvement.rst | 4 -- changelog/11475.feature.rst | 3 - changelog/11475.improvement.rst | 3 - changelog/11653.feature.rst | 2 - changelog/11785.trivial.rst | 7 --- changelog/11790.doc.rst | 1 - changelog/11801.improvement.rst | 2 - changelog/11850.improvement.rst | 1 - changelog/11904.bugfix.rst | 3 - changelog/11962.improvement.rst | 1 - changelog/11978.improvement.rst | 3 - changelog/12011.bugfix.rst | 1 - changelog/12014.bugfix.rst | 1 - changelog/12039.bugfix.rst | 1 - changelog/12047.improvement.rst | 2 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.1.0.rst | 54 +++++++++++++++++ doc/en/builtin.rst | 28 ++++----- doc/en/changelog.rst | 92 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +- doc/en/example/pythoncollection.rst | 4 +- doc/en/example/reportingdemo.rst | 4 +- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/reference/reference.rst | 12 ++++ 26 files changed, 182 insertions(+), 61 deletions(-) delete mode 100644 changelog/10865.improvement.rst delete mode 100644 changelog/11311.improvement.rst delete mode 100644 changelog/11475.feature.rst delete mode 100644 changelog/11475.improvement.rst delete mode 100644 changelog/11653.feature.rst delete mode 100644 changelog/11785.trivial.rst delete mode 100644 changelog/11790.doc.rst delete mode 100644 changelog/11801.improvement.rst delete mode 100644 changelog/11850.improvement.rst delete mode 100644 changelog/11904.bugfix.rst delete mode 100644 changelog/11962.improvement.rst delete mode 100644 changelog/11978.improvement.rst delete mode 100644 changelog/12011.bugfix.rst delete mode 100644 changelog/12014.bugfix.rst delete mode 100644 changelog/12039.bugfix.rst delete mode 100644 changelog/12047.improvement.rst create mode 100644 doc/en/announce/release-8.1.0.rst diff --git a/changelog/10865.improvement.rst b/changelog/10865.improvement.rst deleted file mode 100644 index a5ced8e9ae3..00000000000 --- a/changelog/10865.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -:func:`pytest.warns` now validates that :func:`warnings.warn` was called with a `str` or a `Warning`. -Currently in Python it is possible to use other types, however this causes an exception when :func:`warnings.filterwarnings` is used to filter those warnings (see `CPython #103577 `__ for a discussion). -While this can be considered a bug in CPython, we decided to put guards in pytest as the error message produced without this check in place is confusing. diff --git a/changelog/11311.improvement.rst b/changelog/11311.improvement.rst deleted file mode 100644 index 0072f39743a..00000000000 --- a/changelog/11311.improvement.rst +++ /dev/null @@ -1,4 +0,0 @@ -When using ``--override-ini`` for paths in invocations without a configuration file defined, the current working directory is used -as the relative directory. - -Previoulsy this would raise an :class:`AssertionError`. diff --git a/changelog/11475.feature.rst b/changelog/11475.feature.rst deleted file mode 100644 index 42550235d80..00000000000 --- a/changelog/11475.feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added the new :confval:`consider_namespace_packages` configuration option, defaulting to ``False``. - -If set to ``True``, pytest will attempt to identify modules that are part of `namespace packages `__ when importing modules. diff --git a/changelog/11475.improvement.rst b/changelog/11475.improvement.rst deleted file mode 100644 index 4f6a4bffaad..00000000000 --- a/changelog/11475.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -:ref:`--import-mode=importlib ` now tries to import modules using the standard import mechanism (but still without changing :py:data:`sys.path`), falling back to importing modules directly only if that fails. - -This means that installed packages will be imported under their canonical name if possible first, for example ``app.core.models``, instead of having the module name always be derived from their path (for example ``.env310.lib.site_packages.app.core.models``). diff --git a/changelog/11653.feature.rst b/changelog/11653.feature.rst deleted file mode 100644 index f165c3f8e20..00000000000 --- a/changelog/11653.feature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added the new :confval:`verbosity_test_cases` configuration option for fine-grained control of test execution verbosity. -See :ref:`Fine-grained verbosity ` for more details. diff --git a/changelog/11785.trivial.rst b/changelog/11785.trivial.rst deleted file mode 100644 index b6b74d0dad2..00000000000 --- a/changelog/11785.trivial.rst +++ /dev/null @@ -1,7 +0,0 @@ -Some changes were made to private functions which may affect plugins which access them: - -- ``FixtureManager._getautousenames()`` now takes a ``Node`` itself instead of the nodeid. -- ``FixtureManager.getfixturedefs()`` now takes the ``Node`` itself instead of the nodeid. -- The ``_pytest.nodes.iterparentnodeids()`` function is removed without replacement. - Prefer to traverse the node hierarchy itself instead. - If you really need to, copy the function from the previous pytest release. diff --git a/changelog/11790.doc.rst b/changelog/11790.doc.rst deleted file mode 100644 index 648b20b96af..00000000000 --- a/changelog/11790.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Documented the retention of temporary directories created using the ``tmp_path`` fixture in more detail. diff --git a/changelog/11801.improvement.rst b/changelog/11801.improvement.rst deleted file mode 100644 index d9e5f848328..00000000000 --- a/changelog/11801.improvement.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added the :func:`iter_parents() <_pytest.nodes.Node.iter_parents>` helper method on nodes. -It is similar to :func:`listchain <_pytest.nodes.Node.listchain>`, but goes from bottom to top, and returns an iterator, not a list. diff --git a/changelog/11850.improvement.rst b/changelog/11850.improvement.rst deleted file mode 100644 index 87fc0953c19..00000000000 --- a/changelog/11850.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added support for :data:`sys.last_exc` for post-mortem debugging on Python>=3.12. diff --git a/changelog/11904.bugfix.rst b/changelog/11904.bugfix.rst deleted file mode 100644 index 2aed9bcb059..00000000000 --- a/changelog/11904.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a regression in pytest 8.0.0 that would cause test collection to fail due to permission errors when using ``--pyargs``. - -This change improves the collection tree for tests specified using ``--pyargs``, see :pull:`12043` for a comparison with pytest 8.0 and <8. diff --git a/changelog/11962.improvement.rst b/changelog/11962.improvement.rst deleted file mode 100644 index 453b99d33d7..00000000000 --- a/changelog/11962.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -In case no other suitable candidates for configuration file are found, a ``pyproject.toml`` (even without a ``[tool.pytest.ini_options]`` table) will be considered as the configuration file and define the ``rootdir``. diff --git a/changelog/11978.improvement.rst b/changelog/11978.improvement.rst deleted file mode 100644 index 1f1143dacf0..00000000000 --- a/changelog/11978.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add ``--log-file-mode`` option to the logging plugin, enabling appending to log-files. This option accepts either ``"w"`` or ``"a"`` and defaults to ``"w"``. - -Previously, the mode was hard-coded to be ``"w"`` which truncates the file before logging. diff --git a/changelog/12011.bugfix.rst b/changelog/12011.bugfix.rst deleted file mode 100644 index 5b755ade335..00000000000 --- a/changelog/12011.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a regression in 8.0.1 whereby ``setup_module`` xunit-style fixtures are not executed when ``--doctest-modules`` is passed. diff --git a/changelog/12014.bugfix.rst b/changelog/12014.bugfix.rst deleted file mode 100644 index 344bf8b7e03..00000000000 --- a/changelog/12014.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix the ``stacklevel`` used when warning about marks used on fixtures. diff --git a/changelog/12039.bugfix.rst b/changelog/12039.bugfix.rst deleted file mode 100644 index 267eae6b8b2..00000000000 --- a/changelog/12039.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a regression in ``8.0.2`` where tests created using :fixture:`tmp_path` have been collected multiple times in CI under Windows. diff --git a/changelog/12047.improvement.rst b/changelog/12047.improvement.rst deleted file mode 100644 index e9ad5eddcab..00000000000 --- a/changelog/12047.improvement.rst +++ /dev/null @@ -1,2 +0,0 @@ -When multiple finalizers of a fixture raise an exception, now all exceptions are reported as an exception group. -Previously, only the first exception was reported. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 5374e8c7596..68cae83d773 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.1.0 release-8.0.2 release-8.0.1 release-8.0.0 diff --git a/doc/en/announce/release-8.1.0.rst b/doc/en/announce/release-8.1.0.rst new file mode 100644 index 00000000000..62cafdd78bb --- /dev/null +++ b/doc/en/announce/release-8.1.0.rst @@ -0,0 +1,54 @@ +pytest-8.1.0 +======================================= + +The pytest team is proud to announce the 8.1.0 release! + +This release contains new features, improvements, and bug fixes, +the full list of changes is available in the changelog: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Ben Brown +* Ben Leith +* Bruno Oliveira +* Clément Robert +* Dave Hall +* Dương Quốc Khánh +* Eero Vaher +* Eric Larson +* Fabian Sturm +* Faisal Fawad +* Florian Bruhin +* Franck Charras +* Joachim B Haga +* John Litborn +* Loïc Estève +* Marc Bresson +* Patrick Lannigan +* Pierre Sassoulas +* Ran Benita +* Reagan Lee +* Ronny Pfannschmidt +* Russell Martin +* clee2000 +* donghui +* faph +* jakkdl +* mrbean-bremen +* robotherapist +* whysage +* woutdenolf + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index e9e42b9e8ca..1e1210648eb 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1007 + capsysbinary -- .../_pytest/capture.py:1008 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -50,7 +50,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1034 + capfd -- .../_pytest/capture.py:1035 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -67,7 +67,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1061 + capfdbinary -- .../_pytest/capture.py:1062 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -84,7 +84,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - capsys -- .../_pytest/capture.py:980 + capsys -- .../_pytest/capture.py:981 Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsys.readouterr()`` method @@ -101,7 +101,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:745 + doctest_namespace [session scope] -- .../_pytest/doctest.py:737 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -115,7 +115,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1354 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1346 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -170,18 +170,18 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a `pytest-xdist `__ plugin. See :issue:`7767` for details. - tmpdir_factory [session scope] -- .../_pytest/legacypath.py:302 + tmpdir_factory [session scope] -- .../_pytest/legacypath.py:317 Return a :class:`pytest.TempdirFactory` instance for the test session. - tmpdir -- .../_pytest/legacypath.py:309 + tmpdir -- .../_pytest/legacypath.py:324 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. By default, a new base temporary directory is created each test session, and old bases are removed after 3 sessions, to aid in debugging. If - ``--basetemp`` is used then it is cleared each session. See :ref:`base - temporary directory`. + ``--basetemp`` is used then it is cleared each session. See + :ref:`temporary directory location and retention`. The returned object is a `legacy_path`_ object. @@ -192,7 +192,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:594 + caplog -- .../_pytest/logging.py:601 Access and control log capturing. Captured logs are available through the following properties/methods:: @@ -227,7 +227,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a To undo modifications done by the fixture in a contained scope, use :meth:`context() `. - recwarn -- .../_pytest/recwarn.py:32 + recwarn -- .../_pytest/recwarn.py:31 Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information @@ -245,8 +245,8 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a and old bases are removed after 3 sessions, to aid in debugging. This behavior can be configured with :confval:`tmp_path_retention_count` and :confval:`tmp_path_retention_policy`. - If ``--basetemp`` is used then it is cleared each session. See :ref:`base - temporary directory`. + If ``--basetemp`` is used then it is cleared each session. See + :ref:`temporary directory location and retention`. The returned object is a :class:`pathlib.Path` object. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index bdf5a155031..1c2ef95f5d9 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,98 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.1.0 (2024-03-03) +========================= + +Features +-------- + +- `#11475 `_: Added the new :confval:`consider_namespace_packages` configuration option, defaulting to ``False``. + + If set to ``True``, pytest will attempt to identify modules that are part of `namespace packages `__ when importing modules. + + +- `#11653 `_: Added the new :confval:`verbosity_test_cases` configuration option for fine-grained control of test execution verbosity. + See :ref:`Fine-grained verbosity ` for more details. + + + +Improvements +------------ + +- `#10865 `_: :func:`pytest.warns` now validates that :func:`warnings.warn` was called with a `str` or a `Warning`. + Currently in Python it is possible to use other types, however this causes an exception when :func:`warnings.filterwarnings` is used to filter those warnings (see `CPython #103577 `__ for a discussion). + While this can be considered a bug in CPython, we decided to put guards in pytest as the error message produced without this check in place is confusing. + + +- `#11311 `_: When using ``--override-ini`` for paths in invocations without a configuration file defined, the current working directory is used + as the relative directory. + + Previoulsy this would raise an :class:`AssertionError`. + + +- `#11475 `_: :ref:`--import-mode=importlib ` now tries to import modules using the standard import mechanism (but still without changing :py:data:`sys.path`), falling back to importing modules directly only if that fails. + + This means that installed packages will be imported under their canonical name if possible first, for example ``app.core.models``, instead of having the module name always be derived from their path (for example ``.env310.lib.site_packages.app.core.models``). + + +- `#11801 `_: Added the :func:`iter_parents() <_pytest.nodes.Node.iter_parents>` helper method on nodes. + It is similar to :func:`listchain <_pytest.nodes.Node.listchain>`, but goes from bottom to top, and returns an iterator, not a list. + + +- `#11850 `_: Added support for :data:`sys.last_exc` for post-mortem debugging on Python>=3.12. + + +- `#11962 `_: In case no other suitable candidates for configuration file are found, a ``pyproject.toml`` (even without a ``[tool.pytest.ini_options]`` table) will be considered as the configuration file and define the ``rootdir``. + + +- `#11978 `_: Add ``--log-file-mode`` option to the logging plugin, enabling appending to log-files. This option accepts either ``"w"`` or ``"a"`` and defaults to ``"w"``. + + Previously, the mode was hard-coded to be ``"w"`` which truncates the file before logging. + + +- `#12047 `_: When multiple finalizers of a fixture raise an exception, now all exceptions are reported as an exception group. + Previously, only the first exception was reported. + + + +Bug Fixes +--------- + +- `#11904 `_: Fixed a regression in pytest 8.0.0 that would cause test collection to fail due to permission errors when using ``--pyargs``. + + This change improves the collection tree for tests specified using ``--pyargs``, see :pull:`12043` for a comparison with pytest 8.0 and <8. + + +- `#12011 `_: Fixed a regression in 8.0.1 whereby ``setup_module`` xunit-style fixtures are not executed when ``--doctest-modules`` is passed. + + +- `#12014 `_: Fix the ``stacklevel`` used when warning about marks used on fixtures. + + +- `#12039 `_: Fixed a regression in ``8.0.2`` where tests created using :fixture:`tmp_path` have been collected multiple times in CI under Windows. + + + +Improved Documentation +---------------------- + +- `#11790 `_: Documented the retention of temporary directories created using the ``tmp_path`` fixture in more detail. + + + +Trivial/Internal Changes +------------------------ + +- `#11785 `_: Some changes were made to private functions which may affect plugins which access them: + + - ``FixtureManager._getautousenames()`` now takes a ``Node`` itself instead of the nodeid. + - ``FixtureManager.getfixturedefs()`` now takes the ``Node`` itself instead of the nodeid. + - The ``_pytest.nodes.iterparentnodeids()`` function is removed without replacement. + Prefer to traverse the node hierarchy itself instead. + If you really need to, copy the function from the previous pytest release. + + pytest 8.0.2 (2024-02-24) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index c6ac6489979..85c6836792f 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 7207ca2ae63..6822aa68ea7 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 2e8d4824c3c..2c34cc2b00d 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -445,7 +445,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: self = def test_tupleerror(self): - > a, b = [1] # NOQA + > a, b = [1] # noqa: F841 E ValueError: not enough values to unpack (expected 2, got 1) failure_demo.py:175: ValueError @@ -467,7 +467,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: self = def test_some_error(self): - > if namenotexi: # NOQA + > if namenotexi: # noqa: F821 E NameError: name 'namenotexi' is not defined failure_demo.py:183: NameError diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index f1919886495..89381c8c76f 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.0.2 + pytest 8.1.0 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 329c568c00b..c32de161002 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index f84b7ea4847..358f371e5e9 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2103,6 +2103,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: --log-cli-date-format=LOG_CLI_DATE_FORMAT Log date format used by the logging module --log-file=LOG_FILE Path to a file when logging will be written to + --log-file-mode={w,a} + Log file open mode --log-file-level=LOG_FILE_LEVEL Log file logging level --log-file-format=LOG_FILE_FORMAT @@ -2128,6 +2130,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings. + consider_namespace_packages (bool): + Consider namespace packages when resolving module + names during import usefixtures (args): List of default fixtures to be used with this project python_files (args): Glob-style file patterns for Python test module @@ -2146,6 +2151,11 @@ All the command-line flags can be obtained by running ``pytest --help``:: progress information ("progress" (percentage) | "count" | "progress-even-when-capture-no" (forces progress even when capture=no) + verbosity_test_cases (string): + Specify a verbosity level for test case execution, + overriding the main level. Higher levels will + provide more detailed information about each test + case executed. xfail_strict (bool): Default for the strict parameter of xfail markers when not given explicitly (default: False) tmp_path_retention_count (string): @@ -2193,6 +2203,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: log_cli_date_format (string): Default value for --log-cli-date-format log_file (string): Default value for --log-file + log_file_mode (string): + Default value for --log-file-mode log_file_level (string): Default value for --log-file-level log_file_format (string): From 23bdc643c9bd5ced8f09024f8c5882f078647f93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 03:25:34 +0000 Subject: [PATCH 0527/1271] build(deps): Bump twisted in /testing/plugins_integration Bumps [twisted](https://github.com/twisted/twisted) from 23.10.0 to 24.3.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-23.10.0...twisted-24.3.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 42ab2af997b..d2f3fad17d5 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -13,5 +13,5 @@ pytest-rerunfailures==13.0 pytest-sugar==1.0.0 pytest-trio==0.7.0 pytest-twisted==1.14.0 -twisted==23.10.0 +twisted==24.3.0 pytest-xvfb==3.0.0 From 13558b9f5398595b36ca4b400bbfd57fb839684c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 03:47:21 +0000 Subject: [PATCH 0528/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.8.11 to 1.8.12 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.11 to 1.8.12. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.11...v1.8.12) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0d48982d601..d46f1f91d34 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -47,7 +47,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.8.11 + uses: pypa/gh-action-pypi-publish@v1.8.12 - name: Push tag run: | From 37b340109130c679cddcf2bc3eb1e813827d6acb Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 4 Mar 2024 12:59:54 +0100 Subject: [PATCH 0529/1271] add myself to tidelift --- TIDELIFT.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TIDELIFT.rst b/TIDELIFT.rst index 6c7ad917745..1ba246bd868 100644 --- a/TIDELIFT.rst +++ b/TIDELIFT.rst @@ -25,6 +25,7 @@ The current list of contributors receiving funding are: * `@nicoddemus`_ * `@The-Compiler`_ +* `@RonnyPfannschmidt`_ Contributors interested in receiving a part of the funds just need to submit a PR adding their name to the list. Contributors that want to stop receiving the funds should also submit a PR @@ -56,3 +57,4 @@ funds. Just drop a line to one of the `@pytest-dev/tidelift-admins`_ or use the .. _`@nicoddemus`: https://github.com/nicoddemus .. _`@The-Compiler`: https://github.com/The-Compiler +.. _`@RonnyPfannschmidt`: https://github.com/RonnyPfannschmidt From 6ee02a3e6ca184288bd8fbe5f6d2e76e09facb9c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 4 Mar 2024 12:17:36 -0300 Subject: [PATCH 0530/1271] Yank version 8.1.0 Related to #12069 --- doc/en/changelog.rst | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 1c2ef95f5d9..3442305943f 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,8 +28,16 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start -pytest 8.1.0 (2024-03-03) -========================= +pytest 8.1.0 (YANKED) +===================== + + +.. note:: + + This release has been **yanked**: it broke some plugins without the proper warning period, due to + some warnings not showing up as expected. + + See `#12069 `__. Features -------- From 03e54712dd123138aa4c1035a027e17d0dd9a86c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 4 Mar 2024 12:44:56 -0300 Subject: [PATCH 0531/1271] Do not import duplicated modules with --importmode=importlib (#12074) Regression brought up by #11475. --- changelog/11475.bugfix.rst | 1 + src/_pytest/pathlib.py | 4 +++ testing/test_pathlib.py | 71 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 changelog/11475.bugfix.rst diff --git a/changelog/11475.bugfix.rst b/changelog/11475.bugfix.rst new file mode 100644 index 00000000000..bef8f4f76d3 --- /dev/null +++ b/changelog/11475.bugfix.rst @@ -0,0 +1 @@ +Fixed regression where ``--importmode=importlib`` would import non-test modules more than once. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index a19e89aa116..e39f4772326 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -539,6 +539,10 @@ def import_path( except CouldNotResolvePathError: pass else: + # If the given module name is already in sys.modules, do not import it again. + with contextlib.suppress(KeyError): + return sys.modules[module_name] + mod = _import_module_using_spec( module_name, path, pkg_root, insert_modules=False ) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 357860563a8..a4bccb1b2ac 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -587,6 +587,12 @@ class Data: assert data.value == "foo" assert data.__module__ == "_src.tests.test_dataclass" + # Ensure we do not import the same module again (#11475). + module2 = import_path( + fn, mode="importlib", root=tmp_path, consider_namespace_packages=ns_param + ) + assert module is module2 + def test_importmode_importlib_with_pickle( self, tmp_path: Path, ns_param: bool ) -> None: @@ -616,6 +622,12 @@ def round_trip(): action = round_trip() assert action() == 42 + # Ensure we do not import the same module again (#11475). + module2 = import_path( + fn, mode="importlib", root=tmp_path, consider_namespace_packages=ns_param + ) + assert module is module2 + def test_importmode_importlib_with_pickle_separate_modules( self, tmp_path: Path, ns_param: bool ) -> None: @@ -816,6 +828,14 @@ def __init__(self) -> None: consider_namespace_packages=ns_param, ) assert len(mod.instance.INSTANCES) == 1 + # Ensure we do not import the same module again (#11475). + mod2 = import_path( + init, + root=tmp_path, + mode=ImportMode.importlib, + consider_namespace_packages=ns_param, + ) + assert mod is mod2 def test_importlib_root_is_package(self, pytester: Pytester) -> None: """ @@ -942,6 +962,15 @@ def test_import_using_normal_mechanism_first( assert mod.__name__ == "app.core" assert mod.__file__ and Path(mod.__file__) == core_py + # Ensure we do not import the same module again (#11475). + mod2 = import_path( + core_py, + mode="importlib", + root=pytester.path, + consider_namespace_packages=ns_param, + ) + assert mod is mod2 + # tests are not reachable from sys.path, so they are imported as a standalone modules. # Instead of '.tests.a.test_core', we import as "_tests.a.test_core" because # importlib considers module names starting with '.' to be local imports. @@ -952,6 +981,16 @@ def test_import_using_normal_mechanism_first( consider_namespace_packages=ns_param, ) assert mod.__name__ == "_tests.a.test_core" + + # Ensure we do not import the same module again (#11475). + mod2 = import_path( + test_path1, + mode="importlib", + root=pytester.path, + consider_namespace_packages=ns_param, + ) + assert mod is mod2 + mod = import_path( test_path2, mode="importlib", @@ -960,6 +999,15 @@ def test_import_using_normal_mechanism_first( ) assert mod.__name__ == "_tests.b.test_core" + # Ensure we do not import the same module again (#11475). + mod2 = import_path( + test_path2, + mode="importlib", + root=pytester.path, + consider_namespace_packages=ns_param, + ) + assert mod is mod2 + def test_import_using_normal_mechanism_first_integration( self, monkeypatch: MonkeyPatch, pytester: Pytester, ns_param: bool ) -> None: @@ -1021,6 +1069,14 @@ def test_import_path_imports_correct_file( assert mod.__file__ and Path(mod.__file__) == x_in_sub_folder assert mod.X == "a/b/x" + mod2 = import_path( + x_in_sub_folder, + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=ns_param, + ) + assert mod is mod2 + # Attempt to import root 'x.py'. with pytest.raises(AssertionError, match="x at root"): _ = import_path( @@ -1124,6 +1180,12 @@ def test_resolve_pkg_root_and_module_name_ns_multiple_levels( assert mod.__name__ == "com.company.app.core.models" assert mod.__file__ == str(models_py) + # Ensure we do not import the same module again (#11475). + mod2 = import_path( + models_py, mode=import_mode, root=tmp_path, consider_namespace_packages=True + ) + assert mod is mod2 + pkg_root, module_name = resolve_pkg_root_and_module_name( algorithms_py, consider_namespace_packages=True ) @@ -1141,6 +1203,15 @@ def test_resolve_pkg_root_and_module_name_ns_multiple_levels( assert mod.__name__ == "com.company.calc.algo.algorithms" assert mod.__file__ == str(algorithms_py) + # Ensure we do not import the same module again (#11475). + mod2 = import_path( + algorithms_py, + mode=import_mode, + root=tmp_path, + consider_namespace_packages=True, + ) + assert mod is mod2 + @pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"]) def test_incorrect_namespace_package( self, From 86945f9a1f7cae10a9ac9ccf4b41ce9ddfabe14c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Mar 2024 19:12:19 -0300 Subject: [PATCH 0532/1271] Rename 'testing' extra to 'dev' (#12052) Minor, but seems `dev` is more standard for the development extras than `testing`, being the default for tools like `poetry`. --- CONTRIBUTING.rst | 4 ++-- pyproject.toml | 2 +- tox.ini | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 6f55c230c92..d7da59c812d 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -297,12 +297,12 @@ Here is a simple overview, with pytest-specific bits: When committing, ``pre-commit`` will re-format the files if necessary. #. If instead of using ``tox`` you prefer to run the tests directly, then we suggest to create a virtual environment and use - an editable install with the ``testing`` extra:: + an editable install with the ``dev`` extra:: $ python3 -m venv .venv $ source .venv/bin/activate # Linux $ .venv/Scripts/activate.bat # Windows - $ pip install -e ".[testing]" + $ pip install -e ".[dev]" Afterwards, you can edit the files and run pytest normally:: diff --git a/pyproject.toml b/pyproject.toml index 72988e23387..e14556f2ff0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,7 @@ dependencies = [ 'tomli>=1; python_version < "3.11"', ] [project.optional-dependencies] -testing = [ +dev = [ "argcomplete", "attrs>=19.2", "hypothesis>=3.56", diff --git a/tox.ini b/tox.ini index 0ac2ff2ddba..cb3ca4b8366 100644 --- a/tox.ini +++ b/tox.ini @@ -56,7 +56,7 @@ setenv = lsof: _PYTEST_TOX_POSARGS_LSOF=--lsof xdist: _PYTEST_TOX_POSARGS_XDIST=-n auto -extras = testing +extras = dev deps = doctesting: PyYAML exceptiongroup: exceptiongroup>=1.0.0rc8 From 303cd0d48a66bbeba7e2e3eaf4752c6ef4d38a2c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Mar 2024 19:19:14 -0300 Subject: [PATCH 0533/1271] Revert "Remove deprecated py.path (`fspath`) node constructor arguments" This reverts commit 6c89f9261c6f5bde93bd116ef56b7ac96fc0ef21. --- doc/en/conf.py | 1 + doc/en/deprecations.rst | 79 ++++++++++++++++++------------------ src/_pytest/compat.py | 17 ++++++++ src/_pytest/config/compat.py | 13 ++++++ src/_pytest/deprecated.py | 8 ++++ src/_pytest/legacypath.py | 20 ++------- src/_pytest/main.py | 1 + src/_pytest/nodes.py | 46 ++++++++++++++++++--- src/_pytest/python.py | 3 ++ testing/deprecated_test.py | 22 ++++++++++ testing/test_legacypath.py | 4 +- testing/test_nodes.py | 9 ++-- 12 files changed, 156 insertions(+), 67 deletions(-) create mode 100644 src/_pytest/config/compat.py diff --git a/doc/en/conf.py b/doc/en/conf.py index cf889eb7a86..8059c359fc1 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -200,6 +200,7 @@ ("py:class", "_tracing.TagTracerSub"), ("py:class", "warnings.WarningMessage"), # Undocumented type aliases + ("py:class", "LEGACY_PATH"), ("py:class", "_PluggyPlugin"), # TypeVars ("py:class", "_pytest._code.code.E"), diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index b9a59d7910f..b7ddd8b013f 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -19,6 +19,45 @@ Below is a complete list of all pytest features which are considered deprecated. :class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `. +.. _node-ctor-fspath-deprecation: + +``fspath`` argument for Node constructors replaced with ``pathlib.Path`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 + +In order to support the transition from ``py.path.local`` to :mod:`pathlib`, +the ``fspath`` argument to :class:`~_pytest.nodes.Node` constructors like +:func:`pytest.Function.from_parent()` and :func:`pytest.Class.from_parent()` +is now deprecated. + +Plugins which construct nodes should pass the ``path`` argument, of type +:class:`pathlib.Path`, instead of the ``fspath`` argument. + +Plugins which implement custom items and collectors are encouraged to replace +``fspath`` parameters (``py.path.local``) with ``path`` parameters +(``pathlib.Path``), and drop any other usage of the ``py`` library if possible. + +If possible, plugins with custom items should use :ref:`cooperative +constructors ` to avoid hardcoding +arguments they only pass on to the superclass. + +.. note:: + The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the + new attribute being ``path``) is **the opposite** of the situation for + hooks, :ref:`outlined below ` (the old + argument being ``path``). + + This is an unfortunate artifact due to historical reasons, which should be + resolved in future versions as we slowly get rid of the :pypi:`py` + dependency (see :issue:`9283` for a longer discussion). + +Due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo` +which still is expected to return a ``py.path.local`` object, nodes still have +both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes, +no matter what argument was used in the constructor. We expect to deprecate the +``fspath`` attribute in a future release. + .. _legacy-path-hooks-deprecated: Configuring hook specs/impls using markers @@ -208,46 +247,6 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. -.. _node-ctor-fspath-deprecation: - -``fspath`` argument for Node constructors replaced with ``pathlib.Path`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.0 - -In order to support the transition from ``py.path.local`` to :mod:`pathlib`, -the ``fspath`` argument to :class:`~_pytest.nodes.Node` constructors like -:func:`pytest.Function.from_parent()` and :func:`pytest.Class.from_parent()` -is now deprecated. - -Plugins which construct nodes should pass the ``path`` argument, of type -:class:`pathlib.Path`, instead of the ``fspath`` argument. - -Plugins which implement custom items and collectors are encouraged to replace -``fspath`` parameters (``py.path.local``) with ``path`` parameters -(``pathlib.Path``), and drop any other usage of the ``py`` library if possible. - -If possible, plugins with custom items should use :ref:`cooperative -constructors ` to avoid hardcoding -arguments they only pass on to the superclass. - -.. note:: - The name of the :class:`~_pytest.nodes.Node` arguments and attributes (the - new attribute being ``path``) is **the opposite** of the situation for - hooks, :ref:`outlined below ` (the old - argument being ``path``). - - This is an unfortunate artifact due to historical reasons, which should be - resolved in future versions as we slowly get rid of the :pypi:`py` - dependency (see :issue:`9283` for a longer discussion). - -Due to the ongoing migration of methods like :meth:`~pytest.Item.reportinfo` -which still is expected to return a ``py.path.local`` object, nodes still have -both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes, -no matter what argument was used in the constructor. We expect to deprecate the -``fspath`` attribute in a future release. - - ``py.path.local`` arguments for hooks replaced with ``pathlib.Path`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index fa387f6db12..121b1f9f64f 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Python version compatibility code.""" + from __future__ import annotations import dataclasses @@ -16,6 +17,22 @@ from typing import Final from typing import NoReturn +import py + + +#: constant to prepare valuing pylib path replacements/lazy proxies later on +# intended for removal in pytest 8.0 or 9.0 + +# fmt: off +# intentional space to create a fake difference for the verification +LEGACY_PATH = py.path. local +# fmt: on + + +def legacy_path(path: str | os.PathLike[str]) -> LEGACY_PATH: + """Internal wrapper to prepare lazy proxies for legacy_path instances""" + return LEGACY_PATH(path) + # fmt: off # Singleton type for NOTSET, as described in: diff --git a/src/_pytest/config/compat.py b/src/_pytest/config/compat.py new file mode 100644 index 00000000000..9c61b4dac09 --- /dev/null +++ b/src/_pytest/config/compat.py @@ -0,0 +1,13 @@ +from __future__ import annotations + +from pathlib import Path + +from ..compat import LEGACY_PATH + + +def _check_path(path: Path, fspath: LEGACY_PATH) -> None: + if Path(fspath) != path: + raise ValueError( + f"Path({fspath!r}) != {path!r}\n" + "if both path and fspath are given they need to be equal" + ) diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 56271c9578e..508ea1184f6 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -36,6 +36,14 @@ PRIVATE = PytestDeprecationWarning("A private pytest class or function was used.") +NODE_CTOR_FSPATH_ARG = UnformattedWarning( + PytestRemovedIn9Warning, + "The (fspath: py.path.local) argument to {node_type_name} is deprecated. " + "Please use the (path: pathlib.Path) argument instead.\n" + "See https://docs.pytest.org/en/latest/deprecations.html" + "#fspath-argument-for-node-constructors-replaced-with-pathlib-path", +) + HOOK_LEGACY_MARKING = UnformattedWarning( PytestDeprecationWarning, "The hook{type} {fullname} uses old-style configuration options (marks or attributes).\n" diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index b56f3a6fb63..b28c89767fe 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -1,7 +1,7 @@ # mypy: allow-untyped-defs """Add backward compatibility support for the legacy py path type.""" + import dataclasses -import os from pathlib import Path import shlex import subprocess @@ -14,9 +14,9 @@ from iniconfig import SectionWrapper -import py - from _pytest.cacheprovider import Cache +from _pytest.compat import LEGACY_PATH +from _pytest.compat import legacy_path from _pytest.config import Config from _pytest.config import hookimpl from _pytest.config import PytestPluginManager @@ -39,20 +39,6 @@ import pexpect -#: constant to prepare valuing pylib path replacements/lazy proxies later on -# intended for removal in pytest 8.0 or 9.0 - -# fmt: off -# intentional space to create a fake difference for the verification -LEGACY_PATH = py.path. local -# fmt: on - - -def legacy_path(path: Union[str, "os.PathLike[str]"]) -> LEGACY_PATH: - """Internal wrapper to prepare lazy proxies for legacy_path instances""" - return LEGACY_PATH(path) - - @final class Testdir: """ diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 1de86be868c..145722c25d3 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -557,6 +557,7 @@ def __init__(self, config: Config) -> None: super().__init__( name="", path=config.rootpath, + fspath=None, parent=None, config=config, session=self, diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 2381b65eaf9..cff15001c93 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -3,6 +3,7 @@ from functools import cached_property from inspect import signature import os +import pathlib from pathlib import Path from typing import Any from typing import Callable @@ -29,8 +30,11 @@ from _pytest._code.code import ExceptionInfo from _pytest._code.code import TerminalRepr from _pytest._code.code import Traceback +from _pytest.compat import LEGACY_PATH from _pytest.config import Config from _pytest.config import ConftestImportFailure +from _pytest.config.compat import _check_path +from _pytest.deprecated import NODE_CTOR_FSPATH_ARG from _pytest.mark.structures import Mark from _pytest.mark.structures import MarkDecorator from _pytest.mark.structures import NodeKeywords @@ -55,6 +59,29 @@ _T = TypeVar("_T") + + +def _imply_path( + node_type: Type["Node"], + path: Optional[Path], + fspath: Optional[LEGACY_PATH], +) -> Path: + if fspath is not None: + warnings.warn( + NODE_CTOR_FSPATH_ARG.format( + node_type_name=node_type.__name__, + ), + stacklevel=6, + ) + if path is not None: + if fspath is not None: + _check_path(path, fspath) + return path + else: + assert fspath is not None + return Path(fspath) + + _NodeType = TypeVar("_NodeType", bound="Node") @@ -110,6 +137,13 @@ class Node(abc.ABC, metaclass=NodeMeta): leaf nodes. """ + # Implemented in the legacypath plugin. + #: A ``LEGACY_PATH`` copy of the :attr:`path` attribute. Intended for usage + #: for methods not migrated to ``pathlib.Path`` yet, such as + #: :meth:`Item.reportinfo `. Will be deprecated in + #: a future release, prefer using :attr:`path` instead. + fspath: LEGACY_PATH + # Use __slots__ to make attribute access faster. # Note that __dict__ is still available. __slots__ = ( @@ -129,6 +163,7 @@ def __init__( parent: "Optional[Node]" = None, config: Optional[Config] = None, session: "Optional[Session]" = None, + fspath: Optional[LEGACY_PATH] = None, path: Optional[Path] = None, nodeid: Optional[str] = None, ) -> None: @@ -154,11 +189,10 @@ def __init__( raise TypeError("session or parent must be provided") self.session = parent.session - if path is None: + if path is None and fspath is None: path = getattr(parent, "path", None) - assert path is not None #: Filesystem path where this node was collected from (can be None). - self.path = path + self.path: pathlib.Path = _imply_path(type(self), path, fspath=fspath) # The explicit annotation is to avoid publicly exposing NodeKeywords. #: Keywords/markers collected from all scopes. @@ -529,6 +563,7 @@ class FSCollector(Collector, abc.ABC): def __init__( self, + fspath: Optional[LEGACY_PATH] = None, path_or_parent: Optional[Union[Path, Node]] = None, path: Optional[Path] = None, name: Optional[str] = None, @@ -544,8 +579,8 @@ def __init__( elif isinstance(path_or_parent, Path): assert path is None path = path_or_parent - assert path is not None + path = _imply_path(type(self), path, fspath=fspath) if name is None: name = path.name if parent is not None and parent.path != path: @@ -585,11 +620,12 @@ def from_parent( cls, parent, *, + fspath: Optional[LEGACY_PATH] = None, path: Optional[Path] = None, **kw, ) -> "Self": """The public constructor.""" - return super().from_parent(parent=parent, path=path, **kw) + return super().from_parent(parent=parent, fspath=fspath, path=path, **kw) class File(FSCollector, abc.ABC): diff --git a/src/_pytest/python.py b/src/_pytest/python.py index e1730b1a7e0..1bbe9600492 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -48,6 +48,7 @@ from _pytest.compat import getlocation from _pytest.compat import is_async_function from _pytest.compat import is_generator +from _pytest.compat import LEGACY_PATH from _pytest.compat import NOTSET from _pytest.compat import safe_getattr from _pytest.compat import safe_isclass @@ -665,6 +666,7 @@ class Package(nodes.Directory): def __init__( self, + fspath: Optional[LEGACY_PATH], parent: nodes.Collector, # NOTE: following args are unused: config=None, @@ -676,6 +678,7 @@ def __init__( # super().__init__(self, fspath, parent=parent) session = parent.session super().__init__( + fspath=fspath, path=path, parent=parent, config=config, diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index a5f51306358..6a230a9fdf5 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -1,5 +1,8 @@ # mypy: allow-untyped-defs +import re + from _pytest import deprecated +from _pytest.compat import legacy_path from _pytest.pytester import Pytester import pytest from pytest import PytestDeprecationWarning @@ -85,6 +88,25 @@ def __init__(self, foo: int, *, _ispytest: bool = False) -> None: PrivateInit(10, _ispytest=True) +def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: + mod = pytester.getmodulecol("") + + class MyFile(pytest.File): + def collect(self): + raise NotImplementedError() + + with pytest.warns( + pytest.PytestDeprecationWarning, + match=re.escape( + "The (fspath: py.path.local) argument to MyFile is deprecated." + ), + ): + MyFile.from_parent( + parent=mod.parent, + fspath=legacy_path("bla"), + ) + + def test_fixture_disallow_on_marked_functions(): """Test that applying @pytest.fixture to a marked function warns (#3364).""" with pytest.warns( diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index 850f14c58a0..49e620c1138 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -1,8 +1,8 @@ # mypy: allow-untyped-defs from pathlib import Path +from _pytest.compat import LEGACY_PATH from _pytest.fixtures import TopRequest -from _pytest.legacypath import LEGACY_PATH from _pytest.legacypath import TempdirFactory from _pytest.legacypath import Testdir import pytest @@ -16,7 +16,7 @@ def test_item_fspath(pytester: pytest.Pytester) -> None: items2, hookrec = pytester.inline_genitems(item.nodeid) (item2,) = items2 assert item2.name == item.name - assert item2.fspath == item.fspath # type: ignore[attr-defined] + assert item2.fspath == item.fspath assert item2.path == item.path diff --git a/testing/test_nodes.py b/testing/test_nodes.py index e019f163c2b..a3caf471f70 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -6,6 +6,7 @@ import warnings from _pytest import nodes +from _pytest.compat import legacy_path from _pytest.outcomes import OutcomeException from _pytest.pytester import Pytester from _pytest.warning_types import PytestWarning @@ -44,9 +45,9 @@ def test_subclassing_both_item_and_collector_deprecated( warnings.simplefilter("error") class SoWrong(nodes.Item, nodes.File): - def __init__(self, path, parent): + def __init__(self, fspath, parent): """Legacy ctor with legacy call # don't wana see""" - super().__init__(parent, path) + super().__init__(fspath, parent) def collect(self): raise NotImplementedError() @@ -55,7 +56,9 @@ def runtest(self): raise NotImplementedError() with pytest.warns(PytestWarning) as rec: - SoWrong.from_parent(request.session, path=tmp_path / "broken.txt", wrong=10) + SoWrong.from_parent( + request.session, fspath=legacy_path(tmp_path / "broken.txt") + ) messages = [str(x.message) for x in rec] assert any( re.search(".*SoWrong.* not using a cooperative constructor.*", x) From dacee1f11d7495347fa2cfabeb33e998c95c8c05 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Mar 2024 19:30:51 -0300 Subject: [PATCH 0534/1271] Revert "Remove deprecated py.path hook arguments" This reverts commit a98f02d4238793300f1be01f75bf0fff5609a241. --- doc/en/deprecations.rst | 55 +++++++++++++------------- src/_pytest/config/__init__.py | 4 +- src/_pytest/config/compat.py | 72 ++++++++++++++++++++++++++++++++++ src/_pytest/deprecated.py | 7 ++++ src/_pytest/hookspec.py | 43 ++++++++++---------- src/_pytest/main.py | 3 +- testing/deprecated_test.py | 33 ++++++++++++++++ 7 files changed, 165 insertions(+), 52 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index b7ddd8b013f..cd6d1e60aef 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -58,7 +58,6 @@ both ``fspath`` (``py.path.local``) and ``path`` (``pathlib.Path``) attributes, no matter what argument was used in the constructor. We expect to deprecate the ``fspath`` attribute in a future release. -.. _legacy-path-hooks-deprecated: Configuring hook specs/impls using markers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -101,6 +100,33 @@ Changed ``hookwrapper`` attributes: * ``historic`` +.. _legacy-path-hooks-deprecated: + +``py.path.local`` arguments for hooks replaced with ``pathlib.Path`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 7.0 + +In order to support the transition from ``py.path.local`` to :mod:`pathlib`, the following hooks now receive additional arguments: + +* :hook:`pytest_ignore_collect(collection_path: pathlib.Path) ` as equivalent to ``path`` +* :hook:`pytest_collect_file(file_path: pathlib.Path) ` as equivalent to ``path`` +* :hook:`pytest_pycollect_makemodule(module_path: pathlib.Path) ` as equivalent to ``path`` +* :hook:`pytest_report_header(start_path: pathlib.Path) ` as equivalent to ``startdir`` +* :hook:`pytest_report_collectionfinish(start_path: pathlib.Path) ` as equivalent to ``startdir`` + +The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments. + +.. note:: + The name of the :class:`~_pytest.nodes.Node` arguments and attributes, + :ref:`outlined above ` (the new attribute + being ``path``) is **the opposite** of the situation for hooks (the old + argument being ``path``). + + This is an unfortunate artifact due to historical reasons, which should be + resolved in future versions as we slowly get rid of the :pypi:`py` + dependency (see :issue:`9283` for a longer discussion). + Directly constructing internal classes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -247,33 +273,6 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. -``py.path.local`` arguments for hooks replaced with ``pathlib.Path`` -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.0 -.. versionremoved:: 8.0 - -In order to support the transition from ``py.path.local`` to :mod:`pathlib`, the following hooks now receive additional arguments: - -* :hook:`pytest_ignore_collect(collection_path: pathlib.Path) ` as equivalent to ``path`` -* :hook:`pytest_collect_file(file_path: pathlib.Path) ` as equivalent to ``path`` -* :hook:`pytest_pycollect_makemodule(module_path: pathlib.Path) ` as equivalent to ``path`` -* :hook:`pytest_report_header(start_path: pathlib.Path) ` as equivalent to ``startdir`` -* :hook:`pytest_report_collectionfinish(start_path: pathlib.Path) ` as equivalent to ``startdir`` - -The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments. - -.. note:: - The name of the :class:`~_pytest.nodes.Node` arguments and attributes, - :ref:`outlined above ` (the new attribute - being ``path``) is **the opposite** of the situation for hooks (the old - argument being ``path``). - - This is an unfortunate artifact due to historical reasons, which should be - resolved in future versions as we slowly get rid of the :pypi:`py` - dependency (see :issue:`9283` for a longer discussion). - - .. _nose-deprecation: Support for tests written for nose diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 7ed79483c4e..bf2cfc3996d 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -38,12 +38,14 @@ from typing import Union import warnings +import pluggy from pluggy import HookimplMarker from pluggy import HookimplOpts from pluggy import HookspecMarker from pluggy import HookspecOpts from pluggy import PluginManager +from .compat import PathAwareHookProxy from .exceptions import PrintHelp as PrintHelp from .exceptions import UsageError as UsageError from .findpaths import determine_setup @@ -1068,7 +1070,7 @@ def __init__( self._store = self.stash self.trace = self.pluginmanager.trace.root.get("config") - self.hook = self.pluginmanager.hook # type: ignore[assignment] + self.hook: pluggy.HookRelay = PathAwareHookProxy(self.pluginmanager.hook) # type: ignore[assignment] self._inicache: Dict[str, Any] = {} self._override_ini: Sequence[str] = () self._opt2dest: Dict[str, str] = {} diff --git a/src/_pytest/config/compat.py b/src/_pytest/config/compat.py index 9c61b4dac09..2856d85d195 100644 --- a/src/_pytest/config/compat.py +++ b/src/_pytest/config/compat.py @@ -1,8 +1,26 @@ from __future__ import annotations +import functools from pathlib import Path +from typing import Any +from typing import Mapping +import warnings + +import pluggy from ..compat import LEGACY_PATH +from ..compat import legacy_path +from ..deprecated import HOOK_LEGACY_PATH_ARG + + +# hookname: (Path, LEGACY_PATH) +imply_paths_hooks: Mapping[str, tuple[str, str]] = { + "pytest_ignore_collect": ("collection_path", "path"), + "pytest_collect_file": ("file_path", "path"), + "pytest_pycollect_makemodule": ("module_path", "path"), + "pytest_report_header": ("start_path", "startdir"), + "pytest_report_collectionfinish": ("start_path", "startdir"), +} def _check_path(path: Path, fspath: LEGACY_PATH) -> None: @@ -11,3 +29,57 @@ def _check_path(path: Path, fspath: LEGACY_PATH) -> None: f"Path({fspath!r}) != {path!r}\n" "if both path and fspath are given they need to be equal" ) + + +class PathAwareHookProxy: + """ + this helper wraps around hook callers + until pluggy supports fixingcalls, this one will do + + it currently doesn't return full hook caller proxies for fixed hooks, + this may have to be changed later depending on bugs + """ + + def __init__(self, hook_relay: pluggy.HookRelay) -> None: + self._hook_relay = hook_relay + + def __dir__(self) -> list[str]: + return dir(self._hook_relay) + + def __getattr__(self, key: str) -> pluggy.HookCaller: + hook: pluggy.HookCaller = getattr(self._hook_relay, key) + if key not in imply_paths_hooks: + self.__dict__[key] = hook + return hook + else: + path_var, fspath_var = imply_paths_hooks[key] + + @functools.wraps(hook) + def fixed_hook(**kw: Any) -> Any: + path_value: Path | None = kw.pop(path_var, None) + fspath_value: LEGACY_PATH | None = kw.pop(fspath_var, None) + if fspath_value is not None: + warnings.warn( + HOOK_LEGACY_PATH_ARG.format( + pylib_path_arg=fspath_var, pathlib_path_arg=path_var + ), + stacklevel=2, + ) + if path_value is not None: + if fspath_value is not None: + _check_path(path_value, fspath_value) + else: + fspath_value = legacy_path(path_value) + else: + assert fspath_value is not None + path_value = Path(fspath_value) + + kw[path_var] = path_value + kw[fspath_var] = fspath_value + return hook(**kw) + + fixed_hook.name = hook.name # type: ignore[attr-defined] + fixed_hook.spec = hook.spec # type: ignore[attr-defined] + fixed_hook.__name__ = key + self.__dict__[key] = fixed_hook + return fixed_hook # type: ignore[return-value] diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 508ea1184f6..10811d158aa 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -36,6 +36,13 @@ PRIVATE = PytestDeprecationWarning("A private pytest class or function was used.") +HOOK_LEGACY_PATH_ARG = UnformattedWarning( + PytestRemovedIn9Warning, + "The ({pylib_path_arg}: py.path.local) argument is deprecated, please use ({pathlib_path_arg}: pathlib.Path)\n" + "see https://docs.pytest.org/en/latest/deprecations.html" + "#py-path-local-arguments-for-hooks-replaced-with-pathlib-path", +) + NODE_CTOR_FSPATH_ARG = UnformattedWarning( PytestRemovedIn9Warning, "The (fspath: py.path.local) argument to {node_type_name} is deprecated. " diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 58f4986ec7e..4bee76f1e39 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -22,6 +22,7 @@ from _pytest._code.code import ExceptionInfo from _pytest._code.code import ExceptionRepr + from _pytest.compat import LEGACY_PATH from _pytest.config import _PluggyPlugin from _pytest.config import Config from _pytest.config import ExitCode @@ -296,7 +297,9 @@ def pytest_collection_finish(session: "Session") -> None: @hookspec(firstresult=True) -def pytest_ignore_collect(collection_path: Path, config: "Config") -> Optional[bool]: +def pytest_ignore_collect( + collection_path: Path, path: "LEGACY_PATH", config: "Config" +) -> Optional[bool]: """Return True to prevent considering this path for collection. This hook is consulted for all files and directories prior to calling @@ -310,10 +313,8 @@ def pytest_ignore_collect(collection_path: Path, config: "Config") -> Optional[b .. versionchanged:: 7.0.0 The ``collection_path`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``path`` parameter. - - .. versionchanged:: 8.0.0 - The ``path`` parameter has been removed. + equivalent of the ``path`` parameter. The ``path`` parameter + has been deprecated. Use in conftest plugins ======================= @@ -354,7 +355,9 @@ def pytest_collect_directory(path: Path, parent: "Collector") -> "Optional[Colle """ -def pytest_collect_file(file_path: Path, parent: "Collector") -> "Optional[Collector]": +def pytest_collect_file( + file_path: Path, path: "LEGACY_PATH", parent: "Collector" +) -> "Optional[Collector]": """Create a :class:`~pytest.Collector` for the given path, or None if not relevant. For best results, the returned collector should be a subclass of @@ -367,10 +370,8 @@ def pytest_collect_file(file_path: Path, parent: "Collector") -> "Optional[Colle .. versionchanged:: 7.0.0 The ``file_path`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``path`` parameter. - - .. versionchanged:: 8.0.0 - The ``path`` parameter was removed. + equivalent of the ``path`` parameter. The ``path`` parameter + has been deprecated. Use in conftest plugins ======================= @@ -467,7 +468,9 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor @hookspec(firstresult=True) -def pytest_pycollect_makemodule(module_path: Path, parent) -> Optional["Module"]: +def pytest_pycollect_makemodule( + module_path: Path, path: "LEGACY_PATH", parent +) -> Optional["Module"]: """Return a :class:`pytest.Module` collector or None for the given path. This hook will be called for each matching test module path. @@ -483,8 +486,7 @@ def pytest_pycollect_makemodule(module_path: Path, parent) -> Optional["Module"] The ``module_path`` parameter was added as a :class:`pathlib.Path` equivalent of the ``path`` parameter. - .. versionchanged:: 8.0.0 - The ``path`` parameter has been removed in favor of ``module_path``. + The ``path`` parameter has been deprecated in favor of ``fspath``. Use in conftest plugins ======================= @@ -992,7 +994,7 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No def pytest_report_header( # type:ignore[empty-body] - config: "Config", start_path: Path + config: "Config", start_path: Path, startdir: "LEGACY_PATH" ) -> Union[str, List[str]]: """Return a string or list of strings to be displayed as header info for terminal reporting. @@ -1009,10 +1011,8 @@ def pytest_report_header( # type:ignore[empty-body] .. versionchanged:: 7.0.0 The ``start_path`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``startdir`` parameter. - - .. versionchanged:: 8.0.0 - The ``startdir`` parameter has been removed. + equivalent of the ``startdir`` parameter. The ``startdir`` parameter + has been deprecated. Use in conftest plugins ======================= @@ -1024,6 +1024,7 @@ def pytest_report_header( # type:ignore[empty-body] def pytest_report_collectionfinish( # type:ignore[empty-body] config: "Config", start_path: Path, + startdir: "LEGACY_PATH", items: Sequence["Item"], ) -> Union[str, List[str]]: """Return a string or list of strings to be displayed after collection @@ -1047,10 +1048,8 @@ def pytest_report_collectionfinish( # type:ignore[empty-body] .. versionchanged:: 7.0.0 The ``start_path`` parameter was added as a :class:`pathlib.Path` - equivalent of the ``startdir`` parameter. - - .. versionchanged:: 8.0.0 - The ``startdir`` parameter has been removed. + equivalent of the ``startdir`` parameter. The ``startdir`` parameter + has been deprecated. Use in conftest plugins ======================= diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 145722c25d3..3b9ac93cf3f 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -37,6 +37,7 @@ from _pytest.config import PytestPluginManager from _pytest.config import UsageError from _pytest.config.argparsing import Parser +from _pytest.config.compat import PathAwareHookProxy from _pytest.fixtures import FixtureManager from _pytest.outcomes import exit from _pytest.pathlib import absolutepath @@ -695,7 +696,7 @@ def gethookproxy(self, fspath: "os.PathLike[str]") -> pluggy.HookRelay: proxy: pluggy.HookRelay if remove_mods: # One or more conftests are not in use at this path. - proxy = FSHookProxy(pm, remove_mods) # type: ignore[arg-type,assignment] + proxy = PathAwareHookProxy(FSHookProxy(pm, remove_mods)) # type: ignore[arg-type,assignment] else: # All plugins are active for this fspath. proxy = self.config.hook diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 6a230a9fdf5..2be4d6dfc47 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -1,5 +1,7 @@ # mypy: allow-untyped-defs +from pathlib import Path import re +import sys from _pytest import deprecated from _pytest.compat import legacy_path @@ -88,6 +90,37 @@ def __init__(self, foo: int, *, _ispytest: bool = False) -> None: PrivateInit(10, _ispytest=True) +@pytest.mark.parametrize("hooktype", ["hook", "ihook"]) +def test_hookproxy_warnings_for_pathlib(tmp_path, hooktype, request): + path = legacy_path(tmp_path) + + PATH_WARN_MATCH = r".*path: py\.path\.local\) argument is deprecated, please use \(collection_path: pathlib\.Path.*" + if hooktype == "ihook": + hooks = request.node.ihook + else: + hooks = request.config.hook + + with pytest.warns(PytestDeprecationWarning, match=PATH_WARN_MATCH) as r: + l1 = sys._getframe().f_lineno + hooks.pytest_ignore_collect( + config=request.config, path=path, collection_path=tmp_path + ) + l2 = sys._getframe().f_lineno + + (record,) = r + assert record.filename == __file__ + assert l1 < record.lineno < l2 + + hooks.pytest_ignore_collect(config=request.config, collection_path=tmp_path) + + # Passing entirely *different* paths is an outright error. + with pytest.raises(ValueError, match=r"path.*fspath.*need to be equal"): + with pytest.warns(PytestDeprecationWarning, match=PATH_WARN_MATCH) as r: + hooks.pytest_ignore_collect( + config=request.config, path=path, collection_path=Path("/bla/bla") + ) + + def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: mod = pytester.getmodulecol("") From 221097517b8499a11a2d9c1e1473989fbaf200d5 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 7 Mar 2024 19:38:05 -0300 Subject: [PATCH 0535/1271] Add changelog entry for #12069 --- changelog/12069.trivial.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 changelog/12069.trivial.rst diff --git a/changelog/12069.trivial.rst b/changelog/12069.trivial.rst new file mode 100644 index 00000000000..25c0db1c115 --- /dev/null +++ b/changelog/12069.trivial.rst @@ -0,0 +1,8 @@ +Delayed the deprecation of the following features to ``9.0.0``: + +* :ref:`node-ctor-fspath-deprecation`. +* :ref:`legacy-path-hooks-deprecated`. + +It was discovered after ``8.1.0`` was released that the warnings about the impeding removal were not being displayed, so the team decided to revert the removal. + +This was the reason for ``8.1.0`` being yanked. From 1a5e0eb71d2af0ad113ccd9ee596c7d724d7a4b6 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 7 Mar 2024 00:02:51 +0200 Subject: [PATCH 0536/1271] unittest: make `obj` work more like `Function`/`Class` Previously, the `obj` of a `TestCaseFunction` (the unittest plugin item type) was the unbound method. This is unlike regular `Class` where the `obj` is a bound method to a fresh instance. This difference necessitated several special cases in in places outside of the unittest plugin, such as `FixtureDef` and `FixtureRequest`, and made things a bit harder to understand. Instead, match how the python plugin does it, including collecting fixtures from a fresh instance. The downside is that now this instance for fixture-collection is kept around in memory, but it's the same as `Class` so nothing new. Users should only initialize stuff in `setUp`/`setUpClass` and similar methods, and not in `__init__` which is generally off-limits in `TestCase` subclasses. I am not sure why there was a difference in the first place, though I will say the previous unittest approach is probably the preferable one, but first let's get consistency. --- src/_pytest/compat.py | 8 +++--- src/_pytest/fixtures.py | 57 ++++++++++++---------------------------- src/_pytest/python.py | 1 - src/_pytest/unittest.py | 50 +++++++++++++++++++---------------- testing/test_unittest.py | 6 ++++- 5 files changed, 52 insertions(+), 70 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index fa387f6db12..d39f96c4c6b 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -86,7 +86,6 @@ def getfuncargnames( function: Callable[..., object], *, name: str = "", - is_method: bool = False, cls: type | None = None, ) -> tuple[str, ...]: """Return the names of a function's mandatory arguments. @@ -97,9 +96,8 @@ def getfuncargnames( * Aren't bound with functools.partial. * Aren't replaced with mocks. - The is_method and cls arguments indicate that the function should - be treated as a bound method even though it's not unless, only in - the case of cls, the function is a static method. + The cls arguments indicate that the function should be treated as a bound + method even though it's not unless the function is a static method. The name parameter should be the original name in which the function was collected. """ @@ -137,7 +135,7 @@ def getfuncargnames( # If this function should be treated as a bound method even though # it's passed as an unbound method or function, remove the first # parameter name. - if is_method or ( + if ( # Not using `getattr` because we don't want to resolve the staticmethod. # Not using `cls.__dict__` because we want to check the entire MRO. cls diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 1ee7e84f7fa..45412159e86 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -462,12 +462,8 @@ def cls(self): @property def instance(self): """Instance (can be None) on which test function was collected.""" - # unittest support hack, see _pytest.unittest.TestCaseFunction. - try: - return self._pyfuncitem._testcase # type: ignore[attr-defined] - except AttributeError: - function = getattr(self, "function", None) - return getattr(function, "__self__", None) + function = getattr(self, "function", None) + return getattr(function, "__self__", None) @property def module(self): @@ -965,7 +961,6 @@ def __init__( func: "_FixtureFunc[FixtureValue]", scope: Union[Scope, _ScopeName, Callable[[str, Config], _ScopeName], None], params: Optional[Sequence[object]], - unittest: bool = False, ids: Optional[ Union[Tuple[Optional[object], ...], Callable[[Any], Optional[object]]] ] = None, @@ -1011,9 +1006,7 @@ def __init__( # a parameter value. self.ids: Final = ids # The names requested by the fixtures. - self.argnames: Final = getfuncargnames(func, name=argname, is_method=unittest) - # Whether the fixture was collected from a unittest TestCase class. - self.unittest: Final = unittest + self.argnames: Final = getfuncargnames(func, name=argname) # If the fixture was executed, the current value of the fixture. # Can change if the fixture is executed with different parameters. self.cached_result: Optional[_FixtureCachedResult[FixtureValue]] = None @@ -1092,25 +1085,20 @@ def resolve_fixture_function( """Get the actual callable that can be called to obtain the fixture value, dealing with unittest-specific instances and bound methods.""" fixturefunc = fixturedef.func - if fixturedef.unittest: - if request.instance is not None: - # Bind the unbound method to the TestCase instance. - fixturefunc = fixturedef.func.__get__(request.instance) # type: ignore[union-attr] - else: - # The fixture function needs to be bound to the actual - # request.instance so that code working with "fixturedef" behaves - # as expected. - if request.instance is not None: - # Handle the case where fixture is defined not in a test class, but some other class - # (for example a plugin class with a fixture), see #2270. - if hasattr(fixturefunc, "__self__") and not isinstance( - request.instance, - fixturefunc.__self__.__class__, # type: ignore[union-attr] - ): - return fixturefunc - fixturefunc = getimfunc(fixturedef.func) - if fixturefunc != fixturedef.func: - fixturefunc = fixturefunc.__get__(request.instance) # type: ignore[union-attr] + # The fixture function needs to be bound to the actual + # request.instance so that code working with "fixturedef" behaves + # as expected. + if request.instance is not None: + # Handle the case where fixture is defined not in a test class, but some other class + # (for example a plugin class with a fixture), see #2270. + if hasattr(fixturefunc, "__self__") and not isinstance( + request.instance, + fixturefunc.__self__.__class__, # type: ignore[union-attr] + ): + return fixturefunc + fixturefunc = getimfunc(fixturedef.func) + if fixturefunc != fixturedef.func: + fixturefunc = fixturefunc.__get__(request.instance) # type: ignore[union-attr] return fixturefunc @@ -1614,7 +1602,6 @@ def _register_fixture( Union[Tuple[Optional[object], ...], Callable[[Any], Optional[object]]] ] = None, autouse: bool = False, - unittest: bool = False, ) -> None: """Register a fixture @@ -1635,8 +1622,6 @@ def _register_fixture( The fixture's IDs. :param autouse: Whether this is an autouse fixture. - :param unittest: - Set this if this is a unittest fixture. """ fixture_def = FixtureDef( config=self.config, @@ -1645,7 +1630,6 @@ def _register_fixture( func=func, scope=scope, params=params, - unittest=unittest, ids=ids, _ispytest=True, ) @@ -1667,8 +1651,6 @@ def _register_fixture( def parsefactories( self, node_or_obj: nodes.Node, - *, - unittest: bool = ..., ) -> None: raise NotImplementedError() @@ -1677,8 +1659,6 @@ def parsefactories( self, node_or_obj: object, nodeid: Optional[str], - *, - unittest: bool = ..., ) -> None: raise NotImplementedError() @@ -1686,8 +1666,6 @@ def parsefactories( self, node_or_obj: Union[nodes.Node, object], nodeid: Union[str, NotSetType, None] = NOTSET, - *, - unittest: bool = False, ) -> None: """Collect fixtures from a collection node or object. @@ -1739,7 +1717,6 @@ def parsefactories( func=func, scope=marker.scope, params=marker.params, - unittest=unittest, ids=marker.ids, autouse=marker.autouse, ) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index e1730b1a7e0..a28c3befbaf 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1314,7 +1314,6 @@ def parametrize( func=get_direct_param_fixture_func, scope=scope_, params=None, - unittest=False, ids=None, _ispytest=True, ) diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 2b7966531c1..b0ec02e7d36 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -15,7 +15,6 @@ from typing import Union import _pytest._code -from _pytest.compat import getimfunc from _pytest.compat import is_async_function from _pytest.config import hookimpl from _pytest.fixtures import FixtureRequest @@ -63,6 +62,14 @@ class UnitTestCase(Class): # to declare that our children do not support funcargs. nofuncargs = True + def newinstance(self): + # TestCase __init__ takes the method (test) name. The TestCase + # constructor treats the name "runTest" as a special no-op, so it can be + # used when a dummy instance is needed. While unittest.TestCase has a + # default, some subclasses omit the default (#9610), so always supply + # it. + return self.obj("runTest") + def collect(self) -> Iterable[Union[Item, Collector]]: from unittest import TestLoader @@ -76,15 +83,15 @@ def collect(self) -> Iterable[Union[Item, Collector]]: self._register_unittest_setup_class_fixture(cls) self._register_setup_class_fixture() - self.session._fixturemanager.parsefactories(self, unittest=True) + self.session._fixturemanager.parsefactories(self.newinstance(), self.nodeid) + loader = TestLoader() foundsomething = False for name in loader.getTestCaseNames(self.obj): x = getattr(self.obj, name) if not getattr(x, "__test__", True): continue - funcobj = getimfunc(x) - yield TestCaseFunction.from_parent(self, name=name, callobj=funcobj) + yield TestCaseFunction.from_parent(self, name=name) foundsomething = True if not foundsomething: @@ -169,23 +176,21 @@ def unittest_setup_method_fixture( class TestCaseFunction(Function): nofuncargs = True _excinfo: Optional[List[_pytest._code.ExceptionInfo[BaseException]]] = None - _testcase: Optional["unittest.TestCase"] = None def _getobj(self): - assert self.parent is not None - # Unlike a regular Function in a Class, where `item.obj` returns - # a *bound* method (attached to an instance), TestCaseFunction's - # `obj` returns an *unbound* method (not attached to an instance). - # This inconsistency is probably not desirable, but needs some - # consideration before changing. - return getattr(self.parent.obj, self.originalname) # type: ignore[attr-defined] + assert isinstance(self.parent, UnitTestCase) + testcase = self.parent.obj(self.name) + return getattr(testcase, self.name) + + # Backward compat for pytest-django; can be removed after pytest-django + # updates + some slack. + @property + def _testcase(self): + return self._obj.__self__ def setup(self) -> None: # A bound method to be called during teardown() if set (see 'runtest()'). self._explicit_tearDown: Optional[Callable[[], None]] = None - assert self.parent is not None - self._testcase = self.parent.obj(self.name) # type: ignore[attr-defined] - self._obj = getattr(self._testcase, self.name) super().setup() def teardown(self) -> None: @@ -193,7 +198,6 @@ def teardown(self) -> None: if self._explicit_tearDown is not None: self._explicit_tearDown() self._explicit_tearDown = None - self._testcase = None self._obj = None def startTest(self, testcase: "unittest.TestCase") -> None: @@ -292,14 +296,14 @@ def addDuration(self, testcase: "unittest.TestCase", elapsed: float) -> None: def runtest(self) -> None: from _pytest.debugging import maybe_wrap_pytest_function_for_tracing - assert self._testcase is not None + testcase = self.obj.__self__ maybe_wrap_pytest_function_for_tracing(self) # Let the unittest framework handle async functions. if is_async_function(self.obj): # Type ignored because self acts as the TestResult, but is not actually one. - self._testcase(result=self) # type: ignore[arg-type] + testcase(result=self) # type: ignore[arg-type] else: # When --pdb is given, we want to postpone calling tearDown() otherwise # when entering the pdb prompt, tearDown() would have probably cleaned up @@ -311,16 +315,16 @@ def runtest(self) -> None: assert isinstance(self.parent, UnitTestCase) skipped = _is_skipped(self.obj) or _is_skipped(self.parent.obj) if self.config.getoption("usepdb") and not skipped: - self._explicit_tearDown = self._testcase.tearDown - setattr(self._testcase, "tearDown", lambda *args: None) + self._explicit_tearDown = testcase.tearDown + setattr(testcase, "tearDown", lambda *args: None) # We need to update the actual bound method with self.obj, because # wrap_pytest_function_for_tracing replaces self.obj by a wrapper. - setattr(self._testcase, self.name, self.obj) + setattr(testcase, self.name, self.obj) try: - self._testcase(result=self) # type: ignore[arg-type] + testcase(result=self) # type: ignore[arg-type] finally: - delattr(self._testcase, self.name) + delattr(testcase, self.name) def _traceback_filter( self, excinfo: _pytest._code.ExceptionInfo[BaseException] diff --git a/testing/test_unittest.py b/testing/test_unittest.py index b5d182c14ad..9ecb548eeec 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -208,10 +208,14 @@ def test_demo(self): """ ) + pytester.inline_run("-s", testpath) gc.collect() + + # Either already destroyed, or didn't run setUp. for obj in gc.get_objects(): - assert type(obj).__name__ != "TestCaseObjectsShouldBeCleanedUp" + if type(obj).__name__ == "TestCaseObjectsShouldBeCleanedUp": + assert not hasattr(obj, "an_expensive_obj") def test_unittest_skip_issue148(pytester: Pytester) -> None: From a9d1f55a0f9b6f536967caf0f317cdbc8034a073 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 8 Mar 2024 22:39:44 +0200 Subject: [PATCH 0537/1271] fixtures: simplify scope checking There are two non-optimal things in the current way scope checking is done: - It runs on `SubRequest`, but doesn't use the `SubRequest's scope, which is confusing. Instead it takes `invoking_scope` and `requested_scope`. - Because `_check_scope` is only defined on `SubRequest` and not `TopRequest`, `_compute_fixture_value` first creates the `SubRequest` only then checks the scope (hence the need for the previous point). Instead, also define `_check_scope` on `TopRequest` (always valid), and remove `invoking_scope`, using `self._scope` instead. --- src/_pytest/fixtures.py | 64 ++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 45412159e86..e322c3f182b 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -388,6 +388,14 @@ def scope(self) -> _ScopeName: """Scope string, one of "function", "class", "module", "package", "session".""" return self._scope.value + @abc.abstractmethod + def _check_scope( + self, + requested_fixturedef: Union["FixtureDef[object]", PseudoFixtureDef[object]], + requested_scope: Scope, + ) -> None: + raise NotImplementedError() + @property def fixturenames(self) -> List[str]: """Names of all active fixtures in this request.""" @@ -632,12 +640,12 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: ) fail(msg, pytrace=False) + # Check if a higher-level scoped fixture accesses a lower level one. + self._check_scope(fixturedef, scope) + subrequest = SubRequest( self, scope, param, param_index, fixturedef, _ispytest=True ) - - # Check if a higher-level scoped fixture accesses a lower level one. - subrequest._check_scope(argname, self._scope, scope) try: # Call the fixture function. fixturedef.execute(request=subrequest) @@ -669,6 +677,14 @@ def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: def _scope(self) -> Scope: return Scope.Function + def _check_scope( + self, + requested_fixturedef: Union["FixtureDef[object]", PseudoFixtureDef[object]], + requested_scope: Scope, + ) -> None: + # TopRequest always has function scope so always valid. + pass + @property def node(self): return self._pyfuncitem @@ -740,37 +756,33 @@ def node(self): def _check_scope( self, - argname: str, - invoking_scope: Scope, + requested_fixturedef: Union["FixtureDef[object]", PseudoFixtureDef[object]], requested_scope: Scope, ) -> None: - if argname == "request": + if isinstance(requested_fixturedef, PseudoFixtureDef): return - if invoking_scope > requested_scope: + if self._scope > requested_scope: # Try to report something helpful. - text = "\n".join(self._factorytraceback()) + argname = requested_fixturedef.argname + fixture_stack = "\n".join( + self._format_fixturedef_line(fixturedef) + for fixturedef in self._get_fixturestack() + ) + requested_fixture = self._format_fixturedef_line(requested_fixturedef) fail( f"ScopeMismatch: You tried to access the {requested_scope.value} scoped " - f"fixture {argname} with a {invoking_scope.value} scoped request object, " - f"involved factories:\n{text}", + f"fixture {argname} with a {self._scope.value} scoped request object, " + f"involved factories:\n{fixture_stack}\n{requested_fixture}", pytrace=False, ) - def _factorytraceback(self) -> List[str]: - lines = [] - for fixturedef in self._get_fixturestack(): - factory = fixturedef.func - fs, lineno = getfslineno(factory) - if isinstance(fs, Path): - session: Session = self._pyfuncitem.session - p = bestrelpath(session.path, fs) - else: - p = fs - lines.append( - "%s:%d: def %s%s" - % (p, lineno + 1, factory.__name__, inspect.signature(factory)) - ) - return lines + def _format_fixturedef_line(self, fixturedef: "FixtureDef[object]") -> str: + factory = fixturedef.func + path, lineno = getfslineno(factory) + if isinstance(path, Path): + path = bestrelpath(self._pyfuncitem.session.path, path) + signature = inspect.signature(factory) + return f"{path}:{lineno + 1}: def {factory.__name__}{signature}" def addfinalizer(self, finalizer: Callable[[], object]) -> None: self._fixturedef.addfinalizer(finalizer) @@ -1111,7 +1123,7 @@ def pytest_fixture_setup( fixdef = request._get_active_fixturedef(argname) assert fixdef.cached_result is not None result, arg_cache_key, exc = fixdef.cached_result - request._check_scope(argname, request._scope, fixdef._scope) + request._check_scope(fixdef, fixdef._scope) kwargs[argname] = result fixturefunc = resolve_fixture_function(fixturedef, request) From 71671f60b570e631d0b663ec4285319ade3c1ce5 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 8 Mar 2024 23:08:28 +0200 Subject: [PATCH 0538/1271] fixtures: improve fixture scope mismatch message - Separate the requesting from the requested. - Avoid the term "factory", I think most people don't distinguish between "fixture" and "fixture function" (i.e. "factory") and would find the term "factory" unfamiliar. --- src/_pytest/fixtures.py | 5 +++-- testing/python/fixtures.py | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index e322c3f182b..40568a4a4a2 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -771,8 +771,9 @@ def _check_scope( requested_fixture = self._format_fixturedef_line(requested_fixturedef) fail( f"ScopeMismatch: You tried to access the {requested_scope.value} scoped " - f"fixture {argname} with a {self._scope.value} scoped request object, " - f"involved factories:\n{fixture_stack}\n{requested_fixture}", + f"fixture {argname} with a {self._scope.value} scoped request object. " + f"Requesting fixture stack:\n{fixture_stack}\n" + f"Requested fixture:\n{requested_fixture}", pytrace=False, ) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 6edff6ecd43..8d59b36d319 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1247,8 +1247,9 @@ def test_add(arg2): result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "*ScopeMismatch*involved factories*", + "*ScopeMismatch*Requesting fixture stack*", "test_receives_funcargs_scope_mismatch.py:6: def arg2(arg1)", + "Requested fixture:", "test_receives_funcargs_scope_mismatch.py:2: def arg1()", "*1 error*", ] @@ -1274,7 +1275,13 @@ def test_add(arg1, arg2): ) result = pytester.runpytest() result.stdout.fnmatch_lines( - ["*ScopeMismatch*involved factories*", "* def arg2*", "*1 error*"] + [ + "*ScopeMismatch*Requesting fixture stack*", + "* def arg2(arg1)", + "Requested fixture:", + "* def arg1()", + "*1 error*", + ], ) def test_invalid_scope(self, pytester: Pytester) -> None: @@ -2488,8 +2495,10 @@ def test_it(request, fixfunc): assert result.ret == ExitCode.TESTS_FAILED result.stdout.fnmatch_lines( [ - "*ScopeMismatch*involved factories*", + "*ScopeMismatch*Requesting fixture stack*", "test_it.py:6: def fixmod(fixfunc)", + "Requested fixture:", + "test_it.py:3: def fixfunc()", ] ) From f5de111357d26780760df78b503fdc8f4731f611 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 8 Mar 2024 23:18:43 +0200 Subject: [PATCH 0539/1271] fixtures: check scope mismatch in `getfixturevalue` already-cached case This makes sure the scope is always compatible, and also allows using `getfixturevalue` in `pytest_fixture_setup` so less internal magic. --- src/_pytest/fixtures.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 40568a4a4a2..2d3593df03d 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -573,6 +573,8 @@ def _get_active_fixturedef( raise self._compute_fixture_value(fixturedef) self._fixture_defs[argname] = fixturedef + else: + self._check_scope(fixturedef, fixturedef._scope) return fixturedef def _get_fixturestack(self) -> List["FixtureDef[Any]"]: @@ -1121,11 +1123,7 @@ def pytest_fixture_setup( """Execution of fixture setup.""" kwargs = {} for argname in fixturedef.argnames: - fixdef = request._get_active_fixturedef(argname) - assert fixdef.cached_result is not None - result, arg_cache_key, exc = fixdef.cached_result - request._check_scope(fixdef, fixdef._scope) - kwargs[argname] = result + kwargs[argname] = request.getfixturevalue(argname) fixturefunc = resolve_fixture_function(fixturedef, request) my_cache_key = fixturedef.cache_key(request) From ff551b768520b1f510dbd8413d810191a79d1471 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 8 Mar 2024 23:24:38 +0200 Subject: [PATCH 0540/1271] fixtures: simplify a bit of code --- src/_pytest/fixtures.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 2d3593df03d..4b7c107521b 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1061,9 +1061,7 @@ def execute(self, request: SubRequest) -> FixtureValue: # with their finalization. for argname in self.argnames: fixturedef = request._get_active_fixturedef(argname) - if argname != "request": - # PseudoFixtureDef is only for "request". - assert isinstance(fixturedef, FixtureDef) + if not isinstance(fixturedef, PseudoFixtureDef): fixturedef.addfinalizer(functools.partial(self.finish, request=request)) my_cache_key = self.cache_key(request) From 9033d4d3fff11e52c6812dfeba32f1cfecdea61a Mon Sep 17 00:00:00 2001 From: Levon Saldamli Date: Sat, 9 Mar 2024 07:51:52 +0100 Subject: [PATCH 0541/1271] Parse args from file (#12085) Co-authored-by: Ran Benita Co-authored-by: Bruno Oliveira --- .gitignore | 1 + AUTHORS | 1 + changelog/11871.feature.rst | 1 + doc/en/how-to/usage.rst | 25 ++++++++++++++++++++++++- src/_pytest/config/argparsing.py | 1 + testing/acceptance_test.py | 27 +++++++++++++++++++++++++++ testing/test_parseopt.py | 11 +++++++++++ 7 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 changelog/11871.feature.rst diff --git a/.gitignore b/.gitignore index 3cac2474a59..9fccf93f7c3 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,7 @@ coverage.xml .settings .vscode __pycache__/ +.python-version # generated by pip pip-wheel-metadata/ diff --git a/AUTHORS b/AUTHORS index 4c4d68df147..53f7a8c2a16 100644 --- a/AUTHORS +++ b/AUTHORS @@ -235,6 +235,7 @@ Kyle Altendorf Lawrence Mitchell Lee Kamentsky Lev Maximov +Levon Saldamli Lewis Cowles Llandy Riveron Del Risco Loic Esteve diff --git a/changelog/11871.feature.rst b/changelog/11871.feature.rst new file mode 100644 index 00000000000..530db8c3c6f --- /dev/null +++ b/changelog/11871.feature.rst @@ -0,0 +1 @@ +Added support for reading command line arguments from a file using the prefix character ``@``, like e.g.: ``pytest @tests.txt``. The file must have one argument per line. diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 65f9debd852..fe46fad2db5 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -17,7 +17,8 @@ in the current directory and its subdirectories. More generally, pytest follows Specifying which tests to run ------------------------------ -Pytest supports several ways to run and select tests from the command-line. +Pytest supports several ways to run and select tests from the command-line or from a file +(see below for :ref:`reading arguments from file `). **Run tests in a module** @@ -91,6 +92,28 @@ For more information see :ref:`marks `. This will import ``pkg.testing`` and use its filesystem location to find and run tests from. +.. _args-from-file: + +**Read arguments from file** + +.. versionadded:: 8.2 + +All of the above can be read from a file using the ``@`` prefix: + +.. code-block:: bash + + pytest @tests_to_run.txt + +where ``tests_to_run.txt`` contains an entry per line, e.g.: + +.. code-block:: text + + tests/test_file.py + tests/test_mod.py::test_func[x1,y2] + tests/test_mod.py::TestClass + -m slow + +This file can also be generated using ``pytest --collect-only -q`` and modified as needed. Getting help on version, option names, environment variables -------------------------------------------------------------- diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index d98f1ae9a12..441d79e902c 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -415,6 +415,7 @@ def __init__( add_help=False, formatter_class=DropShorterLongHelpFormatter, allow_abbrev=False, + fromfile_prefix_chars="@", ) # extra_info is a dict of (param -> value) to display if there's # an usage error to provide more contextual information to the user. diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index e41d7a81fd9..8f001bc2401 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -2,6 +2,7 @@ import dataclasses import importlib.metadata import os +from pathlib import Path import subprocess import sys import types @@ -541,6 +542,32 @@ def test_foo(data): res = pytester.runpytest(p) res.assert_outcomes(passed=3) + # Warning ignore because of: + # https://github.com/python/cpython/issues/85308 + # Can be removed once Python<3.12 support is dropped. + @pytest.mark.filterwarnings("ignore:'encoding' argument not specified") + def test_command_line_args_from_file( + self, pytester: Pytester, tmp_path: Path + ) -> None: + pytester.makepyfile( + test_file=""" + import pytest + + class TestClass: + @pytest.mark.parametrize("a", ["x","y"]) + def test_func(self, a): + pass + """ + ) + tests = [ + "test_file.py::TestClass::test_func[x]", + "test_file.py::TestClass::test_func[y]", + "-q", + ] + args_file = pytester.maketxtfile(tests="\n".join(tests)) + result = pytester.runpytest(f"@{args_file}") + result.assert_outcomes(failed=0, passed=2) + class TestInvocationVariants: def test_earlyinit(self, pytester: Pytester) -> None: diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 4678d8bdba7..e959dfd631b 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -125,6 +125,17 @@ def test_parse2(self, parser: parseopt.Parser) -> None: args = parser.parse([Path(".")]) assert getattr(args, parseopt.FILE_OR_DIR)[0] == "." + # Warning ignore because of: + # https://github.com/python/cpython/issues/85308 + # Can be removed once Python<3.12 support is dropped. + @pytest.mark.filterwarnings("ignore:'encoding' argument not specified") + def test_parse_from_file(self, parser: parseopt.Parser, tmp_path: Path) -> None: + tests = [".", "some.py::Test::test_method[param0]", "other/test_file.py"] + args_file = tmp_path / "tests.txt" + args_file.write_text("\n".join(tests), encoding="utf-8") + args = parser.parse([f"@{args_file.absolute()}"]) + assert getattr(args, parseopt.FILE_OR_DIR) == tests + def test_parse_known_args(self, parser: parseopt.Parser) -> None: parser.parse_known_args([Path(".")]) parser.addoption("--hello", action="store_true") From 006058f1f90b00988cc61043f1ea55bdd2c55883 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 9 Mar 2024 10:13:15 +0200 Subject: [PATCH 0542/1271] fixtures: update outdated comment No longer does unittest stuff. Also the rest of the sentence is not really necessary for a docstring. --- src/_pytest/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 4b7c107521b..58b5154347f 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1096,7 +1096,7 @@ def resolve_fixture_function( fixturedef: FixtureDef[FixtureValue], request: FixtureRequest ) -> "_FixtureFunc[FixtureValue]": """Get the actual callable that can be called to obtain the fixture - value, dealing with unittest-specific instances and bound methods.""" + value.""" fixturefunc = fixturedef.func # The fixture function needs to be bound to the actual # request.instance so that code working with "fixturedef" behaves From 774f0c44e63077efb2a7cf35b19b99a255b22332 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 9 Mar 2024 09:11:33 +0200 Subject: [PATCH 0543/1271] fixtures: only call `instance` property once in function No need to compute the property multiple times. --- src/_pytest/fixtures.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 58b5154347f..1eca6820778 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1101,17 +1101,18 @@ def resolve_fixture_function( # The fixture function needs to be bound to the actual # request.instance so that code working with "fixturedef" behaves # as expected. - if request.instance is not None: + instance = request.instance + if instance is not None: # Handle the case where fixture is defined not in a test class, but some other class # (for example a plugin class with a fixture), see #2270. if hasattr(fixturefunc, "__self__") and not isinstance( - request.instance, + instance, fixturefunc.__self__.__class__, # type: ignore[union-attr] ): return fixturefunc fixturefunc = getimfunc(fixturedef.func) if fixturefunc != fixturedef.func: - fixturefunc = fixturefunc.__get__(request.instance) # type: ignore[union-attr] + fixturefunc = fixturefunc.__get__(instance) # type: ignore[union-attr] return fixturefunc From 140c7775901c0f1e17210fed20774945ee82bd0f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 9 Mar 2024 08:51:20 -0300 Subject: [PATCH 0544/1271] Merge pull request #12094 from pytest-dev/release-8.1.1 Prepare release 8.1.1 (cherry picked from commit abb0cf4922919e3554bd16e9fc540bc107289ee9) --- changelog/11475.bugfix.rst | 1 - changelog/12069.trivial.rst | 8 ------- doc/en/announce/index.rst | 1 + doc/en/announce/release-8.1.1.rst | 18 ++++++++++++++ doc/en/builtin.rst | 4 ++-- doc/en/changelog.rst | 37 ++++++++++++++++++++++------- doc/en/example/parametrize.rst | 6 ++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 10 files changed, 57 insertions(+), 26 deletions(-) delete mode 100644 changelog/11475.bugfix.rst delete mode 100644 changelog/12069.trivial.rst create mode 100644 doc/en/announce/release-8.1.1.rst diff --git a/changelog/11475.bugfix.rst b/changelog/11475.bugfix.rst deleted file mode 100644 index bef8f4f76d3..00000000000 --- a/changelog/11475.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed regression where ``--importmode=importlib`` would import non-test modules more than once. diff --git a/changelog/12069.trivial.rst b/changelog/12069.trivial.rst deleted file mode 100644 index 25c0db1c115..00000000000 --- a/changelog/12069.trivial.rst +++ /dev/null @@ -1,8 +0,0 @@ -Delayed the deprecation of the following features to ``9.0.0``: - -* :ref:`node-ctor-fspath-deprecation`. -* :ref:`legacy-path-hooks-deprecated`. - -It was discovered after ``8.1.0`` was released that the warnings about the impeding removal were not being displayed, so the team decided to revert the removal. - -This was the reason for ``8.1.0`` being yanked. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 68cae83d773..40eccdd748a 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.1.1 release-8.1.0 release-8.0.2 release-8.0.1 diff --git a/doc/en/announce/release-8.1.1.rst b/doc/en/announce/release-8.1.1.rst new file mode 100644 index 00000000000..89b617b487d --- /dev/null +++ b/doc/en/announce/release-8.1.1.rst @@ -0,0 +1,18 @@ +pytest-8.1.1 +======================================= + +pytest 8.1.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 1e1210648eb..9d49389f190 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -170,10 +170,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a `pytest-xdist `__ plugin. See :issue:`7767` for details. - tmpdir_factory [session scope] -- .../_pytest/legacypath.py:317 + tmpdir_factory [session scope] -- .../_pytest/legacypath.py:303 Return a :class:`pytest.TempdirFactory` instance for the test session. - tmpdir -- .../_pytest/legacypath.py:324 + tmpdir -- .../_pytest/legacypath.py:310 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 3442305943f..bea4257af0f 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,16 +28,13 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start -pytest 8.1.0 (YANKED) -===================== - +pytest 8.1.1 (2024-03-08) +========================= .. note:: - This release has been **yanked**: it broke some plugins without the proper warning period, due to - some warnings not showing up as expected. - - See `#12069 `__. + This release is not a usual bug fix release -- it contains features and improvements, being a follow up + to ``8.1.0``, which has been yanked from PyPI. Features -------- @@ -94,6 +91,9 @@ Improvements Bug Fixes --------- +- `#11475 `_: Fixed regression where ``--importmode=importlib`` would import non-test modules more than once. + + - `#11904 `_: Fixed a regression in pytest 8.0.0 that would cause test collection to fail due to permission errors when using ``--pyargs``. This change improves the collection tree for tests specified using ``--pyargs``, see :pull:`12043` for a comparison with pytest 8.0 and <8. @@ -108,7 +108,6 @@ Bug Fixes - `#12039 `_: Fixed a regression in ``8.0.2`` where tests created using :fixture:`tmp_path` have been collected multiple times in CI under Windows. - Improved Documentation ---------------------- @@ -128,6 +127,28 @@ Trivial/Internal Changes If you really need to, copy the function from the previous pytest release. +- `#12069 `_: Delayed the deprecation of the following features to ``9.0.0``: + + * :ref:`node-ctor-fspath-deprecation`. + * :ref:`legacy-path-hooks-deprecated`. + + It was discovered after ``8.1.0`` was released that the warnings about the impeding removal were not being displayed, so the team decided to revert the removal. + + This is the reason for ``8.1.0`` being yanked. + + +pytest 8.1.0 (YANKED) +===================== + + +.. note:: + + This release has been **yanked**: it broke some plugins without the proper warning period, due to + some warnings not showing up as expected. + + See `#12069 `__. + + pytest 8.0.2 (2024-02-24) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 85c6836792f..ad17ce0b430 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 6822aa68ea7..68737267ef4 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 89381c8c76f..40632645d16 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.1.0 + pytest 8.1.1 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index c32de161002..795d2caf50d 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From 0dc036035107b213c9b73bf965cbd7356111b85a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 9 Mar 2024 09:08:44 +0200 Subject: [PATCH 0545/1271] python: fix instance handling in static and class method tests and also fixes a regression in pytest 8.0.0 where `setup_method` crashes if the class has static or class method tests. It is allowed to have a test class with static/class methods which request non-static/class method fixtures (including `setup_method` xunit-fixture). I take it as a given that we need to support this somewhat odd scenario (stdlib unittest also supports it). This raises a question -- when a staticmethod test requests a bound fixture, what is that fixture's `self`? stdlib unittest says - a fresh instance for the test. Previously, pytest said - some instance that is shared by all static/class methods. This is definitely broken since it breaks test isolation. Change pytest to behave like stdlib unittest here. In practice, this means stopping to rely on `self.obj.__self__` to get to the instance from the test function's binding. This doesn't work because staticmethods are not bound to anything. Instead, keep the instance explicitly and use that. BTW, I think this will allow us to change `Class`'s fixture collection (`parsefactories`) to happen on the class itself instead of a class instance, allowing us to avoid one class instantiation. But needs more work. Fixes #12065. --- changelog/12065.bugfix.rst | 4 ++++ src/_pytest/fixtures.py | 5 ++-- src/_pytest/python.py | 34 ++++++++++++++++++++------ src/_pytest/unittest.py | 10 ++++---- testing/python/fixtures.py | 45 +++++++++++++++++++++++++++++++++++ testing/python/integration.py | 17 ++++++++++++- 6 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 changelog/12065.bugfix.rst diff --git a/changelog/12065.bugfix.rst b/changelog/12065.bugfix.rst new file mode 100644 index 00000000000..ca55b327e13 --- /dev/null +++ b/changelog/12065.bugfix.rst @@ -0,0 +1,4 @@ +Fixed a regression in pytest 8.0.0 where test classes containing ``setup_method`` and tests using ``@staticmethod`` or ``@classmethod`` would crash with ``AttributeError: 'NoneType' object has no attribute 'setup_method'``. + +Now the :attr:`request.instance ` attribute of tests using ``@staticmethod`` and ``@classmethod`` is no longer ``None``, but a fresh instance of the class, like in non-static methods. +Previously it was ``None``, and all fixtures of such tests would share a single ``self``. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 1eca6820778..daf3145aaac 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -470,8 +470,9 @@ def cls(self): @property def instance(self): """Instance (can be None) on which test function was collected.""" - function = getattr(self, "function", None) - return getattr(function, "__self__", None) + if self.scope != "function": + return None + return getattr(self._pyfuncitem, "instance", None) @property def module(self): diff --git a/src/_pytest/python.py b/src/_pytest/python.py index fce2078cde3..7b0683b6ec5 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -302,10 +302,10 @@ def instance(self): """Python instance object the function is bound to. Returns None if not a test method, e.g. for a standalone test function, - a staticmethod, a class or a module. + a class or a module. """ - node = self.getparent(Function) - return getattr(node.obj, "__self__", None) if node is not None else None + # Overridden by Function. + return None @property def obj(self): @@ -1702,7 +1702,8 @@ def __init__( super().__init__(name, parent, config=config, session=session) if callobj is not NOTSET: - self.obj = callobj + self._obj = callobj + self._instance = getattr(callobj, "__self__", None) #: Original function name, without any decorations (for example #: parametrization adds a ``"[...]"`` suffix to function names), used to access @@ -1752,12 +1753,31 @@ def function(self): """Underlying python 'function' object.""" return getimfunc(self.obj) - def _getobj(self): - assert self.parent is not None + @property + def instance(self): + try: + return self._instance + except AttributeError: + if isinstance(self.parent, Class): + # Each Function gets a fresh class instance. + self._instance = self._getinstance() + else: + self._instance = None + return self._instance + + def _getinstance(self): if isinstance(self.parent, Class): # Each Function gets a fresh class instance. - parent_obj = self.parent.newinstance() + return self.parent.newinstance() + else: + return None + + def _getobj(self): + instance = self.instance + if instance is not None: + parent_obj = instance else: + assert self.parent is not None parent_obj = self.parent.obj # type: ignore[attr-defined] return getattr(parent_obj, self.originalname) diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index b0ec02e7d36..32eb361c6fd 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -177,16 +177,15 @@ class TestCaseFunction(Function): nofuncargs = True _excinfo: Optional[List[_pytest._code.ExceptionInfo[BaseException]]] = None - def _getobj(self): + def _getinstance(self): assert isinstance(self.parent, UnitTestCase) - testcase = self.parent.obj(self.name) - return getattr(testcase, self.name) + return self.parent.obj(self.name) # Backward compat for pytest-django; can be removed after pytest-django # updates + some slack. @property def _testcase(self): - return self._obj.__self__ + return self.instance def setup(self) -> None: # A bound method to be called during teardown() if set (see 'runtest()'). @@ -296,7 +295,8 @@ def addDuration(self, testcase: "unittest.TestCase", elapsed: float) -> None: def runtest(self) -> None: from _pytest.debugging import maybe_wrap_pytest_function_for_tracing - testcase = self.obj.__self__ + testcase = self.instance + assert testcase is not None maybe_wrap_pytest_function_for_tracing(self) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 8d59b36d319..2e277626cde 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4577,3 +4577,48 @@ def test_deduplicate_names() -> None: assert items == ("a", "b", "c", "d") items = deduplicate_names((*items, "g", "f", "g", "e", "b")) assert items == ("a", "b", "c", "d", "g", "f", "e") + + +def test_staticmethod_classmethod_fixture_instance(pytester: Pytester) -> None: + """Ensure that static and class methods get and have access to a fresh + instance. + + This also ensures `setup_method` works well with static and class methods. + + Regression test for #12065. + """ + pytester.makepyfile( + """ + import pytest + + class Test: + ran_setup_method = False + ran_fixture = False + + def setup_method(self): + assert not self.ran_setup_method + self.ran_setup_method = True + + @pytest.fixture(autouse=True) + def fixture(self): + assert not self.ran_fixture + self.ran_fixture = True + + def test_method(self): + assert self.ran_setup_method + assert self.ran_fixture + + @staticmethod + def test_1(request): + assert request.instance.ran_setup_method + assert request.instance.ran_fixture + + @classmethod + def test_2(cls, request): + assert request.instance.ran_setup_method + assert request.instance.ran_fixture + """ + ) + result = pytester.runpytest() + assert result.ret == ExitCode.OK + result.assert_outcomes(passed=3) diff --git a/testing/python/integration.py b/testing/python/integration.py index a6c14ece407..219ebf9cec8 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -410,22 +410,37 @@ def test_function_instance(pytester: Pytester) -> None: items = pytester.getitems( """ def test_func(): pass + class TestIt: def test_method(self): pass + @classmethod def test_class(cls): pass + @staticmethod def test_static(): pass """ ) assert len(items) == 4 + assert isinstance(items[0], Function) assert items[0].name == "test_func" assert items[0].instance is None + assert isinstance(items[1], Function) assert items[1].name == "test_method" assert items[1].instance is not None assert items[1].instance.__class__.__name__ == "TestIt" + + # Even class and static methods get an instance! + # This is the instance used for bound fixture methods, which + # class/staticmethod tests are perfectly able to request. + assert isinstance(items[2], Function) + assert items[2].name == "test_class" + assert items[2].instance is not None + assert isinstance(items[3], Function) assert items[3].name == "test_static" - assert items[3].instance is None + assert items[3].instance is not None + + assert items[1].instance is not items[2].instance is not items[3].instance From b777b05c0e845fd3d26d22348991b2d19212250b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 10 Mar 2024 09:57:13 -0300 Subject: [PATCH 0546/1271] [automated] Update plugin list (#12098) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 184 +++++++++++++++++-------------- 1 file changed, 104 insertions(+), 80 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index fb3ff912cd7..8ca3a748ba3 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.1.0 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 06, 2023 N/A pytest (>=6.0) + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Mar 04, 2024 N/A pytest (>=6.0) :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -107,7 +107,7 @@ This list contains 1408 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Feb 09, 2024 4 - Beta pytest <9,>=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Mar 08, 2024 4 - Beta pytest <9,>=7.0.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 25, 2024 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) @@ -135,7 +135,7 @@ This list contains 1408 plugins. :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 - :pypi:`pytest-bdd` BDD for pytest Dec 02, 2023 6 - Mature pytest (>=6.2.0) + :pypi:`pytest-bdd` BDD for pytest Mar 04, 2024 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Feb 19, 2024 N/A pytest >=7.1.3 @@ -149,7 +149,7 @@ This list contains 1408 plugins. :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A - :pypi:`pytest-better-parametrize` Better description of parametrized test cases Feb 26, 2024 4 - Beta pytest >=6.2.0 + :pypi:`pytest-better-parametrize` Better description of parametrized test cases Mar 05, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) @@ -193,11 +193,11 @@ This list contains 1408 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-cases` Separate test code from test cases in pytest. Jan 12, 2024 5 - Production/Stable N/A + :pypi:`pytest-cases` Separate test code from test cases in pytest. Mar 08, 2024 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Feb 12, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Mar 09, 2024 N/A N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -211,7 +211,8 @@ This list contains 1408 plugins. :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A - :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest>=7.0 + :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<8,>=7.0 + :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Mar 06, 2024 N/A N/A :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 20, 2024 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 @@ -232,7 +233,7 @@ This list contains 1408 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Jul 19, 2023 N/A pytest<8,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Mar 04, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 @@ -274,7 +275,7 @@ This list contains 1408 plugins. :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Aug 26, 2023 N/A N/A + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Mar 09, 2024 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -393,7 +394,7 @@ This list contains 1408 plugins. :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) :pypi:`pytest-doctest-mkdocstrings` Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) Mar 02, 2024 N/A pytest - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Dec 13, 2023 5 - Production/Stable pytest >=4.6 + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Mar 04, 2024 5 - Production/Stable 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 Dec 14, 2023 N/A N/A :pypi:`pytest-dolphin` Some extra stuff that we use ininternally Nov 30, 2016 4 - Beta pytest (==3.0.4) @@ -404,7 +405,7 @@ This list contains 1408 plugins. :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A - :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection May 23, 2020 4 - Beta pytest (>=2.7) + :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection Mar 04, 2024 5 - Production/Stable pytest >=7 :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 18, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A @@ -483,7 +484,7 @@ This list contains 1408 plugins. :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) - :pypi:`pytest-factoryboy` Factory Boy support for pytest. Oct 10, 2023 6 - Mature pytest (>=6.2) + :pypi:`pytest-factoryboy` Factory Boy support for pytest. Mar 05, 2024 6 - Mature pytest (>=6.2) :pypi:`pytest-factoryboy-fixtures` Generates pytest fixtures that allow the use of type hinting Jun 25, 2020 N/A N/A :pypi:`pytest-factoryboy-state` Simple factoryboy random state management Mar 22, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-failed-screen-record` Create a video of the screen when pytest fails Jan 05, 2023 4 - Beta pytest (>=7.1.2d,<8.0.0) @@ -506,7 +507,7 @@ This list contains 1408 plugins. :pypi:`pytest-filemarker` A pytest plugin that runs marked tests when files change. Dec 01, 2020 N/A pytest :pypi:`pytest-file-watcher` Pytest-File-Watcher is a CLI tool that watches for changes in your code and runs pytest on the changed files. Mar 23, 2023 N/A pytest :pypi:`pytest-filter-case` run test cases filter by mark Nov 05, 2020 N/A N/A - :pypi:`pytest-filter-subpackage` Pytest plugin for filtering based on sub-packages Dec 12, 2022 3 - Alpha pytest (>=3.0) + :pypi:`pytest-filter-subpackage` Pytest plugin for filtering based on sub-packages Mar 04, 2024 5 - Production/Stable pytest >=4.6 :pypi:`pytest-find-dependencies` A pytest plugin to find dependencies between tests Apr 09, 2022 4 - Beta pytest (>=4.3.0) :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) @@ -539,6 +540,7 @@ This list contains 1408 plugins. :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A + :pypi:`pytest-forks` Fork helper for pytest Mar 05, 2024 N/A N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Oct 29, 2023 4 - Beta pytest>=7.0.0 @@ -600,7 +602,7 @@ This list contains 1408 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Mar 01, 2024 3 - Alpha pytest ==8.0.2 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 07, 2024 3 - Alpha pytest ==8.0.2 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jan 06, 2024 N/A N/A @@ -669,7 +671,7 @@ This list contains 1408 plugins. :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest - :pypi:`pytest-isort` py.test plugin to check import ordering using isort Oct 31, 2022 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A @@ -718,7 +720,7 @@ This list contains 1408 plugins. :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A - :pypi:`pytest-leaping` Coming soon! Mar 02, 2024 N/A N/A + :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 08, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A @@ -754,7 +756,7 @@ This list contains 1408 plugins. :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) - :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Feb 07, 2024 N/A pytest (>=7.0.0) + :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 05, 2024 N/A pytest (>=7.0.0) :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A @@ -787,7 +789,7 @@ This list contains 1408 plugins. :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Jan 04, 2024 N/A pytest >=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Feb 28, 2024 N/A pytest >=7.0 + :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Mar 07, 2024 N/A pytest >=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Oct 19, 2023 5 - Production/Stable pytest >=5.0 @@ -796,7 +798,7 @@ This list contains 1408 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Feb 01, 2024 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Mar 06, 2024 N/A pytest (>=1.0) :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -829,12 +831,12 @@ This list contains 1408 plugins. :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Feb 29, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 - :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Feb 26, 2024 N/A pytest>=7,<9 + :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Oct 26, 2023 N/A pytest <7.3,>=3.5.0 + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Mar 07, 2024 N/A pytest <7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -868,7 +870,7 @@ This list contains 1408 plugins. :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 May 16, 2023 N/A N/A :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A - :pypi:`pytest-only` Use @pytest.mark.only to run a single test Jun 14, 2022 5 - Production/Stable pytest (<7.1); python_version <= "3.6" + :pypi:`pytest-only` Use @pytest.mark.only to run a single test Mar 09, 2024 5 - Production/Stable pytest (<7.1) ; python_full_version <= "3.6.0" :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 11, 2023 4 - Beta N/A :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) @@ -956,7 +958,7 @@ This list contains 1408 plugins. :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Jan 29, 2024 5 - Production/Stable pytest >=6.2 + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 07, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 @@ -1082,7 +1084,7 @@ This list contains 1408 plugins. :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jul 10, 2023 5 - Production/Stable pytest - :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Feb 27, 2024 N/A pytest>=7.2.0 + :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A @@ -1098,14 +1100,14 @@ This list contains 1408 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Feb 27, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 08, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Oct 31, 2023 4 - Beta N/A + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Mar 03, 2024 4 - Beta pytest (>=5) :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest @@ -1122,7 +1124,7 @@ This list contains 1408 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 09, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1131,7 +1133,7 @@ This list contains 1408 plugins. :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 Feb 01, 2024 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. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 09, 2024 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 @@ -1236,7 +1238,7 @@ This list contains 1408 plugins. :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) + :pypi:`pytest-subtests` unittest subTest() support and subtests fixture Mar 07, 2024 4 - Beta pytest >=7.0 :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Feb 01, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A @@ -1244,7 +1246,7 @@ This list contains 1408 plugins. :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A - :pypi:`pytest-synodic` Synodic Pytest utilities Jan 12, 2024 N/A pytest>=7.4.4 + :pypi:`pytest-synodic` Synodic Pytest utilities Mar 09, 2024 N/A pytest>=8.0.2 :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A :pypi:`pytest_tagging` a pytest plugin to tag tests Feb 15, 2024 N/A pytest (>=7.1.3,<8.0.0) @@ -1290,7 +1292,7 @@ This list contains 1408 plugins. :pypi:`pytest-testrail-ns` pytest plugin for creating TestRail runs and adding results Aug 12, 2022 N/A N/A :pypi:`pytest-testrail-plugin` PyTest plugin for TestRail Apr 21, 2020 3 - Alpha pytest :pypi:`pytest-testrail-reporter` Sep 10, 2018 N/A N/A - :pypi:`pytest-testrail-results` A pytest plugin to upload results to TestRail. Mar 01, 2024 N/A pytest >=7.2.0 + :pypi:`pytest-testrail-results` A pytest plugin to upload results to TestRail. Mar 04, 2024 N/A pytest >=7.2.0 :pypi:`pytest-testreport` Dec 01, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-testreport-new` Oct 07, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) @@ -1307,7 +1309,7 @@ This list contains 1408 plugins. :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest :pypi:`pytest-timeassert-ethan` execution duration Dec 25, 2023 N/A pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A - :pypi:`pytest-timeout` pytest plugin to abort hanging tests Oct 08, 2023 5 - Production/Stable pytest >=5.0.0 + :pypi:`pytest-timeout` pytest plugin to abort hanging tests Mar 07, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A :pypi:`pytest-timer` A timer plugin for pytest Dec 26, 2023 N/A pytest :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A @@ -1416,7 +1418,7 @@ This list contains 1408 plugins. :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jan 28, 2024 N/A pytest<8.1,>=7.4.0 + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jan 28, 2024 N/A pytest<8,>=7.4.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Sep 23, 2023 4 - Beta pytest (>=2.8) :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A @@ -1440,6 +1442,7 @@ This list contains 1408 plugins. :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jan 08, 2024 5 - Production/Stable pytest (>=4.5.0) :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A + :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ @@ -1623,7 +1626,7 @@ This list contains 1408 plugins. :pypi:`pytest-alembic` - *last release*: Jul 06, 2023, + *last release*: Mar 04, 2024, *status*: N/A, *requires*: pytest (>=6.0) @@ -1959,7 +1962,7 @@ This list contains 1408 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Feb 09, 2024, + *last release*: Mar 08, 2024, *status*: 4 - Beta, *requires*: pytest <9,>=7.0.0 @@ -2155,7 +2158,7 @@ This list contains 1408 plugins. pytest plugin for URL based testing :pypi:`pytest-bdd` - *last release*: Dec 02, 2023, + *last release*: Mar 04, 2024, *status*: 6 - Mature, *requires*: pytest (>=6.2.0) @@ -2253,7 +2256,7 @@ This list contains 1408 plugins. A small example package :pypi:`pytest-better-parametrize` - *last release*: Feb 26, 2024, + *last release*: Mar 05, 2024, *status*: 4 - Beta, *requires*: pytest >=6.2.0 @@ -2561,7 +2564,7 @@ This list contains 1408 plugins. pytest plugin to capture all warnings and put them in one file of your choice :pypi:`pytest-cases` - *last release*: Jan 12, 2024, + *last release*: Mar 08, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -2589,7 +2592,7 @@ This list contains 1408 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Feb 12, 2024, + *last release*: Mar 09, 2024, *status*: N/A, *requires*: N/A @@ -2689,10 +2692,17 @@ This list contains 1408 plugins. :pypi:`pytest-check-links` *last release*: Jul 29, 2020, *status*: N/A, - *requires*: pytest>=7.0 + *requires*: pytest<8,>=7.0 Check links in files + :pypi:`pytest-checklist` + *last release*: Mar 06, 2024, + *status*: N/A, + *requires*: N/A + + Pytest plugin to track and report unit/function coverage. + :pypi:`pytest-check-mk` *last release*: Nov 19, 2015, *status*: 4 - Beta, @@ -2834,9 +2844,9 @@ This list contains 1408 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Jul 19, 2023, + *last release*: Mar 04, 2024, *status*: N/A, - *requires*: pytest<8,>=4 + *requires*: pytest<9,>=4 Provide CMake module for Pytest @@ -3128,7 +3138,7 @@ This list contains 1408 plugins. Use pytest's runner to discover and execute C++ tests :pypi:`pytest-cppython` - *last release*: Aug 26, 2023, + *last release*: Mar 09, 2024, *status*: N/A, *requires*: N/A @@ -3961,7 +3971,7 @@ This list contains 1408 plugins. Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) :pypi:`pytest-doctestplus` - *last release*: Dec 13, 2023, + *last release*: Mar 04, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=4.6 @@ -4038,9 +4048,9 @@ This list contains 1408 plugins. Tool to allow webdriver automation to be ran locally or remotely :pypi:`pytest-drop-dup-tests` - *last release*: May 23, 2020, - *status*: 4 - Beta, - *requires*: pytest (>=2.7) + *last release*: Mar 04, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest >=7 A Pytest plugin to drop duplicated tests during collection @@ -4591,7 +4601,7 @@ This list contains 1408 plugins. Use factories for test setup with py.test :pypi:`pytest-factoryboy` - *last release*: Oct 10, 2023, + *last release*: Mar 05, 2024, *status*: 6 - Mature, *requires*: pytest (>=6.2) @@ -4752,9 +4762,9 @@ This list contains 1408 plugins. run test cases filter by mark :pypi:`pytest-filter-subpackage` - *last release*: Dec 12, 2022, - *status*: 3 - Alpha, - *requires*: pytest (>=3.0) + *last release*: Mar 04, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest >=4.6 Pytest plugin for filtering based on sub-packages @@ -4982,6 +4992,13 @@ This list contains 1408 plugins. py.test plugin to make the test failing regardless of pytest.mark.xfail + :pypi:`pytest-forks` + *last release*: Mar 05, 2024, + *status*: N/A, + *requires*: N/A + + Fork helper for pytest + :pypi:`pytest-forward-compatability` *last release*: Sep 06, 2020, *status*: N/A, @@ -5410,7 +5427,7 @@ This list contains 1408 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 01, 2024, + *last release*: Mar 07, 2024, *status*: 3 - Alpha, *requires*: pytest ==8.0.2 @@ -5893,7 +5910,7 @@ This list contains 1408 plugins. :pypi:`pytest-isort` - *last release*: Oct 31, 2022, + *last release*: Mar 05, 2024, *status*: 5 - Production/Stable, *requires*: pytest (>=5.0) @@ -6236,11 +6253,11 @@ This list contains 1408 plugins. A pytest plugin to trace resource leaks. :pypi:`pytest-leaping` - *last release*: Mar 02, 2024, - *status*: N/A, - *requires*: N/A + *last release*: Mar 08, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 - Coming soon! + A simple plugin to use with pytest :pypi:`pytest-level` *last release*: Oct 21, 2019, @@ -6488,7 +6505,7 @@ This list contains 1408 plugins. Test your markdown docs with pytest :pypi:`pytest-markdown-docs` - *last release*: Feb 07, 2024, + *last release*: Mar 05, 2024, *status*: N/A, *requires*: pytest (>=7.0.0) @@ -6719,7 +6736,7 @@ This list contains 1408 plugins. Pytest plugin that creates missing fixtures :pypi:`pytest-mitmproxy` - *last release*: Feb 28, 2024, + *last release*: Mar 07, 2024, *status*: N/A, *requires*: pytest >=7.0 @@ -6782,7 +6799,7 @@ This list contains 1408 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Feb 01, 2024, + *last release*: Mar 06, 2024, *status*: N/A, *requires*: pytest (>=1.0) @@ -7013,7 +7030,7 @@ This list contains 1408 plugins. Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. :pypi:`pytest-mypy-testing` - *last release*: Feb 26, 2024, + *last release*: Mar 04, 2024, *status*: N/A, *requires*: pytest>=7,<9 @@ -7048,7 +7065,7 @@ This list contains 1408 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-netdut` - *last release*: Oct 26, 2023, + *last release*: Mar 07, 2024, *status*: N/A, *requires*: pytest <7.3,>=3.5.0 @@ -7286,9 +7303,9 @@ This list contains 1408 plugins. The ultimate pytest output plugin :pypi:`pytest-only` - *last release*: Jun 14, 2022, + *last release*: Mar 09, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (<7.1); python_version <= "3.6" + *requires*: pytest (<7.1) ; python_full_version <= "3.6.0" Use @pytest.mark.only to run a single test @@ -7902,7 +7919,7 @@ This list contains 1408 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: Jan 29, 2024, + *last release*: Mar 07, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=6.2 @@ -8784,7 +8801,7 @@ This list contains 1408 plugins. Pytest plugin to restrict the test types allowed :pypi:`pytest-result-log` - *last release*: Feb 27, 2024, + *last release*: Jan 10, 2024, *status*: N/A, *requires*: pytest>=7.2.0 @@ -8896,7 +8913,7 @@ This list contains 1408 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Feb 27, 2024, + *last release*: Mar 08, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -8945,9 +8962,9 @@ This list contains 1408 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Oct 31, 2023, + *last release*: Mar 03, 2024, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest (>=5) pytest plugin to check ruff requirements. @@ -9064,7 +9081,7 @@ This list contains 1408 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Mar 01, 2024, + *last release*: Mar 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9127,7 +9144,7 @@ This list contains 1408 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Mar 01, 2024, + *last release*: Mar 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9862,9 +9879,9 @@ This list contains 1408 plugins. A hack to explicitly set up and tear down fixtures. :pypi:`pytest-subtests` - *last release*: May 15, 2023, + *last release*: Mar 07, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.0) + *requires*: pytest >=7.0 unittest subTest() support and subtests fixture @@ -9918,9 +9935,9 @@ This list contains 1408 plugins. pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. :pypi:`pytest-synodic` - *last release*: Jan 12, 2024, + *last release*: Mar 09, 2024, *status*: N/A, - *requires*: pytest>=7.4.4 + *requires*: pytest>=8.0.2 Synodic Pytest utilities @@ -10240,7 +10257,7 @@ This list contains 1408 plugins. :pypi:`pytest-testrail-results` - *last release*: Mar 01, 2024, + *last release*: Mar 04, 2024, *status*: N/A, *requires*: pytest >=7.2.0 @@ -10359,9 +10376,9 @@ This list contains 1408 plugins. A pytest plugin to time test function runs :pypi:`pytest-timeout` - *last release*: Oct 08, 2023, + *last release*: Mar 07, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=5.0.0 + *requires*: pytest >=7.0.0 pytest plugin to abort hanging tests @@ -11124,7 +11141,7 @@ This list contains 1408 plugins. :pypi:`pytest-xlsx` *last release*: Jan 28, 2024, *status*: N/A, - *requires*: pytest<8.1,>=7.4.0 + *requires*: pytest<8,>=7.4.0 pytest plugin for generating test cases by xlsx(excel) @@ -11289,6 +11306,13 @@ This list contains 1408 plugins. Zesty additions to pytest. + :pypi:`pytest-zhongwen-wendang` + *last release*: Mar 04, 2024, + *status*: 4 - Beta, + *requires*: N/A + + PyTest 中文文档 + :pypi:`pytest-zigzag` *last release*: Feb 27, 2019, *status*: 4 - Beta, From 0a442a959920df1d782a19b48b8c63abf6b2aef4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 10 Mar 2024 16:51:04 +0200 Subject: [PATCH 0547/1271] doc/flaky: remove `box/flaky` plugin suggestion (#12100) The plugin is abandoned and no longer working with new pytest versions. I also reordered a bit to put pytest-rerunfailures first since it seems most maintained and is under pytest-dev. --- doc/en/explanation/flaky.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/en/explanation/flaky.rst b/doc/en/explanation/flaky.rst index ccf3fbb2b0c..2beeb34e0f8 100644 --- a/doc/en/explanation/flaky.rst +++ b/doc/en/explanation/flaky.rst @@ -52,10 +52,9 @@ Plugins Rerunning any failed tests can mitigate the negative effects of flaky tests by giving them additional chances to pass, so that the overall build does not fail. Several pytest plugins support this: -* `flaky `_ -* `pytest-flakefinder `_ - `blog post `_ * `pytest-rerunfailures `_ * `pytest-replay `_: This plugin helps to reproduce locally crashes or flaky tests observed during CI runs. +* `pytest-flakefinder `_ - `blog post `_ Plugins to deliberately randomize tests can help expose tests with state problems: From a29ea1bc326dee3f6ddb66d3749fcfea917b8093 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 07:04:19 +0100 Subject: [PATCH 0548/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.8.12 to 1.8.14 (#12105) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.12 to 1.8.14. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.12...v1.8.14) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d46f1f91d34..9d23d22e832 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -47,7 +47,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.8.12 + uses: pypa/gh-action-pypi-publish@v1.8.14 - name: Push tag run: | From 122b43439c872ed39fc5099344191ab418b6a2a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 07:05:41 +0100 Subject: [PATCH 0549/1271] build(deps): Bump django in /testing/plugins_integration (#12103) Bumps [django](https://github.com/django/django) from 5.0.2 to 5.0.3. - [Commits](https://github.com/django/django/compare/5.0.2...5.0.3) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d2f3fad17d5..43e7ed4f22b 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.3.0 -django==5.0.2 +django==5.0.3 pytest-asyncio==0.23.5 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 From 6c9e1076813f9be6c87bdb31b81a8149eb047c6c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:48:06 -0300 Subject: [PATCH 0550/1271] build(deps): Bump softprops/action-gh-release from 1 to 2 (#12106) Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2. - [Release notes](https://github.com/softprops/action-gh-release/releases) - [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2) --- updated-dependencies: - dependency-name: softprops/action-gh-release dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9d23d22e832..4ed68c286cb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -94,7 +94,7 @@ jobs: tox -e generate-gh-release-notes -- ${{ github.event.inputs.version }} scripts/latest-release-notes.md - name: Publish GitHub Release - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: body_path: scripts/latest-release-notes.md files: dist/* From 7eaaf370bb40252701bf1dfad39669541d92c27e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 11 Mar 2024 18:22:16 +0200 Subject: [PATCH 0551/1271] doc: add versionadded to `Stash` and `StashKey` Fixes #12107 --- src/_pytest/stash.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/_pytest/stash.py b/src/_pytest/stash.py index e61d75b95f7..a4b829fc6dd 100644 --- a/src/_pytest/stash.py +++ b/src/_pytest/stash.py @@ -19,6 +19,8 @@ class StashKey(Generic[T]): A ``StashKey`` is associated with the type ``T`` of the value of the key. A ``StashKey`` is unique and cannot conflict with another key. + + .. versionadded:: 7.0 """ __slots__ = () @@ -61,6 +63,8 @@ class Stash: some_str = stash[some_str_key] # The static type of some_bool is bool. some_bool = stash[some_bool_key] + + .. versionadded:: 7.0 """ __slots__ = ("_storage",) From c0532dda18a5cfd0e6f67113bb164485fa80eb86 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 15:30:18 +0200 Subject: [PATCH 0552/1271] [pre-commit.ci] pre-commit autoupdate (#12115) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas Co-authored-by: Ran Benita --- .pre-commit-config.yaml | 4 +- pyproject.toml | 2 + scripts/generate-gh-release-notes.py | 1 + scripts/prepare-release-pr.py | 1 + scripts/release.py | 1 + src/_pytest/__init__.py | 2 +- src/_pytest/_code/code.py | 28 +++++++------- src/_pytest/_code/source.py | 6 +-- src/_pytest/_io/terminalwriter.py | 3 ++ src/_pytest/_py/path.py | 37 ++++++------------- src/_pytest/assertion/__init__.py | 1 + src/_pytest/assertion/rewrite.py | 14 +++---- src/_pytest/assertion/util.py | 6 +-- src/_pytest/cacheprovider.py | 3 +- src/_pytest/capture.py | 33 +++++++---------- src/_pytest/compat.py | 2 +- src/_pytest/config/__init__.py | 1 + src/_pytest/config/argparsing.py | 3 +- src/_pytest/debugging.py | 5 +-- src/_pytest/doctest.py | 1 + src/_pytest/fixtures.py | 34 ++++++++--------- src/_pytest/freeze_support.py | 2 +- src/_pytest/helpconfig.py | 1 + src/_pytest/hookspec.py | 1 + src/_pytest/junitxml.py | 5 ++- src/_pytest/logging.py | 5 ++- src/_pytest/main.py | 6 +-- src/_pytest/mark/structures.py | 24 +++++------- src/_pytest/monkeypatch.py | 7 ++-- src/_pytest/nodes.py | 6 +-- src/_pytest/pastebin.py | 1 + src/_pytest/pytester.py | 22 ++++------- src/_pytest/python.py | 1 + src/_pytest/python_api.py | 16 ++++---- src/_pytest/recwarn.py | 16 +++----- src/_pytest/reports.py | 9 ++--- src/_pytest/runner.py | 6 +-- src/_pytest/setuponly.py | 4 +- src/_pytest/skipping.py | 3 +- src/_pytest/terminal.py | 1 + src/_pytest/tmpdir.py | 1 + src/_pytest/unittest.py | 13 +++---- src/pytest/__init__.py | 1 + testing/_py/test_local.py | 10 ++--- testing/code/test_excinfo.py | 2 +- .../acceptance/fixture_mock_integration.py | 1 + .../unittest/test_setup_skip.py | 1 + .../unittest/test_setup_skip_class.py | 1 + .../unittest/test_setup_skip_module.py | 1 + .../unittest/test_unittest_asynctest.py | 1 + testing/io/test_wcwidth.py | 4 +- testing/python/metafunc.py | 4 +- testing/test_config.py | 2 +- testing/test_debugging.py | 2 +- testing/test_junitxml.py | 2 +- testing/test_mark.py | 4 +- testing/test_pathlib.py | 14 +++---- testing/test_reports.py | 6 +-- testing/test_runner_xunit.py | 1 + testing/test_terminal.py | 1 + testing/typing_checks.py | 1 + 61 files changed, 185 insertions(+), 212 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 78cf36bae4c..deb187fec13 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.2.2" + rev: "v0.3.2" hooks: - id: ruff args: ["--fix"] @@ -26,7 +26,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 + rev: v1.9.0 hooks: - id: mypy files: ^(src/|testing/|scripts/) diff --git a/pyproject.toml b/pyproject.toml index e14556f2ff0..7d1b8a22df9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -281,6 +281,7 @@ template = "changelog/_template.rst" showcontent = true [tool.mypy] +files = ["src", "testing", "scripts"] mypy_path = ["src"] check_untyped_defs = true disallow_any_generics = true @@ -293,3 +294,4 @@ warn_return_any = true warn_unreachable = true warn_unused_configs = true no_implicit_reexport = true +warn_unused_ignores = true diff --git a/scripts/generate-gh-release-notes.py b/scripts/generate-gh-release-notes.py index c27f5774b6e..4222702d5d4 100644 --- a/scripts/generate-gh-release-notes.py +++ b/scripts/generate-gh-release-notes.py @@ -8,6 +8,7 @@ Requires Python3.6+. """ + from pathlib import Path import re import sys diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index 8a9f0aa0f3b..7dabbd3b328 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -13,6 +13,7 @@ **Token**: currently the token from the GitHub Actions is used, pushed with `pytest bot ` commit author. """ + import argparse from pathlib import Path import re diff --git a/scripts/release.py b/scripts/release.py index 73f5f52b1b0..bcbc4262d08 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -1,5 +1,6 @@ # mypy: disallow-untyped-defs """Invoke development tasks.""" + import argparse import os from pathlib import Path diff --git a/src/_pytest/__init__.py b/src/_pytest/__init__.py index 9062768eae3..b694a5f244a 100644 --- a/src/_pytest/__init__.py +++ b/src/_pytest/__init__.py @@ -7,4 +7,4 @@ # broken installation, we don't even try # unknown only works because we do poor mans version compare __version__ = "unknown" - version_tuple = (0, 0, "unknown") # type:ignore[assignment] + version_tuple = (0, 0, "unknown") diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 12168be607c..64a8f243a2d 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -279,9 +279,9 @@ def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool: Mostly for internal use. """ - tbh: Union[ - bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool] - ] = False + tbh: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]] = ( + False + ) for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals): # in normal cases, f_locals and f_globals are dictionaries # however via `exec(...)` / `eval(...)` they can be other types @@ -378,12 +378,10 @@ def cut( return self @overload - def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: - ... + def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: ... @overload - def __getitem__(self, key: slice) -> "Traceback": - ... + def __getitem__(self, key: slice) -> "Traceback": ... def __getitem__( self, key: Union["SupportsIndex", slice] @@ -1051,13 +1049,13 @@ def repr_excinfo( # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 if isinstance(e, BaseExceptionGroup): - reprtraceback: Union[ - ReprTracebackNative, ReprTraceback - ] = ReprTracebackNative( - traceback.format_exception( - type(excinfo_.value), - excinfo_.value, - excinfo_.traceback[0]._rawentry, + reprtraceback: Union[ReprTracebackNative, ReprTraceback] = ( + ReprTracebackNative( + traceback.format_exception( + type(excinfo_.value), + excinfo_.value, + excinfo_.traceback[0]._rawentry, + ) ) ) else: @@ -1348,7 +1346,7 @@ def getfslineno(obj: object) -> Tuple[Union[str, Path], int]: # in 6ec13a2b9. It ("place_as") appears to be something very custom. obj = get_real_func(obj) if hasattr(obj, "place_as"): - obj = obj.place_as # type: ignore[attr-defined] + obj = obj.place_as try: code = Code.from_function(obj) diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index dac3c3867d8..7fa577e03b3 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -47,12 +47,10 @@ def __eq__(self, other: object) -> bool: __hash__ = None # type: ignore @overload - def __getitem__(self, key: int) -> str: - ... + def __getitem__(self, key: int) -> str: ... @overload - def __getitem__(self, key: slice) -> "Source": - ... + def __getitem__(self, key: slice) -> "Source": ... def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]: if isinstance(key, int): diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index badbb7e4a5f..deb6ecc3c94 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -9,6 +9,7 @@ from typing import Sequence from typing import TextIO +from ..compat import assert_never from .wcwidth import wcswidth @@ -209,6 +210,8 @@ def _highlight( from pygments.lexers.python import PythonLexer as Lexer elif lexer == "diff": from pygments.lexers.diff import DiffLexer as Lexer + else: + assert_never(lexer) from pygments import highlight import pygments.util except ImportError: diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 7701561d90e..7bb3693f938 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """local path implementation.""" + from __future__ import annotations import atexit @@ -205,12 +206,10 @@ class Stat: if TYPE_CHECKING: @property - def size(self) -> int: - ... + def size(self) -> int: ... @property - def mtime(self) -> float: - ... + def mtime(self) -> float: ... def __getattr__(self, name: str) -> Any: return getattr(self._osstatresult, "st_" + name) @@ -225,7 +224,7 @@ def owner(self): raise NotImplementedError("XXX win32") import pwd - entry = error.checked_call(pwd.getpwuid, self.uid) # type:ignore[attr-defined] + entry = error.checked_call(pwd.getpwuid, self.uid) # type:ignore[attr-defined,unused-ignore] return entry[0] @property @@ -235,7 +234,7 @@ def group(self): raise NotImplementedError("XXX win32") import grp - entry = error.checked_call(grp.getgrgid, self.gid) # type:ignore[attr-defined] + entry = error.checked_call(grp.getgrgid, self.gid) # type:ignore[attr-defined,unused-ignore] return entry[0] def isdir(self): @@ -253,7 +252,7 @@ def getuserid(user): import pwd if not isinstance(user, int): - user = pwd.getpwnam(user)[2] # type:ignore[attr-defined] + user = pwd.getpwnam(user)[2] # type:ignore[attr-defined,unused-ignore] return user @@ -261,7 +260,7 @@ def getgroupid(group): import grp if not isinstance(group, int): - group = grp.getgrnam(group)[2] # type:ignore[attr-defined] + group = grp.getgrnam(group)[2] # type:ignore[attr-defined,unused-ignore] return group @@ -318,7 +317,7 @@ def chown(self, user, group, rec=0): def readlink(self) -> str: """Return value of a symbolic link.""" # https://github.com/python/mypy/issues/12278 - return error.checked_call(os.readlink, self.strpath) # type: ignore[arg-type,return-value] + return error.checked_call(os.readlink, self.strpath) # type: ignore[arg-type,return-value,unused-ignore] def mklinkto(self, oldname): """Posix style hard link to another name.""" @@ -757,15 +756,11 @@ def open(self, mode="r", ensure=False, encoding=None): if ensure: self.dirpath().ensure(dir=1) if encoding: - # Using type ignore here because of this error: - # error: Argument 1 has incompatible type overloaded function; - # expected "Callable[[str, Any, Any], TextIOWrapper]" [arg-type] - # Which seems incorrect, given io.open supports the given argument types. return error.checked_call( io.open, self.strpath, mode, - encoding=encoding, # type:ignore[arg-type] + encoding=encoding, ) return error.checked_call(open, self.strpath, mode) @@ -966,12 +961,10 @@ def ensure(self, *args, **kwargs): return p @overload - def stat(self, raising: Literal[True] = ...) -> Stat: - ... + def stat(self, raising: Literal[True] = ...) -> Stat: ... @overload - def stat(self, raising: Literal[False]) -> Stat | None: - ... + def stat(self, raising: Literal[False]) -> Stat | None: ... def stat(self, raising: bool = True) -> Stat | None: """Return an os.stat() tuple.""" @@ -1277,13 +1270,7 @@ def mkdtemp(cls, rootdir=None): if rootdir is None: rootdir = cls.get_temproot() - # Using type ignore here because of this error: - # error: Argument 1 has incompatible type overloaded function; expected "Callable[[str], str]" [arg-type] - # Which seems incorrect, given tempfile.mkdtemp supports the given argument types. - path = error.checked_call( - tempfile.mkdtemp, - dir=str(rootdir), # type:ignore[arg-type] - ) + path = error.checked_call(tempfile.mkdtemp, dir=str(rootdir)) return cls(path) @classmethod diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index ea71230e129..21dd4a4a4bb 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Support for presenting detailed information in failing assertions.""" + import sys from typing import Any from typing import Generator diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index ddae34c7326..678471ee992 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -289,15 +289,13 @@ def get_data(self, pathname: Union[str, bytes]) -> bytes: else: from importlib.abc import TraversableResources - def get_resource_reader(self, name: str) -> TraversableResources: # type: ignore + def get_resource_reader(self, name: str) -> TraversableResources: if sys.version_info < (3, 11): from importlib.readers import FileReader else: from importlib.resources.readers import FileReader - return FileReader( # type:ignore[no-any-return] - types.SimpleNamespace(path=self._rewritten_names[name]) - ) + return FileReader(types.SimpleNamespace(path=self._rewritten_names[name])) def _write_pyc_fp( @@ -672,9 +670,9 @@ def __init__( self.enable_assertion_pass_hook = False self.source = source self.scope: tuple[ast.AST, ...] = () - self.variables_overwrite: defaultdict[ - tuple[ast.AST, ...], Dict[str, str] - ] = defaultdict(dict) + self.variables_overwrite: defaultdict[tuple[ast.AST, ...], Dict[str, str]] = ( + defaultdict(dict) + ) def run(self, mod: ast.Module) -> None: """Find all assert statements in *mod* and rewrite them.""" @@ -975,7 +973,7 @@ def visit_NamedExpr(self, name: ast.NamedExpr) -> Tuple[ast.NamedExpr, str]: # name if it's a local variable or _should_repr_global_name() # thinks it's acceptable. locs = ast.Call(self.builtin("locals"), [], []) - target_id = name.target.id # type: ignore[attr-defined] + target_id = name.target.id inlocs = ast.Compare(ast.Constant(target_id), [ast.In()], [locs]) dorepr = self.helper("_should_repr_global_name", name) test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index ca3df74903d..cb671641041 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Utilities for assertion debugging.""" + import collections.abc import os import pprint @@ -222,10 +223,9 @@ def assertrepr_compare( except outcomes.Exit: raise except Exception: + repr_crash = _pytest._code.ExceptionInfo.from_current()._getreprcrash() explanation = [ - "(pytest_assertion plugin: representation of details failed: {}.".format( - _pytest._code.ExceptionInfo.from_current()._getreprcrash() - ), + f"(pytest_assertion plugin: representation of details failed: {repr_crash}.", " Probably an object has a faulty __repr__.)", ] diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 5ccd2168ddf..81703ddac44 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Implementation of the cache provider.""" + # This plugin was not named "cache" to avoid conflicts with the external # pytest-cache version. import dataclasses @@ -432,7 +433,7 @@ def pytest_collection_modifyitems( return res def _get_increasing_order(self, items: Iterable[nodes.Item]) -> List[nodes.Item]: - return sorted(items, key=lambda item: item.path.stat().st_mtime, reverse=True) # type: ignore[no-any-return] + return sorted(items, key=lambda item: item.path.stat().st_mtime, reverse=True) def pytest_sessionfinish(self) -> None: config = self.config diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index dce431c3db4..3f6a2510348 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Per-test stdout/stderr capturing mechanism.""" + import abc import collections import contextlib @@ -105,17 +106,16 @@ def _windowsconsoleio_workaround(stream: TextIO) -> None: return # Bail out if ``stream`` doesn't seem like a proper ``io`` stream (#2666). - if not hasattr(stream, "buffer"): # type: ignore[unreachable] + if not hasattr(stream, "buffer"): # type: ignore[unreachable,unused-ignore] return - buffered = hasattr(stream.buffer, "raw") - raw_stdout = stream.buffer.raw if buffered else stream.buffer # type: ignore[attr-defined] + raw_stdout = stream.buffer.raw if hasattr(stream.buffer, "raw") else stream.buffer - if not isinstance(raw_stdout, io._WindowsConsoleIO): # type: ignore[attr-defined] + if not isinstance(raw_stdout, io._WindowsConsoleIO): # type: ignore[attr-defined,unused-ignore] return def _reopen_stdio(f, mode): - if not buffered and mode[0] == "w": + if not hasattr(stream.buffer, "raw") and mode[0] == "w": buffering = 0 else: buffering = -1 @@ -482,12 +482,9 @@ def __init__(self, targetfd: int) -> None: self._state = "initialized" def __repr__(self) -> str: - return "<{} {} oldfd={} _state={!r} tmpfile={!r}>".format( - self.__class__.__name__, - self.targetfd, - self.targetfd_save, - self._state, - self.tmpfile, + return ( + f"<{self.__class__.__name__} {self.targetfd} oldfd={self.targetfd_save} " + f"_state={self._state!r} tmpfile={self.tmpfile!r}>" ) def _assert_state(self, op: str, states: Tuple[str, ...]) -> None: @@ -621,12 +618,9 @@ def __init__( self.err: Optional[CaptureBase[AnyStr]] = err def __repr__(self) -> str: - return "".format( - self.out, - self.err, - self.in_, - self._state, - self._in_suspended, + return ( + f"" ) def start_capturing(self) -> None: @@ -735,8 +729,9 @@ def __init__(self, method: _CaptureMethod) -> None: self._capture_fixture: Optional[CaptureFixture[Any]] = None def __repr__(self) -> str: - return "".format( - self._method, self._global_capturing, self._capture_fixture + return ( + f"" ) def is_capturing(self) -> Union[str, bool]: diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 8d49d6fb631..9d9411818ac 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -304,7 +304,7 @@ def get_user_id() -> int | None: # mypy follows the version and platform checking expectation of PEP 484: # https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks # Containment checks are too complex for mypy v1.5.0 and cause failure. - if sys.platform == "win32" or sys.platform == "emscripten": # noqa: PLR1714 + if sys.platform == "win32" or sys.platform == "emscripten": # win32 does not have a getuid() function. # Emscripten has a return 0 stub. return None diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index bf2cfc3996d..7ff27643f10 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Command line options, ini-file and conftest.py processing.""" + import argparse import collections.abc import copy diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 441d79e902c..95dc28d4a16 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -426,8 +426,7 @@ def error(self, message: str) -> NoReturn: msg = f"{self.prog}: error: {message}" if hasattr(self._parser, "_config_source_hint"): - # Type ignored because the attribute is set dynamically. - msg = f"{msg} ({self._parser._config_source_hint})" # type: ignore + msg = f"{msg} ({self._parser._config_source_hint})" raise UsageError(self.format_usage() + msg) diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index cb157cd6724..6ed0c5c7aee 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Interactive debugging with PDB, the Python Debugger.""" + import argparse import functools import sys @@ -154,9 +155,7 @@ def _import_pdb_cls(cls, capman: Optional["CaptureManager"]): def _get_pdb_wrapper_class(cls, pdb_cls, capman: Optional["CaptureManager"]): import _pytest.config - # Type ignored because mypy doesn't support "dynamic" - # inheritance like this. - class PytestPdbWrapper(pdb_cls): # type: ignore[valid-type,misc] + class PytestPdbWrapper(pdb_cls): _pytest_capman = capman _continued = False diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index ced3b82f5ea..7fff99f37b5 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Discover and run doctests in modules and test files.""" + import bdb from contextlib import contextmanager import functools diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index daf3145aaac..8b25d743ca4 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -447,7 +447,7 @@ def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": @property def config(self) -> Config: """The pytest config object associated with this request.""" - return self._pyfuncitem.config # type: ignore[no-any-return] + return self._pyfuncitem.config @property def function(self): @@ -499,7 +499,7 @@ def keywords(self) -> MutableMapping[str, Any]: @property def session(self) -> "Session": """Pytest session object.""" - return self._pyfuncitem.session # type: ignore[no-any-return] + return self._pyfuncitem.session @abc.abstractmethod def addfinalizer(self, finalizer: Callable[[], object]) -> None: @@ -629,17 +629,14 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: ) except ValueError: source_path_str = str(source_path) + location = getlocation(fixturedef.func, funcitem.config.rootpath) msg = ( "The requested fixture has no parameter defined for test:\n" - " {}\n\n" - "Requested fixture '{}' defined in:\n{}" - "\n\nRequested here:\n{}:{}".format( - funcitem.nodeid, - fixturedef.argname, - getlocation(fixturedef.func, funcitem.config.rootpath), - source_path_str, - source_lineno, - ) + f" {funcitem.nodeid}\n\n" + f"Requested fixture '{fixturedef.argname}' defined in:\n" + f"{location}\n\n" + f"Requested here:\n" + f"{source_path_str}:{source_lineno}" ) fail(msg, pytrace=False) @@ -1108,12 +1105,12 @@ def resolve_fixture_function( # (for example a plugin class with a fixture), see #2270. if hasattr(fixturefunc, "__self__") and not isinstance( instance, - fixturefunc.__self__.__class__, # type: ignore[union-attr] + fixturefunc.__self__.__class__, ): return fixturefunc fixturefunc = getimfunc(fixturedef.func) if fixturefunc != fixturedef.func: - fixturefunc = fixturefunc.__get__(instance) # type: ignore[union-attr] + fixturefunc = fixturefunc.__get__(instance) return fixturefunc @@ -1147,12 +1144,13 @@ def wrap_function_to_error_out_if_called_directly( ) -> FixtureFunction: """Wrap the given fixture function so we can raise an error about it being called directly, instead of used as an argument in a test function.""" + name = fixture_marker.name or function.__name__ message = ( - 'Fixture "{name}" called directly. Fixtures are not meant to be called directly,\n' + f'Fixture "{name}" called directly. Fixtures are not meant to be called directly,\n' "but are created automatically when test functions request them as parameters.\n" "See https://docs.pytest.org/en/stable/explanation/fixtures.html for more information about fixtures, and\n" "https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly about how to update your code." - ).format(name=fixture_marker.name or function.__name__) + ) @functools.wraps(function) def result(*args, **kwargs): @@ -1219,8 +1217,7 @@ def fixture( Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] ] = ..., name: Optional[str] = ..., -) -> FixtureFunction: - ... +) -> FixtureFunction: ... @overload @@ -1234,8 +1231,7 @@ def fixture( Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] ] = ..., name: Optional[str] = None, -) -> FixtureFunctionMarker: - ... +) -> FixtureFunctionMarker: ... def fixture( diff --git a/src/_pytest/freeze_support.py b/src/_pytest/freeze_support.py index d028058e365..e03a6d1753d 100644 --- a/src/_pytest/freeze_support.py +++ b/src/_pytest/freeze_support.py @@ -35,7 +35,7 @@ def _iter_all_modules( else: # Type ignored because typeshed doesn't define ModuleType.__path__ # (only defined on packages). - package_path = package.__path__ # type: ignore[attr-defined] + package_path = package.__path__ path, prefix = package_path[0], package.__name__ + "." for _, name, is_package in pkgutil.iter_modules([path]): if is_package: diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index aa8bf65c73f..37fbdf04d7e 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Version info, help messages, tracing configuration.""" + from argparse import Action import os import sys diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 4bee76f1e39..db55bd82d04 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs """Hook specifications for pytest plugins which are invoked by pytest itself and by builtin plugins.""" + from pathlib import Path from typing import Any from typing import Dict diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 4ca356f31f2..e6ccebc2020 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -7,6 +7,7 @@ Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd """ + from datetime import datetime import functools import os @@ -60,7 +61,7 @@ def repl(matchobj: Match[str]) -> str: # Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] # For an unknown(?) reason, we disallow #x7F (DEL) as well. illegal_xml_re = ( - "[^\u0009\u000A\u000D\u0020-\u007E\u0080-\uD7FF\uE000-\uFFFD\u10000-\u10FFFF]" + "[^\u0009\u000a\u000d\u0020-\u007e\u0080-\ud7ff\ue000-\ufffd\u10000-\u10ffff]" ) return re.sub(illegal_xml_re, repl, str(arg)) @@ -261,7 +262,7 @@ def finalize(self) -> None: self.__dict__.clear() # Type ignored because mypy doesn't like overriding a method. # Also the return value doesn't match... - self.to_xml = lambda: data # type: ignore[assignment] + self.to_xml = lambda: data # type: ignore[method-assign] def _warn_incompatibility_with_xunit2( diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index e9a3234fdec..af5e443ced1 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Access and control log capturing.""" + from contextlib import contextmanager from contextlib import nullcontext from datetime import datetime @@ -209,7 +210,7 @@ def format(self, record: logging.LogRecord) -> str: if "\n" in record.message: if hasattr(record, "auto_indent"): # Passed in from the "extra={}" kwarg on the call to logging.log(). - auto_indent = self._get_auto_indent(record.auto_indent) # type: ignore[attr-defined] + auto_indent = self._get_auto_indent(record.auto_indent) else: auto_indent = self._auto_indent @@ -512,7 +513,7 @@ def _force_enable_logging( :return: The original disabled logging level. """ - original_disable_level: int = logger_obj.manager.disable # type: ignore[attr-defined] + original_disable_level: int = logger_obj.manager.disable if isinstance(level, str): # Try to translate the level string to an int for `logging.disable()` diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 3b9ac93cf3f..716d5cf783b 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -736,14 +736,12 @@ def _collect_path( @overload def perform_collect( self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ... - ) -> Sequence[nodes.Item]: - ... + ) -> Sequence[nodes.Item]: ... @overload def perform_collect( self, args: Optional[Sequence[str]] = ..., genitems: bool = ... - ) -> Sequence[Union[nodes.Item, nodes.Collector]]: - ... + ) -> Sequence[Union[nodes.Item, nodes.Collector]]: ... def perform_collect( self, args: Optional[Sequence[str]] = None, genitems: bool = True diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 1da300c8213..a6503bf1d46 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -342,7 +342,7 @@ def with_args(self, *args: object, **kwargs: object) -> "MarkDecorator": # return type. Not much we can do about that. Thankfully mypy picks # the first match so it works out even if we break the rules. @overload - def __call__(self, arg: Markable) -> Markable: # type: ignore[misc] + def __call__(self, arg: Markable) -> Markable: # type: ignore[overload-overlap] pass @overload @@ -433,13 +433,11 @@ def store_mark(obj, mark: Mark, *, stacklevel: int = 2) -> None: from _pytest.scope import _ScopeName class _SkipMarkDecorator(MarkDecorator): - @overload # type: ignore[override,misc,no-overload-impl] - def __call__(self, arg: Markable) -> Markable: - ... + @overload # type: ignore[override,no-overload-impl] + def __call__(self, arg: Markable) -> Markable: ... @overload - def __call__(self, reason: str = ...) -> "MarkDecorator": - ... + def __call__(self, reason: str = ...) -> "MarkDecorator": ... class _SkipifMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] @@ -447,13 +445,11 @@ def __call__( # type: ignore[override] condition: Union[str, bool] = ..., *conditions: Union[str, bool], reason: str = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _XfailMarkDecorator(MarkDecorator): - @overload # type: ignore[override,misc,no-overload-impl] - def __call__(self, arg: Markable) -> Markable: - ... + @overload # type: ignore[override,no-overload-impl] + def __call__(self, arg: Markable) -> Markable: ... @overload def __call__( @@ -466,8 +462,7 @@ def __call__( None, Type[BaseException], Tuple[Type[BaseException], ...] ] = ..., strict: bool = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _ParametrizeMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] @@ -483,8 +478,7 @@ def __call__( # type: ignore[override] ] ] = ..., scope: Optional[_ScopeName] = ..., - ) -> MarkDecorator: - ... + ) -> MarkDecorator: ... class _UsefixturesMarkDecorator(MarkDecorator): def __call__(self, *fixtures: str) -> MarkDecorator: # type: ignore[override] diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index e96a938681f..3f398df76b1 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Monkeypatching and mocking functionality.""" + from contextlib import contextmanager import os import re @@ -167,8 +168,7 @@ def setattr( name: object, value: Notset = ..., raising: bool = ..., - ) -> None: - ... + ) -> None: ... @overload def setattr( @@ -177,8 +177,7 @@ def setattr( name: str, value: object, raising: bool = ..., - ) -> None: - ... + ) -> None: ... def setattr( self, diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index cff15001c93..1b91bdb6e43 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -363,12 +363,10 @@ def iter_markers_with_node( yield node, mark @overload - def get_closest_marker(self, name: str) -> Optional[Mark]: - ... + def get_closest_marker(self, name: str) -> Optional[Mark]: ... @overload - def get_closest_marker(self, name: str, default: Mark) -> Mark: - ... + def get_closest_marker(self, name: str, default: Mark) -> Mark: ... def get_closest_marker( self, name: str, default: Optional[Mark] = None diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 98ba5c9c154..533d78c9a2a 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Submit failure or test session information to a pastebin service.""" + from io import StringIO import tempfile from typing import IO diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 8002528b965..23f44da69ca 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -3,6 +3,7 @@ PYTEST_DONT_REWRITE """ + import collections.abc import contextlib from fnmatch import fnmatch @@ -245,8 +246,7 @@ def __repr__(self) -> str: if TYPE_CHECKING: # The class has undetermined attributes, this tells mypy about it. - def __getattr__(self, key: str): - ... + def __getattr__(self, key: str): ... @final @@ -327,15 +327,13 @@ def getcall(self, name: str) -> RecordedHookCall: def getreports( self, names: "Literal['pytest_collectreport']", - ) -> Sequence[CollectReport]: - ... + ) -> Sequence[CollectReport]: ... @overload def getreports( self, names: "Literal['pytest_runtest_logreport']", - ) -> Sequence[TestReport]: - ... + ) -> Sequence[TestReport]: ... @overload def getreports( @@ -344,8 +342,7 @@ def getreports( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: - ... + ) -> Sequence[Union[CollectReport, TestReport]]: ... def getreports( self, @@ -390,15 +387,13 @@ def matchreport( def getfailures( self, names: "Literal['pytest_collectreport']", - ) -> Sequence[CollectReport]: - ... + ) -> Sequence[CollectReport]: ... @overload def getfailures( self, names: "Literal['pytest_runtest_logreport']", - ) -> Sequence[TestReport]: - ... + ) -> Sequence[TestReport]: ... @overload def getfailures( @@ -407,8 +402,7 @@ def getfailures( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: - ... + ) -> Sequence[Union[CollectReport, TestReport]]: ... def getfailures( self, diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 7b0683b6ec5..3242d517ea0 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Python test discovery, setup and run of test functions.""" + import abc from collections import Counter from collections import defaultdict diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 7e51da3194a..0ba86e816d3 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -393,7 +393,7 @@ def __repr__(self) -> str: # tolerances, i.e. non-numerics and infinities. Need to call abs to # handle complex numbers, e.g. (inf + 1j). if (not isinstance(self.expected, (Complex, Decimal))) or math.isinf( - abs(self.expected) # type: ignore[arg-type] + abs(self.expected) ): return str(self.expected) @@ -437,8 +437,8 @@ def __eq__(self, actual) -> bool: # Allow the user to control whether NaNs are considered equal to each # other or not. The abs() calls are for compatibility with complex # numbers. - if math.isnan(abs(self.expected)): # type: ignore[arg-type] - return self.nan_ok and math.isnan(abs(actual)) # type: ignore[arg-type] + if math.isnan(abs(self.expected)): + return self.nan_ok and math.isnan(abs(actual)) # Infinity shouldn't be approximately equal to anything but itself, but # if there's a relative tolerance, it will be infinite and infinity @@ -446,11 +446,11 @@ def __eq__(self, actual) -> bool: # case would have been short circuited above, so here we can just # return false if the expected value is infinite. The abs() call is # for compatibility with complex numbers. - if math.isinf(abs(self.expected)): # type: ignore[arg-type] + if math.isinf(abs(self.expected)): return False # Return true if the two numbers are within the tolerance. - result: bool = abs(self.expected - actual) <= self.tolerance + result: bool = abs(self.expected - actual) <= self.tolerance # type: ignore[arg-type] return result # Ignore type because of https://github.com/python/mypy/issues/4266. @@ -769,8 +769,7 @@ def raises( expected_exception: Union[Type[E], Tuple[Type[E], ...]], *, match: Optional[Union[str, Pattern[str]]] = ..., -) -> "RaisesContext[E]": - ... +) -> "RaisesContext[E]": ... @overload @@ -779,8 +778,7 @@ def raises( func: Callable[..., Any], *args: Any, **kwargs: Any, -) -> _pytest._code.ExceptionInfo[E]: - ... +) -> _pytest._code.ExceptionInfo[E]: ... def raises( diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index bcf9f1466c5..63e7a4bd6dc 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Record warnings during test function execution.""" + from pprint import pformat import re from types import TracebackType @@ -43,13 +44,11 @@ def recwarn() -> Generator["WarningsRecorder", None, None]: @overload def deprecated_call( *, match: Optional[Union[str, Pattern[str]]] = ... -) -> "WarningsRecorder": - ... +) -> "WarningsRecorder": ... @overload -def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: - ... +def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: ... def deprecated_call( @@ -91,8 +90,7 @@ def warns( expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ..., *, match: Optional[Union[str, Pattern[str]]] = ..., -) -> "WarningsChecker": - ... +) -> "WarningsChecker": ... @overload @@ -101,8 +99,7 @@ def warns( func: Callable[..., T], *args: Any, **kwargs: Any, -) -> T: - ... +) -> T: ... def warns( @@ -184,8 +181,7 @@ class WarningsRecorder(warnings.catch_warnings): # type:ignore[type-arg] def __init__(self, *, _ispytest: bool = False) -> None: check_ispytest(_ispytest) - # Type ignored due to the way typeshed handles warnings.catch_warnings. - super().__init__(record=True) # type: ignore[call-arg] + super().__init__(record=True) self._entered = False self._list: List[warnings.WarningMessage] = [] diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 7cdb70e324b..70f3212ce7b 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -72,8 +72,7 @@ def __init__(self, **kw: Any) -> None: if TYPE_CHECKING: # Can have arbitrary fields given to __init__(). - def __getattr__(self, key: str) -> Any: - ... + def __getattr__(self, key: str) -> Any: ... def toterminal(self, out: TerminalWriter) -> None: if hasattr(self, "node"): @@ -606,9 +605,9 @@ def deserialize_repr_crash(repr_crash_dict: Optional[Dict[str, Any]]): description, ) ) - exception_info: Union[ - ExceptionChainRepr, ReprExceptionInfo - ] = ExceptionChainRepr(chain) + exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = ( + ExceptionChainRepr(chain) + ) else: exception_info = ReprExceptionInfo( reprtraceback=reprtraceback, diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 16abb895d58..3f706b927c8 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Basic collect and runtest protocol implementations.""" + import bdb import dataclasses import os @@ -84,7 +85,7 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None: dlist.append(rep) if not dlist: return - dlist.sort(key=lambda x: x.duration, reverse=True) # type: ignore[no-any-return] + dlist.sort(key=lambda x: x.duration, reverse=True) if not durations: tr.write_sep("=", "slowest durations") else: @@ -395,8 +396,7 @@ def collect() -> List[Union[Item, Collector]]: skip_exceptions = [Skipped] unittest = sys.modules.get("unittest") if unittest is not None: - # Type ignored because unittest is loaded dynamically. - skip_exceptions.append(unittest.SkipTest) # type: ignore + skip_exceptions.append(unittest.SkipTest) if isinstance(call.excinfo.value, tuple(skip_exceptions)): outcome = "skipped" r_ = collector._repr_failure_py(call.excinfo, "line") diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index c87de1e32fb..39ab28b466b 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -58,7 +58,7 @@ def pytest_fixture_post_finalizer( if config.option.setupshow: _show_fixture_action(fixturedef, request.config, "TEARDOWN") if hasattr(fixturedef, "cached_param"): - del fixturedef.cached_param # type: ignore[attr-defined] + del fixturedef.cached_param def _show_fixture_action( @@ -87,7 +87,7 @@ def _show_fixture_action( tw.write(" (fixtures used: {})".format(", ".join(deps))) if hasattr(fixturedef, "cached_param"): - tw.write(f"[{saferepr(fixturedef.cached_param, maxsize=42)}]") # type: ignore[attr-defined] + tw.write(f"[{saferepr(fixturedef.cached_param, maxsize=42)}]") tw.flush() diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 4799ae6496a..188dcae3f1c 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Support for skip/xfail functions and markers.""" + from collections.abc import Mapping import dataclasses import os @@ -109,7 +110,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool, ) globals_.update(dictionary) if hasattr(item, "obj"): - globals_.update(item.obj.__globals__) # type: ignore[attr-defined] + globals_.update(item.obj.__globals__) try: filename = f"<{mark.name} condition>" condition_code = compile(condition, filename, "eval") diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 75d57197aac..2c9c0d3b1cf 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -3,6 +3,7 @@ This is a good source for looking at the various reporting hooks. """ + import argparse from collections import Counter import dataclasses diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 1cb9fbbe0e0..72efed3e87a 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Support for providing temporary directories to test functions.""" + import dataclasses import os from pathlib import Path diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 32eb361c6fd..5099904fd41 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Discover and run std-library "unittest" style tests.""" + import sys import traceback import types @@ -98,8 +99,7 @@ def collect(self) -> Iterable[Union[Item, Collector]]: runtest = getattr(self.obj, "runTest", None) if runtest is not None: ut = sys.modules.get("twisted.trial.unittest", None) - # Type ignored because `ut` is an opaque module. - if ut is None or runtest != ut.TestCase.runTest: # type: ignore + if ut is None or runtest != ut.TestCase.runTest: yield TestCaseFunction.from_parent(self, name="runTest") def _register_unittest_setup_class_fixture(self, cls: type) -> None: @@ -302,8 +302,7 @@ def runtest(self) -> None: # Let the unittest framework handle async functions. if is_async_function(self.obj): - # Type ignored because self acts as the TestResult, but is not actually one. - testcase(result=self) # type: ignore[arg-type] + testcase(result=self) else: # When --pdb is given, we want to postpone calling tearDown() otherwise # when entering the pdb prompt, tearDown() would have probably cleaned up @@ -322,7 +321,7 @@ def runtest(self) -> None: # wrap_pytest_function_for_tracing replaces self.obj by a wrapper. setattr(testcase, self.name, self.obj) try: - testcase(result=self) # type: ignore[arg-type] + testcase(result=self) finally: delattr(testcase, self.name) @@ -353,9 +352,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None: # its own nose.SkipTest. For unittest TestCases, SkipTest is already # handled internally, and doesn't reach here. unittest = sys.modules.get("unittest") - if ( - unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest) # type: ignore[attr-defined] - ): + if unittest and call.excinfo and isinstance(call.excinfo.value, unittest.SkipTest): excinfo = call.excinfo call2 = CallInfo[None].from_call( lambda: pytest.skip(str(excinfo.value)), call.when diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 20829aa585f..c6b6de827e9 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -1,5 +1,6 @@ # PYTHON_ARGCOMPLETE_OK """pytest: unit and functional testing with Python.""" + from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 0c8575c4ec7..ad2526571e6 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -16,8 +16,8 @@ @contextlib.contextmanager def ignore_encoding_warning(): with warnings.catch_warnings(): - with contextlib.suppress(NameError): # new in 3.10 - warnings.simplefilter("ignore", EncodingWarning) # type: ignore [name-defined] + if sys.version_info > (3, 10): + warnings.simplefilter("ignore", EncodingWarning) yield @@ -822,7 +822,7 @@ def test_long_filenames(self, tmpdir): # depending on how the paths are used), but > 4096 (which is the # Linux' limitation) - the behaviour of paths with names > 4096 chars # is undetermined - newfilename = "/test" * 60 # type:ignore[unreachable] + newfilename = "/test" * 60 # type:ignore[unreachable,unused-ignore] l1 = tmpdir.join(newfilename) l1.ensure(file=True) l1.write_text("foo", encoding="utf-8") @@ -1368,8 +1368,8 @@ def test_realpath_file(self, tmpdir): assert realpath.basename == "file" def test_owner(self, path1, tmpdir): - from grp import getgrgid # type:ignore[attr-defined] - from pwd import getpwuid # type:ignore[attr-defined] + from grp import getgrgid # type:ignore[attr-defined,unused-ignore] + from pwd import getpwuid # type:ignore[attr-defined,unused-ignore] stat = path1.stat() assert stat.path == path1 diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 49c5dd3715b..419c11abcc0 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -180,7 +180,7 @@ def test_traceback_cut(self) -> None: def test_traceback_cut_excludepath(self, pytester: Pytester) -> None: p = pytester.makepyfile("def f(): raise ValueError") with pytest.raises(ValueError) as excinfo: - import_path(p, root=pytester.path, consider_namespace_packages=False).f() # type: ignore[attr-defined] + import_path(p, root=pytester.path, consider_namespace_packages=False).f() basedir = Path(pytest.__file__).parent newtraceback = excinfo.traceback.cut(excludepath=basedir) for x in newtraceback: diff --git a/testing/example_scripts/acceptance/fixture_mock_integration.py b/testing/example_scripts/acceptance/fixture_mock_integration.py index 36e711f40eb..d802a7f8728 100644 --- a/testing/example_scripts/acceptance/fixture_mock_integration.py +++ b/testing/example_scripts/acceptance/fixture_mock_integration.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Reproduces issue #3774""" + from unittest import mock import pytest diff --git a/testing/example_scripts/unittest/test_setup_skip.py b/testing/example_scripts/unittest/test_setup_skip.py index 4681cda0352..7550a097576 100644 --- a/testing/example_scripts/unittest/test_setup_skip.py +++ b/testing/example_scripts/unittest/test_setup_skip.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Skipping an entire subclass with unittest.skip() should *not* call setUp from a base class.""" + import unittest diff --git a/testing/example_scripts/unittest/test_setup_skip_class.py b/testing/example_scripts/unittest/test_setup_skip_class.py index eae98287f91..48f7e476f40 100644 --- a/testing/example_scripts/unittest/test_setup_skip_class.py +++ b/testing/example_scripts/unittest/test_setup_skip_class.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Skipping an entire subclass with unittest.skip() should *not* call setUpClass from a base class.""" + import unittest diff --git a/testing/example_scripts/unittest/test_setup_skip_module.py b/testing/example_scripts/unittest/test_setup_skip_module.py index 43c24136edf..eee4263d22b 100644 --- a/testing/example_scripts/unittest/test_setup_skip_module.py +++ b/testing/example_scripts/unittest/test_setup_skip_module.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """setUpModule is always called, even if all tests in the module are skipped""" + import unittest diff --git a/testing/example_scripts/unittest/test_unittest_asynctest.py b/testing/example_scripts/unittest/test_unittest_asynctest.py index b3f03e3256b..e9b10171e8d 100644 --- a/testing/example_scripts/unittest/test_unittest_asynctest.py +++ b/testing/example_scripts/unittest/test_unittest_asynctest.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Issue #7110""" + import asyncio from typing import List diff --git a/testing/io/test_wcwidth.py b/testing/io/test_wcwidth.py index 0989af00d07..82503b8300c 100644 --- a/testing/io/test_wcwidth.py +++ b/testing/io/test_wcwidth.py @@ -11,8 +11,8 @@ ("a", 1), ("1", 1), ("א", 1), - ("\u200B", 0), - ("\u1ABE", 0), + ("\u200b", 0), + ("\u1abe", 0), ("\u0591", 0), ("🉐", 2), ("$", 2), # noqa: RUF001 diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index ed22c2b5a1c..3d0058fa0a7 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -109,7 +109,7 @@ def gen() -> Iterator[Union[int, None, Exc]]: metafunc = self.Metafunc(func) # When the input is an iterator, only len(args) are taken, # so the bad Exc isn't reached. - metafunc.parametrize("x", [1, 2], ids=gen()) # type: ignore[arg-type] + metafunc.parametrize("x", [1, 2], ids=gen()) assert [(x.params, x.id) for x in metafunc._calls] == [ ({"x": 1}, "0"), ({"x": 2}, "2"), @@ -121,7 +121,7 @@ def gen() -> Iterator[Union[int, None, Exc]]: r"Supported types are: .*" ), ): - metafunc.parametrize("x", [1, 2, 3], ids=gen()) # type: ignore[arg-type] + metafunc.parametrize("x", [1, 2, 3], ids=gen()) def test_parametrize_bad_scope(self) -> None: def func(x): diff --git a/testing/test_config.py b/testing/test_config.py index 88470ff2d49..147c2cb851c 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1243,7 +1243,7 @@ def distributions(): monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1") monkeypatch.setattr(importlib.metadata, "distributions", distributions) - monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin()) # type: ignore[misc] + monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin()) config = pytester.parseconfig(*parse_args) has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None assert has_loaded == should_load diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 91a0be48108..53ebadbdba4 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -29,7 +29,7 @@ def runpdb_and_get_stdout(pytester: Pytester, source: str): def runpdb_and_get_report(pytester: Pytester, source: str): result = runpdb(pytester, source) - reports = result.reprec.getreports("pytest_runtest_logreport") # type: ignore[attr-defined] + reports = result.reprec.getreports("pytest_runtest_logreport") assert len(reports) == 3, reports # setup/call/teardown return reports[1] diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 42104255b28..3b92d65bdb9 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1202,7 +1202,7 @@ class Report(BaseReport): node_reporter.append_skipped(test_report) test_report.longrepr = "filename", 1, "Skipped: 卡嘣嘣" node_reporter.append_skipped(test_report) - test_report.wasxfail = ustr # type: ignore[attr-defined] + test_report.wasxfail = ustr node_reporter.append_skipped(test_report) log.pytest_sessionfinish() diff --git a/testing/test_mark.py b/testing/test_mark.py index 6e183a17887..2896afa4532 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -18,7 +18,7 @@ class TestMark: @pytest.mark.parametrize("attr", ["mark", "param"]) def test_pytest_exists_in_namespace_all(self, attr: str) -> None: module = sys.modules["pytest"] - assert attr in module.__all__ # type: ignore + assert attr in module.__all__ def test_pytest_mark_notcallable(self) -> None: mark = MarkGenerator(_ispytest=True) @@ -34,7 +34,7 @@ class SomeClass: assert pytest.mark.foo(some_function) is some_function marked_with_args = pytest.mark.foo.with_args(some_function) - assert marked_with_args is not some_function # type: ignore[comparison-overlap] + assert marked_with_args is not some_function assert pytest.mark.foo(SomeClass) is SomeClass assert pytest.mark.foo.with_args(SomeClass) is not SomeClass # type: ignore[comparison-overlap] diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index a4bccb1b2ac..7f740a0607b 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -183,7 +183,7 @@ def test_smoke_test(self, path1: Path, ns_param: bool) -> None: obj = import_path( path1 / "execfile.py", root=path1, consider_namespace_packages=ns_param ) - assert obj.x == 42 # type: ignore[attr-defined] + assert obj.x == 42 assert obj.__name__ == "execfile" def test_import_path_missing_file(self, path1: Path, ns_param: bool) -> None: @@ -246,7 +246,7 @@ def test_a(self, path1: Path, ns_param: bool) -> None: mod = import_path( otherdir / "a.py", root=path1, consider_namespace_packages=ns_param ) - assert mod.result == "got it" # type: ignore[attr-defined] + assert mod.result == "got it" assert mod.__name__ == "otherdir.a" def test_b(self, path1: Path, ns_param: bool) -> None: @@ -254,7 +254,7 @@ def test_b(self, path1: Path, ns_param: bool) -> None: mod = import_path( otherdir / "b.py", root=path1, consider_namespace_packages=ns_param ) - assert mod.stuff == "got it" # type: ignore[attr-defined] + assert mod.stuff == "got it" assert mod.__name__ == "otherdir.b" def test_c(self, path1: Path, ns_param: bool) -> None: @@ -262,14 +262,14 @@ def test_c(self, path1: Path, ns_param: bool) -> None: mod = import_path( otherdir / "c.py", root=path1, consider_namespace_packages=ns_param ) - assert mod.value == "got it" # type: ignore[attr-defined] + assert mod.value == "got it" def test_d(self, path1: Path, ns_param: bool) -> None: otherdir = path1 / "otherdir" mod = import_path( otherdir / "d.py", root=path1, consider_namespace_packages=ns_param ) - assert mod.value2 == "got it" # type: ignore[attr-defined] + assert mod.value2 == "got it" def test_import_after(self, tmp_path: Path, ns_param: bool) -> None: tmp_path.joinpath("xxxpackage").mkdir() @@ -360,7 +360,7 @@ def test_importmode_importlib( root=tmp_path, consider_namespace_packages=ns_param, ) - assert module.foo(2) == 42 # type: ignore[attr-defined] + assert module.foo(2) == 42 assert str(simple_module.parent) not in sys.path assert module.__name__ in sys.modules assert module.__name__ == f"_src.tests.mymod_{request.node.name}" @@ -400,7 +400,7 @@ def test_no_meta_path_found( root=tmp_path, consider_namespace_packages=ns_param, ) - assert module.foo(2) == 42 # type: ignore[attr-defined] + assert module.foo(2) == 42 # mode='importlib' fails if no spec is found to load the module import importlib.util diff --git a/testing/test_reports.py b/testing/test_reports.py index 2de5ae60090..c6baeebc9dd 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -294,9 +294,9 @@ def test_a(): reprec = pytester.inline_run() if report_class is TestReport: - reports: Union[ - Sequence[TestReport], Sequence[CollectReport] - ] = reprec.getreports("pytest_runtest_logreport") + reports: Union[Sequence[TestReport], Sequence[CollectReport]] = ( + reprec.getreports("pytest_runtest_logreport") + ) # we have 3 reports: setup/call/teardown assert len(reports) == 3 # get the call report diff --git a/testing/test_runner_xunit.py b/testing/test_runner_xunit.py index 8076e20bc40..587c9eb9fef 100644 --- a/testing/test_runner_xunit.py +++ b/testing/test_runner_xunit.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Test correct setup/teardowns at module, class, and instance level.""" + from typing import List from _pytest.pytester import Pytester diff --git a/testing/test_terminal.py b/testing/test_terminal.py index b311d6c9b14..f4942510991 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1,5 +1,6 @@ # mypy: allow-untyped-defs """Terminal reporting of the full testing process.""" + from io import StringIO import os from pathlib import Path diff --git a/testing/typing_checks.py b/testing/typing_checks.py index a2ceabcbd67..4b146a25110 100644 --- a/testing/typing_checks.py +++ b/testing/typing_checks.py @@ -4,6 +4,7 @@ This file is not executed, it is only checked by mypy to ensure that none of the code triggers any mypy errors. """ + import contextlib from typing import Optional From 2e5da5d2fbb7fba2d31c2ca90f2850fedbea7b25 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Thu, 14 Mar 2024 17:36:11 +0100 Subject: [PATCH 0553/1271] doc: fix typos (#12118) * doc: add missing word * doc: fix typos Typos found with codespell --- doc/en/conf.py | 2 +- doc/en/how-to/writing_hook_functions.rst | 2 +- doc/en/index.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/conf.py b/doc/en/conf.py index 8059c359fc1..32ecaa17435 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -395,7 +395,7 @@ # The format is a list of tuples containing the path and title. # epub_pre_files = [] -# HTML files shat should be inserted after the pages created by sphinx. +# HTML files that should be inserted after the pages created by sphinx. # The format is a list of tuples containing the path and title. # epub_post_files = [] diff --git a/doc/en/how-to/writing_hook_functions.rst b/doc/en/how-to/writing_hook_functions.rst index 5d0a52f9d38..f4c00d04fda 100644 --- a/doc/en/how-to/writing_hook_functions.rst +++ b/doc/en/how-to/writing_hook_functions.rst @@ -100,7 +100,7 @@ object, the wrapper may modify that result, but it's probably better to avoid it If the hook implementation failed with an exception, the wrapper can handle that exception using a ``try-catch-finally`` around the ``yield``, by propagating it, -supressing it, or raising a different exception entirely. +suppressing it, or raising a different exception entirely. For more information, consult the :ref:`pluggy documentation about hook wrappers `. diff --git a/doc/en/index.rst b/doc/en/index.rst index 9d97dfaa680..08a1468986a 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -87,7 +87,7 @@ Features Documentation ------------- -* :ref:`Get started ` - install pytest and grasp its basics just twenty minutes +* :ref:`Get started ` - install pytest and grasp its basics in just twenty minutes * :ref:`How-to guides ` - step-by-step guides, covering a vast range of use-cases and needs * :ref:`Reference guides ` - includes the complete pytest API reference, lists of plugins and more * :ref:`Explanation ` - background, discussion of key topics, answers to higher-level questions From bec0e9caf83616a4cd6494c6efed5cb5ba5f406d Mon Sep 17 00:00:00 2001 From: jakkdl Date: Fri, 15 Mar 2024 12:26:28 +0100 Subject: [PATCH 0554/1271] Add tests to ensure setup&finalization for scoped fixtures only run once. --- testing/python/fixtures.py | 74 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 2e277626cde..6051ab18fd8 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4622,3 +4622,77 @@ def test_2(cls, request): result = pytester.runpytest() assert result.ret == ExitCode.OK result.assert_outcomes(passed=3) + + +def test_scoped_fixture_caching(pytester: Pytester) -> None: + """Make sure setup and finalization is only run once when using scoped fixture + multiple times.""" + pytester.makepyfile( + """ + from __future__ import annotations + + from typing import Generator + + import pytest + executed: list[str] = [] + @pytest.fixture(scope="class") + def fixture_1() -> Generator[None, None, None]: + executed.append("fix setup") + yield + executed.append("fix teardown") + + + class TestFixtureCaching: + def test_1(self, fixture_1: None) -> None: + assert executed == ["fix setup"] + + def test_2(self, fixture_1: None) -> None: + assert executed == ["fix setup"] + + + def test_expected_setup_and_teardown() -> None: + assert executed == ["fix setup", "fix teardown"] + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + + +def test_scoped_fixture_caching_exception(pytester: Pytester) -> None: + """Make sure setup & finalization is only run once for scoped fixture, with a cached exception.""" + pytester.makepyfile( + """ + from __future__ import annotations + + import pytest + executed_crash: list[str] = [] + + + @pytest.fixture(scope="class") + def fixture_crash(request: pytest.FixtureRequest) -> None: + executed_crash.append("fix_crash setup") + + def my_finalizer() -> None: + executed_crash.append("fix_crash teardown") + + request.addfinalizer(my_finalizer) + + raise Exception("foo") + + + class TestFixtureCachingException: + @pytest.mark.xfail + def test_crash_1(self, fixture_crash: None) -> None: + ... + + @pytest.mark.xfail + def test_crash_2(self, fixture_crash: None) -> None: + ... + + + def test_crash_expected_setup_and_teardown() -> None: + assert executed_crash == ["fix_crash setup", "fix_crash teardown"] + """ + ) + result = pytester.runpytest() + assert result.ret == 0 From 70c11582aaede285c0d160c221b91f421f2d06c3 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Sat, 16 Mar 2024 22:45:56 +0100 Subject: [PATCH 0555/1271] Don't add fixture finalizer if the value is cached (#11833) Fixes #1489 --- changelog/1489.bugfix.rst | 1 + src/_pytest/fixtures.py | 50 +++++++++++++--------------------- testing/python/fixtures.py | 55 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 31 deletions(-) create mode 100644 changelog/1489.bugfix.rst diff --git a/changelog/1489.bugfix.rst b/changelog/1489.bugfix.rst new file mode 100644 index 00000000000..70c5dd1252e --- /dev/null +++ b/changelog/1489.bugfix.rst @@ -0,0 +1 @@ +Fix some instances where teardown of higher-scoped fixtures was not happening in the reverse order they were initialized in. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 8b25d743ca4..48429a023ac 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -543,6 +543,11 @@ def getfixturevalue(self, argname: str) -> Any: :raises pytest.FixtureLookupError: If the given fixture could not be found. """ + # Note that in addition to the use case described in the docstring, + # getfixturevalue() is also called by pytest itself during item and fixture + # setup to evaluate the fixtures that are requested statically + # (using function parameters, autouse, etc). + fixturedef = self._get_active_fixturedef(argname) assert fixturedef.cached_result is not None, ( f'The fixture value for "{argname}" is not available. ' @@ -587,9 +592,8 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: """Create a SubRequest based on "self" and call the execute method of the given FixtureDef object. - This will force the FixtureDef object to throw away any previous - results and compute a new fixture value, which will be stored into - the FixtureDef object itself. + If the FixtureDef has cached the result it will do nothing, otherwise it will + setup and run the fixture, cache the value, and schedule a finalizer for it. """ # prepare a subrequest object before calling fixture function # (latter managed by fixturedef) @@ -646,18 +650,9 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: subrequest = SubRequest( self, scope, param, param_index, fixturedef, _ispytest=True ) - try: - # Call the fixture function. - fixturedef.execute(request=subrequest) - finally: - self._schedule_finalizers(fixturedef, subrequest) - def _schedule_finalizers( - self, fixturedef: "FixtureDef[object]", subrequest: "SubRequest" - ) -> None: - # If fixture function failed it might have registered finalizers. - finalizer = functools.partial(fixturedef.finish, request=subrequest) - subrequest.node.addfinalizer(finalizer) + # Make sure the fixture value is cached, running it if it isn't + fixturedef.execute(request=subrequest) @final @@ -788,21 +783,6 @@ def _format_fixturedef_line(self, fixturedef: "FixtureDef[object]") -> str: def addfinalizer(self, finalizer: Callable[[], object]) -> None: self._fixturedef.addfinalizer(finalizer) - def _schedule_finalizers( - self, fixturedef: "FixtureDef[object]", subrequest: "SubRequest" - ) -> None: - # If the executing fixturedef was not explicitly requested in the argument list (via - # getfixturevalue inside the fixture call) then ensure this fixture def will be finished - # first. - if ( - fixturedef.argname not in self._fixture_defs - and fixturedef.argname not in self._pyfuncitem.fixturenames - ): - fixturedef.addfinalizer( - functools.partial(self._fixturedef.finish, request=self) - ) - super()._schedule_finalizers(fixturedef, subrequest) - @final class FixtureLookupError(LookupError): @@ -1055,12 +1035,13 @@ def finish(self, request: SubRequest) -> None: raise BaseExceptionGroup(msg, exceptions[::-1]) def execute(self, request: SubRequest) -> FixtureValue: + finalizer = functools.partial(self.finish, request=request) # Get required arguments and register our own finish() # with their finalization. for argname in self.argnames: fixturedef = request._get_active_fixturedef(argname) if not isinstance(fixturedef, PseudoFixtureDef): - fixturedef.addfinalizer(functools.partial(self.finish, request=request)) + fixturedef.addfinalizer(finalizer) my_cache_key = self.cache_key(request) if self.cached_result is not None: @@ -1080,7 +1061,14 @@ def execute(self, request: SubRequest) -> FixtureValue: assert self.cached_result is None ihook = request.node.ihook - result = ihook.pytest_fixture_setup(fixturedef=self, request=request) + try: + # Setup the fixture, run the code in it, and cache the value + # in self.cached_result + result = ihook.pytest_fixture_setup(fixturedef=self, request=request) + finally: + # schedule our finalizer, even if the setup failed + request.node.addfinalizer(finalizer) + return result def cache_key(self, request: SubRequest) -> object: diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 6051ab18fd8..1e22270e51b 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4696,3 +4696,58 @@ def test_crash_expected_setup_and_teardown() -> None: ) result = pytester.runpytest() assert result.ret == 0 + + +def test_scoped_fixture_teardown_order(pytester: Pytester) -> None: + """ + Make sure teardowns happen in reverse order of setup with scoped fixtures, when + a later test only depends on a subset of scoped fixtures. + + Regression test for https://github.com/pytest-dev/pytest/issues/1489 + """ + pytester.makepyfile( + """ + from typing import Generator + + import pytest + + + last_executed = "" + + + @pytest.fixture(scope="module") + def fixture_1() -> Generator[None, None, None]: + global last_executed + assert last_executed == "" + last_executed = "fixture_1_setup" + yield + assert last_executed == "fixture_2_teardown" + last_executed = "fixture_1_teardown" + + + @pytest.fixture(scope="module") + def fixture_2() -> Generator[None, None, None]: + global last_executed + assert last_executed == "fixture_1_setup" + last_executed = "fixture_2_setup" + yield + assert last_executed == "run_test" + last_executed = "fixture_2_teardown" + + + def test_fixture_teardown_order(fixture_1: None, fixture_2: None) -> None: + global last_executed + assert last_executed == "fixture_2_setup" + last_executed = "run_test" + + + def test_2(fixture_1: None) -> None: + # This would previously queue an additional teardown of fixture_1, + # despite fixture_1's value being cached, which caused fixture_1 to be + # torn down before fixture_2 - violating the rule that teardowns should + # happen in reverse order of setup. + pass + """ + ) + result = pytester.runpytest() + assert result.ret == 0 From 2e69f31444895dc9453f177eb78498d68fed8f20 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 17 Mar 2024 00:20:04 +0000 Subject: [PATCH 0556/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 166 ++++++++++++++++++------------- 1 file changed, 95 insertions(+), 71 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 8ca3a748ba3..52bcc96d6de 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.2) + :pypi:`pytest-ai1899` pytest plugin for connecting to ai1899 smart system stack Mar 13, 2024 5 - Production/Stable N/A :pypi:`pytest-aio` Pytest plugin for testing async python code Feb 03, 2023 4 - Beta pytest :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A :pypi:`pytest-aiogram` May 06, 2023 N/A N/A @@ -193,11 +194,11 @@ This list contains 1411 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-cases` Separate test code from test cases in pytest. Mar 08, 2024 5 - Production/Stable N/A + :pypi:`pytest-cases` Separate test code from test cases in pytest. Mar 16, 2024 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Mar 09, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Mar 11, 2024 N/A N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -212,9 +213,10 @@ This list contains 1411 plugins. :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<8,>=7.0 - :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Mar 06, 2024 N/A N/A + :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Mar 12, 2024 N/A N/A :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 20, 2024 N/A N/A + :pypi:`pytest-ch-framework` My pytest framework Mar 13, 2024 N/A pytest ==8.0.1 :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 Feb 04, 2024 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) @@ -275,7 +277,7 @@ This list contains 1411 plugins. :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Mar 09, 2024 N/A N/A + :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Mar 14, 2024 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -394,7 +396,7 @@ This list contains 1411 plugins. :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) :pypi:`pytest-doctest-mkdocstrings` Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) Mar 02, 2024 N/A pytest - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Mar 04, 2024 5 - Production/Stable pytest >=4.6 + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Mar 10, 2024 5 - Production/Stable 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 Dec 14, 2023 N/A N/A :pypi:`pytest-dolphin` Some extra stuff that we use ininternally Nov 30, 2016 4 - Beta pytest (==3.0.4) @@ -412,7 +414,7 @@ This list contains 1411 plugins. :pypi:`pytest-duration-insights` Jun 25, 2021 N/A N/A :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Apr 22, 2022 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A - :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Jun 12, 2023 5 - Production/Stable pytest + :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Mar 12, 2024 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Feb 16, 2024 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A @@ -422,7 +424,7 @@ This list contains 1411 plugins. :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest - :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Sep 13, 2023 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 15, 2024 5 - Production/Stable pytest >=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) @@ -563,7 +565,7 @@ This list contains 1411 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Feb 15, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Mar 14, 2024 N/A pytest>=3.6 :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 @@ -589,7 +591,7 @@ This list contains 1411 plugins. :pypi:`pytest_gui_status` Show pytest status in gui Jan 23, 2016 N/A pytest :pypi:`pytest-hammertime` Display "🔨 " instead of "." for passed pytest tests. Jul 28, 2018 N/A pytest :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) - :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Jun 10, 2022 5 - Production/Stable N/A + :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Mar 16, 2024 5 - Production/Stable N/A :pypi:`pytest-helm-chart` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Jun 15, 2020 4 - Beta pytest (>=5.4.2,<6.0.0) :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Feb 07, 2024 4 - Beta pytest (>=8.0.0,<9.0.0) :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A @@ -602,7 +604,7 @@ This list contains 1411 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Mar 07, 2024 3 - Alpha pytest ==8.0.2 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 15, 2024 3 - Alpha pytest ==8.0.2 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jan 06, 2024 N/A N/A @@ -633,7 +635,7 @@ This list contains 1411 plugins. :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Jan 24, 2024 3 - Alpha pytest (>=7.0.0,<8.0.0) + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Mar 14, 2024 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A @@ -657,7 +659,7 @@ This list contains 1411 plugins. :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest - :pypi:`pytest-insper` Pytest plugin for courses at Insper Feb 01, 2024 N/A pytest + :pypi:`pytest-insper` Pytest plugin for courses at Insper Mar 16, 2024 N/A pytest :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Feb 19, 2024 N/A pytest (>=7.2.0,<9.0.0) :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) :pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0) @@ -692,7 +694,7 @@ This list contains 1411 plugins. :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Feb 21, 2024 4 - Beta pytest + :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Mar 12, 2024 4 - Beta pytest :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest @@ -716,11 +718,11 @@ This list contains 1411 plugins. :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Feb 06, 2024 N/A pytest (>=7) + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Mar 16, 2024 N/A pytest (>=7) :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A - :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 08, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 11, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A @@ -745,7 +747,7 @@ This list contains 1411 plugins. :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) :pypi:`pytest-logdog` Pytest plugin to test logging Jun 15, 2021 1 - Planning pytest (>=6.2.0) :pypi:`pytest-logfest` Pytest plugin providing three logger fixtures with basic or full writing to log files Jul 21, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Feb 21, 2024 5 - Production/Stable pytest (>=3.2) + :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logikal` Common testing environment Feb 05, 2024 5 - Production/Stable pytest ==8.0.0 @@ -762,7 +764,7 @@ This list contains 1411 plugins. :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A - :pypi:`pytest-matcher` Keep a ChangeLog Feb 29, 2024 5 - Production/Stable pytest + :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Mar 15, 2024 5 - Production/Stable pytest :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -783,7 +785,7 @@ This list contains 1411 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 Feb 12, 2024 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 Feb 21, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Mar 14, 2024 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) @@ -808,7 +810,7 @@ This list contains 1411 plugins. :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Jul 20, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Mar 13, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A @@ -829,7 +831,7 @@ This list contains 1411 plugins. :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Feb 29, 2024 4 - Beta pytest >=7.0.0 + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Mar 13, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 @@ -913,7 +915,7 @@ This list contains 1411 plugins. :pypi:`pytest-pep257` py.test plugin for pep257 Jul 09, 2016 N/A N/A :pypi:`pytest-pep8` pytest plugin to check PEP8 requirements Apr 27, 2014 N/A N/A :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) - :pypi:`pytest-percents` Feb 10, 2024 N/A N/A + :pypi:`pytest-percents` Mar 16, 2024 N/A N/A :pypi:`pytest-perf` Run performance tests against the mainline code. Jan 28, 2024 5 - Production/Stable pytest >=6 ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A @@ -936,7 +938,7 @@ This list contains 1411 plugins. :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Feb 02, 2024 N/A pytest (<9.0.0,>=6.2.4) :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Feb 25, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A - :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 02, 2024 N/A pytest (>=8.0.0,<9.0.0) + :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 14, 2024 N/A pytest (>=8.0.0,<9.0.0) :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A @@ -945,6 +947,7 @@ This list contains 1411 plugins. :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Jan 10, 2024 5 - Production/Stable pytest >=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A + :pypi:`pytest-pogo` Pytest plugin for pogo-migrate Mar 11, 2024 1 - Planning pytest (>=7,<9) :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A :pypi:`pytest-pokie` Pokie plugin for pytest Oct 19, 2023 5 - Production/Stable N/A :pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A @@ -958,7 +961,7 @@ This list contains 1411 plugins. :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 07, 2024 5 - Production/Stable pytest >=6.2 + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 11, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 @@ -972,7 +975,7 @@ This list contains 1411 plugins. :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest :pypi:`pytest-prosper` Test helpers for Prosper projects Sep 24, 2018 N/A N/A - :pypi:`pytest-prysk` Pytest plugin for prysk Dec 30, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-prysk` Pytest plugin for prysk Mar 12, 2024 4 - Beta pytest (>=7.3.2) :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) @@ -1030,7 +1033,7 @@ This list contains 1411 plugins. :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Mar 01, 2024 4 - Beta pytest >=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A - :pypi:`pytest-reana` Pytest fixtures for REANA. Nov 30, 2023 3 - Alpha N/A + :pypi:`pytest-reana` Pytest fixtures for REANA. Mar 14, 2024 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 Dec 06, 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 @@ -1073,7 +1076,7 @@ This list contains 1411 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 Nov 22, 2023 5 - Production/Stable pytest >=7 + :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 :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. Feb 08, 2024 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Feb 14, 2024 N/A pytest ~=4.6 ; python_version == "2.7" @@ -1100,14 +1103,14 @@ This list contains 1411 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 08, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 13, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Mar 03, 2024 4 - Beta pytest (>=5) + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Mar 10, 2024 4 - Beta pytest (>=5) :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest @@ -1124,7 +1127,7 @@ This list contains 1411 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 16, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1133,7 +1136,7 @@ This list contains 1411 plugins. :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 Feb 01, 2024 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. Mar 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 16, 2024 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 @@ -1230,7 +1233,7 @@ This list contains 1411 plugins. :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-structlog` Structured logging assertions Feb 04, 2024 N/A pytest + :pypi:`pytest-structlog` Structured logging assertions Mar 13, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) @@ -1364,7 +1367,7 @@ This list contains 1411 plugins. :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A - :pypi:`pytest-unordered` Test equality of unordered collections in pytest Nov 28, 2022 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-unordered` Test equality of unordered collections in pytest Mar 13, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A @@ -1555,6 +1558,13 @@ This list contains 1411 plugins. pytest plugin for pytest-repeat that generate aggregate report of the same test cases with additional statistics details. + :pypi:`pytest-ai1899` + *last release*: Mar 13, 2024, + *status*: 5 - Production/Stable, + *requires*: N/A + + pytest plugin for connecting to ai1899 smart system stack + :pypi:`pytest-aio` *last release*: Feb 03, 2023, *status*: 4 - Beta, @@ -2564,7 +2574,7 @@ This list contains 1411 plugins. pytest plugin to capture all warnings and put them in one file of your choice :pypi:`pytest-cases` - *last release*: Mar 08, 2024, + *last release*: Mar 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -2592,7 +2602,7 @@ This list contains 1411 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Mar 09, 2024, + *last release*: Mar 11, 2024, *status*: N/A, *requires*: N/A @@ -2697,7 +2707,7 @@ This list contains 1411 plugins. Check links in files :pypi:`pytest-checklist` - *last release*: Mar 06, 2024, + *last release*: Mar 12, 2024, *status*: N/A, *requires*: N/A @@ -2717,6 +2727,13 @@ This list contains 1411 plugins. A package to prevent Dependency Confusion attacks against Yandex. + :pypi:`pytest-ch-framework` + *last release*: Mar 13, 2024, + *status*: N/A, + *requires*: pytest ==8.0.1 + + My pytest framework + :pypi:`pytest-chic-report` *last release*: Jan 31, 2023, *status*: 5 - Production/Stable, @@ -3138,7 +3155,7 @@ This list contains 1411 plugins. Use pytest's runner to discover and execute C++ tests :pypi:`pytest-cppython` - *last release*: Mar 09, 2024, + *last release*: Mar 14, 2024, *status*: N/A, *requires*: N/A @@ -3971,7 +3988,7 @@ This list contains 1411 plugins. Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) :pypi:`pytest-doctestplus` - *last release*: Mar 04, 2024, + *last release*: Mar 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=4.6 @@ -4097,7 +4114,7 @@ This list contains 1411 plugins. A pytest plugin to rerun tests dynamically based off of test outcome and output. :pypi:`pytest-dynamodb` - *last release*: Jun 12, 2023, + *last release*: Mar 12, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -4167,7 +4184,7 @@ This list contains 1411 plugins. Pytest plugin to select test using Ekstazi algorithm :pypi:`pytest-elasticsearch` - *last release*: Sep 13, 2023, + *last release*: Mar 15, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=7.0 @@ -5154,7 +5171,7 @@ This list contains 1411 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Feb 15, 2024, + *last release*: Mar 14, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5336,7 +5353,7 @@ This list contains 1411 plugins. Chain tests and data with pytest :pypi:`pytest-harvest` - *last release*: Jun 10, 2022, + *last release*: Mar 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5427,7 +5444,7 @@ This list contains 1411 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 07, 2024, + *last release*: Mar 15, 2024, *status*: 3 - Alpha, *requires*: pytest ==8.0.2 @@ -5644,9 +5661,9 @@ This list contains 1411 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Jan 24, 2024, + *last release*: Mar 14, 2024, *status*: 3 - Alpha, - *requires*: pytest (>=7.0.0,<8.0.0) + *requires*: pytest (>=7.0.0) A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite @@ -5812,7 +5829,7 @@ This list contains 1411 plugins. The extension enables easy execution of pytest tests within the Robot Framework environment. :pypi:`pytest-insper` - *last release*: Feb 01, 2024, + *last release*: Mar 16, 2024, *status*: N/A, *requires*: pytest @@ -6057,7 +6074,7 @@ This list contains 1411 plugins. pytest plugin supporting json test report output :pypi:`pytest-jupyter` - *last release*: Feb 21, 2024, + *last release*: Mar 12, 2024, *status*: 4 - Beta, *requires*: pytest @@ -6225,7 +6242,7 @@ This list contains 1411 plugins. It helps to use fixtures in pytest.mark.parametrize :pypi:`pytest-lazy-fixtures` - *last release*: Feb 06, 2024, + *last release*: Mar 16, 2024, *status*: N/A, *requires*: pytest (>=7) @@ -6253,7 +6270,7 @@ This list contains 1411 plugins. A pytest plugin to trace resource leaks. :pypi:`pytest-leaping` - *last release*: Mar 08, 2024, + *last release*: Mar 11, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -6428,7 +6445,7 @@ This list contains 1411 plugins. Pytest plugin providing three logger fixtures with basic or full writing to log files :pypi:`pytest-logger` - *last release*: Feb 21, 2024, + *last release*: Mar 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest (>=3.2) @@ -6547,11 +6564,11 @@ This list contains 1411 plugins. UNKNOWN :pypi:`pytest-matcher` - *last release*: Feb 29, 2024, + *last release*: Mar 15, 2024, *status*: 5 - Production/Stable, *requires*: pytest - Keep a ChangeLog + Easy way to match captured \`pytest\` output against expectations stored in files :pypi:`pytest-match-skip` *last release*: May 15, 2019, @@ -6694,7 +6711,7 @@ This list contains 1411 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Feb 21, 2024, + *last release*: Mar 14, 2024, *status*: N/A, *requires*: pytest @@ -6869,9 +6886,9 @@ This list contains 1411 plugins. PyTest Molecule Plugin :: discover and run molecule tests :pypi:`pytest-mongo` - *last release*: Jul 20, 2023, + *last release*: Mar 13, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2) + *requires*: pytest >=6.2 MongoDB process and client fixtures plugin for Pytest. @@ -7016,7 +7033,7 @@ This list contains 1411 plugins. Mypy static type checker plugin for Pytest :pypi:`pytest-mypy-plugins` - *last release*: Feb 29, 2024, + *last release*: Mar 13, 2024, *status*: 4 - Beta, *requires*: pytest >=7.0.0 @@ -7604,7 +7621,7 @@ This list contains 1411 plugins. Change the exit code of pytest test sessions when a required percent of tests pass. :pypi:`pytest-percents` - *last release*: Feb 10, 2024, + *last release*: Mar 16, 2024, *status*: N/A, *requires*: N/A @@ -7765,7 +7782,7 @@ This list contains 1411 plugins. :pypi:`pytest-playwright-enhanced` - *last release*: Mar 02, 2024, + *last release*: Mar 14, 2024, *status*: N/A, *requires*: pytest (>=8.0.0,<9.0.0) @@ -7827,6 +7844,13 @@ This list contains 1411 plugins. + :pypi:`pytest-pogo` + *last release*: Mar 11, 2024, + *status*: 1 - Planning, + *requires*: pytest (>=7,<9) + + Pytest plugin for pogo-migrate + :pypi:`pytest-pointers` *last release*: Dec 26, 2022, *status*: N/A, @@ -7919,7 +7943,7 @@ This list contains 1411 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: Mar 07, 2024, + *last release*: Mar 11, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=6.2 @@ -8017,9 +8041,9 @@ This list contains 1411 plugins. Test helpers for Prosper projects :pypi:`pytest-prysk` - *last release*: Dec 30, 2023, + *last release*: Mar 12, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.3.2,<8.0.0) + *requires*: pytest (>=7.3.2) Pytest plugin for prysk @@ -8423,7 +8447,7 @@ This list contains 1411 plugins. Test your README.md file :pypi:`pytest-reana` - *last release*: Nov 30, 2023, + *last release*: Mar 14, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -8724,9 +8748,9 @@ This list contains 1411 plugins. Rerun testsuite for a certain time or iterations :pypi:`pytest-rerunfailures` - *last release*: Nov 22, 2023, + *last release*: Mar 13, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7 + *requires*: pytest >=7.2 pytest plugin to re-run tests to eliminate flaky failures @@ -8913,7 +8937,7 @@ This list contains 1411 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Mar 08, 2024, + *last release*: Mar 13, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -8962,7 +8986,7 @@ This list contains 1411 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Mar 03, 2024, + *last release*: Mar 10, 2024, *status*: 4 - Beta, *requires*: pytest (>=5) @@ -9081,7 +9105,7 @@ This list contains 1411 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Mar 09, 2024, + *last release*: Mar 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9144,7 +9168,7 @@ This list contains 1411 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Mar 09, 2024, + *last release*: Mar 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9823,7 +9847,7 @@ This list contains 1411 plugins. A Pytest plugin that allows you to loop tests for a user defined amount of time. :pypi:`pytest-structlog` - *last release*: Feb 04, 2024, + *last release*: Mar 13, 2024, *status*: N/A, *requires*: pytest @@ -10761,9 +10785,9 @@ This list contains 1411 plugins. Run only unmarked tests :pypi:`pytest-unordered` - *last release*: Nov 28, 2022, + *last release*: Mar 13, 2024, *status*: 4 - Beta, - *requires*: pytest (>=6.0.0) + *requires*: pytest >=7.0.0 Test equality of unordered collections in pytest From 6be5c9d88ccfaf9f4648a703fba5b85635b50f06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 03:02:28 +0000 Subject: [PATCH 0557/1271] build(deps): Bump pytest-rerunfailures in /testing/plugins_integration Bumps [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) from 13.0 to 14.0. - [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/13.0...14.0) --- updated-dependencies: - dependency-name: pytest-rerunfailures dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 43e7ed4f22b..dad246112f3 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -9,7 +9,7 @@ pytest-django==4.8.0 pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.12.0 -pytest-rerunfailures==13.0 +pytest-rerunfailures==14.0 pytest-sugar==1.0.0 pytest-trio==0.7.0 pytest-twisted==1.14.0 From 027464975f04cc7ec5cb53899b924a6872bc8927 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 03:12:45 +0000 Subject: [PATCH 0558/1271] build(deps): Bump peter-evans/create-pull-request from 6.0.0 to 6.0.2 Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.0.0 to 6.0.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/b1ddad2c994a25fbc81a28b3ec0e368bb2021c50...70a41aba780001da0a30141984ae2a0c95d8704e) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 55fb4dc6f01..53ba0e368d9 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -46,7 +46,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request - uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 + uses: peter-evans/create-pull-request@70a41aba780001da0a30141984ae2a0c95d8704e with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From bf8b088bbe49aed2b92179a490d9f228486ca3b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 03:12:49 +0000 Subject: [PATCH 0559/1271] build(deps): Bump hynek/build-and-inspect-python-package Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.0.1 to 2.0.2. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.0.1...v2.0.2) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4ed68c286cb..95713e4e774 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.0.1 + uses: hynek/build-and-inspect-python-package@v2.0.2 deploy: if: github.repository == 'pytest-dev/pytest' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9fe01dc72cc..00d6c608ac3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.0.1 + uses: hynek/build-and-inspect-python-package@v2.0.2 build: needs: [package] From 532782a22807c9dd0b0f8c7b1d114bda67f03593 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 22:51:23 +0000 Subject: [PATCH 0560/1271] [pre-commit.ci] pre-commit autoupdate (#12137) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.3.2 → v0.3.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.3.2...v0.3.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index deb187fec13..b9547c27f8c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.3.2" + rev: "v0.3.3" hooks: - id: ruff args: ["--fix"] From e7bf21651633237b485cdf02ba7a2be004e97f1a Mon Sep 17 00:00:00 2001 From: Sebastian Meyer Date: Tue, 19 Mar 2024 23:54:26 +0100 Subject: [PATCH 0561/1271] doc: add versionadded to `ExceptionInfo.group_contains` (#12141) --- src/_pytest/_code/code.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 64a8f243a2d..3b4a62a4fa0 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -786,6 +786,8 @@ def group_contains( If `None`, will search for a matching exception at any nesting depth. If >= 1, will only match an exception if it's at the specified depth (depth = 1 being the exceptions contained within the topmost exception group). + + .. versionadded:: 8.0 """ msg = "Captured exception is not an instance of `BaseExceptionGroup`" assert isinstance(self.value, BaseExceptionGroup), msg From c650e3a94fb7e64001ada05ed9b0855d65693395 Mon Sep 17 00:00:00 2001 From: Linghao Zhang Date: Thu, 21 Mar 2024 22:21:43 +0800 Subject: [PATCH 0562/1271] Add research item in doc (#12147) --- doc/en/explanation/flaky.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/explanation/flaky.rst b/doc/en/explanation/flaky.rst index 2beeb34e0f8..41cbe847989 100644 --- a/doc/en/explanation/flaky.rst +++ b/doc/en/explanation/flaky.rst @@ -105,7 +105,7 @@ This is a limited list, please submit an issue or pull request to expand it! * Gao, Zebao, Yalan Liang, Myra B. Cohen, Atif M. Memon, and Zhen Wang. "Making system user interactive tests repeatable: When and what should we control?." In *Software Engineering (ICSE), 2015 IEEE/ACM 37th IEEE International Conference on*, vol. 1, pp. 55-65. IEEE, 2015. `PDF `__ * Palomba, Fabio, and Andy Zaidman. "Does refactoring of test smells induce fixing flaky tests?." In *Software Maintenance and Evolution (ICSME), 2017 IEEE International Conference on*, pp. 1-12. IEEE, 2017. `PDF in Google Drive `__ * Bell, Jonathan, Owolabi Legunsen, Michael Hilton, Lamyaa Eloussi, Tifany Yung, and Darko Marinov. "DeFlaker: Automatically detecting flaky tests." In *Proceedings of the 2018 International Conference on Software Engineering*. 2018. `PDF `__ - +* Dutta, Saikat and Shi, August and Choudhary, Rutvik and Zhang, Zhekun and Jain, Aryaman and Misailovic, Sasa. "Detecting flaky tests in probabilistic and machine learning applications." In *Proceedings of the 29th ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA)*, pp. 211-224. ACM, 2020. `PDF `__ Resources ^^^^^^^^^ From 3eb16b34be1900fe41d8b91e00facd62170e2878 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 23 Mar 2024 12:05:40 +0200 Subject: [PATCH 0563/1271] fixtures: stop using `request.param_index` in fixture cache key When `param` is not defined, `param_index` is always 0 (see `_compute_fixture_value`), so no point in using it besides adding some confusion. --- src/_pytest/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 48429a023ac..a8fed047e7f 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1072,7 +1072,7 @@ def execute(self, request: SubRequest) -> FixtureValue: return result def cache_key(self, request: SubRequest) -> object: - return request.param_index if not hasattr(request, "param") else request.param + return getattr(request, "param", None) def __repr__(self) -> str: return f"" From aeae91e27dbc67ed8f8ffb0098b829d58d8afcc2 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 24 Mar 2024 00:20:37 +0000 Subject: [PATCH 0564/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 220 ++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 74 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 52bcc96d6de..59c6a400260 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Mar 19, 2024 4 - Beta pytest <9,>=7.0.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 25, 2024 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) @@ -136,7 +136,7 @@ This list contains 1414 plugins. :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 - :pypi:`pytest-bdd` BDD for pytest Mar 04, 2024 6 - Mature pytest (>=6.2.0) + :pypi:`pytest-bdd` BDD for pytest Mar 17, 2024 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Feb 19, 2024 N/A pytest >=7.1.3 @@ -198,7 +198,7 @@ This list contains 1414 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Mar 11, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Mar 20, 2024 N/A N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -208,7 +208,7 @@ This list contains 1414 plugins. :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 18, 2024 N/A pytest>=7.0.0 - :pypi:`pytest-checkdocs` check the README when running tests Jul 30, 2023 5 - Production/Stable pytest (>=6) ; extra == 'testing' + :pypi:`pytest-checkdocs` check the README when running tests Mar 21, 2024 5 - Production/Stable pytest>=6; extra == "testing" :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A @@ -228,14 +228,14 @@ This list contains 1414 plugins. :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A - :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 25, 2023 4 - Beta N/A + :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Mar 04, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Mar 18, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 @@ -245,7 +245,7 @@ This list contains 1414 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Sep 01, 2023 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Mar 19, 2024 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -440,15 +440,17 @@ This list contains 1414 plugins. :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) - :pypi:`pytest-enabler` Enable installed pytest plugins Dec 23, 2023 5 - Production/Stable pytest >=6 ; extra == 'testing' + :pypi:`pytest-enabler` Enable installed pytest plugins Mar 21, 2024 5 - Production/Stable pytest>=6; extra == "testing" :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest + :pypi:`pytest-energy-reporter` A energy estimation reporter for pytest Mar 19, 2024 N/A N/A :pypi:`pytest-enhanced-reports` Enhanced test reports for pytest Dec 15, 2022 N/A N/A :pypi:`pytest-enhancements` Improvements for pytest (rejected upstream) Oct 30, 2019 4 - Beta N/A :pypi:`pytest-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-environment` Pytest Environment Mar 17, 2024 1 - Planning N/A :pypi:`pytest-envraw` py.test plugin that allows you to add environment variables. Aug 27, 2020 4 - Beta pytest (>=2.6.0) :pypi:`pytest-envvars` Pytest plugin to validate use of envvars on your tests Jun 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-env-yaml` Apr 02, 2019 N/A N/A @@ -504,13 +506,14 @@ This list contains 1414 plugins. :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A + :pypi:`pytest-file` Pytest File Mar 18, 2024 1 - Planning N/A :pypi:`pytest-filecov` A pytest plugin to detect unused files Jun 27, 2021 4 - Beta pytest :pypi:`pytest-filedata` easily load data from files Jan 17, 2019 4 - Beta N/A :pypi:`pytest-filemarker` A pytest plugin that runs marked tests when files change. Dec 01, 2020 N/A pytest :pypi:`pytest-file-watcher` Pytest-File-Watcher is a CLI tool that watches for changes in your code and runs pytest on the changed files. Mar 23, 2023 N/A pytest :pypi:`pytest-filter-case` run test cases filter by mark Nov 05, 2020 N/A N/A :pypi:`pytest-filter-subpackage` Pytest plugin for filtering based on sub-packages Mar 04, 2024 5 - Production/Stable pytest >=4.6 - :pypi:`pytest-find-dependencies` A pytest plugin to find dependencies between tests Apr 09, 2022 4 - Beta pytest (>=4.3.0) + :pypi:`pytest-find-dependencies` A pytest plugin to find dependencies between tests Mar 16, 2024 4 - Beta pytest >=4.3.0 :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest @@ -604,7 +607,7 @@ This list contains 1414 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Mar 15, 2024 3 - Alpha pytest ==8.0.2 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 23, 2024 3 - Alpha pytest==8.0.2 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jan 06, 2024 N/A N/A @@ -659,7 +662,7 @@ This list contains 1414 plugins. :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest - :pypi:`pytest-insper` Pytest plugin for courses at Insper Mar 16, 2024 N/A pytest + :pypi:`pytest-insper` Pytest plugin for courses at Insper Mar 21, 2024 N/A pytest :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Feb 19, 2024 N/A pytest (>=7.2.0,<9.0.0) :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) :pypi:`pytest-instrument` pytest plugin to instrument tests Apr 05, 2020 5 - Production/Stable pytest (>=5.1.0) @@ -682,7 +685,7 @@ This list contains 1414 plugins. :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Jun 12, 2023 3 - Alpha N/A + :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Mar 18, 2024 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Sep 08, 2023 4 - Beta pytest >=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) @@ -722,7 +725,7 @@ This list contains 1414 plugins. :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A - :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 11, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 22, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A @@ -752,7 +755,7 @@ This list contains 1414 plugins. :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logikal` Common testing environment Feb 05, 2024 5 - Production/Stable pytest ==8.0.0 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A - :pypi:`pytest-loguru` Pytest Loguru Oct 04, 2023 5 - Production/Stable pytest + :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Feb 07, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 @@ -794,7 +797,7 @@ This list contains 1414 plugins. :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Mar 07, 2024 N/A pytest >=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) - :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Oct 19, 2023 5 - Production/Stable pytest >=5.0 + :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Mar 21, 2024 5 - Production/Stable pytest>=6.2.5 :pypi:`pytest-mock-api` A mock API server with configurable routes and responses available as a fixture. Feb 13, 2019 1 - Planning pytest (>=4.0.0) :pypi:`pytest-mock-generator` A pytest fixture wrapper for https://pypi.org/project/mock-generator May 16, 2022 5 - Production/Stable N/A :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest @@ -886,7 +889,8 @@ This list contains 1414 plugins. :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 - :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Feb 19, 2024 N/A pytest==8.0.1 + :pypi:`pytest-ot` A pytest plugin for instrumenting test runs via OpenTelemetry Mar 21, 2024 N/A pytest; extra == "dev" + :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Mar 18, 2024 N/A pytest==8.1.1 :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A :pypi:`pytest-owner` Add owner mark for tests Apr 25, 2022 N/A N/A :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A @@ -918,6 +922,7 @@ This list contains 1414 plugins. :pypi:`pytest-percents` Mar 16, 2024 N/A N/A :pypi:`pytest-perf` Run performance tests against the mainline code. Jan 28, 2024 5 - Production/Stable pytest >=6 ; extra == 'testing' :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) + :pypi:`pytest-performancetotal` A performance plugin for pytest Mar 19, 2024 4 - Beta N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) @@ -938,7 +943,7 @@ This list contains 1414 plugins. :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Feb 02, 2024 N/A pytest (<9.0.0,>=6.2.4) :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Feb 25, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A - :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 14, 2024 N/A pytest (>=8.0.0,<9.0.0) + :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 19, 2024 N/A pytest (>=8.0.0,<9.0.0) :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A @@ -963,6 +968,7 @@ This list contains 1414 plugins. :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 11, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) + :pypi:`pytest-powerpack` Mar 17, 2024 N/A pytest (>=8.1.1,<9.0.0) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) @@ -1031,7 +1037,7 @@ This list contains 1414 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Mar 01, 2024 4 - Beta pytest >=7.4.3 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Mar 18, 2024 4 - Beta pytest >=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Mar 14, 2024 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 @@ -1068,6 +1074,7 @@ This list contains 1414 plugins. :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Mar 01, 2024 N/A pytest >=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A + :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A @@ -1103,7 +1110,7 @@ This list contains 1414 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 13, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 19, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1120,14 +1127,14 @@ This list contains 1414 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 Jan 23, 2024 4 - Beta pytest (>=6.0.0) + :pypi:`pytest-salt-factories` Pytest Salt Plugin Mar 22, 2024 5 - Production/Stable pytest>=7.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_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 21, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1136,7 +1143,7 @@ This list contains 1414 plugins. :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 Feb 01, 2024 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. Mar 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 21, 2024 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 @@ -1144,7 +1151,7 @@ This list contains 1414 plugins. :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Feb 14, 2024 3 - Alpha pytest >=6.2 + :pypi:`pytest-servers` pytest servers Mar 19, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1160,6 +1167,7 @@ This list contains 1414 plugins. :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-simbind` Pytest plugin to operate with objects generated by Simbind tool. Mar 20, 2024 N/A pytest>=7.0.0 :pypi:`pytest-simplehttpserver` Simple pytest fixture to spin up an HTTP server Jun 24, 2021 4 - Beta N/A :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest @@ -1352,7 +1360,7 @@ This list contains 1414 plugins. :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A - :pypi:`pytest-twisted` A twisted plugin for pytest. Oct 16, 2022 5 - Production/Stable pytest (>=2.3) + :pypi:`pytest-twisted` A twisted plugin for pytest. Mar 19, 2024 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 Feb 01, 2024 4 - Beta N/A @@ -1395,7 +1403,7 @@ This list contains 1414 plugins. :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-wake` Nov 07, 2023 N/A pytest + :pypi:`pytest-wake` Mar 20, 2024 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Feb 06, 2024 4 - Beta N/A :pypi:`pytest_wdb` Trace pytest tests with wdb to halt on error with --wdb. Jul 04, 2016 N/A N/A @@ -1404,14 +1412,14 @@ This list contains 1414 plugins. :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 13, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable Jan 30, 2024 N/A pytest>=7.3.1 + :pypi:`pytest-when` Utility which makes mocking more readable and controllable Mar 22, 2024 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A :pypi:`pytest-winnotify` Windows tray notifications for py.test results. Apr 22, 2016 N/A N/A :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-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Mar 18, 2024 5 - Production/Stable pytest >=7.0.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) @@ -1421,9 +1429,9 @@ This list contains 1414 plugins. :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Jan 28, 2024 N/A pytest<8,>=7.4.0 + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Mar 22, 2024 N/A N/A :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest - :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Sep 23, 2023 4 - Beta pytest (>=2.8) + :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Mar 23, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) @@ -1448,6 +1456,7 @@ This list contains 1414 plugins. :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest + :pypi:`pytest-zy` 接口自动化测试框架 Mar 23, 2024 N/A pytest~=7.2.0 =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -1972,7 +1981,7 @@ This list contains 1414 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Mar 08, 2024, + *last release*: Mar 19, 2024, *status*: 4 - Beta, *requires*: pytest <9,>=7.0.0 @@ -2168,7 +2177,7 @@ This list contains 1414 plugins. pytest plugin for URL based testing :pypi:`pytest-bdd` - *last release*: Mar 04, 2024, + *last release*: Mar 17, 2024, *status*: 6 - Mature, *requires*: pytest (>=6.2.0) @@ -2602,7 +2611,7 @@ This list contains 1414 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Mar 11, 2024, + *last release*: Mar 20, 2024, *status*: N/A, *requires*: N/A @@ -2672,9 +2681,9 @@ This list contains 1414 plugins. A pytest plugin that allows multiple failures per test. :pypi:`pytest-checkdocs` - *last release*: Jul 30, 2023, + *last release*: Mar 21, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6) ; extra == 'testing' + *requires*: pytest>=6; extra == "testing" check the README when running tests @@ -2812,8 +2821,8 @@ This list contains 1414 plugins. Automated, comprehensive and well-organised pytest test cases. :pypi:`pytest-cleanuptotal` - *last release*: Sep 25, 2023, - *status*: 4 - Beta, + *last release*: Mar 19, 2024, + *status*: 5 - Production/Stable, *requires*: N/A A cleanup plugin for pytest @@ -2861,7 +2870,7 @@ This list contains 1414 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Mar 04, 2024, + *last release*: Mar 18, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -2931,7 +2940,7 @@ This list contains 1414 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Sep 01, 2023, + *last release*: Mar 19, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -4296,9 +4305,9 @@ This list contains 1414 plugins. Pytest plugin to represent test output with emoji support :pypi:`pytest-enabler` - *last release*: Dec 23, 2023, + *last release*: Mar 21, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6 ; extra == 'testing' + *requires*: pytest>=6; extra == "testing" Enable installed pytest plugins @@ -4323,6 +4332,13 @@ This list contains 1414 plugins. set your encoding and logger + :pypi:`pytest-energy-reporter` + *last release*: Mar 19, 2024, + *status*: N/A, + *requires*: N/A + + A energy estimation reporter for pytest + :pypi:`pytest-enhanced-reports` *last release*: Dec 15, 2022, *status*: N/A, @@ -4358,6 +4374,13 @@ This list contains 1414 plugins. Push information about the running pytest into envvars + :pypi:`pytest-environment` + *last release*: Mar 17, 2024, + *status*: 1 - Planning, + *requires*: N/A + + Pytest Environment + :pypi:`pytest-envraw` *last release*: Aug 27, 2020, *status*: 4 - Beta, @@ -4743,6 +4766,13 @@ This list contains 1414 plugins. py.test figleaf coverage plugin + :pypi:`pytest-file` + *last release*: Mar 18, 2024, + *status*: 1 - Planning, + *requires*: N/A + + Pytest File + :pypi:`pytest-filecov` *last release*: Jun 27, 2021, *status*: 4 - Beta, @@ -4786,9 +4816,9 @@ This list contains 1414 plugins. Pytest plugin for filtering based on sub-packages :pypi:`pytest-find-dependencies` - *last release*: Apr 09, 2022, + *last release*: Mar 16, 2024, *status*: 4 - Beta, - *requires*: pytest (>=4.3.0) + *requires*: pytest >=4.3.0 A pytest plugin to find dependencies between tests @@ -5444,9 +5474,9 @@ This list contains 1414 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 15, 2024, + *last release*: Mar 23, 2024, *status*: 3 - Alpha, - *requires*: pytest ==8.0.2 + *requires*: pytest==8.0.2 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -5829,7 +5859,7 @@ This list contains 1414 plugins. The extension enables easy execution of pytest tests within the Robot Framework environment. :pypi:`pytest-insper` - *last release*: Mar 16, 2024, + *last release*: Mar 21, 2024, *status*: N/A, *requires*: pytest @@ -5990,7 +6020,7 @@ This list contains 1414 plugins. A plugin to generate customizable jinja-based HTML reports in pytest :pypi:`pytest-jira` - *last release*: Jun 12, 2023, + *last release*: Mar 18, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -6270,7 +6300,7 @@ This list contains 1414 plugins. A pytest plugin to trace resource leaks. :pypi:`pytest-leaping` - *last release*: Mar 11, 2024, + *last release*: Mar 22, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -6480,9 +6510,9 @@ This list contains 1414 plugins. Package for creating a pytest test run reprot :pypi:`pytest-loguru` - *last release*: Oct 04, 2023, + *last release*: Mar 20, 2024, *status*: 5 - Production/Stable, - *requires*: pytest + *requires*: pytest; extra == "test" Pytest Loguru @@ -6774,9 +6804,9 @@ This list contains 1414 plugins. pytest plugin to display test execution output like a mochajs :pypi:`pytest-mock` - *last release*: Oct 19, 2023, + *last release*: Mar 21, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=5.0 + *requires*: pytest>=6.2.5 Thin-wrapper around the mock package for easier use with pytest @@ -7417,10 +7447,17 @@ This list contains 1414 plugins. OS X notifications for py.test results. + :pypi:`pytest-ot` + *last release*: Mar 21, 2024, + *status*: N/A, + *requires*: pytest; extra == "dev" + + A pytest plugin for instrumenting test runs via OpenTelemetry + :pypi:`pytest-otel` - *last release*: Feb 19, 2024, + *last release*: Mar 18, 2024, *status*: N/A, - *requires*: pytest==8.0.1 + *requires*: pytest==8.1.1 OpenTelemetry plugin for Pytest @@ -7641,6 +7678,13 @@ This list contains 1414 plugins. A simple plugin to ensure the execution of critical sections of code has not been impacted + :pypi:`pytest-performancetotal` + *last release*: Mar 19, 2024, + *status*: 4 - Beta, + *requires*: N/A + + A performance plugin for pytest + :pypi:`pytest-persistence` *last release*: Jul 04, 2023, *status*: N/A, @@ -7782,7 +7826,7 @@ This list contains 1414 plugins. :pypi:`pytest-playwright-enhanced` - *last release*: Mar 14, 2024, + *last release*: Mar 19, 2024, *status*: N/A, *requires*: pytest (>=8.0.0,<9.0.0) @@ -7956,6 +8000,13 @@ This list contains 1414 plugins. pytest plugin with powerful fixtures + :pypi:`pytest-powerpack` + *last release*: Mar 17, 2024, + *status*: N/A, + *requires*: pytest (>=8.1.1,<9.0.0) + + + :pypi:`pytest-prefer-nested-dup-tests` *last release*: Apr 27, 2022, *status*: 4 - Beta, @@ -8433,7 +8484,7 @@ This list contains 1414 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-ranking` - *last release*: Mar 01, 2024, + *last release*: Mar 18, 2024, *status*: 4 - Beta, *requires*: pytest >=7.4.3 @@ -8691,6 +8742,13 @@ This list contains 1414 plugins. A pytest plugin which allows to stream test reports at runtime + :pypi:`pytest-repo-structure` + *last release*: Mar 18, 2024, + *status*: 1 - Planning, + *requires*: N/A + + Pytest Repo Structure + :pypi:`pytest-reqs` *last release*: May 12, 2019, *status*: N/A, @@ -8937,7 +8995,7 @@ This list contains 1414 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Mar 13, 2024, + *last release*: Mar 19, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9056,9 +9114,9 @@ This list contains 1414 plugins. A Pytest plugin that builds and creates docker containers :pypi:`pytest-salt-factories` - *last release*: Jan 23, 2024, - *status*: 4 - Beta, - *requires*: pytest (>=6.0.0) + *last release*: Mar 22, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=7.0.0 Pytest Salt Plugin @@ -9105,7 +9163,7 @@ This list contains 1414 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Mar 16, 2024, + *last release*: Mar 21, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9168,7 +9226,7 @@ This list contains 1414 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Mar 16, 2024, + *last release*: Mar 21, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9224,9 +9282,9 @@ This list contains 1414 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Feb 14, 2024, + *last release*: Mar 19, 2024, *status*: 3 - Alpha, - *requires*: pytest >=6.2 + *requires*: pytest>=6.2 pytest servers @@ -9335,6 +9393,13 @@ This list contains 1414 plugins. A goodie-bag of unix shell and environment tools for py.test + :pypi:`pytest-simbind` + *last release*: Mar 20, 2024, + *status*: N/A, + *requires*: pytest>=7.0.0 + + Pytest plugin to operate with objects generated by Simbind tool. + :pypi:`pytest-simplehttpserver` *last release*: Jun 24, 2021, *status*: 4 - Beta, @@ -10680,9 +10745,9 @@ This list contains 1414 plugins. :pypi:`pytest-twisted` - *last release*: Oct 16, 2022, + *last release*: Mar 19, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=2.3) + *requires*: pytest >=2.3 A twisted plugin for pytest. @@ -10981,7 +11046,7 @@ This list contains 1414 plugins. Pytest plugin for testing whatsapp bots with end to end tests :pypi:`pytest-wake` - *last release*: Nov 07, 2023, + *last release*: Mar 20, 2024, *status*: N/A, *requires*: pytest @@ -11044,7 +11109,7 @@ This list contains 1414 plugins. Welian API Automation test framework pytest plugin :pypi:`pytest-when` - *last release*: Jan 30, 2024, + *last release*: Mar 22, 2024, *status*: N/A, *requires*: pytest>=7.3.1 @@ -11093,9 +11158,9 @@ This list contains 1414 plugins. pytest with docker helpers. :pypi:`pytest-workflow` - *last release*: Jan 13, 2023, + *last release*: Mar 18, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.0.0) + *requires*: pytest >=7.0.0 A pytest plugin for configuring workflow/pipeline tests using YAML files @@ -11163,9 +11228,9 @@ This list contains 1414 plugins. Extended logging for test and decorators :pypi:`pytest-xlsx` - *last release*: Jan 28, 2024, + *last release*: Mar 22, 2024, *status*: N/A, - *requires*: pytest<8,>=7.4.0 + *requires*: N/A pytest plugin for generating test cases by xlsx(excel) @@ -11177,9 +11242,9 @@ This list contains 1414 plugins. An extended parametrizing plugin of pytest. :pypi:`pytest-xprocess` - *last release*: Sep 23, 2023, + *last release*: Mar 23, 2024, *status*: 4 - Beta, - *requires*: pytest (>=2.8) + *requires*: pytest>=2.8 A pytest plugin for managing processes across test runs. @@ -11350,3 +11415,10 @@ This list contains 1414 plugins. *requires*: pytest Pytest report plugin for Zulip + + :pypi:`pytest-zy` + *last release*: Mar 23, 2024, + *status*: N/A, + *requires*: pytest~=7.2.0 + + 接口自动化测试框架 From 909759de2d2c699dfe97132d4d5487e0b44e0e6c Mon Sep 17 00:00:00 2001 From: tserg <8017125+tserg@users.noreply.github.com> Date: Sun, 24 Mar 2024 22:59:07 +0800 Subject: [PATCH 0565/1271] Improve sentence in marks documentation (#12157) --- doc/en/reference/reference.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 358f371e5e9..21890fbf63e 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -136,7 +136,7 @@ pytest.freeze_includes Marks ----- -Marks can be used apply meta data to *test functions* (but not fixtures), which can then be accessed by +Marks can be used to apply metadata to *test functions* (but not fixtures), which can then be accessed by fixtures or plugins. From 4a8cefbf64acb47ec0eb411b04ed24bc9f5d44b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 07:30:08 +0100 Subject: [PATCH 0566/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#12161) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.5 to 0.23.6. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.5...v0.23.6) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index dad246112f3..b6d592f2473 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.3.0 django==5.0.3 -pytest-asyncio==0.23.5 +pytest-asyncio==0.23.6 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 # pytest-bdd==7.0.1 From e7b048e92dcdc8f286d360bb6b92b386f7beb628 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 07:30:45 +0100 Subject: [PATCH 0567/1271] build(deps): Bump pytest-mock in /testing/plugins_integration (#12160) Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.12.0 to 3.14.0. - [Release notes](https://github.com/pytest-dev/pytest-mock/releases) - [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.12.0...v3.14.0) --- updated-dependencies: - dependency-name: pytest-mock dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index b6d592f2473..ab197b5854e 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -8,7 +8,7 @@ pytest-cov==4.1.0 pytest-django==4.8.0 pytest-flakes==4.0.5 pytest-html==4.1.1 -pytest-mock==3.12.0 +pytest-mock==3.14.0 pytest-rerunfailures==14.0 pytest-sugar==1.0.0 pytest-trio==0.7.0 From 2cba2237cdbff964854e7964986cdbe6855bf75e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 07:32:29 +0100 Subject: [PATCH 0568/1271] build(deps): Bump pytest-twisted in /testing/plugins_integration (#12158) Bumps [pytest-twisted](https://github.com/pytest-dev/pytest-twisted) from 1.14.0 to 1.14.1. - [Release notes](https://github.com/pytest-dev/pytest-twisted/releases) - [Commits](https://github.com/pytest-dev/pytest-twisted/compare/v1.14.0...v1.14.1) --- updated-dependencies: - dependency-name: pytest-twisted dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index ab197b5854e..a226b16ada1 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -12,6 +12,6 @@ pytest-mock==3.14.0 pytest-rerunfailures==14.0 pytest-sugar==1.0.0 pytest-trio==0.7.0 -pytest-twisted==1.14.0 +pytest-twisted==1.14.1 twisted==24.3.0 pytest-xvfb==3.0.0 From 5d345f6d7feea00ecce9659f176731d5705debc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 06:32:55 +0000 Subject: [PATCH 0569/1271] build(deps): Bump pytest-cov in /testing/plugins_integration Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 4.1.0 to 5.0.0. - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.1.0...v5.0.0) --- updated-dependencies: - dependency-name: pytest-cov dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index a226b16ada1..7f22548629d 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -4,7 +4,7 @@ pytest-asyncio==0.23.6 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 # pytest-bdd==7.0.1 -pytest-cov==4.1.0 +pytest-cov==5.0.0 pytest-django==4.8.0 pytest-flakes==4.0.5 pytest-html==4.1.1 From 12e061e2e838fb2c17d54df40a4a11aeb8723c6b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Mar 2024 23:37:36 +0100 Subject: [PATCH 0570/1271] [pre-commit.ci] pre-commit autoupdate (#12162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.3.3 → v0.3.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.3.3...v0.3.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b9547c27f8c..1f0214b7e57 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.3.3" + rev: "v0.3.4" hooks: - id: ruff args: ["--fix"] From 2dd58e827e98fd45d8f35a9fa9137faf179bd26e Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 31 Mar 2024 00:20:45 +0000 Subject: [PATCH 0571/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 188 +++++++++++++++++++++---------- 1 file changed, 130 insertions(+), 58 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 59c6a400260..1ab93ddc093 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7,<9) ; extra == "pytest" + :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A @@ -154,7 +154,7 @@ This list contains 1423 plugins. :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) - :pypi:`pytest-bisect-tests` Find tests leaking state and affecting other Feb 17, 2024 N/A N/A + :pypi:`pytest-bisect-tests` Find tests leaking state and affecting other Mar 25, 2024 N/A N/A :pypi:`pytest-black` A pytest plugin to enable format checking with black Oct 05, 2020 4 - Beta N/A :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) @@ -198,7 +198,7 @@ This list contains 1423 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Mar 20, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Mar 27, 2024 N/A N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -261,7 +261,7 @@ This list contains 1423 plugins. :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest - :pypi:`pytest-container` Pytest fixtures for writing container based tests Sep 26, 2023 4 - Beta pytest (>=3.10) + :pypi:`pytest-container` Pytest fixtures for writing container based tests Mar 27, 2024 4 - Beta pytest>=3.10 :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) @@ -269,7 +269,7 @@ This list contains 1423 plugins. :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A - :pypi:`pytest-cov` Pytest plugin for measuring coverage. May 24, 2023 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-cov` Pytest plugin for measuring coverage. Mar 24, 2024 5 - Production/Stable pytest>=4.6 :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A @@ -294,7 +294,7 @@ This list contains 1423 plugins. :pypi:`pytest-custom-nodeid` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 07, 2021 N/A N/A :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A - :pypi:`pytest-cython` A plugin for testing Cython extension modules Feb 16, 2023 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-cython` A plugin for testing Cython extension modules Mar 30, 2024 5 - Production/Stable pytest<8,>=4.6 :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A @@ -335,6 +335,7 @@ This list contains 1423 plugins. :pypi:`pytest-deprecate` Mark tests as testing a deprecated feature with a warning note. Jul 01, 2019 N/A N/A :pypi:`pytest-describe` Describe-style plugin for pytest Feb 10, 2024 5 - Production/Stable pytest <9,>=4.6 :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest + :pypi:`pytest-deselect-if` A plugin to deselect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-devpi-server` DevPI server fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-dhos` Common fixtures for pytest in DHOS services and libraries Sep 07, 2022 N/A N/A :pypi:`pytest-diamond` pytest plugin for diamond Aug 31, 2015 4 - Beta N/A @@ -348,6 +349,7 @@ This list contains 1423 plugins. :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 + :pypi:`pytest-discover` Pytest plugin to record discovered tests in a file Mar 26, 2024 N/A pytest :pypi:`pytest-django` A Django plugin for pytest. Jan 30, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest @@ -444,7 +446,7 @@ This list contains 1423 plugins. :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest - :pypi:`pytest-energy-reporter` A energy estimation reporter for pytest Mar 19, 2024 N/A N/A + :pypi:`pytest_energy_reporter` An energy estimation reporter for pytest Mar 28, 2024 3 - Alpha pytest<9.0.0,>=8.1.1 :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. Nov 28, 2023 5 - Production/Stable pytest>=7.4.3 @@ -480,6 +482,7 @@ This list contains 1423 plugins. :pypi:`pytest-explicit` A Pytest plugin to ignore certain marked tests by default Jun 15, 2021 5 - Production/Stable pytest :pypi:`pytest-exploratory` Interactive console for pytest. Aug 18, 2023 N/A pytest (>=6.2) :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A + :pypi:`pytest-ext` pytest plugin for automation test Mar 30, 2024 N/A pytest>=5.3 :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A @@ -572,12 +575,14 @@ This list contains 1423 plugins. :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 + :pypi:`pytest-git-diff` Pytest plugin that allows the user to select the tests affected by a range of git commits Mar 30, 2024 N/A N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A + :pypi:`pytest-gitlab-codequality` Collects warnings while testing and generates a GitLab Codequality Report. Mar 29, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest @@ -657,7 +662,7 @@ This list contains 1423 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 19, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Dec 13, 2023 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Feb 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package Mar 29, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Feb 20, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A @@ -687,7 +692,7 @@ This list contains 1423 plugins. :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Mar 18, 2024 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Sep 08, 2023 4 - Beta pytest >=6.2.4 + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Mar 27, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -696,6 +701,7 @@ This list contains 1423 plugins. :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 + :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Mar 12, 2024 4 - Beta pytest :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest @@ -725,7 +731,7 @@ This list contains 1423 plugins. :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A - :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 22, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A @@ -756,7 +762,7 @@ This list contains 1423 plugins. :pypi:`pytest-logikal` Common testing environment Feb 05, 2024 5 - Production/Stable pytest ==8.0.0 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-loop` pytest plugin for looping tests Jul 22, 2022 5 - Production/Stable pytest (>=6) + :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Feb 07, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) @@ -924,6 +930,7 @@ This list contains 1423 plugins. :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-performancetotal` A performance plugin for pytest Mar 19, 2024 4 - Beta N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A + :pypi:`pytest-pexpect` Pytest pexpect plugin. Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) @@ -943,14 +950,14 @@ This list contains 1423 plugins. :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Feb 02, 2024 N/A pytest (<9.0.0,>=6.2.4) :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Feb 25, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A - :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 19, 2024 N/A pytest (>=8.0.0,<9.0.0) + :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A :pypi:`pytest-plone` Pytest plugin to test Plone addons Jan 05, 2023 3 - Alpha pytest :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Jan 10, 2024 5 - Production/Stable pytest >=7.4.2 + :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Mar 26, 2024 5 - Production/Stable pytest>=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A :pypi:`pytest-pogo` Pytest plugin for pogo-migrate Mar 11, 2024 1 - Planning pytest (>=7,<9) :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A @@ -1053,7 +1060,7 @@ This list contains 1423 plugins. :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Feb 26, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A - :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest May 23, 2023 5 - Production/Stable pytest (>=7) + :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Mar 29, 2024 5 - Production/Stable pytest>=7 :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Sep 26, 2023 5 - Production/Stable pytest >=4.6 :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) @@ -1072,7 +1079,7 @@ This list contains 1423 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Mar 01, 2024 N/A pytest >=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Mar 27, 2024 N/A pytest>=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) @@ -1083,6 +1090,7 @@ This list contains 1423 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-rerunclassfailures` pytest rerun class failures plugin Mar 29, 2024 5 - Production/Stable pytest>=7.2 :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 :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. Feb 08, 2024 4 - Beta pytest @@ -1110,7 +1118,7 @@ This list contains 1423 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 19, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 29, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1167,7 +1175,7 @@ This list contains 1423 plugins. :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-simbind` Pytest plugin to operate with objects generated by Simbind tool. Mar 20, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-simbind` Pytest plugin to operate with objects generated by Simbind tool. Mar 28, 2024 N/A pytest>=7.0.0 :pypi:`pytest-simplehttpserver` Simple pytest fixture to spin up an HTTP server Jun 24, 2021 4 - Beta N/A :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest @@ -1219,7 +1227,7 @@ This list contains 1423 plugins. :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 Jan 12, 2024 N/A pytest (>5.4.0,<8) - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Feb 23, 2024 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 26, 2024 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 @@ -1237,7 +1245,7 @@ This list contains 1423 plugins. :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A - :pypi:`pytest-stf` pytest plugin for openSTF Feb 08, 2024 N/A pytest >=5.0 + :pypi:`pytest-stf` pytest plugin for openSTF Mar 25, 2024 N/A pytest>=5.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) @@ -1323,7 +1331,7 @@ This list contains 1423 plugins. :pypi:`pytest-timeout` pytest plugin to abort hanging tests Mar 07, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A :pypi:`pytest-timer` A timer plugin for pytest Dec 26, 2023 N/A pytest - :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Jun 06, 2021 N/A N/A + :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Mar 27, 2024 N/A N/A :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) @@ -1370,6 +1378,7 @@ This list contains 1423 plugins. :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest :pypi:`pytest-ui-failed-screenshot` UI自动测试失败时自动截图,并将截图加入到测试报告中 Dec 06, 2022 N/A N/A :pypi:`pytest-ui-failed-screenshot-allure` UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 Dec 06, 2022 N/A N/A + :pypi:`pytest-uncollect-if` A plugin to uncollect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unflakable` Unflakable plugin for PyTest Nov 12, 2023 4 - Beta pytest >=6.2.0 :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) @@ -1456,7 +1465,7 @@ This list contains 1423 plugins. :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest - :pypi:`pytest-zy` 接口自动化测试框架 Mar 23, 2024 N/A pytest~=7.2.0 + :pypi:`pytest-zy` 接口自动化测试框架 Mar 24, 2024 N/A pytest~=7.2.0 =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -1470,9 +1479,9 @@ This list contains 1423 plugins. Simple but powerful assertion and verification of logged lines. :pypi:`logot` - *last release*: Feb 29, 2024, + *last release*: Mar 23, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=7,<9) ; extra == "pytest" + *requires*: pytest<9,>=7; extra == "pytest" Test whether your code is logging correctly 🪵 @@ -2303,7 +2312,7 @@ This list contains 1423 plugins. Provides a mock fixture for python bigquery client :pypi:`pytest-bisect-tests` - *last release*: Feb 17, 2024, + *last release*: Mar 25, 2024, *status*: N/A, *requires*: N/A @@ -2611,7 +2620,7 @@ This list contains 1423 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Mar 20, 2024, + *last release*: Mar 27, 2024, *status*: N/A, *requires*: N/A @@ -3052,9 +3061,9 @@ This list contains 1423 plugins. pytest plugin with fixtures for testing consul aware apps :pypi:`pytest-container` - *last release*: Sep 26, 2023, + *last release*: Mar 27, 2024, *status*: 4 - Beta, - *requires*: pytest (>=3.10) + *requires*: pytest>=3.10 Pytest fixtures for writing container based tests @@ -3108,9 +3117,9 @@ This list contains 1423 plugins. count erros and send email :pypi:`pytest-cov` - *last release*: May 24, 2023, + *last release*: Mar 24, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.6) + *requires*: pytest>=4.6 Pytest plugin for measuring coverage. @@ -3283,9 +3292,9 @@ This list contains 1423 plugins. Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report :pypi:`pytest-cython` - *last release*: Feb 16, 2023, + *last release*: Mar 30, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.6.0) + *requires*: pytest<8,>=4.6 A plugin for testing Cython extension modules @@ -3569,6 +3578,13 @@ This list contains 1423 plugins. plugin for rich text descriptions + :pypi:`pytest-deselect-if` + *last release*: Mar 24, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A plugin to deselect pytests tests rather than using skipif + :pypi:`pytest-devpi-server` *last release*: May 28, 2019, *status*: 5 - Production/Stable, @@ -3660,6 +3676,13 @@ This list contains 1423 plugins. A pytest plugin to notify test results to a Discord channel. + :pypi:`pytest-discover` + *last release*: Mar 26, 2024, + *status*: N/A, + *requires*: pytest + + Pytest plugin to record discovered tests in a file + :pypi:`pytest-django` *last release*: Jan 30, 2024, *status*: 5 - Production/Stable, @@ -4332,12 +4355,12 @@ This list contains 1423 plugins. set your encoding and logger - :pypi:`pytest-energy-reporter` - *last release*: Mar 19, 2024, - *status*: N/A, - *requires*: N/A + :pypi:`pytest_energy_reporter` + *last release*: Mar 28, 2024, + *status*: 3 - Alpha, + *requires*: pytest<9.0.0,>=8.1.1 - A energy estimation reporter for pytest + An energy estimation reporter for pytest :pypi:`pytest-enhanced-reports` *last release*: Dec 15, 2022, @@ -4584,6 +4607,13 @@ This list contains 1423 plugins. terminal ui for exploring and running tests + :pypi:`pytest-ext` + *last release*: Mar 30, 2024, + *status*: N/A, + *requires*: pytest>=5.3 + + pytest plugin for automation test + :pypi:`pytest-extensions` *last release*: Aug 17, 2022, *status*: 4 - Beta, @@ -5228,6 +5258,13 @@ This list contains 1423 plugins. Pytest plugin for reporting on coverage of the last git commit. + :pypi:`pytest-git-diff` + *last release*: Mar 30, 2024, + *status*: N/A, + *requires*: N/A + + Pytest plugin that allows the user to select the tests affected by a range of git commits + :pypi:`pytest-git-fixtures` *last release*: Mar 11, 2021, *status*: 4 - Beta, @@ -5270,6 +5307,13 @@ This list contains 1423 plugins. Parallelize pytest across GitLab CI workers. + :pypi:`pytest-gitlab-codequality` + *last release*: Mar 29, 2024, + *status*: N/A, + *requires*: pytest>=8.1.1 + + Collects warnings while testing and generates a GitLab Codequality Report. + :pypi:`pytest-gitlab-fold` *last release*: Dec 31, 2023, *status*: 4 - Beta, @@ -5824,7 +5868,7 @@ This list contains 1423 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Feb 09, 2024, + *last release*: Mar 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6034,9 +6078,9 @@ This list contains 1423 plugins. Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: Sep 08, 2023, + *last release*: Mar 27, 2024, *status*: 4 - Beta, - *requires*: pytest >=6.2.4 + *requires*: pytest>=6.2.4 pytest plugin to integrate tests with JIRA XRAY @@ -6096,6 +6140,13 @@ This list contains 1423 plugins. A pytest plugin to report test results as JSON files + :pypi:`pytest-jsonschema` + *last release*: Mar 27, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A pytest plugin to perform JSONSchema validations + :pypi:`pytest-jtr` *last release*: Nov 29, 2022, *status*: N/A, @@ -6300,7 +6351,7 @@ This list contains 1423 plugins. A pytest plugin to trace resource leaks. :pypi:`pytest-leaping` - *last release*: Mar 22, 2024, + *last release*: Mar 27, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -6517,9 +6568,9 @@ This list contains 1423 plugins. Pytest Loguru :pypi:`pytest-loop` - *last release*: Jul 22, 2022, + *last release*: Mar 30, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6) + *requires*: pytest pytest plugin for looping tests @@ -7692,6 +7743,13 @@ This list contains 1423 plugins. Pytest tool for persistent objects + :pypi:`pytest-pexpect` + *last release*: Mar 27, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + Pytest pexpect plugin. + :pypi:`pytest-pg` *last release*: May 04, 2023, *status*: 5 - Production/Stable, @@ -7826,9 +7884,9 @@ This list contains 1423 plugins. :pypi:`pytest-playwright-enhanced` - *last release*: Mar 19, 2024, + *last release*: Mar 24, 2024, *status*: N/A, - *requires*: pytest (>=8.0.0,<9.0.0) + *requires*: pytest<9.0.0,>=8.0.0 A pytest plugin for playwright python @@ -7875,9 +7933,9 @@ This list contains 1423 plugins. A plugin to help developing and testing other plugins :pypi:`pytest-plus` - *last release*: Jan 10, 2024, + *last release*: Mar 26, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.4.2 + *requires*: pytest>=7.4.2 PyTest Plus Plugin :: extends pytest functionality @@ -8596,9 +8654,9 @@ This list contains 1423 plugins. a pytest plugin that sorts tests using "before" and "after" markers :pypi:`pytest-relaxed` - *last release*: May 23, 2023, + *last release*: Mar 29, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=7) + *requires*: pytest>=7 Relaxed test discovery/organization for pytest @@ -8729,9 +8787,9 @@ This list contains 1423 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Mar 01, 2024, + *last release*: Mar 27, 2024, *status*: N/A, - *requires*: pytest >=3.8.0 + *requires*: pytest>=3.8.0 Agent for Reporting results of tests to the Report Portal @@ -8805,6 +8863,13 @@ This list contains 1423 plugins. Rerun testsuite for a certain time or iterations + :pypi:`pytest-rerunclassfailures` + *last release*: Mar 29, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=7.2 + + pytest rerun class failures plugin + :pypi:`pytest-rerunfailures` *last release*: Mar 13, 2024, *status*: 5 - Production/Stable, @@ -8995,7 +9060,7 @@ This list contains 1423 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Mar 19, 2024, + *last release*: Mar 29, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9394,7 +9459,7 @@ This list contains 1423 plugins. A goodie-bag of unix shell and environment tools for py.test :pypi:`pytest-simbind` - *last release*: Mar 20, 2024, + *last release*: Mar 28, 2024, *status*: N/A, *requires*: pytest>=7.0.0 @@ -9758,7 +9823,7 @@ This list contains 1423 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Feb 23, 2024, + *last release*: Mar 26, 2024, *status*: N/A, *requires*: N/A @@ -9884,9 +9949,9 @@ This list contains 1423 plugins. Run a test suite one failing test at a time. :pypi:`pytest-stf` - *last release*: Feb 08, 2024, + *last release*: Mar 25, 2024, *status*: N/A, - *requires*: pytest >=5.0 + *requires*: pytest>=5.0 pytest plugin for openSTF @@ -10486,7 +10551,7 @@ This list contains 1423 plugins. A timer plugin for pytest :pypi:`pytest-timestamper` - *last release*: Jun 06, 2021, + *last release*: Mar 27, 2024, *status*: N/A, *requires*: N/A @@ -10814,6 +10879,13 @@ This list contains 1423 plugins. UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 + :pypi:`pytest-uncollect-if` + *last release*: Mar 24, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A plugin to uncollect pytests tests rather than using skipif + :pypi:`pytest-unflakable` *last release*: Nov 12, 2023, *status*: 4 - Beta, @@ -11417,7 +11489,7 @@ This list contains 1423 plugins. Pytest report plugin for Zulip :pypi:`pytest-zy` - *last release*: Mar 23, 2024, + *last release*: Mar 24, 2024, *status*: N/A, *requires*: pytest~=7.2.0 From e64efd865368cc72a9ab5a775c5c780a47716587 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Sun, 31 Mar 2024 14:02:09 +0200 Subject: [PATCH 0572/1271] Don't reregister subfixture finalizer in requested fixture if value is cached (#12136) --- changelog/12135.bugfix.rst | 1 + src/_pytest/fixtures.py | 26 ++++++++++++++++--- testing/python/fixtures.py | 52 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 changelog/12135.bugfix.rst diff --git a/changelog/12135.bugfix.rst b/changelog/12135.bugfix.rst new file mode 100644 index 00000000000..734733b100d --- /dev/null +++ b/changelog/12135.bugfix.rst @@ -0,0 +1 @@ +Fix fixtures adding their finalizer multiple times to fixtures they request, causing unreliable and non-intuitive teardown ordering in some instances. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index a8fed047e7f..265ed601d9f 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1035,14 +1035,25 @@ def finish(self, request: SubRequest) -> None: raise BaseExceptionGroup(msg, exceptions[::-1]) def execute(self, request: SubRequest) -> FixtureValue: - finalizer = functools.partial(self.finish, request=request) - # Get required arguments and register our own finish() - # with their finalization. + """Return the value of this fixture, executing it if not cached.""" + # Ensure that the dependent fixtures requested by this fixture are loaded. + # This needs to be done before checking if we have a cached value, since + # if a dependent fixture has their cache invalidated, e.g. due to + # parametrization, they finalize themselves and fixtures depending on it + # (which will likely include this fixture) setting `self.cached_result = None`. + # See #4871 + requested_fixtures_that_should_finalize_us = [] for argname in self.argnames: fixturedef = request._get_active_fixturedef(argname) + # Saves requested fixtures in a list so we later can add our finalizer + # to them, ensuring that if a requested fixture gets torn down we get torn + # down first. This is generally handled by SetupState, but still currently + # needed when this fixture is not parametrized but depends on a parametrized + # fixture. if not isinstance(fixturedef, PseudoFixtureDef): - fixturedef.addfinalizer(finalizer) + requested_fixtures_that_should_finalize_us.append(fixturedef) + # Check for (and return) cached value/exception. my_cache_key = self.cache_key(request) if self.cached_result is not None: cache_key = self.cached_result[1] @@ -1060,6 +1071,13 @@ def execute(self, request: SubRequest) -> FixtureValue: self.finish(request) assert self.cached_result is None + # Add finalizer to requested fixtures we saved previously. + # We make sure to do this after checking for cached value to avoid + # adding our finalizer multiple times. (#12135) + finalizer = functools.partial(self.finish, request=request) + for parent_fixture in requested_fixtures_that_should_finalize_us: + parent_fixture.addfinalizer(finalizer) + ihook = request.node.ihook try: # Setup the fixture, run the code in it, and cache the value diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 1e22270e51b..12ca6e92630 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4751,3 +4751,55 @@ def test_2(fixture_1: None) -> None: ) result = pytester.runpytest() assert result.ret == 0 + + +def test_subfixture_teardown_order(pytester: Pytester) -> None: + """ + Make sure fixtures don't re-register their finalization in parent fixtures multiple + times, causing ordering failure in their teardowns. + + Regression test for #12135 + """ + pytester.makepyfile( + """ + import pytest + + execution_order = [] + + @pytest.fixture(scope="class") + def fixture_1(): + ... + + @pytest.fixture(scope="class") + def fixture_2(fixture_1): + execution_order.append("setup 2") + yield + execution_order.append("teardown 2") + + @pytest.fixture(scope="class") + def fixture_3(fixture_1): + execution_order.append("setup 3") + yield + execution_order.append("teardown 3") + + class TestFoo: + def test_initialize_fixtures(self, fixture_2, fixture_3): + ... + + # This would previously reschedule fixture_2's finalizer in the parent fixture, + # causing it to be torn down before fixture 3. + def test_reschedule_fixture_2(self, fixture_2): + ... + + # Force finalization directly on fixture_1 + # Otherwise the cleanup would sequence 3&2 before 1 as normal. + @pytest.mark.parametrize("fixture_1", [None], indirect=["fixture_1"]) + def test_finalize_fixture_1(self, fixture_1): + ... + + def test_result(): + assert execution_order == ["setup 2", "setup 3", "teardown 3", "teardown 2"] + """ + ) + result = pytester.runpytest() + assert result.ret == 0 From bd9b62161a1caa152ceeaf0cec8586978b5d7e21 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sat, 30 Mar 2024 20:55:27 +0100 Subject: [PATCH 0573/1271] [tooling] Add a manual step to run pylint in pre-commit --- .pre-commit-config.yaml | 7 +++ pyproject.toml | 114 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f0214b7e57..e7f45679115 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -50,6 +50,13 @@ repos: additional_dependencies: ["tox>=4.9"] - repo: local hooks: + - id: pylint + name: pylint + entry: pylint + language: system + types: [python] + args: ["-rn", "-sn", "--fail-on=I"] + stages: [manual] - id: rst name: rst entry: rst-lint --encoding utf-8 diff --git a/pyproject.toml b/pyproject.toml index 7d1b8a22df9..b33f449b22b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -165,6 +165,120 @@ lines-after-imports = 2 "src/_pytest/_version.py" = ["I001"] "testing/python/approx.py" = ["B015"] +[tool.pylint.main] +# Maximum number of characters on a single line. +max-line-length = 120 +disable= [ + "abstract-method", + "arguments-differ", + "arguments-renamed", + "assigning-non-slot", + "attribute-defined-outside-init", + "bad-classmethod-argument", + "bad-mcs-method-argument", + "broad-exception-caught", + "broad-exception-raised", + "cell-var-from-loop", + "comparison-of-constants", + "comparison-with-callable", + "comparison-with-itself", + "condition-evals-to-constant", + "consider-iterating-dictionary", + "consider-using-dict-items", + "consider-using-enumerate", + "consider-using-from-import", + "consider-using-f-string", + "consider-using-in", + "consider-using-sys-exit", + "consider-using-ternary", + "consider-using-with", + "cyclic-import", + "disallowed-name", + "duplicate-code", + "eval-used", + "exec-used", + "expression-not-assigned", + "fixme", + "global-statement", + "implicit-str-concat", + "import-error", + "import-outside-toplevel", + "inconsistent-return-statements", + "invalid-bool-returned", + "invalid-name", + "invalid-repr-returned", + "invalid-str-returned", + "keyword-arg-before-vararg", + "line-too-long", + "method-hidden", + "misplaced-bare-raise", + "missing-docstring", + "missing-timeout", + "multiple-statements", + "no-else-break", + "no-else-continue", + "no-else-raise", + "no-else-return", + "no-member", + "no-name-in-module", + "no-self-argument", + "not-an-iterable", + "not-callable", + "pointless-exception-statement", + "pointless-statement", + "pointless-string-statement", + "protected-access", + "raise-missing-from", + "redefined-argument-from-local", + "redefined-builtin", + "redefined-outer-name", + "reimported", + "simplifiable-condition", + "simplifiable-if-expression", + "singleton-comparison", + "superfluous-parens", + "super-init-not-called", + "too-few-public-methods", + "too-many-ancestors", + "too-many-arguments", + "too-many-branches", + "too-many-function-args", + "too-many-instance-attributes", + "too-many-lines", + "too-many-locals", + "too-many-nested-blocks", + "too-many-public-methods", + "too-many-return-statements", + "too-many-statements", + "try-except-raise", + "typevar-name-incorrect-variance", + "unbalanced-tuple-unpacking", + "undefined-loop-variable", + "undefined-variable", + "unexpected-keyword-arg", + "unidiomatic-typecheck", + "unnecessary-comprehension", + "unnecessary-dunder-call", + "unnecessary-lambda", + "unnecessary-lambda-assignment", + "unpacking-non-sequence", + "unspecified-encoding", + "unsubscriptable-object", + "unused-argument", + "unused-import", + "unused-variable", + "used-before-assignment", + "use-dict-literal", + "use-implicit-booleaness-not-comparison", + "use-implicit-booleaness-not-len", + "useless-else-on-loop", + "useless-import-alias", + "useless-return", + "use-maxsplit-arg", + "using-constant-test", + "wrong-import-order", +] + [tool.check-wheel-contents] # check-wheel-contents is executed by the build-and-inspect-python-package action. # W009: Wheel contains multiple toplevel library entries From 1125296b53303b1495c2ae93d5814d4b1cd9d293 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 25 Feb 2024 23:56:00 +0100 Subject: [PATCH 0574/1271] Small performance/readability improvments when iterating dictionnary with ``keys()`` Based on pylint's message ``consider-iterating-dictionary`` suggestion. Surprisingly using a dict or set comprehension instead of a new temp var is actually consistently slower here, which was not intuitive for me. ```python from timeit import timeit families = {1: {"testcase": [1, 2, 3, 5, 8]}} attrs = {1: "a", 2: "b", 3: "c", 4: "d", 5: "e", 6: "f", 7: "g", 8: "h"} class Old: def old(self): self.attrs = attrs temp_attrs = {} for key in self.attrs.keys(): if key in families[1]["testcase"]: temp_attrs[key] = self.attrs[key] self.attrs = temp_attrs class OldBis: def old(self): self.attrs = attrs temp_attrs = {} for key in self.attrs: if key in families[1]["testcase"]: temp_attrs[key] = self.attrs[key] self.attrs = temp_attrs class New: def new(self): self.attrs = attrs self.attrs = { # Even worse with k: v for k in self.attrs.items() k: self.attrs[k] for k in self.attrs if k in families[1]["testcase"] } if __name__ == "__main__": n = 1000000 print(f"Old: {timeit(Old().old, number=n)}") print(f"Just removing the keys(): {timeit(OldBis().old, number=n)}") print(f"List comp, no temp var: {timeit(New().new, number=n)}") ``` Result: Old: 0.9493889989680611 Just removing the keys(): 0.9042672360083088 List comp, no temp var: 0.9916125109884888 It's also true for the other example with similar benchmark, but the exact code probably does not need to be in the commit message. --- pyproject.toml | 1 - src/_pytest/junitxml.py | 2 +- src/_pytest/terminal.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b33f449b22b..4d4b522870c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -183,7 +183,6 @@ disable= [ "comparison-with-callable", "comparison-with-itself", "condition-evals-to-constant", - "consider-iterating-dictionary", "consider-using-dict-items", "consider-using-enumerate", "consider-using-from-import", diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index e6ccebc2020..13fc9277aec 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -143,7 +143,7 @@ def record_testreport(self, testreport: TestReport) -> None: # Filter out attributes not permitted by this test family. # Including custom attributes because they are not valid here. temp_attrs = {} - for key in self.attrs.keys(): + for key in self.attrs: if key in families[self.family]["testcase"]: temp_attrs[key] = self.attrs[key] self.attrs = temp_attrs diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 2c9c0d3b1cf..973168dc6ff 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1267,7 +1267,7 @@ def _determine_main_color(self, unknown_type_seen: bool) -> str: def _set_main_color(self) -> None: unknown_types: List[str] = [] - for found_type in self.stats.keys(): + for found_type in self.stats: if found_type: # setup/teardown reports have an empty key, ignore them if found_type not in KNOWN_TYPES and found_type not in unknown_types: unknown_types.append(found_type) From 9d6b5f8772133353b9357f4c8eeaf9545a5772eb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:13:25 +0000 Subject: [PATCH 0575/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.3.4 → v0.3.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.3.4...v0.3.5) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e7f45679115..035b80a1588 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.3.4" + rev: "v0.3.5" hooks: - id: ruff args: ["--fix"] From 1188ea2608b8d52891e6d2b68024b075535ba2c7 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 2 Feb 2024 15:02:48 +0200 Subject: [PATCH 0576/1271] Move show-fixtures code from python.py to fixtures.py It makes more sense, also, we have a long term idea of generalizing fixture support to items defined by other plugins, not just python, in which case `--fixtures` would definitely not be python-plugin specific. --- src/_pytest/fixtures.py | 162 +++++++++++++++++++++++++++++++++++++++ src/_pytest/python.py | 165 ---------------------------------------- 2 files changed, 162 insertions(+), 165 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 265ed601d9f..5303948c4d5 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -51,6 +51,7 @@ from _pytest.compat import safe_getattr from _pytest.config import _PluggyPlugin from _pytest.config import Config +from _pytest.config import ExitCode from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest from _pytest.deprecated import MARKED_FIXTURE @@ -1365,6 +1366,33 @@ def pytest_addoption(parser: Parser) -> None: default=[], help="List of default fixtures to be used with this project", ) + group = parser.getgroup("general") + group.addoption( + "--fixtures", + "--funcargs", + action="store_true", + dest="showfixtures", + default=False, + help="Show available fixtures, sorted by plugin appearance " + "(fixtures with leading '_' are only shown with '-v')", + ) + group.addoption( + "--fixtures-per-test", + action="store_true", + dest="show_fixtures_per_test", + default=False, + help="Show fixtures per test", + ) + + +def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: + if config.option.showfixtures: + showfixtures(config) + return 0 + if config.option.show_fixtures_per_test: + show_fixtures_per_test(config) + return 0 + return None def _get_direct_parametrize_args(node: nodes.Node) -> Set[str]: @@ -1761,3 +1789,137 @@ def _matchfactories( for fixturedef in fixturedefs: if fixturedef.baseid in parentnodeids: yield fixturedef + + +def show_fixtures_per_test(config: Config) -> Union[int, ExitCode]: + from _pytest.main import wrap_session + + return wrap_session(config, _show_fixtures_per_test) + + +_PYTEST_DIR = Path(_pytest.__file__).parent + + +def _pretty_fixture_path(invocation_dir: Path, func) -> str: + loc = Path(getlocation(func, invocation_dir)) + prefix = Path("...", "_pytest") + try: + return str(prefix / loc.relative_to(_PYTEST_DIR)) + except ValueError: + return bestrelpath(invocation_dir, loc) + + +def _show_fixtures_per_test(config: Config, session: "Session") -> None: + import _pytest.config + + session.perform_collect() + invocation_dir = config.invocation_params.dir + tw = _pytest.config.create_terminal_writer(config) + verbose = config.getvalue("verbose") + + def get_best_relpath(func) -> str: + loc = getlocation(func, invocation_dir) + return bestrelpath(invocation_dir, Path(loc)) + + def write_fixture(fixture_def: FixtureDef[object]) -> None: + argname = fixture_def.argname + if verbose <= 0 and argname.startswith("_"): + return + prettypath = _pretty_fixture_path(invocation_dir, fixture_def.func) + tw.write(f"{argname}", green=True) + tw.write(f" -- {prettypath}", yellow=True) + tw.write("\n") + fixture_doc = inspect.getdoc(fixture_def.func) + if fixture_doc: + write_docstring( + tw, fixture_doc.split("\n\n")[0] if verbose <= 0 else fixture_doc + ) + else: + tw.line(" no docstring available", red=True) + + def write_item(item: nodes.Item) -> None: + # Not all items have _fixtureinfo attribute. + info: Optional[FuncFixtureInfo] = getattr(item, "_fixtureinfo", None) + if info is None or not info.name2fixturedefs: + # This test item does not use any fixtures. + return + tw.line() + tw.sep("-", f"fixtures used by {item.name}") + # TODO: Fix this type ignore. + tw.sep("-", f"({get_best_relpath(item.function)})") # type: ignore[attr-defined] + # dict key not used in loop but needed for sorting. + for _, fixturedefs in sorted(info.name2fixturedefs.items()): + assert fixturedefs is not None + if not fixturedefs: + continue + # Last item is expected to be the one used by the test item. + write_fixture(fixturedefs[-1]) + + for session_item in session.items: + write_item(session_item) + + +def showfixtures(config: Config) -> Union[int, ExitCode]: + from _pytest.main import wrap_session + + return wrap_session(config, _showfixtures_main) + + +def _showfixtures_main(config: Config, session: "Session") -> None: + import _pytest.config + + session.perform_collect() + invocation_dir = config.invocation_params.dir + tw = _pytest.config.create_terminal_writer(config) + verbose = config.getvalue("verbose") + + fm = session._fixturemanager + + available = [] + seen: Set[Tuple[str, str]] = set() + + for argname, fixturedefs in fm._arg2fixturedefs.items(): + assert fixturedefs is not None + if not fixturedefs: + continue + for fixturedef in fixturedefs: + loc = getlocation(fixturedef.func, invocation_dir) + if (fixturedef.argname, loc) in seen: + continue + seen.add((fixturedef.argname, loc)) + available.append( + ( + len(fixturedef.baseid), + fixturedef.func.__module__, + _pretty_fixture_path(invocation_dir, fixturedef.func), + fixturedef.argname, + fixturedef, + ) + ) + + available.sort() + currentmodule = None + for baseid, module, prettypath, argname, fixturedef in available: + if currentmodule != module: + if not module.startswith("_pytest."): + tw.line() + tw.sep("-", f"fixtures defined from {module}") + currentmodule = module + if verbose <= 0 and argname.startswith("_"): + continue + tw.write(f"{argname}", green=True) + if fixturedef.scope != "function": + tw.write(" [%s scope]" % fixturedef.scope, cyan=True) + tw.write(f" -- {prettypath}", yellow=True) + tw.write("\n") + doc = inspect.getdoc(fixturedef.func) + if doc: + write_docstring(tw, doc.split("\n\n")[0] if verbose <= 0 else doc) + else: + tw.line(" no docstring available", red=True) + tw.line() + + +def write_docstring(tw: TerminalWriter, doc: str, indent: str = " ") -> None: + for line in doc.split("\n"): + tw.line(indent + line) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 3242d517ea0..5e059f2c4e6 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -40,13 +40,11 @@ from _pytest._code.code import ExceptionInfo from _pytest._code.code import TerminalRepr from _pytest._code.code import Traceback -from _pytest._io import TerminalWriter from _pytest._io.saferepr import saferepr from _pytest.compat import ascii_escaped from _pytest.compat import get_default_arg_names from _pytest.compat import get_real_func from _pytest.compat import getimfunc -from _pytest.compat import getlocation from _pytest.compat import is_async_function from _pytest.compat import is_generator from _pytest.compat import LEGACY_PATH @@ -54,7 +52,6 @@ from _pytest.compat import safe_getattr from _pytest.compat import safe_isclass from _pytest.config import Config -from _pytest.config import ExitCode from _pytest.config import hookimpl from _pytest.config.argparsing import Parser from _pytest.deprecated import check_ispytest @@ -71,7 +68,6 @@ from _pytest.mark.structures import normalize_mark_list from _pytest.outcomes import fail from _pytest.outcomes import skip -from _pytest.pathlib import bestrelpath from _pytest.pathlib import fnmatch_ex from _pytest.pathlib import import_path from _pytest.pathlib import ImportPathMismatchError @@ -88,27 +84,7 @@ from typing import Self -_PYTEST_DIR = Path(_pytest.__file__).parent - - def pytest_addoption(parser: Parser) -> None: - group = parser.getgroup("general") - group.addoption( - "--fixtures", - "--funcargs", - action="store_true", - dest="showfixtures", - default=False, - help="Show available fixtures, sorted by plugin appearance " - "(fixtures with leading '_' are only shown with '-v')", - ) - group.addoption( - "--fixtures-per-test", - action="store_true", - dest="show_fixtures_per_test", - default=False, - help="Show fixtures per test", - ) parser.addini( "python_files", type="args", @@ -137,16 +113,6 @@ def pytest_addoption(parser: Parser) -> None: ) -def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: - if config.option.showfixtures: - showfixtures(config) - return 0 - if config.option.show_fixtures_per_test: - show_fixtures_per_test(config) - return 0 - return None - - def pytest_generate_tests(metafunc: "Metafunc") -> None: for marker in metafunc.definition.iter_markers(name="parametrize"): metafunc.parametrize(*marker.args, **marker.kwargs, _param_mark=marker) @@ -1525,137 +1491,6 @@ def _ascii_escaped_by_config(val: Union[str, bytes], config: Optional[Config]) - return val if escape_option else ascii_escaped(val) # type: ignore -def _pretty_fixture_path(invocation_dir: Path, func) -> str: - loc = Path(getlocation(func, invocation_dir)) - prefix = Path("...", "_pytest") - try: - return str(prefix / loc.relative_to(_PYTEST_DIR)) - except ValueError: - return bestrelpath(invocation_dir, loc) - - -def show_fixtures_per_test(config): - from _pytest.main import wrap_session - - return wrap_session(config, _show_fixtures_per_test) - - -def _show_fixtures_per_test(config: Config, session: Session) -> None: - import _pytest.config - - session.perform_collect() - invocation_dir = config.invocation_params.dir - tw = _pytest.config.create_terminal_writer(config) - verbose = config.getvalue("verbose") - - def get_best_relpath(func) -> str: - loc = getlocation(func, invocation_dir) - return bestrelpath(invocation_dir, Path(loc)) - - def write_fixture(fixture_def: fixtures.FixtureDef[object]) -> None: - argname = fixture_def.argname - if verbose <= 0 and argname.startswith("_"): - return - prettypath = _pretty_fixture_path(invocation_dir, fixture_def.func) - tw.write(f"{argname}", green=True) - tw.write(f" -- {prettypath}", yellow=True) - tw.write("\n") - fixture_doc = inspect.getdoc(fixture_def.func) - if fixture_doc: - write_docstring( - tw, fixture_doc.split("\n\n")[0] if verbose <= 0 else fixture_doc - ) - else: - tw.line(" no docstring available", red=True) - - def write_item(item: nodes.Item) -> None: - # Not all items have _fixtureinfo attribute. - info: Optional[FuncFixtureInfo] = getattr(item, "_fixtureinfo", None) - if info is None or not info.name2fixturedefs: - # This test item does not use any fixtures. - return - tw.line() - tw.sep("-", f"fixtures used by {item.name}") - # TODO: Fix this type ignore. - tw.sep("-", f"({get_best_relpath(item.function)})") # type: ignore[attr-defined] - # dict key not used in loop but needed for sorting. - for _, fixturedefs in sorted(info.name2fixturedefs.items()): - assert fixturedefs is not None - if not fixturedefs: - continue - # Last item is expected to be the one used by the test item. - write_fixture(fixturedefs[-1]) - - for session_item in session.items: - write_item(session_item) - - -def showfixtures(config: Config) -> Union[int, ExitCode]: - from _pytest.main import wrap_session - - return wrap_session(config, _showfixtures_main) - - -def _showfixtures_main(config: Config, session: Session) -> None: - import _pytest.config - - session.perform_collect() - invocation_dir = config.invocation_params.dir - tw = _pytest.config.create_terminal_writer(config) - verbose = config.getvalue("verbose") - - fm = session._fixturemanager - - available = [] - seen: Set[Tuple[str, str]] = set() - - for argname, fixturedefs in fm._arg2fixturedefs.items(): - assert fixturedefs is not None - if not fixturedefs: - continue - for fixturedef in fixturedefs: - loc = getlocation(fixturedef.func, invocation_dir) - if (fixturedef.argname, loc) in seen: - continue - seen.add((fixturedef.argname, loc)) - available.append( - ( - len(fixturedef.baseid), - fixturedef.func.__module__, - _pretty_fixture_path(invocation_dir, fixturedef.func), - fixturedef.argname, - fixturedef, - ) - ) - - available.sort() - currentmodule = None - for baseid, module, prettypath, argname, fixturedef in available: - if currentmodule != module: - if not module.startswith("_pytest."): - tw.line() - tw.sep("-", f"fixtures defined from {module}") - currentmodule = module - if verbose <= 0 and argname.startswith("_"): - continue - tw.write(f"{argname}", green=True) - if fixturedef.scope != "function": - tw.write(" [%s scope]" % fixturedef.scope, cyan=True) - tw.write(f" -- {prettypath}", yellow=True) - tw.write("\n") - doc = inspect.getdoc(fixturedef.func) - if doc: - write_docstring(tw, doc.split("\n\n")[0] if verbose <= 0 else doc) - else: - tw.line(" no docstring available", red=True) - tw.line() - - -def write_docstring(tw: TerminalWriter, doc: str, indent: str = " ") -> None: - for line in doc.split("\n"): - tw.line(indent + line) - - class Function(PyobjMixin, nodes.Item): """Item responsible for setting up and executing a Python test function. From cc588d1a1ae549f5e9cf52df2fe132229fcc57cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20L=C3=B3pez-Ib=C3=A1=C3=B1ez?= <2620021+MLopez-Ibanez@users.noreply.github.com> Date: Wed, 3 Apr 2024 13:02:09 +0100 Subject: [PATCH 0577/1271] Doc: `import pytest` in `conftest.py` example in `doctest.rst` (#12181) --- doc/en/how-to/doctest.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/en/how-to/doctest.rst b/doc/en/how-to/doctest.rst index f70d28ce135..c2a6cc8e958 100644 --- a/doc/en/how-to/doctest.rst +++ b/doc/en/how-to/doctest.rst @@ -224,6 +224,7 @@ place the objects you want to appear in the doctest namespace: .. code-block:: python # content of conftest.py + import pytest import numpy From 2e65f4e3ac81dd5e294839441262b8b112ba18bd Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 29 Mar 2024 15:51:51 +0000 Subject: [PATCH 0578/1271] Initialize cache directory in isolation Creating and initializing the cache directory is interruptible; this avoids a pathological case where interrupting a cache write can cause the cache directory to never be properly initialized with its supporting files. Unify `Cache.mkdir` with `Cache.set` while I'm here so the former also properly initializes the cache directory. Closes #12167. --- changelog/12167.trivial.rst | 1 + src/_pytest/cacheprovider.py | 50 ++++++++++++++++++++++------------- testing/test_assertrewrite.py | 4 +-- 3 files changed, 35 insertions(+), 20 deletions(-) create mode 100644 changelog/12167.trivial.rst diff --git a/changelog/12167.trivial.rst b/changelog/12167.trivial.rst new file mode 100644 index 00000000000..da9363420e6 --- /dev/null +++ b/changelog/12167.trivial.rst @@ -0,0 +1 @@ +cache: create cache directory supporting files (``CACHEDIR.TAG``, ``.gitignore``, etc.) in a temporary directory to provide atomic semantics. diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 81703ddac44..e9f66f1f44f 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -7,6 +7,7 @@ import json import os from pathlib import Path +import tempfile from typing import Dict from typing import final from typing import Generator @@ -123,6 +124,10 @@ def warn(self, fmt: str, *, _ispytest: bool = False, **args: object) -> None: stacklevel=3, ) + def _mkdir(self, path: Path) -> None: + self._ensure_cache_dir_and_supporting_files() + path.mkdir(exist_ok=True, parents=True) + def mkdir(self, name: str) -> Path: """Return a directory path object with the given name. @@ -141,7 +146,7 @@ def mkdir(self, name: str) -> Path: if len(path.parts) > 1: raise ValueError("name is not allowed to contain path separators") res = self._cachedir.joinpath(self._CACHE_PREFIX_DIRS, path) - res.mkdir(exist_ok=True, parents=True) + self._mkdir(res) return res def _getvaluepath(self, key: str) -> Path: @@ -178,19 +183,13 @@ def set(self, key: str, value: object) -> None: """ path = self._getvaluepath(key) try: - if path.parent.is_dir(): - cache_dir_exists_already = True - else: - cache_dir_exists_already = self._cachedir.exists() - path.parent.mkdir(exist_ok=True, parents=True) + self._mkdir(path.parent) except OSError as exc: self.warn( f"could not create cache path {path}: {exc}", _ispytest=True, ) return - if not cache_dir_exists_already: - self._ensure_supporting_files() data = json.dumps(value, ensure_ascii=False, indent=2) try: f = path.open("w", encoding="UTF-8") @@ -203,17 +202,32 @@ def set(self, key: str, value: object) -> None: with f: f.write(data) - def _ensure_supporting_files(self) -> None: - """Create supporting files in the cache dir that are not really part of the cache.""" - readme_path = self._cachedir / "README.md" - readme_path.write_text(README_CONTENT, encoding="UTF-8") - - gitignore_path = self._cachedir.joinpath(".gitignore") - msg = "# Created by pytest automatically.\n*\n" - gitignore_path.write_text(msg, encoding="UTF-8") + def _ensure_cache_dir_and_supporting_files(self) -> None: + """Create the cache dir and its supporting files.""" + if self._cachedir.is_dir(): + return - cachedir_tag_path = self._cachedir.joinpath("CACHEDIR.TAG") - cachedir_tag_path.write_bytes(CACHEDIR_TAG_CONTENT) + self._cachedir.parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory( + prefix="pytest-cache-files-", + dir=self._cachedir.parent, + ) as newpath: + path = Path(newpath) + with open(path.joinpath("README.md"), "xt", encoding="UTF-8") as f: + f.write(README_CONTENT) + with open(path.joinpath(".gitignore"), "xt", encoding="UTF-8") as f: + f.write("# Created by pytest automatically.\n*\n") + with open(path.joinpath("CACHEDIR.TAG"), "xb") as f: + f.write(CACHEDIR_TAG_CONTENT) + + path.rename(self._cachedir) + # Create a directory in place of the one we just moved so that `TemporaryDirectory`'s + # cleanup doesn't complain. + # + # TODO: pass ignore_cleanup_errors=True when we no longer support python < 3.10. See + # https://github.com/python/cpython/issues/74168. Note that passing delete=False would + # do the wrong thing in case of errors and isn't supported until python 3.12. + path.mkdir() class LFPluginCollWrapper: diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index e676d562cf4..7acc8cdf1d9 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1731,8 +1731,8 @@ def test_cwd_changed(self, pytester: Pytester, monkeypatch) -> None: import os import tempfile - with tempfile.TemporaryDirectory() as d: - os.chdir(d) + with tempfile.TemporaryDirectory() as newpath: + os.chdir(newpath) """, "test_test.py": """\ def test(): From 4e3dd21506a9e543c04c63ebff966a9b604d2b9e Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 4 Apr 2024 00:24:34 +0200 Subject: [PATCH 0579/1271] Improve stale bot messages (#12185) To avoid confusion, see e.g. https://github.com/pytest-dev/pytest/issues/12123#issuecomment-2035283472 Co-authored-by: Bruno Oliveira --- .github/workflows/stale.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 3f83839cd02..82f9a1f2579 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,7 +17,7 @@ jobs: days-before-issue-close: 7 only-labels: "status: needs information" stale-issue-label: "stale" - stale-issue-message: "This issue is stale because it has been open for 14 days with no activity." - close-issue-message: "This issue was closed because it has been inactive for 7 days since being marked as stale." + stale-issue-message: "This issue is stale because it has the `status: needs information` label and requested follow-up information was not provided for 14 days." + close-issue-message: "This issue was closed because it has the `status: needs information` label and follow-up information has not been provided for 7 days since being marked as stale." days-before-pr-stale: -1 days-before-pr-close: -1 From f75dd87eb7f31c4d14c84c18ce97353f51e801d4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 7 Apr 2024 08:57:04 -0300 Subject: [PATCH 0580/1271] [automated] Update plugin list (#12193) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 228 ++++++++++++++++++------------- 1 file changed, 134 insertions(+), 94 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 1ab93ddc093..3c7409f0157 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.4,<7.0.0) :pypi:`pytest-breed-adapter` A simple plugin to connect with breed-server Nov 07, 2018 4 - Beta pytest (>=3.5.0) :pypi:`pytest-briefcase` A pytest plugin for running tests on a Briefcase project. Jun 14, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-broadcaster` Pytest plugin to broadcast pytest output to various destinations Apr 06, 2024 3 - Alpha pytest :pypi:`pytest-browser` A pytest plugin for console based browser test selection just after the collection phase Dec 10, 2016 3 - Alpha N/A :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A :pypi:`pytest_browserstack` Py.test plugin for BrowserStack Jan 27, 2016 4 - Beta N/A @@ -194,11 +195,11 @@ This list contains 1432 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-cases` Separate test code from test cases in pytest. Mar 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-cases` Separate test code from test cases in pytest. Apr 04, 2024 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Mar 27, 2024 N/A N/A + :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Apr 05, 2024 N/A N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -208,11 +209,11 @@ This list contains 1432 plugins. :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 18, 2024 N/A pytest>=7.0.0 - :pypi:`pytest-checkdocs` check the README when running tests Mar 21, 2024 5 - Production/Stable pytest>=6; extra == "testing" + :pypi:`pytest-checkdocs` check the README when running tests Mar 31, 2024 5 - Production/Stable pytest>=6; extra == "testing" :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A - :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<8,>=7.0 + :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<9,>=7.0 :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Mar 12, 2024 N/A N/A :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 20, 2024 N/A N/A @@ -261,7 +262,7 @@ This list contains 1432 plugins. :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest - :pypi:`pytest-container` Pytest fixtures for writing container based tests Mar 27, 2024 4 - Beta pytest>=3.10 + :pypi:`pytest-container` Pytest fixtures for writing container based tests Apr 03, 2024 4 - Beta pytest>=3.10 :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) @@ -294,11 +295,12 @@ This list contains 1432 plugins. :pypi:`pytest-custom-nodeid` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 07, 2021 N/A N/A :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A - :pypi:`pytest-cython` A plugin for testing Cython extension modules Mar 30, 2024 5 - Production/Stable pytest<8,>=4.6 + :pypi:`pytest-cython` A plugin for testing Cython extension modules Apr 05, 2024 5 - Production/Stable pytest>=8 :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 06, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -312,7 +314,7 @@ This list contains 1432 plugins. :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Feb 15, 2024 5 - Production/Stable pytest :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A - :pypi:`pytest-data-suites` Class-based pytest parametrization Jul 24, 2022 N/A pytest (>=6.0,<8.0) + :pypi:`pytest-data-suites` Class-based pytest parametrization Apr 06, 2024 N/A pytest<9.0,>=6.0 :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Dec 04, 2019 N/A N/A :pypi:`pytest-dbfixtures` Databases fixtures plugin for py.test. Dec 07, 2016 4 - Beta N/A @@ -382,7 +384,7 @@ This list contains 1432 plugins. :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) :pypi:`pytest-docker-compose-v2` Manages Docker containers during your integration tests Feb 28, 2024 4 - Beta pytest<8,>=7.2.2 :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) - :pypi:`pytest-docker-fixtures` pytest docker fixtures Nov 17, 2023 3 - Alpha N/A + :pypi:`pytest-docker-fixtures` pytest docker fixtures Apr 03, 2024 3 - Alpha N/A :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Feb 09, 2022 4 - Beta pytest :pypi:`pytest-docker-haproxy-fixtures` Pytest fixtures for testing with haproxy. Feb 09, 2022 4 - Beta pytest :pypi:`pytest-docker-pexpect` pytest plugin for writing functional tests with pexpect and docker Jan 14, 2019 N/A pytest @@ -429,16 +431,16 @@ This list contains 1432 plugins. :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 15, 2024 5 - Production/Stable pytest >=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) - :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jan 24, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Apr 04, 2024 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. Mar 01, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Mar 01, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Mar 01, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Mar 01, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Mar 01, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Mar 01, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Mar 01, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Mar 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Apr 02, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 02, 2024 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) @@ -482,7 +484,7 @@ This list contains 1432 plugins. :pypi:`pytest-explicit` A Pytest plugin to ignore certain marked tests by default Jun 15, 2021 5 - Production/Stable pytest :pypi:`pytest-exploratory` Interactive console for pytest. Aug 18, 2023 N/A pytest (>=6.2) :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A - :pypi:`pytest-ext` pytest plugin for automation test Mar 30, 2024 N/A pytest>=5.3 + :pypi:`pytest-ext` pytest plugin for automation test Mar 31, 2024 N/A pytest>=5.3 :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A @@ -571,18 +573,18 @@ This list contains 1432 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Mar 14, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 03, 2024 N/A pytest>=3.6 :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 - :pypi:`pytest-git-diff` Pytest plugin that allows the user to select the tests affected by a range of git commits Mar 30, 2024 N/A N/A + :pypi:`pytest-git-diff` Pytest plugin that allows the user to select the tests affected by a range of git commits Apr 02, 2024 N/A N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A - :pypi:`pytest-gitlab-codequality` Collects warnings while testing and generates a GitLab Codequality Report. Mar 29, 2024 N/A pytest>=8.1.1 + :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Apr 03, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest @@ -598,10 +600,12 @@ This list contains 1432 plugins. :pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Feb 05, 2023 N/A N/A :pypi:`pytest_gui_status` Show pytest status in gui Jan 23, 2016 N/A pytest :pypi:`pytest-hammertime` Display "🔨 " instead of "." for passed pytest tests. Jul 28, 2018 N/A pytest + :pypi:`pytest-hardware-test-report` A simple plugin to use with pytest Apr 01, 2024 4 - Beta pytest<9.0.0,>=8.0.0 :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Mar 16, 2024 5 - Production/Stable N/A :pypi:`pytest-helm-chart` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Jun 15, 2020 4 - Beta pytest (>=5.4.2,<6.0.0) :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Feb 07, 2024 4 - Beta pytest (>=8.0.0,<9.0.0) + :pypi:`pytest-helm-templates` Pytest fixtures for unit testing the output of helm templates Apr 05, 2024 N/A pytest~=7.4.0; extra == "dev" :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) @@ -612,7 +616,7 @@ This list contains 1432 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Mar 23, 2024 3 - Alpha pytest==8.0.2 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 06, 2024 3 - Alpha pytest==8.1.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jan 06, 2024 N/A N/A @@ -643,7 +647,7 @@ This list contains 1432 plugins. :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Mar 14, 2024 3 - Alpha pytest (>=7.0.0) + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Mar 30, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A @@ -662,7 +666,7 @@ This list contains 1432 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 19, 2023 4 - Beta pytest >=7.0.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Dec 13, 2023 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Mar 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 02, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Feb 20, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A @@ -703,7 +707,7 @@ This list contains 1432 plugins. :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Mar 12, 2024 4 - Beta pytest + :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest @@ -759,7 +763,7 @@ This list contains 1432 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Feb 05, 2024 5 - Production/Stable pytest ==8.0.0 + :pypi:`pytest-logikal` Common testing environment Mar 30, 2024 5 - Production/Stable pytest==8.1.1 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest @@ -831,7 +835,7 @@ This list contains 1432 plugins. :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Feb 14, 2024 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Aug 03, 2023 4 - Beta pytest (<8) ; extra == 'test' + :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Mar 31, 2024 4 - Beta pytest<8; extra == "test" :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A @@ -840,7 +844,7 @@ This list contains 1432 plugins. :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Mar 13, 2024 4 - Beta pytest >=7.0.0 + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Mar 31, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 @@ -891,7 +895,7 @@ This list contains 1432 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 Nov 18, 2023 4 - Beta pytest >=5.0 ; python_version < "3.10" + :pypi:`pytest-order` pytest plugin to run your tests in a specific order Apr 02, 2024 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 @@ -931,7 +935,7 @@ This list contains 1432 plugins. :pypi:`pytest-performancetotal` A performance plugin for pytest Mar 19, 2024 4 - Beta N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Mar 27, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 04, 2023 5 - Production/Stable pytest (>=6.0.0) + :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker Apr 03, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-picked` Run the tests related to the changed files Jul 27, 2023 N/A pytest (>=3.7.0) @@ -1094,7 +1098,7 @@ This list contains 1432 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 :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. Feb 08, 2024 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Feb 14, 2024 N/A pytest ~=4.6 ; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Apr 03, 2024 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 @@ -1142,7 +1146,7 @@ This list contains 1432 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 21, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 05, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1151,11 +1155,12 @@ This list contains 1432 plugins. :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 Feb 01, 2024 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. Mar 21, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 05, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A - :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Jan 05, 2023 N/A N/A + :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Apr 05, 2024 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A @@ -1217,7 +1222,7 @@ This list contains 1432 plugins. :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. 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 Feb 03, 2024 4 - Beta pytest >=8.0.0 + :pypi:`pytest-sphinx` Doctest plugin for pytest with support for Sphinx-specific doctest-directives Apr 01, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-spiratest` Exports unit tests as test runs in Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Feb 01, 2024 6 - Mature pytest >=8.0.0 @@ -1414,7 +1419,7 @@ This list contains 1432 plugins. :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-wake` Mar 20, 2024 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A - :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Feb 06, 2024 4 - Beta N/A + :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Apr 01, 2024 4 - Beta N/A :pypi:`pytest_wdb` Trace pytest tests with wdb to halt on error with --wdb. Jul 04, 2016 N/A N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest @@ -1440,7 +1445,7 @@ This list contains 1432 plugins. :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Mar 22, 2024 N/A N/A :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest - :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Mar 23, 2024 4 - Beta pytest>=2.8 + :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Mar 31, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) @@ -1455,7 +1460,7 @@ This list contains 1432 plugins. :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A - :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Jan 11, 2024 N/A pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Mar 30, 2024 N/A pytest<8.0.0,>=7.2.2 :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A @@ -2437,6 +2442,13 @@ This list contains 1432 plugins. A pytest plugin for running tests on a Briefcase project. + :pypi:`pytest-broadcaster` + *last release*: Apr 06, 2024, + *status*: 3 - Alpha, + *requires*: pytest + + Pytest plugin to broadcast pytest output to various destinations + :pypi:`pytest-browser` *last release*: Dec 10, 2016, *status*: 3 - Alpha, @@ -2592,7 +2604,7 @@ This list contains 1432 plugins. pytest plugin to capture all warnings and put them in one file of your choice :pypi:`pytest-cases` - *last release*: Mar 16, 2024, + *last release*: Apr 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -2620,7 +2632,7 @@ This list contains 1432 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Mar 27, 2024, + *last release*: Apr 05, 2024, *status*: N/A, *requires*: N/A @@ -2690,7 +2702,7 @@ This list contains 1432 plugins. A pytest plugin that allows multiple failures per test. :pypi:`pytest-checkdocs` - *last release*: Mar 21, 2024, + *last release*: Mar 31, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6; extra == "testing" @@ -2720,7 +2732,7 @@ This list contains 1432 plugins. :pypi:`pytest-check-links` *last release*: Jul 29, 2020, *status*: N/A, - *requires*: pytest<8,>=7.0 + *requires*: pytest<9,>=7.0 Check links in files @@ -3061,7 +3073,7 @@ This list contains 1432 plugins. pytest plugin with fixtures for testing consul aware apps :pypi:`pytest-container` - *last release*: Mar 27, 2024, + *last release*: Apr 03, 2024, *status*: 4 - Beta, *requires*: pytest>=3.10 @@ -3292,9 +3304,9 @@ This list contains 1432 plugins. Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report :pypi:`pytest-cython` - *last release*: Mar 30, 2024, + *last release*: Apr 05, 2024, *status*: 5 - Production/Stable, - *requires*: pytest<8,>=4.6 + *requires*: pytest>=8 A plugin for testing Cython extension modules @@ -3326,6 +3338,13 @@ This list contains 1432 plugins. Useful functions for managing data for pytest fixtures + :pypi:`pytest-databases` + *last release*: Apr 06, 2024, + *status*: 4 - Beta, + *requires*: pytest + + Reusable database fixtures for any and all databases. + :pypi:`pytest-databricks` *last release*: Jul 29, 2020, *status*: N/A, @@ -3418,9 +3437,9 @@ This list contains 1432 plugins. Plugin for loading different datasets for pytest by prefix from json or yaml files :pypi:`pytest-data-suites` - *last release*: Jul 24, 2022, + *last release*: Apr 06, 2024, *status*: N/A, - *requires*: pytest (>=6.0,<8.0) + *requires*: pytest<9.0,>=6.0 Class-based pytest parametrization @@ -3908,7 +3927,7 @@ This list contains 1432 plugins. A plugin to use docker databases for pytests :pypi:`pytest-docker-fixtures` - *last release*: Nov 17, 2023, + *last release*: Apr 03, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -4237,9 +4256,9 @@ This list contains 1432 plugins. An eliot plugin for pytest. :pypi:`pytest-elk-reporter` - *last release*: Jan 24, 2021, + *last release*: Apr 04, 2024, *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *requires*: pytest>=3.5.0 A simple plugin to use with pytest @@ -4251,56 +4270,56 @@ This list contains 1432 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Mar 01, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Mar 01, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Mar 01, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Mar 01, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Mar 01, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Mar 01, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Mar 01, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Mar 01, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4608,7 +4627,7 @@ This list contains 1432 plugins. terminal ui for exploring and running tests :pypi:`pytest-ext` - *last release*: Mar 30, 2024, + *last release*: Mar 31, 2024, *status*: N/A, *requires*: pytest>=5.3 @@ -5231,7 +5250,7 @@ This list contains 1432 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Mar 14, 2024, + *last release*: Apr 03, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5259,7 +5278,7 @@ This list contains 1432 plugins. Pytest plugin for reporting on coverage of the last git commit. :pypi:`pytest-git-diff` - *last release*: Mar 30, 2024, + *last release*: Apr 02, 2024, *status*: N/A, *requires*: N/A @@ -5307,12 +5326,12 @@ This list contains 1432 plugins. Parallelize pytest across GitLab CI workers. - :pypi:`pytest-gitlab-codequality` - *last release*: Mar 29, 2024, + :pypi:`pytest-gitlab-code-quality` + *last release*: Apr 03, 2024, *status*: N/A, *requires*: pytest>=8.1.1 - Collects warnings while testing and generates a GitLab Codequality Report. + Collects warnings while testing and generates a GitLab Code Quality Report. :pypi:`pytest-gitlab-fold` *last release*: Dec 31, 2023, @@ -5419,6 +5438,13 @@ This list contains 1432 plugins. Display "🔨 " instead of "." for passed pytest tests. + :pypi:`pytest-hardware-test-report` + *last release*: Apr 01, 2024, + *status*: 4 - Beta, + *requires*: pytest<9.0.0,>=8.0.0 + + A simple plugin to use with pytest + :pypi:`pytest-harmony` *last release*: Jan 17, 2023, *status*: N/A, @@ -5447,6 +5473,13 @@ This list contains 1432 plugins. A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. + :pypi:`pytest-helm-templates` + *last release*: Apr 05, 2024, + *status*: N/A, + *requires*: pytest~=7.4.0; extra == "dev" + + Pytest fixtures for unit testing the output of helm templates + :pypi:`pytest-helper` *last release*: May 31, 2019, *status*: 5 - Production/Stable, @@ -5518,9 +5551,9 @@ This list contains 1432 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 23, 2024, + *last release*: Apr 06, 2024, *status*: 3 - Alpha, - *requires*: pytest==8.0.2 + *requires*: pytest==8.1.1 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -5735,9 +5768,9 @@ This list contains 1432 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Mar 14, 2024, + *last release*: Mar 30, 2024, *status*: 3 - Alpha, - *requires*: pytest (>=7.0.0) + *requires*: pytest>=7.0.0 A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite @@ -5868,7 +5901,7 @@ This list contains 1432 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Mar 29, 2024, + *last release*: Apr 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6155,9 +6188,9 @@ This list contains 1432 plugins. pytest plugin supporting json test report output :pypi:`pytest-jupyter` - *last release*: Mar 12, 2024, + *last release*: Apr 04, 2024, *status*: 4 - Beta, - *requires*: pytest + *requires*: pytest>=7.0 A pytest plugin for testing Jupyter libraries and extensions. @@ -6547,9 +6580,9 @@ This list contains 1432 plugins. :pypi:`pytest-logikal` - *last release*: Feb 05, 2024, + *last release*: Mar 30, 2024, *status*: 5 - Production/Stable, - *requires*: pytest ==8.0.0 + *requires*: pytest==8.1.1 Common testing environment @@ -7051,9 +7084,9 @@ This list contains 1432 plugins. low-startup-overhead, scalable, distributed-testing pytest plugin :pypi:`pytest-mqtt` - *last release*: Aug 03, 2023, + *last release*: Mar 31, 2024, *status*: 4 - Beta, - *requires*: pytest (<8) ; extra == 'test' + *requires*: pytest<8; extra == "test" pytest-mqtt supports testing systems based on MQTT @@ -7114,9 +7147,9 @@ This list contains 1432 plugins. Mypy static type checker plugin for Pytest :pypi:`pytest-mypy-plugins` - *last release*: Mar 13, 2024, + *last release*: Mar 31, 2024, *status*: 4 - Beta, - *requires*: pytest >=7.0.0 + *requires*: pytest>=7.0.0 pytest plugin for writing tests for mypy plugins @@ -7471,9 +7504,9 @@ This list contains 1432 plugins. A pytest plugin for orchestrating tests :pypi:`pytest-order` - *last release*: Nov 18, 2023, + *last release*: Apr 02, 2024, *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 @@ -7751,9 +7784,9 @@ This list contains 1432 plugins. Pytest pexpect plugin. :pypi:`pytest-pg` - *last release*: May 04, 2023, + *last release*: Apr 03, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.0.0) + *requires*: pytest>=6.0.0 A tiny plugin for pytest which runs PostgreSQL in Docker @@ -8892,9 +8925,9 @@ This list contains 1432 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Feb 14, 2024, + *last release*: Apr 03, 2024, *status*: N/A, - *requires*: pytest ~=4.6 ; python_version == "2.7" + *requires*: pytest~=4.6; python_version == "2.7" Resilient Circuits fixtures for PyTest @@ -9228,7 +9261,7 @@ This list contains 1432 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Mar 21, 2024, + *last release*: Apr 05, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9291,7 +9324,7 @@ This list contains 1432 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Mar 21, 2024, + *last release*: Apr 05, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9311,6 +9344,13 @@ This list contains 1432 plugins. A pytest package implementing perceptualdiff for Selenium tests. + :pypi:`pytest-selfie` + *last release*: Apr 05, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.0.0 + + A pytest plugin for selfie snapshot testing. + :pypi:`pytest-send-email` *last release*: Dec 04, 2019, *status*: N/A, @@ -9319,9 +9359,9 @@ This list contains 1432 plugins. Send pytest execution result email :pypi:`pytest-sentry` - *last release*: Jan 05, 2023, + *last release*: Apr 05, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest A pytest plugin to send testrun information to Sentry.io @@ -9753,9 +9793,9 @@ This list contains 1432 plugins. Modern benchmarking library for python with pytest integration. :pypi:`pytest-sphinx` - *last release*: Feb 03, 2024, + *last release*: Apr 01, 2024, *status*: 4 - Beta, - *requires*: pytest >=8.0.0 + *requires*: pytest>=8.0.0 Doctest plugin for pytest with support for Sphinx-specific doctest-directives @@ -11132,7 +11172,7 @@ This list contains 1432 plugins. Local continuous test runner with pytest and watchdog. :pypi:`pytest-watcher` - *last release*: Feb 06, 2024, + *last release*: Apr 01, 2024, *status*: 4 - Beta, *requires*: N/A @@ -11314,7 +11354,7 @@ This list contains 1432 plugins. An extended parametrizing plugin of pytest. :pypi:`pytest-xprocess` - *last release*: Mar 23, 2024, + *last release*: Mar 31, 2024, *status*: 4 - Beta, *requires*: pytest>=2.8 @@ -11419,9 +11459,9 @@ This list contains 1432 plugins. PyTest plugin to run tests concurrently, each \`yield\` switch context to other one :pypi:`pytest-yls` - *last release*: Jan 11, 2024, + *last release*: Mar 30, 2024, *status*: N/A, - *requires*: pytest (>=7.2.2,<8.0.0) + *requires*: pytest<8.0.0,>=7.2.2 Pytest plugin to test the YLS as a whole. From 74f05648d5ea9e69d75f27a77972756ee32f6730 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 12:15:01 +0200 Subject: [PATCH 0581/1271] build(deps): Bump django in /testing/plugins_integration (#12196) Bumps [django](https://github.com/django/django) from 5.0.3 to 5.0.4. - [Commits](https://github.com/django/django/compare/5.0.3...5.0.4) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 7f22548629d..9e152f1191b 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.3.0 -django==5.0.3 +django==5.0.4 pytest-asyncio==0.23.6 # Temporarily not installed until pytest-bdd is fixed: # https://github.com/pytest-dev/pytest/pull/11785 From a02cc0ad1b575cbc5b87f8db4ac49f3783c921d3 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 8 Apr 2024 14:59:51 +0100 Subject: [PATCH 0582/1271] Add types --- testing/test_cacheprovider.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index c020b77f978..9c70271b43a 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -1,9 +1,11 @@ -# mypy: allow-untyped-defs import os from pathlib import Path import shutil +from typing import Any from typing import Generator from typing import List +from typing import Sequence +from typing import Tuple from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch @@ -175,7 +177,9 @@ def test_custom_cache_dir_with_env_var( @pytest.mark.parametrize("env", ((), ("TOX_ENV_DIR", "/tox_env_dir"))) -def test_cache_reportheader(env, pytester: Pytester, monkeypatch: MonkeyPatch) -> None: +def test_cache_reportheader( + env: Sequence[str], pytester: Pytester, monkeypatch: MonkeyPatch +) -> None: pytester.makepyfile("""def test_foo(): pass""") if env: monkeypatch.setenv(*env) @@ -507,7 +511,7 @@ def test_hello(): """ ) - def rlf(fail_import, fail_run): + def rlf(fail_import: int, fail_run: int) -> Any: monkeypatch.setenv("FAILIMPORT", str(fail_import)) monkeypatch.setenv("FAILTEST", str(fail_run)) @@ -555,7 +559,9 @@ def test_pass(): """ ) - def rlf(fail_import, fail_run, args=()): + def rlf( + fail_import: int, fail_run: int, args: Sequence[str] = () + ) -> Tuple[Any, Any]: monkeypatch.setenv("FAILIMPORT", str(fail_import)) monkeypatch.setenv("FAILTEST", str(fail_run)) From e06c337bd851c24b2d3db188b4a137ab63015b03 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Mon, 8 Apr 2024 15:02:31 +0100 Subject: [PATCH 0583/1271] Add test for Cache.mkdir --- testing/test_cacheprovider.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 9c70271b43a..304e5414abc 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -1,3 +1,5 @@ +from enum import auto +from enum import Enum import os from pathlib import Path import shutil @@ -7,6 +9,7 @@ from typing import Sequence from typing import Tuple +from _pytest.compat import assert_never from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester @@ -1260,20 +1263,41 @@ def test_readme_failed(self, pytester: Pytester) -> None: assert self.check_readme(pytester) is True -def test_gitignore(pytester: Pytester) -> None: +class Action(Enum): + """Action to perform on the cache directory.""" + + MKDIR = auto() + SET = auto() + + +@pytest.mark.parametrize("action", list(Action)) +def test_gitignore( + pytester: Pytester, + action: Action, +) -> None: """Ensure we automatically create .gitignore file in the pytest_cache directory (#3286).""" from _pytest.cacheprovider import Cache config = pytester.parseconfig() cache = Cache.for_config(config, _ispytest=True) - cache.set("foo", "bar") + if action == Action.MKDIR: + cache.mkdir("foo") + elif action == Action.SET: + cache.set("foo", "bar") + else: + assert_never(action) msg = "# Created by pytest automatically.\n*\n" gitignore_path = cache._cachedir.joinpath(".gitignore") assert gitignore_path.read_text(encoding="UTF-8") == msg # Does not overwrite existing/custom one. gitignore_path.write_text("custom", encoding="utf-8") - cache.set("something", "else") + if action == Action.MKDIR: + cache.mkdir("something") + elif action == Action.SET: + cache.set("something", "else") + else: + assert_never(action) assert gitignore_path.read_text(encoding="UTF-8") == "custom" From 1ca59dfd6bdea33cdee3997329694f366ecd07e9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 09:55:05 -0300 Subject: [PATCH 0584/1271] [pre-commit.ci] pre-commit autoupdate (#12200) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v4.6.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 035b80a1588..65a7e4efb62 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,7 +6,7 @@ repos: args: ["--fix"] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer From 17fc20af78d0c7b739806c4e461d2c9b8c30ceeb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:04:42 -0300 Subject: [PATCH 0585/1271] build(deps): Bump hynek/build-and-inspect-python-package (#12195) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.0.2 to 2.2.1. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.0.2...v2.2.1) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 95713e4e774..26d77ffd052 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.0.2 + uses: hynek/build-and-inspect-python-package@v2.2.1 deploy: if: github.repository == 'pytest-dev/pytest' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 00d6c608ac3..6868c21c51f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.0.2 + uses: hynek/build-and-inspect-python-package@v2.2.1 build: needs: [package] From 99890636bfd9bb156655050f22f1df47e74ac3f6 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 9 Apr 2024 13:21:51 -0300 Subject: [PATCH 0586/1271] Refine how we detect namespace packages (#12169) Previously we used a hand crafted approach to detect namespace packages, however we should rely on ``importlib`` to detect them for us. Fix #12112 --------- Co-authored-by: Ran Benita --- changelog/12112.improvement.rst | 1 + doc/en/reference/reference.rst | 3 +- src/_pytest/pathlib.py | 99 ++++++++++--- testing/test_pathlib.py | 244 ++++++++++++++++++++++++++++---- 4 files changed, 298 insertions(+), 49 deletions(-) create mode 100644 changelog/12112.improvement.rst diff --git a/changelog/12112.improvement.rst b/changelog/12112.improvement.rst new file mode 100644 index 00000000000..3f997b2af65 --- /dev/null +++ b/changelog/12112.improvement.rst @@ -0,0 +1 @@ +Improve namespace packages detection when :confval:`consider_namespace_packages` is enabled, covering more situations (like editable installs). diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 21890fbf63e..c9d7aeb552c 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1279,8 +1279,7 @@ passed multiple times. The expected format is ``name=value``. For example:: Controls if pytest should attempt to identify `namespace packages `__ when collecting Python modules. Default is ``False``. - Set to ``True`` if you are testing namespace packages installed into a virtual environment and it is important for - your packages to be imported using their full namespace package name. + Set to ``True`` if the package you are testing is part of a namespace package. Only `native namespace packages `__ are supported, with no plans to support `legacy namespace packages `__. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index e39f4772326..254d9d9468e 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -8,6 +8,7 @@ from errno import ENOTDIR import fnmatch from functools import partial +from importlib.machinery import ModuleSpec import importlib.util import itertools import os @@ -628,11 +629,13 @@ def _import_module_using_spec( # such as our own assertion-rewrite hook. for meta_importer in sys.meta_path: spec = meta_importer.find_spec(module_name, [str(module_location)]) - if spec is not None: + if spec_matches_module_path(spec, module_path): break else: spec = importlib.util.spec_from_file_location(module_name, str(module_path)) - if spec is not None: + + if spec_matches_module_path(spec, module_path): + assert spec is not None mod = importlib.util.module_from_spec(spec) sys.modules[module_name] = mod spec.loader.exec_module(mod) # type: ignore[union-attr] @@ -643,6 +646,16 @@ def _import_module_using_spec( return None +def spec_matches_module_path( + module_spec: Optional[ModuleSpec], module_path: Path +) -> bool: + """Return true if the given ModuleSpec can be used to import the given module path.""" + if module_spec is None or module_spec.origin is None: + return False + + return Path(module_spec.origin) == module_path + + # Implement a special _is_same function on Windows which returns True if the two filenames # compare equal, to circumvent os.path.samefile returning False for mounts in UNC (#7678). if sys.platform.startswith("win"): @@ -762,39 +775,79 @@ def resolve_pkg_root_and_module_name( Passing the full path to `models.py` will yield Path("src") and "app.core.models". If consider_namespace_packages is True, then we additionally check upwards in the hierarchy - until we find a directory that is reachable from sys.path, which marks it as a namespace package: + for namespace packages: https://packaging.python.org/en/latest/guides/packaging-namespace-packages Raises CouldNotResolvePathError if the given path does not belong to a package (missing any __init__.py files). """ + pkg_root: Optional[Path] = None pkg_path = resolve_package_path(path) if pkg_path is not None: pkg_root = pkg_path.parent - # https://packaging.python.org/en/latest/guides/packaging-namespace-packages/ - if consider_namespace_packages: - # Go upwards in the hierarchy, if we find a parent path included - # in sys.path, it means the package found by resolve_package_path() - # actually belongs to a namespace package. - for parent in pkg_root.parents: - # If any of the parent paths has a __init__.py, it means it is not - # a namespace package (see the docs linked above). - if (parent / "__init__.py").is_file(): - break - if str(parent) in sys.path: - # Point the pkg_root to the root of the namespace package. - pkg_root = parent - break - - names = list(path.with_suffix("").relative_to(pkg_root).parts) - if names[-1] == "__init__": - names.pop() - module_name = ".".join(names) - return pkg_root, module_name + if consider_namespace_packages: + start = pkg_root if pkg_root is not None else path.parent + for candidate in (start, *start.parents): + module_name = compute_module_name(candidate, path) + if module_name and is_importable(module_name, path): + # Point the pkg_root to the root of the namespace package. + pkg_root = candidate + break + + if pkg_root is not None: + module_name = compute_module_name(pkg_root, path) + if module_name: + return pkg_root, module_name raise CouldNotResolvePathError(f"Could not resolve for {path}") +def is_importable(module_name: str, module_path: Path) -> bool: + """ + Return if the given module path could be imported normally by Python, akin to the user + entering the REPL and importing the corresponding module name directly, and corresponds + to the module_path specified. + + :param module_name: + Full module name that we want to check if is importable. + For example, "app.models". + + :param module_path: + Full path to the python module/package we want to check if is importable. + For example, "/projects/src/app/models.py". + """ + try: + # Note this is different from what we do in ``_import_module_using_spec``, where we explicitly search through + # sys.meta_path to be able to pass the path of the module that we want to import (``meta_importer.find_spec``). + # Using importlib.util.find_spec() is different, it gives the same results as trying to import + # the module normally in the REPL. + spec = importlib.util.find_spec(module_name) + except (ImportError, ValueError, ImportWarning): + return False + else: + return spec_matches_module_path(spec, module_path) + + +def compute_module_name(root: Path, module_path: Path) -> Optional[str]: + """Compute a module name based on a path and a root anchor.""" + try: + path_without_suffix = module_path.with_suffix("") + except ValueError: + # Empty paths (such as Path.cwd()) might break meta_path hooks (like our own assertion rewriter). + return None + + try: + relative = path_without_suffix.relative_to(root) + except ValueError: # pragma: no cover + return None + names = list(relative.parts) + if not names: + return None + if names[-1] == "__init__": + names.pop() + return ".".join(names) + + class CouldNotResolvePathError(Exception): """Custom exception raised by resolve_pkg_root_and_module_name.""" diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 7f740a0607b..f96151bdd44 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1,5 +1,7 @@ # mypy: allow-untyped-defs import errno +import importlib.abc +import importlib.machinery import os.path from pathlib import Path import pickle @@ -10,12 +12,15 @@ from typing import Any from typing import Generator from typing import Iterator +from typing import Optional +from typing import Sequence from typing import Tuple import unittest.mock from _pytest.monkeypatch import MonkeyPatch from _pytest.pathlib import bestrelpath from _pytest.pathlib import commonpath +from _pytest.pathlib import compute_module_name from _pytest.pathlib import CouldNotResolvePathError from _pytest.pathlib import ensure_deletable from _pytest.pathlib import fnmatch_ex @@ -25,6 +30,7 @@ from _pytest.pathlib import ImportMode from _pytest.pathlib import ImportPathMismatchError from _pytest.pathlib import insert_missing_modules +from _pytest.pathlib import is_importable from _pytest.pathlib import maybe_delete_a_numbered_dir from _pytest.pathlib import module_name_from_path from _pytest.pathlib import resolve_package_path @@ -33,6 +39,7 @@ from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit from _pytest.pytester import Pytester +from _pytest.pytester import RunResult from _pytest.tmpdir import TempPathFactory import pytest @@ -717,12 +724,13 @@ def test_module_name_from_path(self, tmp_path: Path) -> None: assert result == "_env_310.tests.test_foo" def test_resolve_pkg_root_and_module_name( - self, tmp_path: Path, monkeypatch: MonkeyPatch + self, tmp_path: Path, monkeypatch: MonkeyPatch, pytester: Pytester ) -> None: # Create a directory structure first without __init__.py files. (tmp_path / "src/app/core").mkdir(parents=True) models_py = tmp_path / "src/app/core/models.py" models_py.touch() + with pytest.raises(CouldNotResolvePathError): _ = resolve_pkg_root_and_module_name(models_py) @@ -738,6 +746,8 @@ def test_resolve_pkg_root_and_module_name( # If we add tmp_path to sys.path, src becomes a namespace package. monkeypatch.syspath_prepend(tmp_path) + validate_namespace_package(pytester, [tmp_path], ["src.app.core.models"]) + assert resolve_pkg_root_and_module_name( models_py, consider_namespace_packages=True ) == ( @@ -1119,39 +1129,56 @@ def test_safe_exists(tmp_path: Path) -> None: class TestNamespacePackages: """Test import_path support when importing from properly namespace packages.""" + @pytest.fixture(autouse=True) + def setup_imports_tracking(self, monkeypatch: MonkeyPatch) -> None: + monkeypatch.setattr(sys, "pytest_namespace_packages_test", [], raising=False) + def setup_directories( - self, tmp_path: Path, monkeypatch: MonkeyPatch, pytester: Pytester + self, tmp_path: Path, monkeypatch: Optional[MonkeyPatch], pytester: Pytester ) -> Tuple[Path, Path]: + # Use a code to guard against modules being imported more than once. + # This is a safeguard in case future changes break this invariant. + code = dedent( + """ + import sys + imported = getattr(sys, "pytest_namespace_packages_test", []) + assert __name__ not in imported, f"{__name__} already imported" + imported.append(__name__) + sys.pytest_namespace_packages_test = imported + """ + ) + # Set up a namespace package "com.company", containing # two subpackages, "app" and "calc". (tmp_path / "src/dist1/com/company/app/core").mkdir(parents=True) - (tmp_path / "src/dist1/com/company/app/__init__.py").touch() - (tmp_path / "src/dist1/com/company/app/core/__init__.py").touch() + (tmp_path / "src/dist1/com/company/app/__init__.py").write_text( + code, encoding="UTF-8" + ) + (tmp_path / "src/dist1/com/company/app/core/__init__.py").write_text( + code, encoding="UTF-8" + ) models_py = tmp_path / "src/dist1/com/company/app/core/models.py" models_py.touch() (tmp_path / "src/dist2/com/company/calc/algo").mkdir(parents=True) - (tmp_path / "src/dist2/com/company/calc/__init__.py").touch() - (tmp_path / "src/dist2/com/company/calc/algo/__init__.py").touch() + (tmp_path / "src/dist2/com/company/calc/__init__.py").write_text( + code, encoding="UTF-8" + ) + (tmp_path / "src/dist2/com/company/calc/algo/__init__.py").write_text( + code, encoding="UTF-8" + ) algorithms_py = tmp_path / "src/dist2/com/company/calc/algo/algorithms.py" - algorithms_py.touch() + algorithms_py.write_text(code, encoding="UTF-8") - # Validate the namespace package by importing it in a Python subprocess. - r = pytester.runpython_c( - dedent( - f""" - import sys - sys.path.append(r{str(tmp_path / "src/dist1")!r}) - sys.path.append(r{str(tmp_path / "src/dist2")!r}) - import com.company.app.core.models - import com.company.calc.algo.algorithms - """ - ) + r = validate_namespace_package( + pytester, + [tmp_path / "src/dist1", tmp_path / "src/dist2"], + ["com.company.app.core.models", "com.company.calc.algo.algorithms"], ) assert r.ret == 0 - - monkeypatch.syspath_prepend(tmp_path / "src/dist1") - monkeypatch.syspath_prepend(tmp_path / "src/dist2") + if monkeypatch is not None: + monkeypatch.syspath_prepend(tmp_path / "src/dist1") + monkeypatch.syspath_prepend(tmp_path / "src/dist2") return models_py, algorithms_py @pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"]) @@ -1223,11 +1250,76 @@ def test_incorrect_namespace_package( models_py, algorithms_py = self.setup_directories( tmp_path, monkeypatch, pytester ) - # Namespace packages must not have an __init__.py at any of its - # directories; if it does, we then fall back to importing just the - # part of the package containing the __init__.py files. + # Namespace packages must not have an __init__.py at its top-level + # directory; if it does, it is no longer a namespace package, and we fall back + # to importing just the part of the package containing the __init__.py files. (tmp_path / "src/dist1/com/__init__.py").touch() + # Because of the __init__ file, 'com' is no longer a namespace package: + # 'com.company.app' is importable as a normal module. + # 'com.company.calc' is no longer importable because 'com' is not a namespace package anymore. + r = validate_namespace_package( + pytester, + [tmp_path / "src/dist1", tmp_path / "src/dist2"], + ["com.company.app.core.models", "com.company.calc.algo.algorithms"], + ) + assert r.ret == 1 + r.stderr.fnmatch_lines("*No module named 'com.company.calc*") + + pkg_root, module_name = resolve_pkg_root_and_module_name( + models_py, consider_namespace_packages=True + ) + assert (pkg_root, module_name) == ( + tmp_path / "src/dist1", + "com.company.app.core.models", + ) + + # dist2/com/company will contain a normal Python package. + pkg_root, module_name = resolve_pkg_root_and_module_name( + algorithms_py, consider_namespace_packages=True + ) + assert (pkg_root, module_name) == ( + tmp_path / "src/dist2/com/company", + "calc.algo.algorithms", + ) + + def test_detect_meta_path( + self, + tmp_path: Path, + monkeypatch: MonkeyPatch, + pytester: Pytester, + ) -> None: + """ + resolve_pkg_root_and_module_name() considers sys.meta_path when importing namespace packages. + + Regression test for #12112. + """ + + class CustomImporter(importlib.abc.MetaPathFinder): + """ + Imports the module name "com" as a namespace package. + + This ensures our namespace detection considers sys.meta_path, which is important + to support all possible ways a module can be imported (for example editable installs). + """ + + def find_spec( + self, name: str, path: Any = None, target: Any = None + ) -> Optional[importlib.machinery.ModuleSpec]: + if name == "com": + spec = importlib.machinery.ModuleSpec("com", loader=None) + spec.submodule_search_locations = [str(com_root_2), str(com_root_1)] + return spec + return None + + # Setup directories without configuring sys.path. + models_py, algorithms_py = self.setup_directories( + tmp_path, monkeypatch=None, pytester=pytester + ) + com_root_1 = tmp_path / "src/dist1/com" + com_root_2 = tmp_path / "src/dist2/com" + + # Because the namespace package is not setup correctly, we cannot resolve it as a namespace package. pkg_root, module_name = resolve_pkg_root_and_module_name( models_py, consider_namespace_packages=True ) @@ -1235,3 +1327,107 @@ def test_incorrect_namespace_package( tmp_path / "src/dist1/com/company", "app.core.models", ) + + # Insert our custom importer, which will recognize the "com" directory as a namespace package. + new_meta_path = [CustomImporter(), *sys.meta_path] + monkeypatch.setattr(sys, "meta_path", new_meta_path) + + # Now we should be able to resolve the path as namespace package. + pkg_root, module_name = resolve_pkg_root_and_module_name( + models_py, consider_namespace_packages=True + ) + assert (pkg_root, module_name) == ( + tmp_path / "src/dist1", + "com.company.app.core.models", + ) + + @pytest.mark.parametrize("insert", [True, False]) + def test_full_ns_packages_without_init_files( + self, pytester: Pytester, tmp_path: Path, monkeypatch: MonkeyPatch, insert: bool + ) -> None: + (tmp_path / "src/dist1/ns/b/app/bar/test").mkdir(parents=True) + (tmp_path / "src/dist1/ns/b/app/bar/m.py").touch() + + if insert: + # The presence of this __init__.py is not a problem, ns.b.app is still part of the namespace package. + (tmp_path / "src/dist1/ns/b/app/__init__.py").touch() + + (tmp_path / "src/dist2/ns/a/core/foo/test").mkdir(parents=True) + (tmp_path / "src/dist2/ns/a/core/foo/m.py").touch() + + # Validate the namespace package by importing it in a Python subprocess. + r = validate_namespace_package( + pytester, + [tmp_path / "src/dist1", tmp_path / "src/dist2"], + ["ns.b.app.bar.m", "ns.a.core.foo.m"], + ) + assert r.ret == 0 + monkeypatch.syspath_prepend(tmp_path / "src/dist1") + monkeypatch.syspath_prepend(tmp_path / "src/dist2") + + assert resolve_pkg_root_and_module_name( + tmp_path / "src/dist1/ns/b/app/bar/m.py", consider_namespace_packages=True + ) == (tmp_path / "src/dist1", "ns.b.app.bar.m") + assert resolve_pkg_root_and_module_name( + tmp_path / "src/dist2/ns/a/core/foo/m.py", consider_namespace_packages=True + ) == (tmp_path / "src/dist2", "ns.a.core.foo.m") + + +def test_is_importable(pytester: Pytester) -> None: + pytester.syspathinsert() + + path = pytester.path / "bar/foo.py" + path.parent.mkdir() + path.touch() + assert is_importable("bar.foo", path) is True + + # Ensure that the module that can be imported points to the path we expect. + path = pytester.path / "some/other/path/bar/foo.py" + path.mkdir(parents=True, exist_ok=True) + assert is_importable("bar.foo", path) is False + + # Paths containing "." cannot be imported. + path = pytester.path / "bar.x/__init__.py" + path.parent.mkdir() + path.touch() + assert is_importable("bar.x", path) is False + + # Pass starting with "." denote relative imports and cannot be checked using is_importable. + path = pytester.path / ".bar.x/__init__.py" + path.parent.mkdir() + path.touch() + assert is_importable(".bar.x", path) is False + + +def test_compute_module_name(tmp_path: Path) -> None: + assert compute_module_name(tmp_path, tmp_path) is None + assert compute_module_name(Path(), Path()) is None + + assert compute_module_name(tmp_path, tmp_path / "mod.py") == "mod" + assert compute_module_name(tmp_path, tmp_path / "src/app/bar") == "src.app.bar" + assert compute_module_name(tmp_path, tmp_path / "src/app/bar.py") == "src.app.bar" + assert ( + compute_module_name(tmp_path, tmp_path / "src/app/bar/__init__.py") + == "src.app.bar" + ) + + +def validate_namespace_package( + pytester: Pytester, paths: Sequence[Path], modules: Sequence[str] +) -> RunResult: + """ + Validate that a Python namespace package is set up correctly. + + In a sub interpreter, add 'paths' to sys.path and attempt to import the given modules. + + In this module many tests configure a set of files as a namespace package, this function + is used as sanity check that our files are configured correctly from the point of view of Python. + """ + lines = [ + "import sys", + # Configure sys.path. + *[f"sys.path.append(r{str(x)!r})" for x in paths], + # Imports. + *[f"import {x}" for x in modules], + ] + return pytester.runpython_c("\n".join(lines)) From 089116bdff4a82b624caa50913910e11cfad2d51 Mon Sep 17 00:00:00 2001 From: HolyMagician03-UMich <122073322+HolyMagician03-UMich@users.noreply.github.com> Date: Wed, 10 Apr 2024 07:07:18 -0400 Subject: [PATCH 0587/1271] short test summary: do not truncate text when -vv is given Fix #11777 --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 2 ++ changelog/11777.improvement.rst | 1 + src/_pytest/terminal.py | 6 ++--- testing/test_terminal.py | 46 +++++++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 changelog/11777.improvement.rst diff --git a/AUTHORS b/AUTHORS index 53f7a8c2a16..cc054bfd978 100644 --- a/AUTHORS +++ b/AUTHORS @@ -137,6 +137,7 @@ Endre Galaczi Eric Hunsberger Eric Liu Eric Siegerman +Eric Yuan Erik Aronesty Erik Hasse Erik M. Bray @@ -432,6 +433,7 @@ Xixi Zhao Xuan Luong Xuecong Liao Yannick Péroux +Yao Xiao Yoav Caspi Yuliang Shao Yusuke Kadowaki diff --git a/changelog/11777.improvement.rst b/changelog/11777.improvement.rst new file mode 100644 index 00000000000..fb53c63c10a --- /dev/null +++ b/changelog/11777.improvement.rst @@ -0,0 +1 @@ +Text is no longer truncated in the ``short test summary info`` section when ``-vv`` is given. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 973168dc6ff..724d5c54d2f 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1408,11 +1408,11 @@ def _get_line_with_reprcrash_message( except AttributeError: pass else: - if not running_on_ci(): + if running_on_ci() or config.option.verbose >= 2: + msg = f" - {msg}" + else: available_width = tw.fullwidth - line_width msg = _format_trimmed(" - {}", msg, available_width) - else: - msg = f" - {msg}" if msg is not None: line += msg diff --git a/testing/test_terminal.py b/testing/test_terminal.py index f4942510991..170f1efcf91 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2377,8 +2377,13 @@ def mock_get_pos(*args): monkeypatch.setattr(_pytest.terminal, "_get_node_id_with_markup", mock_get_pos) + class Namespace: + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + class config: - pass + def __init__(self): + self.option = Namespace(verbose=0) class rep: def _get_verbose_word(self, *args): @@ -2399,7 +2404,7 @@ def markup(self, word: str, **markup: str): if msg: rep.longrepr.reprcrash.message = msg # type: ignore actual = _get_line_with_reprcrash_message( - config, # type: ignore[arg-type] + config(), # type: ignore[arg-type] rep(), # type: ignore[arg-type] DummyTerminalWriter(), # type: ignore[arg-type] {}, @@ -2443,6 +2448,43 @@ def markup(self, word: str, **markup: str): check("🉐🉐🉐🉐🉐\n2nd line", 80, "FAILED nodeid::🉐::withunicode - 🉐🉐🉐🉐🉐") +def test_short_summary_with_verbose( + monkeypatch: MonkeyPatch, pytester: Pytester +) -> None: + """With -vv do not truncate the summary info (#11777).""" + # On CI we also do not truncate the summary info, monkeypatch it to ensure we + # are testing against the -vv flag on CI. + monkeypatch.setattr(_pytest.terminal, "running_on_ci", lambda: False) + + string_length = 200 + pytester.makepyfile( + f""" + def test(): + s1 = "A" * {string_length} + s2 = "B" * {string_length} + assert s1 == s2 + """ + ) + + # No -vv, summary info should be truncated. + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*short test summary info*", + "* assert 'AAA...", + ], + ) + + # No truncation with -vv. + result = pytester.runpytest("-vv") + result.stdout.fnmatch_lines( + [ + "*short test summary info*", + f"*{'A' * string_length}*{'B' * string_length}'", + ] + ) + + @pytest.mark.parametrize( "seconds, expected", [ From 5f6e825a2687f6bb8bc437e67a59c0a92fb16c06 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 14 Apr 2024 00:21:52 +0000 Subject: [PATCH 0588/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 186 +++++++++++++++++++------------ 1 file changed, 117 insertions(+), 69 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 3c7409f0157..911a6bf7bae 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.2) :pypi:`pytest-ai1899` pytest plugin for connecting to ai1899 smart system stack Mar 13, 2024 5 - Production/Stable N/A - :pypi:`pytest-aio` Pytest plugin for testing async python code Feb 03, 2023 4 - Beta pytest + :pypi:`pytest-aio` Pytest plugin for testing async python code Apr 08, 2024 5 - Production/Stable pytest :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A :pypi:`pytest-aiogram` May 06, 2023 N/A N/A :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Sep 06, 2023 4 - Beta pytest >=6.1.0 @@ -199,7 +199,7 @@ This list contains 1437 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` pytest-celery a shim pytest plugin to enable celery.contrib.pytest Apr 05, 2024 N/A N/A + :pypi:`pytest-celery` Pytest plugin for Celery Apr 11, 2024 4 - Beta N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -262,7 +262,7 @@ This list contains 1437 plugins. :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest - :pypi:`pytest-container` Pytest fixtures for writing container based tests Apr 03, 2024 4 - Beta pytest>=3.10 + :pypi:`pytest-container` Pytest fixtures for writing container based tests Apr 10, 2024 4 - Beta pytest>=3.10 :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) @@ -300,7 +300,7 @@ This list contains 1437 plugins. :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 06, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 10, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -433,14 +433,14 @@ This list contains 1437 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 Apr 04, 2024 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. Apr 02, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Apr 09, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 09, 2024 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) @@ -546,6 +546,7 @@ This list contains 1437 plugins. :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jun 26, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-fly` pytest observer Apr 14, 2024 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) @@ -573,7 +574,7 @@ This list contains 1437 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 03, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 12, 2024 N/A pytest>=3.6 :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 @@ -611,12 +612,13 @@ This list contains 1437 plugins. :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-henry` Aug 29, 2023 N/A N/A :pypi:`pytest-hidecaptured` Hide captured output May 04, 2018 4 - Beta pytest (>=2.8.5) + :pypi:`pytest-himark` A plugin that reads a config.json file in your test root directory, searches the 'markers' key, lists the markers declared as 'true' as enabled markers and automatically adds -m option to the command line with an OR on the enabled markers. Apr 07, 2024 4 - Beta pytest>=6.2.0 :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 Jan 14, 2024 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 Apr 06, 2024 3 - Alpha pytest==8.1.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 13, 2024 3 - Alpha pytest==8.1.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Jan 06, 2024 N/A N/A @@ -647,13 +649,13 @@ This list contains 1437 plugins. :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Mar 30, 2024 3 - Alpha pytest>=7.0.0 + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Apr 12, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Dec 13, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A - :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Oct 11, 2023 5 - Production/Stable pytest >=6.0 + :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 08, 2024 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. Dec 01, 2023 4 - Beta pytest >=3.5.0 @@ -664,6 +666,7 @@ This list contains 1437 plugins. :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A + :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 09, 2024 N/A pytest<9.0.0,>=8.1.1 :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. Dec 13, 2023 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 02, 2024 5 - Production/Stable N/A @@ -684,6 +687,7 @@ This list contains 1437 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A + :pypi:`pytest-ipywidgets` Apr 08, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -694,7 +698,7 @@ This list contains 1437 plugins. :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Mar 18, 2024 3 - Alpha N/A + :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 12, 2024 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Mar 27, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) @@ -737,7 +741,7 @@ This list contains 1437 plugins. :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest - :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest. Dec 22, 2018 4 - Beta pytest (>=3.0.0) + :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A @@ -813,7 +817,7 @@ This list contains 1437 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Mar 06, 2024 N/A pytest (>=1.0) + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Apr 11, 2024 N/A pytest>=1.0 :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -862,8 +866,9 @@ This list contains 1437 plugins. :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Feb 16, 2024 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A - :pypi:`pytest-nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Jul 07, 2021 N/A N/A - :pypi:`pytest-nocustom` Run all tests without custom markers Jul 07, 2021 5 - Production/Stable N/A + :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Apr 11, 2024 N/A N/A + :pypi:`pytest-nocustom` Run all tests without custom markers Apr 11, 2024 5 - Production/Stable N/A + :pypi:`pytest-node-dependency` pytest plugin for controlling execution flow Apr 10, 2024 5 - Production/Stable N/A :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A @@ -986,6 +991,7 @@ This list contains 1437 plugins. :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Aug 25, 2023 5 - Production/Stable pytest>=7.4 :pypi:`pytest-priority` pytest plugin for add priority for tests Jul 23, 2023 N/A N/A + :pypi:`pytest-proceed` Apr 10, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A @@ -1146,7 +1152,7 @@ This list contains 1437 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 05, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 11, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1155,7 +1161,7 @@ This list contains 1437 plugins. :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 Feb 01, 2024 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. Apr 05, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 11, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1220,7 +1226,7 @@ This list contains 1437 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. Nov 21, 2023 N/A pytest (>7.0) + :pypi:`pytest-spec2md` Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. Apr 10, 2024 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 Apr 01, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-spiratest` Exports unit tests as test runs in Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A @@ -1273,7 +1279,7 @@ This list contains 1437 plugins. :pypi:`pytest-synodic` Synodic Pytest utilities Mar 09, 2024 N/A pytest>=8.0.2 :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A - :pypi:`pytest_tagging` a pytest plugin to tag tests Feb 15, 2024 N/A pytest (>=7.1.3,<8.0.0) + :pypi:`pytest_tagging` a pytest plugin to tag tests Apr 08, 2024 N/A pytest<8.0.0,>=7.1.3 :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) @@ -1391,7 +1397,7 @@ This list contains 1437 plugins. :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Mar 13, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A - :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Aug 08, 2023 4 - Beta pytest (>=7.3.2,<8.0.0) + :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Apr 08, 2024 4 - Beta pytest>7.3.2 :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest @@ -1438,7 +1444,7 @@ This list contains 1437 plugins. :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) - :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Sep 29, 2023 4 - Beta pytest (>=7.3,<8.0) + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 11, 2024 4 - Beta pytest>7.3.2 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A @@ -1453,7 +1459,7 @@ This list contains 1437 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 Dec 18, 2023 N/A pytest>=7.4.0 + :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Apr 07, 2024 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) @@ -1589,8 +1595,8 @@ This list contains 1437 plugins. pytest plugin for connecting to ai1899 smart system stack :pypi:`pytest-aio` - *last release*: Feb 03, 2023, - *status*: 4 - Beta, + *last release*: Apr 08, 2024, + *status*: 5 - Production/Stable, *requires*: pytest Pytest plugin for testing async python code @@ -2632,11 +2638,11 @@ This list contains 1437 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Apr 05, 2024, - *status*: N/A, + *last release*: Apr 11, 2024, + *status*: 4 - Beta, *requires*: N/A - pytest-celery a shim pytest plugin to enable celery.contrib.pytest + Pytest plugin for Celery :pypi:`pytest-cfg-fetcher` *last release*: Feb 26, 2024, @@ -3073,7 +3079,7 @@ This list contains 1437 plugins. pytest plugin with fixtures for testing consul aware apps :pypi:`pytest-container` - *last release*: Apr 03, 2024, + *last release*: Apr 10, 2024, *status*: 4 - Beta, *requires*: pytest>=3.10 @@ -3339,7 +3345,7 @@ This list contains 1437 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Apr 06, 2024, + *last release*: Apr 10, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4270,56 +4276,56 @@ This list contains 1437 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Apr 02, 2024, + *last release*: Apr 09, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Apr 02, 2024, + *last release*: Apr 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Apr 02, 2024, + *last release*: Apr 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Apr 02, 2024, + *last release*: Apr 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Apr 02, 2024, + *last release*: Apr 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Apr 02, 2024, + *last release*: Apr 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Apr 02, 2024, + *last release*: Apr 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Apr 02, 2024, + *last release*: Apr 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5060,6 +5066,13 @@ This list contains 1437 plugins. A pytest plugin in order to provide logs via fluentbit + :pypi:`pytest-fly` + *last release*: Apr 14, 2024, + *status*: 3 - Alpha, + *requires*: pytest + + pytest observer + :pypi:`pytest-flyte` *last release*: May 03, 2021, *status*: N/A, @@ -5250,7 +5263,7 @@ This list contains 1437 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Apr 03, 2024, + *last release*: Apr 12, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5515,6 +5528,13 @@ This list contains 1437 plugins. Hide captured output + :pypi:`pytest-himark` + *last release*: Apr 07, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A plugin that reads a config.json file in your test root directory, searches the 'markers' key, lists the markers declared as 'true' as enabled markers and automatically adds -m option to the command line with an OR on the enabled markers. + :pypi:`pytest-historic` *last release*: Apr 08, 2020, *status*: N/A, @@ -5551,7 +5571,7 @@ This list contains 1437 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 06, 2024, + *last release*: Apr 13, 2024, *status*: 3 - Alpha, *requires*: pytest==8.1.1 @@ -5768,7 +5788,7 @@ This list contains 1437 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Mar 30, 2024, + *last release*: Apr 12, 2024, *status*: 3 - Alpha, *requires*: pytest>=7.0.0 @@ -5810,9 +5830,9 @@ This list contains 1437 plugins. Pytest plugin for testing function idempotence. :pypi:`pytest-ignore-flaky` - *last release*: Oct 11, 2023, + *last release*: Apr 08, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6.0 + *requires*: pytest>=6.0 ignore failures from flaky tests (pytest plugin) @@ -5886,6 +5906,13 @@ This list contains 1437 plugins. Reuse pytest.ini to store env variables + :pypi:`pytest-initry` + *last release*: Apr 09, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.1.1 + + Plugin for sending automation test data from Pytest to the initry + :pypi:`pytest-inline` *last release*: Oct 19, 2023, *status*: 4 - Beta, @@ -6026,6 +6053,13 @@ This list contains 1437 plugins. THIS PROJECT IS ABANDONED + :pypi:`pytest-ipywidgets` + *last release*: Apr 08, 2024, + *status*: N/A, + *requires*: pytest + + + :pypi:`pytest-isolate` *last release*: Feb 20, 2023, *status*: 4 - Beta, @@ -6097,7 +6131,7 @@ This list contains 1437 plugins. A plugin to generate customizable jinja-based HTML reports in pytest :pypi:`pytest-jira` - *last release*: Mar 18, 2024, + *last release*: Apr 12, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -6398,11 +6432,11 @@ This list contains 1437 plugins. Select tests of a given level or lower :pypi:`pytest-libfaketime` - *last release*: Dec 22, 2018, + *last release*: Apr 12, 2024, *status*: 4 - Beta, - *requires*: pytest (>=3.0.0) + *requires*: pytest>=3.0.0 - A python-libfaketime plugin for pytest. + A python-libfaketime plugin for pytest :pypi:`pytest-libiio` *last release*: Dec 22, 2023, @@ -6930,9 +6964,9 @@ This list contains 1437 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Mar 06, 2024, + *last release*: Apr 11, 2024, *status*: N/A, - *requires*: pytest (>=1.0) + *requires*: pytest>=1.0 A pytest plugin for easily instantiating reproducible mock resources. @@ -7272,20 +7306,27 @@ This list contains 1437 plugins. A small snippet for nicer PyTest's Parametrize - :pypi:`pytest-nlcov` - *last release*: Jul 07, 2021, + :pypi:`pytest_nlcov` + *last release*: Apr 11, 2024, *status*: N/A, *requires*: N/A Pytest plugin to get the coverage of the new lines (based on git diff) only :pypi:`pytest-nocustom` - *last release*: Jul 07, 2021, + *last release*: Apr 11, 2024, *status*: 5 - Production/Stable, *requires*: N/A Run all tests without custom markers + :pypi:`pytest-node-dependency` + *last release*: Apr 10, 2024, + *status*: 5 - Production/Stable, + *requires*: N/A + + pytest plugin for controlling execution flow + :pypi:`pytest-nodev` *last release*: Jul 21, 2016, *status*: 4 - Beta, @@ -8140,6 +8181,13 @@ This list contains 1437 plugins. pytest plugin for add priority for tests + :pypi:`pytest-proceed` + *last release*: Apr 10, 2024, + *status*: N/A, + *requires*: pytest + + + :pypi:`pytest-profiles` *last release*: Dec 09, 2021, *status*: 4 - Beta, @@ -9261,7 +9309,7 @@ This list contains 1437 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Apr 05, 2024, + *last release*: Apr 11, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9324,7 +9372,7 @@ This list contains 1437 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Apr 05, 2024, + *last release*: Apr 11, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9779,9 +9827,9 @@ This list contains 1437 plugins. Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. :pypi:`pytest-spec2md` - *last release*: Nov 21, 2023, + *last release*: Apr 10, 2024, *status*: N/A, - *requires*: pytest (>7.0) + *requires*: pytest>7.0 Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. @@ -10150,9 +10198,9 @@ This list contains 1437 plugins. Pyst - Pytest System-Test Plugin :pypi:`pytest_tagging` - *last release*: Feb 15, 2024, + *last release*: Apr 08, 2024, *status*: N/A, - *requires*: pytest (>=7.1.3,<8.0.0) + *requires*: pytest<8.0.0,>=7.1.3 a pytest plugin to tag tests @@ -10976,9 +11024,9 @@ This list contains 1437 plugins. Set a test as unstable to return 0 even if it failed :pypi:`pytest-unused-fixtures` - *last release*: Aug 08, 2023, + *last release*: Apr 08, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.3.2,<8.0.0) + *requires*: pytest>7.3.2 A pytest plugin to list unused fixtures after a test run. @@ -11305,9 +11353,9 @@ This list contains 1437 plugins. pytest plugin helps to reproduce failures for particular xdist node :pypi:`pytest-xdist-worker-stats` - *last release*: Sep 29, 2023, + *last release*: Apr 11, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.3,<8.0) + *requires*: pytest>7.3.2 A pytest plugin to list worker statistics after a xdist run. @@ -11410,7 +11458,7 @@ This list contains 1437 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Dec 18, 2023, + *last release*: Apr 07, 2024, *status*: N/A, *requires*: pytest>=7.4.0 From 0644e467fbe5a57ee137f6bf5c98db71da8f446e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:33:41 +0200 Subject: [PATCH 0589/1271] build(deps): Bump hynek/build-and-inspect-python-package (#12214) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.2.1 to 2.4.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.2.1...v2.4.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 26d77ffd052..cc0e6331d45 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.2.1 + uses: hynek/build-and-inspect-python-package@v2.4.0 deploy: if: github.repository == 'pytest-dev/pytest' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6868c21c51f..4434740675e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.2.1 + uses: hynek/build-and-inspect-python-package@v2.4.0 build: needs: [package] From b56b294f54268b45f611917e6d1fd577a2f848be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:08:38 -0300 Subject: [PATCH 0590/1271] build(deps): Bump peter-evans/create-pull-request from 6.0.2 to 6.0.3 (#12215) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.0.2 to 6.0.3. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/70a41aba780001da0a30141984ae2a0c95d8704e...c55203cfde3e5c11a452d352b4393e68b85b4533) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 53ba0e368d9..fd3443d8e9e 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -46,7 +46,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request - uses: peter-evans/create-pull-request@70a41aba780001da0a30141984ae2a0c95d8704e + uses: peter-evans/create-pull-request@c55203cfde3e5c11a452d352b4393e68b85b4533 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 58844247f7ae4a7a213a73c8af2462253b3d8fc7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 23:04:19 +0000 Subject: [PATCH 0591/1271] [pre-commit.ci] pre-commit autoupdate (#12218) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.3.5 → v0.3.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.3.5...v0.3.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 65a7e4efb62..5d216d2db6f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.3.5" + rev: "v0.3.7" hooks: - id: ruff args: ["--fix"] From 48b6d188349b426a34e013820df6542087f0d08b Mon Sep 17 00:00:00 2001 From: dj <112573278+dheerajck@users.noreply.github.com> Date: Thu, 18 Apr 2024 16:15:47 +0530 Subject: [PATCH 0592/1271] Add PYTEST_VERSION environment variable (#12190) Among other things, it can be used to check if a code is running from within a pytest session. Fixes #9502 --- AUTHORS | 1 + changelog/9502.improvement.rst | 1 + doc/en/reference/reference.rst | 5 +++++ src/_pytest/config/__init__.py | 8 ++++++++ testing/test_runner.py | 17 +++++++++++++++++ 5 files changed, 32 insertions(+) create mode 100644 changelog/9502.improvement.rst diff --git a/AUTHORS b/AUTHORS index cc054bfd978..7c35a615232 100644 --- a/AUTHORS +++ b/AUTHORS @@ -118,6 +118,7 @@ Daw-Ran Liou Debi Mishra Denis Kirisov Denivy Braiam Rück +Dheeraj C K Dhiren Serai Diego Russo Dmitry Dygalo diff --git a/changelog/9502.improvement.rst b/changelog/9502.improvement.rst new file mode 100644 index 00000000000..2eaf6a72747 --- /dev/null +++ b/changelog/9502.improvement.rst @@ -0,0 +1 @@ +Added :envvar:`PYTEST_VERSION` environment variable which is defined at the start of the pytest session and undefined afterwards. It contains the value of ``pytest.__version__``, and among other things can be used to easily check if code is running from within a pytest run. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index c9d7aeb552c..39317497ebd 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1117,6 +1117,11 @@ When set (regardless of value), pytest acknowledges that is running in a CI proc This contains a command-line (parsed by the py:mod:`shlex` module) that will be **prepended** to the command line given by the user, see :ref:`adding default options` for more information. +.. envvar:: PYTEST_VERSION + +This environment variable is defined at the start of the pytest session and is undefined afterwards. +It contains the value of ``pytest.__version__``, and among other things can be used to easily check if a code is running from within a pytest run. + .. envvar:: PYTEST_CURRENT_TEST This is not meant to be set by users, but is set by pytest internally with the name of the current test so other diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 7ff27643f10..306b14cce28 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -50,6 +50,7 @@ from .exceptions import PrintHelp as PrintHelp from .exceptions import UsageError as UsageError from .findpaths import determine_setup +from _pytest import __version__ import _pytest._code from _pytest._code import ExceptionInfo from _pytest._code import filter_traceback @@ -151,7 +152,9 @@ def main( :returns: An exit code. """ + old_pytest_version = os.environ.get("PYTEST_VERSION") try: + os.environ["PYTEST_VERSION"] = __version__ try: config = _prepareconfig(args, plugins) except ConftestImportFailure as e: @@ -186,6 +189,11 @@ def main( for msg in e.args: tw.line(f"ERROR: {msg}\n", red=True) return ExitCode.USAGE_ERROR + finally: + if old_pytest_version is None: + os.environ.pop("PYTEST_VERSION", None) + else: + os.environ["PYTEST_VERSION"] = old_pytest_version def console_main() -> int: diff --git a/testing/test_runner.py b/testing/test_runner.py index 8cc496f7064..d3ddc5d9acb 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1094,3 +1094,20 @@ def func() -> None: with pytest.raises(TypeError) as excinfo: OutcomeException(func) # type: ignore assert str(excinfo.value) == expected + + +def test_pytest_version_env_var(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: + os.environ["PYTEST_VERSION"] = "old version" + pytester.makepyfile( + """ + import pytest + import os + + + def test(): + assert os.environ.get("PYTEST_VERSION") == pytest.__version__ + """ + ) + result = pytester.runpytest_inprocess() + assert result.ret == ExitCode.OK + assert os.environ["PYTEST_VERSION"] == "old version" From ad95d59d6158076768cccd0000b968cd691cb62a Mon Sep 17 00:00:00 2001 From: dj <112573278+dheerajck@users.noreply.github.com> Date: Fri, 19 Apr 2024 07:35:29 +0530 Subject: [PATCH 0593/1271] Use monkeypatch in test_pytest_version_env_var Follow up to #12190 --- testing/test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_runner.py b/testing/test_runner.py index d3ddc5d9acb..ffac0f2d92b 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1097,7 +1097,7 @@ def func() -> None: def test_pytest_version_env_var(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: - os.environ["PYTEST_VERSION"] = "old version" + monkeypatch.setenv("PYTEST_VERSION", "old version") pytester.makepyfile( """ import pytest From ff806b239e6fb542ef1c9a5feb7cfad229a433df Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 20 Apr 2024 08:31:33 -0300 Subject: [PATCH 0594/1271] importlib: set children as attribute of parent modules (#12208) Now `importlib` mode will correctly set the imported modules as an attribute of their parent modules. As helpfully posted on #12194, that's how the Python import module works so we should follow suit. In addition, we also try to import the parent modules as part of the process of importing a child module, again mirroring how Python importing works. Fix #12194 --- changelog/12194.bugfix.rst | 1 + src/_pytest/pathlib.py | 36 ++++++++-- testing/test_pathlib.py | 133 +++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 changelog/12194.bugfix.rst diff --git a/changelog/12194.bugfix.rst b/changelog/12194.bugfix.rst new file mode 100644 index 00000000000..6983ba35a90 --- /dev/null +++ b/changelog/12194.bugfix.rst @@ -0,0 +1 @@ +Fixed a bug with ``--importmode=importlib`` and ``--doctest-modules`` where child modules did not appear as attributes in parent modules. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 254d9d9468e..7f01c011ba6 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -620,10 +620,6 @@ def _import_module_using_spec( :param insert_modules: If True, will call insert_missing_modules to create empty intermediate modules for made-up module names (when importing test files not reachable from sys.path). - Note: we can probably drop insert_missing_modules altogether: instead of - generating module names such as "src.tests.test_foo", which require intermediate - empty modules, we might just as well generate unique module names like - "src_tests_test_foo". """ # Checking with sys.meta_path first in case one of its hooks can import this module, # such as our own assertion-rewrite hook. @@ -636,9 +632,41 @@ def _import_module_using_spec( if spec_matches_module_path(spec, module_path): assert spec is not None + # Attempt to import the parent module, seems is our responsibility: + # https://github.com/python/cpython/blob/73906d5c908c1e0b73c5436faeff7d93698fc074/Lib/importlib/_bootstrap.py#L1308-L1311 + parent_module_name, _, name = module_name.rpartition(".") + parent_module: Optional[ModuleType] = None + if parent_module_name: + parent_module = sys.modules.get(parent_module_name) + if parent_module is None: + # Find the directory of this module's parent. + parent_dir = ( + module_path.parent.parent + if module_path.name == "__init__.py" + else module_path.parent + ) + # Consider the parent module path as its __init__.py file, if it has one. + parent_module_path = ( + parent_dir / "__init__.py" + if (parent_dir / "__init__.py").is_file() + else parent_dir + ) + parent_module = _import_module_using_spec( + parent_module_name, + parent_module_path, + parent_dir, + insert_modules=insert_modules, + ) + + # Find spec and import this module. mod = importlib.util.module_from_spec(spec) sys.modules[module_name] = mod spec.loader.exec_module(mod) # type: ignore[union-attr] + + # Set this module as an attribute of the parent module (#12194). + if parent_module is not None: + setattr(parent_module, name, mod) + if insert_modules: insert_missing_modules(sys.modules, module_name) return mod diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index f96151bdd44..688d13f2f05 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1126,6 +1126,139 @@ def test_safe_exists(tmp_path: Path) -> None: assert safe_exists(p) is False +def test_import_sets_module_as_attribute(pytester: Pytester) -> None: + """Unittest test for #12194.""" + pytester.path.joinpath("foo/bar/baz").mkdir(parents=True) + pytester.path.joinpath("foo/__init__.py").touch() + pytester.path.joinpath("foo/bar/__init__.py").touch() + pytester.path.joinpath("foo/bar/baz/__init__.py").touch() + pytester.syspathinsert() + + # Import foo.bar.baz and ensure parent modules also ended up imported. + baz = import_path( + pytester.path.joinpath("foo/bar/baz/__init__.py"), + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=False, + ) + assert baz.__name__ == "foo.bar.baz" + foo = sys.modules["foo"] + assert foo.__name__ == "foo" + bar = sys.modules["foo.bar"] + assert bar.__name__ == "foo.bar" + + # Check parent modules have an attribute pointing to their children. + assert bar.baz is baz + assert foo.bar is bar + + # Ensure we returned the "foo.bar" module cached in sys.modules. + bar_2 = import_path( + pytester.path.joinpath("foo/bar/__init__.py"), + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=False, + ) + assert bar_2 is bar + + +def test_import_sets_module_as_attribute_without_init_files(pytester: Pytester) -> None: + """Similar to test_import_sets_module_as_attribute, but without __init__.py files.""" + pytester.path.joinpath("foo/bar").mkdir(parents=True) + pytester.path.joinpath("foo/bar/baz.py").touch() + pytester.syspathinsert() + + # Import foo.bar.baz and ensure parent modules also ended up imported. + baz = import_path( + pytester.path.joinpath("foo/bar/baz.py"), + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=False, + ) + assert baz.__name__ == "foo.bar.baz" + foo = sys.modules["foo"] + assert foo.__name__ == "foo" + bar = sys.modules["foo.bar"] + assert bar.__name__ == "foo.bar" + + # Check parent modules have an attribute pointing to their children. + assert bar.baz is baz + assert foo.bar is bar + + # Ensure we returned the "foo.bar.baz" module cached in sys.modules. + baz_2 = import_path( + pytester.path.joinpath("foo/bar/baz.py"), + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=False, + ) + assert baz_2 is baz + + +def test_import_sets_module_as_attribute_regression(pytester: Pytester) -> None: + """Regression test for #12194.""" + pytester.path.joinpath("foo/bar/baz").mkdir(parents=True) + pytester.path.joinpath("foo/__init__.py").touch() + pytester.path.joinpath("foo/bar/__init__.py").touch() + pytester.path.joinpath("foo/bar/baz/__init__.py").touch() + f = pytester.makepyfile( + """ + import foo + from foo.bar import baz + foo.bar.baz + + def test_foo() -> None: + pass + """ + ) + + pytester.syspathinsert() + result = pytester.runpython(f) + assert result.ret == 0 + + result = pytester.runpytest("--import-mode=importlib", "--doctest-modules") + assert result.ret == 0 + + +def test_import_submodule_not_namespace(pytester: Pytester) -> None: + """ + Regression test for importing a submodule 'foo.bar' while there is a 'bar' directory + reachable from sys.path -- ensuring the top-level module does not end up imported as a namespace + package. + + #12194 + https://github.com/pytest-dev/pytest/pull/12208#issuecomment-2056458432 + """ + pytester.syspathinsert() + # Create package 'foo' with a submodule 'bar'. + pytester.path.joinpath("foo").mkdir() + foo_path = pytester.path.joinpath("foo/__init__.py") + foo_path.touch() + bar_path = pytester.path.joinpath("foo/bar.py") + bar_path.touch() + # Create top-level directory in `sys.path` with the same name as that submodule. + pytester.path.joinpath("bar").mkdir() + + # Import `foo`, then `foo.bar`, and check they were imported from the correct location. + foo = import_path( + foo_path, + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=False, + ) + bar = import_path( + bar_path, + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=False, + ) + assert foo.__name__ == "foo" + assert bar.__name__ == "foo.bar" + assert foo.__file__ is not None + assert bar.__file__ is not None + assert Path(foo.__file__) == foo_path + assert Path(bar.__file__) == bar_path + + class TestNamespacePackages: """Test import_path support when importing from properly namespace packages.""" From 6fb474a3eb3ba2b5d971735134d8fcfe9d3dc657 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 20 Apr 2024 08:58:14 -0300 Subject: [PATCH 0595/1271] Refactor insert_missing_modules function (#12210) Makes the logic more straightforward IMO. --- src/_pytest/pathlib.py | 47 ++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 7f01c011ba6..0ef8d094fc5 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -737,34 +737,31 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) -> otherwise "src.tests.test_foo" is not importable by ``__import__``. """ module_parts = module_name.split(".") - child_module: Union[ModuleType, None] = None - module: Union[ModuleType, None] = None - child_name: str = "" while module_name: - if module_name not in modules: - try: - # If sys.meta_path is empty, calling import_module will issue - # a warning and raise ModuleNotFoundError. To avoid the - # warning, we check sys.meta_path explicitly and raise the error - # ourselves to fall back to creating a dummy module. - if not sys.meta_path: - raise ModuleNotFoundError - module = importlib.import_module(module_name) - except ModuleNotFoundError: - module = ModuleType( - module_name, - doc="Empty module created by pytest's importmode=importlib.", - ) - else: - module = modules[module_name] - if child_module: + parent_module_name, _, child_name = module_name.rpartition(".") + if parent_module_name: + parent_module = modules.get(parent_module_name) + if parent_module is None: + try: + # If sys.meta_path is empty, calling import_module will issue + # a warning and raise ModuleNotFoundError. To avoid the + # warning, we check sys.meta_path explicitly and raise the error + # ourselves to fall back to creating a dummy module. + if not sys.meta_path: + raise ModuleNotFoundError + parent_module = importlib.import_module(parent_module_name) + except ModuleNotFoundError: + parent_module = ModuleType( + module_name, + doc="Empty module created by pytest's importmode=importlib.", + ) + modules[parent_module_name] = parent_module + # Add child attribute to the parent that can reference the child # modules. - if not hasattr(module, child_name): - setattr(module, child_name, child_module) - modules[module_name] = module - # Keep track of the child module while moving up the tree. - child_module, child_name = module, module_name.rpartition(".")[-1] + if not hasattr(parent_module, child_name): + setattr(parent_module, child_name, modules[module_name]) + module_parts.pop(-1) module_name = ".".join(module_parts) From 042625957a51b3e5eb0fc2b6f4682fa1cc3f607f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 20 Apr 2024 16:32:36 -0300 Subject: [PATCH 0596/1271] Fully type annotate pathlib.py (#12229) Add full type annotations to `pathlib.py` and remove the `allow-untyped-defs` directive. --- src/_pytest/pathlib.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 0ef8d094fc5..190d9dd8ce6 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,4 +1,3 @@ -# mypy: allow-untyped-defs import atexit import contextlib from enum import Enum @@ -23,6 +22,7 @@ import sys import types from types import ModuleType +from typing import Any from typing import Callable from typing import Dict from typing import Iterable @@ -59,7 +59,7 @@ ) -def _ignore_error(exception): +def _ignore_error(exception: Exception) -> bool: return ( getattr(exception, "errno", None) in _IGNORED_ERRORS or getattr(exception, "winerror", None) in _IGNORED_WINERRORS @@ -71,7 +71,7 @@ def get_lock_path(path: _AnyPurePath) -> _AnyPurePath: def on_rm_rf_error( - func, + func: Optional[Callable[..., Any]], path: str, excinfo: Union[ BaseException, @@ -196,7 +196,7 @@ def find_suffixes(root: Path, prefix: str) -> Iterator[str]: return extract_suffixes(find_prefixed(root, prefix), prefix) -def parse_num(maybe_num) -> int: +def parse_num(maybe_num: str) -> int: """Parse number path suffixes, returns -1 on error.""" try: return int(maybe_num) @@ -264,7 +264,9 @@ def create_cleanup_lock(p: Path) -> Path: return lock_path -def register_cleanup_lock_removal(lock_path: Path, register=atexit.register): +def register_cleanup_lock_removal( + lock_path: Path, register: Any = atexit.register +) -> Any: """Register a cleanup function for removing a lock, by default on atexit.""" pid = os.getpid() @@ -355,7 +357,7 @@ def cleanup_candidates(root: Path, prefix: str, keep: int) -> Iterator[Path]: yield Path(entry) -def cleanup_dead_symlinks(root: Path): +def cleanup_dead_symlinks(root: Path) -> None: for left_dir in root.iterdir(): if left_dir.is_symlink(): if not left_dir.resolve().exists(): @@ -459,10 +461,14 @@ def parts(s: str) -> Set[str]: return {sep.join(parts[: i + 1]) or sep for i in range(len(parts))} -def symlink_or_skip(src, dst, **kwargs): +def symlink_or_skip( + src: Union["os.PathLike[str]", str], + dst: Union["os.PathLike[str]", str], + **kwargs: Any, +) -> None: """Make a symlink, or skip the test in case symlinks are not supported.""" try: - os.symlink(str(src), str(dst), **kwargs) + os.symlink(src, dst, **kwargs) except OSError as e: skip(f"symlinks not supported: {e}") From 58136c53762fe90b06814750c69f42e034d82f09 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 18 Apr 2024 22:08:28 +0300 Subject: [PATCH 0597/1271] hookspec: deprecate hookimpls requesting py.path parameters --- .pre-commit-config.yaml | 2 +- changelog/12069.deprecation.rst | 12 ++++++++++ changelog/12069.trivial.rst | 1 + doc/en/requirements.txt | 2 +- pyproject.toml | 2 +- src/_pytest/hookspec.py | 41 +++++++++++++++++++++++++++++++-- testing/deprecated_test.py | 26 +++++++++++++++++++++ 7 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 changelog/12069.deprecation.rst create mode 100644 changelog/12069.trivial.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5d216d2db6f..81ed1d5f0dd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,7 +34,7 @@ repos: additional_dependencies: - iniconfig>=1.1.0 - attrs>=19.2.0 - - pluggy>=1.4.0 + - pluggy>=1.5.0 - packaging - tomli - types-pkg_resources diff --git a/changelog/12069.deprecation.rst b/changelog/12069.deprecation.rst new file mode 100644 index 00000000000..c8798b5ff25 --- /dev/null +++ b/changelog/12069.deprecation.rst @@ -0,0 +1,12 @@ +A deprecation warning is now raised when implementations of one of the following hooks request a deprecated ``py.path.local`` parameter instead of the ``pathlib.Path`` parameter which replaced it: + +- :hook:`pytest_ignore_collect` - the ``path`` parameter - use ``collection_path`` instead. +- :hook:`pytest_collect_file` - the ``path`` parameter - use ``file_path`` instead. +- :hook:`pytest_pycollect_makemodule` - the ``path`` parameter - use ``module_path`` instead. +- :hook:`pytest_report_header` - the ``startdir`` parameter - use ``start_path`` instead. +- :hook:`pytest_report_collectionfinish` - the ``startdir`` parameter - use ``start_path`` instead. + +The replacement parameters are available since pytest 7.0.0. +The old parameters will be removed in pytest 9.0.0. + +See :ref:`legacy-path-hooks-deprecated` for more details. diff --git a/changelog/12069.trivial.rst b/changelog/12069.trivial.rst new file mode 100644 index 00000000000..8eb9b0c464a --- /dev/null +++ b/changelog/12069.trivial.rst @@ -0,0 +1 @@ +``pluggy>=1.5.0`` is now required. diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 52415740470..974988c8cf4 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -1,5 +1,5 @@ pallets-sphinx-themes -pluggy>=1.2.0 +pluggy>=1.5.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 sphinx>=7 diff --git a/pyproject.toml b/pyproject.toml index 4d4b522870c..43efacf09f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,7 @@ dependencies = [ 'exceptiongroup>=1.0.0rc8; python_version < "3.11"', "iniconfig", "packaging", - "pluggy<2.0,>=1.4", + "pluggy<2.0,>=1.5", 'tomli>=1; python_version < "3.11"', ] [project.optional-dependencies] diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index db55bd82d04..acfe7eb9587 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -15,6 +15,8 @@ from pluggy import HookspecMarker +from .deprecated import HOOK_LEGACY_PATH_ARG + if TYPE_CHECKING: import pdb @@ -297,7 +299,14 @@ def pytest_collection_finish(session: "Session") -> None: """ -@hookspec(firstresult=True) +@hookspec( + firstresult=True, + warn_on_impl_args={ + "path": HOOK_LEGACY_PATH_ARG.format( + pylib_path_arg="path", pathlib_path_arg="collection_path" + ), + }, +) def pytest_ignore_collect( collection_path: Path, path: "LEGACY_PATH", config: "Config" ) -> Optional[bool]: @@ -356,6 +365,13 @@ def pytest_collect_directory(path: Path, parent: "Collector") -> "Optional[Colle """ +@hookspec( + warn_on_impl_args={ + "path": HOOK_LEGACY_PATH_ARG.format( + pylib_path_arg="path", pathlib_path_arg="file_path" + ), + }, +) def pytest_collect_file( file_path: Path, path: "LEGACY_PATH", parent: "Collector" ) -> "Optional[Collector]": @@ -468,7 +484,14 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor # ------------------------------------------------------------------------- -@hookspec(firstresult=True) +@hookspec( + firstresult=True, + warn_on_impl_args={ + "path": HOOK_LEGACY_PATH_ARG.format( + pylib_path_arg="path", pathlib_path_arg="module_path" + ), + }, +) def pytest_pycollect_makemodule( module_path: Path, path: "LEGACY_PATH", parent ) -> Optional["Module"]: @@ -994,6 +1017,13 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No # ------------------------------------------------------------------------- +@hookspec( + warn_on_impl_args={ + "startdir": HOOK_LEGACY_PATH_ARG.format( + pylib_path_arg="startdir", pathlib_path_arg="start_path" + ), + }, +) def pytest_report_header( # type:ignore[empty-body] config: "Config", start_path: Path, startdir: "LEGACY_PATH" ) -> Union[str, List[str]]: @@ -1022,6 +1052,13 @@ def pytest_report_header( # type:ignore[empty-body] """ +@hookspec( + warn_on_impl_args={ + "startdir": HOOK_LEGACY_PATH_ARG.format( + pylib_path_arg="startdir", pathlib_path_arg="start_path" + ), + }, +) def pytest_report_collectionfinish( # type:ignore[empty-body] config: "Config", start_path: Path, diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 2be4d6dfc47..9e83a49d554 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -121,6 +121,32 @@ def test_hookproxy_warnings_for_pathlib(tmp_path, hooktype, request): ) +def test_hookimpl_warnings_for_pathlib() -> None: + class Plugin: + def pytest_ignore_collect(self, path: object) -> None: + raise NotImplementedError() + + def pytest_collect_file(self, path: object) -> None: + raise NotImplementedError() + + def pytest_pycollect_makemodule(self, path: object) -> None: + raise NotImplementedError() + + def pytest_report_header(self, startdir: object) -> str: + raise NotImplementedError() + + def pytest_report_collectionfinish(self, startdir: object) -> str: + raise NotImplementedError() + + pm = pytest.PytestPluginManager() + with pytest.warns( + pytest.PytestRemovedIn9Warning, + match=r"py\.path\.local.* argument is deprecated", + ) as wc: + pm.register(Plugin()) + assert len(wc.list) == 5 + + def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: mod = pytester.getmodulecol("") From 63d985c6d3e61f02a0774aef26df63027e8b4d67 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 21 Apr 2024 10:57:36 -0300 Subject: [PATCH 0598/1271] [automated] Update plugin list (#12230) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 130 ++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 45 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 911a6bf7bae..e1d1e3ec24a 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.0.0 :pypi:`pytest-chunks` Run only a chunk of your test suite Jul 05, 2022 N/A pytest (>=6.0.0) @@ -230,6 +231,7 @@ This list contains 1443 plugins. :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Apr 19, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) @@ -274,7 +276,7 @@ This list contains 1443 plugins. :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Apr 15, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 @@ -299,8 +301,9 @@ This list contains 1443 plugins. :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A + :pypi:`pytest-dashboard` Apr 18, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 10, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 19, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -465,7 +468,7 @@ This list contains 1443 plugins. :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' - :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Jan 24, 2024 4 - Beta pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Apr 20, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 :pypi:`pytest-exasol-itde` Feb 15, 2024 N/A pytest (>=7,<9) @@ -612,7 +615,7 @@ This list contains 1443 plugins. :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-henry` Aug 29, 2023 N/A N/A :pypi:`pytest-hidecaptured` Hide captured output May 04, 2018 4 - Beta pytest (>=2.8.5) - :pypi:`pytest-himark` A plugin that reads a config.json file in your test root directory, searches the 'markers' key, lists the markers declared as 'true' as enabled markers and automatically adds -m option to the command line with an OR on the enabled markers. Apr 07, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-himark` A plugin that will filter pytest's test collection using a json file. It will read a json file provided with a --json argument in pytest command line (or in pytest.ini), search the markers key and automatically add -m option to the command line for filtering out the tests marked with disabled markers. Apr 14, 2024 4 - Beta pytest>=6.2.0 :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 Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) @@ -621,7 +624,7 @@ This list contains 1443 plugins. :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 13, 2024 3 - Alpha pytest==8.1.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A - :pypi:`pytest-hot-reloading` Jan 06, 2024 N/A N/A + :pypi:`pytest-hot-reloading` Apr 18, 2024 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. Feb 09, 2024 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) @@ -666,11 +669,11 @@ This list contains 1443 plugins. :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A - :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 09, 2024 N/A pytest<9.0.0,>=8.1.1 + :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 14, 2024 N/A pytest<9.0.0,>=8.1.1 :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. Dec 13, 2023 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Feb 20, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Apr 15, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest @@ -710,7 +713,7 @@ This list contains 1443 plugins. :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-jtr` pytest plugin supporting json test report output Nov 29, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-jtr` pytest plugin supporting json test report output Apr 15, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest @@ -794,7 +797,7 @@ This list contains 1443 plugins. :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Feb 15, 2024 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A - :pypi:`pytest-memray` A simple plugin to use with pytest Aug 23, 2023 N/A pytest>=7.2 + :pypi:`pytest-memray` A simple plugin to use with pytest Apr 18, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) @@ -806,7 +809,7 @@ This list contains 1443 plugins. :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Jan 04, 2024 N/A pytest >=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Apr 15, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Mar 07, 2024 N/A pytest >=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A @@ -855,6 +858,7 @@ This list contains 1443 plugins. :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) + :pypi:`pytest-neos` Pytest plugin for neos Apr 15, 2024 1 - Planning N/A :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Mar 07, 2024 N/A pytest <7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest @@ -1152,7 +1156,7 @@ This list contains 1443 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 11, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 14, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1161,7 +1165,7 @@ This list contains 1443 plugins. :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 Feb 01, 2024 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. Apr 11, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 14, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1228,7 +1232,7 @@ This list contains 1443 plugins. :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. Apr 10, 2024 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 Apr 01, 2024 4 - Beta pytest>=8.0.0 + :pypi:`pytest-sphinx` Doctest plugin for pytest with support for Sphinx-specific doctest-directives Apr 13, 2024 4 - Beta pytest>=8.1.1 :pypi:`pytest-spiratest` Exports unit tests as test runs in Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Feb 01, 2024 6 - Mature pytest >=8.0.0 @@ -1237,7 +1241,7 @@ This list contains 1443 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 Jan 12, 2024 N/A pytest (>5.4.0,<8) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Apr 19, 2024 N/A pytest (>5.4.0,<8) :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 26, 2024 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 @@ -1359,6 +1363,7 @@ This list contains 1443 plugins. :pypi:`pytest-tomato` Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-toolbelt` This is just a collection of utilities for pytest, but don't really belong in pytest proper. Aug 12, 2019 3 - Alpha N/A :pypi:`pytest-toolbox` Numerous useful plugins for pytest. Apr 07, 2018 N/A pytest (>=3.5.0) + :pypi:`pytest-toolkit` Useful utils for testing Apr 13, 2024 N/A N/A :pypi:`pytest-tools` Pytest tools Oct 21, 2022 4 - Beta N/A :pypi:`pytest-tornado` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Jun 17, 2020 5 - Production/Stable pytest (>=3.6) :pypi:`pytest-tornado5` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Nov 16, 2018 5 - Production/Stable pytest (>=3.6) @@ -1440,11 +1445,11 @@ This list contains 1443 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 Mar 18, 2024 5 - Production/Stable pytest >=7.0.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` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Apr 19, 2024 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) - :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 11, 2024 4 - Beta pytest>7.3.2 + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A @@ -1459,7 +1464,7 @@ This list contains 1443 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 Apr 07, 2024 N/A pytest>=7.4.0 + :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Apr 19, 2024 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) @@ -2259,6 +2264,13 @@ This list contains 1443 plugins. Pytest plugin to run your tests with beartype checking enabled. + :pypi:`pytest-bec-e2e` + *last release*: Apr 19, 2024, + *status*: 3 - Alpha, + *requires*: pytest + + BEC pytest plugin for end-to-end tests + :pypi:`pytest-beds` *last release*: Jun 07, 2016, *status*: 4 - Beta, @@ -2764,9 +2776,9 @@ This list contains 1443 plugins. A package to prevent Dependency Confusion attacks against Yandex. :pypi:`pytest-ch-framework` - *last release*: Mar 13, 2024, + *last release*: Apr 17, 2024, *status*: N/A, - *requires*: pytest ==8.0.1 + *requires*: pytest==8.0.1 My pytest framework @@ -2854,6 +2866,13 @@ This list contains 1443 plugins. A cleanup plugin for pytest + :pypi:`pytest-clerk` + *last release*: Apr 19, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.0.0 + + A set of pytest fixtures to help with integration testing with Clerk. + :pypi:`pytest-click` *last release*: Feb 11, 2022, *status*: 5 - Production/Stable, @@ -3163,9 +3182,9 @@ This list contains 1443 plugins. Coverage dynamic context support for PyTest, including sub-processes :pypi:`pytest-coveragemarkers` - *last release*: Nov 29, 2022, + *last release*: Apr 15, 2024, *status*: N/A, - *requires*: pytest (>=7.1.2,<8.0.0) + *requires*: pytest<8.0.0,>=7.1.2 Using pytest markers to track functional coverage and filtering of tests @@ -3337,6 +3356,13 @@ This list contains 1443 plugins. pytest fixtures to run dash applications. + :pypi:`pytest-dashboard` + *last release*: Apr 18, 2024, + *status*: N/A, + *requires*: pytest<8.0.0,>=7.4.3 + + + :pypi:`pytest-data` *last release*: Nov 01, 2016, *status*: 5 - Production/Stable, @@ -3345,7 +3371,7 @@ This list contains 1443 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Apr 10, 2024, + *last release*: Apr 19, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4500,9 +4526,9 @@ This list contains 1443 plugins. Applies eventlet monkey-patch as a pytest plugin. :pypi:`pytest-evm` - *last release*: Jan 24, 2024, + *last release*: Apr 20, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.4.3,<8.0.0) + *requires*: pytest<9.0.0,>=8.1.1 The testing package containing tools to test Web3-based projects @@ -5529,11 +5555,11 @@ This list contains 1443 plugins. Hide captured output :pypi:`pytest-himark` - *last release*: Apr 07, 2024, + *last release*: Apr 14, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 - A plugin that reads a config.json file in your test root directory, searches the 'markers' key, lists the markers declared as 'true' as enabled markers and automatically adds -m option to the command line with an OR on the enabled markers. + A plugin that will filter pytest's test collection using a json file. It will read a json file provided with a --json argument in pytest command line (or in pytest.ini), search the markers key and automatically add -m option to the command line for filtering out the tests marked with disabled markers. :pypi:`pytest-historic` *last release*: Apr 08, 2020, @@ -5592,7 +5618,7 @@ This list contains 1443 plugins. Report on tests that honor constraints, and guard against regressions :pypi:`pytest-hot-reloading` - *last release*: Jan 06, 2024, + *last release*: Apr 18, 2024, *status*: N/A, *requires*: N/A @@ -5907,7 +5933,7 @@ This list contains 1443 plugins. Reuse pytest.ini to store env variables :pypi:`pytest-initry` - *last release*: Apr 09, 2024, + *last release*: Apr 14, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.1.1 @@ -5935,7 +5961,7 @@ This list contains 1443 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Feb 20, 2024, + *last release*: Apr 15, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6215,9 +6241,9 @@ This list contains 1443 plugins. A pytest plugin to perform JSONSchema validations :pypi:`pytest-jtr` - *last release*: Nov 29, 2022, + *last release*: Apr 15, 2024, *status*: N/A, - *requires*: pytest (>=7.1.2,<8.0.0) + *requires*: pytest<8.0.0,>=7.1.2 pytest plugin supporting json test report output @@ -6803,7 +6829,7 @@ This list contains 1443 plugins. Estimates memory consumption of test functions :pypi:`pytest-memray` - *last release*: Aug 23, 2023, + *last release*: Apr 18, 2024, *status*: N/A, *requires*: pytest>=7.2 @@ -6887,9 +6913,9 @@ This list contains 1443 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: Jan 04, 2024, + *last release*: Apr 15, 2024, *status*: N/A, - *requires*: pytest >=5.0.0 + *requires*: pytest>=5.0.0 A pytest plugin for mocking Minio S3 interactions @@ -7229,6 +7255,13 @@ This list contains 1443 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. + :pypi:`pytest-neos` + *last release*: Apr 15, 2024, + *status*: 1 - Planning, + *requires*: N/A + + Pytest plugin for neos + :pypi:`pytest-netdut` *last release*: Mar 07, 2024, *status*: N/A, @@ -9309,7 +9342,7 @@ This list contains 1443 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Apr 11, 2024, + *last release*: Apr 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9372,7 +9405,7 @@ This list contains 1443 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Apr 11, 2024, + *last release*: Apr 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9841,9 +9874,9 @@ This list contains 1443 plugins. Modern benchmarking library for python with pytest integration. :pypi:`pytest-sphinx` - *last release*: Apr 01, 2024, + *last release*: Apr 13, 2024, *status*: 4 - Beta, - *requires*: pytest>=8.0.0 + *requires*: pytest>=8.1.1 Doctest plugin for pytest with support for Sphinx-specific doctest-directives @@ -9904,7 +9937,7 @@ This list contains 1443 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jan 12, 2024, + *last release*: Apr 19, 2024, *status*: N/A, *requires*: pytest (>5.4.0,<8) @@ -10757,6 +10790,13 @@ This list contains 1443 plugins. Numerous useful plugins for pytest. + :pypi:`pytest-toolkit` + *last release*: Apr 13, 2024, + *status*: N/A, + *requires*: N/A + + Useful utils for testing + :pypi:`pytest-tools` *last release*: Oct 21, 2022, *status*: 4 - Beta, @@ -11325,7 +11365,7 @@ This list contains 1443 plugins. A pytest plugin for configuring workflow/pipeline tests using YAML files :pypi:`pytest-xdist` - *last release*: Nov 21, 2023, + *last release*: Apr 19, 2024, *status*: 5 - Production/Stable, *requires*: pytest >=6.2.0 @@ -11353,9 +11393,9 @@ This list contains 1443 plugins. pytest plugin helps to reproduce failures for particular xdist node :pypi:`pytest-xdist-worker-stats` - *last release*: Apr 11, 2024, + *last release*: Apr 16, 2024, *status*: 4 - Beta, - *requires*: pytest>7.3.2 + *requires*: pytest>=7.0.0 A pytest plugin to list worker statistics after a xdist run. @@ -11458,7 +11498,7 @@ This list contains 1443 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Apr 07, 2024, + *last release*: Apr 19, 2024, *status*: N/A, *requires*: pytest>=7.4.0 From 1d322ffb48e62dbe199a8edf875e2ff1f9dc4cae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 11:54:48 +0200 Subject: [PATCH 0599/1271] build(deps): Bump peter-evans/create-pull-request from 6.0.3 to 6.0.4 (#12233) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.0.3 to 6.0.4. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/c55203cfde3e5c11a452d352b4393e68b85b4533...9153d834b60caba6d51c9b9510b087acf9f33f83) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index fd3443d8e9e..6943e207608 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -46,7 +46,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request - uses: peter-evans/create-pull-request@c55203cfde3e5c11a452d352b4393e68b85b4533 + uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From a830a3e98df0e1c020c48fde3138a112534cea96 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 22 Apr 2024 19:52:25 +0200 Subject: [PATCH 0600/1271] Update events/trainings (#12236) --- doc/en/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 08a1468986a..67501c0530c 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -5,7 +5,8 @@ - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training): * **June 11th to 13th 2024**, Remote * **March 4th to 6th 2025**, Leipzig, Germany / Remote - - `pytest development sprint `_, June 2024 (`date poll `_) + - `pytest development sprint `_, **June 17th -- 22nd 2024** + - pytest tips and tricks for a better testsuite, `Europython 2024 `_, **July 8th -- 14th 2024** (3h), Prague Also see :doc:`previous talks and blogposts `. From 5cffef7f07a1007681b671304e4ee69864c13940 Mon Sep 17 00:00:00 2001 From: poulami-sau <109125687+poulami-sau@users.noreply.github.com> Date: Tue, 23 Apr 2024 04:45:33 -0400 Subject: [PATCH 0601/1271] Fixed Bug Regarding Attribute Error in pytest.approx For Types Implicitly Convertible to Numpy Arrays (#12232) * added test case in testing/python/approx.py based on test case provided by reporter in issue #12114 * test cases pass for pytest testing/python/approx.py * expanded the type annotation to include objects which may cast to a array and renamed other_side to other_side_as_array and asserted that it is not none --- AUTHORS | 1 + changelog/12114.bugfix.rst | 1 + src/_pytest/python_api.py | 14 +++++++++----- testing/python/approx.py | 17 +++++++++++++++++ 4 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 changelog/12114.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 7c35a615232..d7148acfc51 100644 --- a/AUTHORS +++ b/AUTHORS @@ -321,6 +321,7 @@ Pierre Sassoulas Pieter Mulder Piotr Banaszkiewicz Piotr Helm +Poulami Sau Prakhar Gurunani Prashant Anand Prashant Sharma diff --git a/changelog/12114.bugfix.rst b/changelog/12114.bugfix.rst new file mode 100644 index 00000000000..79849692505 --- /dev/null +++ b/changelog/12114.bugfix.rst @@ -0,0 +1 @@ +Fixed attribute error in pytest.approx for types implicitly convertible to numpy arrays by converting other_side to a numpy array so that np_array_shape != other_side.shape can be properly checked. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 0ba86e816d3..7d89fdd809e 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -142,7 +142,7 @@ def __repr__(self) -> str: ) return f"approx({list_scalars!r})" - def _repr_compare(self, other_side: "ndarray") -> List[str]: + def _repr_compare(self, other_side: Union["ndarray", List[Any]]) -> List[str]: import itertools import math @@ -163,10 +163,14 @@ def get_value_from_nested_list( self._approx_scalar, self.expected.tolist() ) - if np_array_shape != other_side.shape: + # convert other_side to numpy array to ensure shape attribute is available + other_side_as_array = _as_numpy_array(other_side) + assert other_side_as_array is not None + + if np_array_shape != other_side_as_array.shape: return [ "Impossible to compare arrays with different shapes.", - f"Shapes: {np_array_shape} and {other_side.shape}", + f"Shapes: {np_array_shape} and {other_side_as_array.shape}", ] number_of_elements = self.expected.size @@ -175,7 +179,7 @@ def get_value_from_nested_list( different_ids = [] for index in itertools.product(*(range(i) for i in np_array_shape)): approx_value = get_value_from_nested_list(approx_side_as_seq, index) - other_value = get_value_from_nested_list(other_side, index) + other_value = get_value_from_nested_list(other_side_as_array, index) if approx_value != other_value: abs_diff = abs(approx_value.expected - other_value) max_abs_diff = max(max_abs_diff, abs_diff) @@ -188,7 +192,7 @@ def get_value_from_nested_list( message_data = [ ( str(index), - str(get_value_from_nested_list(other_side, index)), + str(get_value_from_nested_list(other_side_as_array, index)), str(get_value_from_nested_list(approx_side_as_seq, index)), ) for index in different_ids diff --git a/testing/python/approx.py b/testing/python/approx.py index 079667bd093..968e8828512 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -763,6 +763,23 @@ def test_numpy_array_wrong_shape(self): assert a12 != approx(a21) assert a21 != approx(a12) + def test_numpy_array_implicit_conversion(self): + np = pytest.importorskip("numpy") + + class ImplicitArray: + """Type which is implicitly convertible to a numpy array.""" + + def __init__(self, vals): + self.vals = vals + + def __array__(self, dtype=None, copy=None): + return np.array(self.vals) + + vec1 = ImplicitArray([1.0, 2.0, 3.0]) + vec2 = ImplicitArray([1.0, 2.0, 4.0]) + # see issue #12114 for test case + assert vec1 != approx(vec2) + def test_numpy_array_protocol(self): """ array-like objects such as tensorflow's DeviceArray are handled like ndarray. From fafab1dbfd2414c2282b558f0c7af9a7ad0318ab Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:59:12 -0300 Subject: [PATCH 0602/1271] [pre-commit.ci] pre-commit autoupdate (#12238) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.3.7 → v0.4.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.3.7...v0.4.1) - [github.com/tox-dev/pyproject-fmt: 1.7.0 → 1.8.0](https://github.com/tox-dev/pyproject-fmt/compare/1.7.0...1.8.0) * noqa a test --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 4 ++-- testing/io/test_saferepr.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 81ed1d5f0dd..a80edd28cdc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.3.7" + rev: "v0.4.1" hooks: - id: ruff args: ["--fix"] @@ -43,7 +43,7 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "1.7.0" + rev: "1.8.0" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index eefa3f72b88..5d270f1756c 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -79,7 +79,7 @@ def raise_exc(self, *args): raise self.exc_type(*args) raise self.exc_type - def __str__(self): + def __str__(self): # noqa: PLE0307 self.raise_exc("__str__") def __repr__(self): From 4eb8b6d525b7704432f378cfa45ab9ec02bf4e39 Mon Sep 17 00:00:00 2001 From: Shekhar verma Date: Fri, 26 Apr 2024 13:18:57 +0530 Subject: [PATCH 0603/1271] Changed importError to ModuleNotFoundError (#12220) * Changed importError to ModuleNotFoundError * added testing for importorskip * added exc_types parameter in importorskip * Added warning and Test Cases * Improve tests and docs * Improve deprecation docs * Change exc_type to kw only * Apply suggestions from code review Co-authored-by: Florian Bruhin * Fix check --------- Co-authored-by: Bruno Oliveira Co-authored-by: Florian Bruhin --- changelog/11523.improvement.rst | 5 +++ doc/en/deprecations.rst | 35 +++++++++++++++++ src/_pytest/outcomes.py | 63 ++++++++++++++++++++++++++++-- testing/test_runner.py | 68 +++++++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 changelog/11523.improvement.rst diff --git a/changelog/11523.improvement.rst b/changelog/11523.improvement.rst new file mode 100644 index 00000000000..f7d8ff89df6 --- /dev/null +++ b/changelog/11523.improvement.rst @@ -0,0 +1,5 @@ +:func:`pytest.importorskip` will now issue a warning if the module could be found, but raised :class:`ImportError` instead of :class:`ModuleNotFoundError`. + +The warning can be suppressed by passing ``exc_type=ImportError`` to :func:`pytest.importorskip`. + +See :ref:`import-or-skip-import-error` for details. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index cd6d1e60aef..5ac93f15144 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -19,6 +19,41 @@ Below is a complete list of all pytest features which are considered deprecated. :class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `. +.. _import-or-skip-import-error: + +``pytest.importorskip`` default behavior regarding :class:`ImportError` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 8.2 + +Traditionally :func:`pytest.importorskip` will capture :class:`ImportError`, with the original intent being to skip +tests where a dependent module is not installed, for example testing with different dependencies. + +However some packages might be installed in the system, but are not importable due to +some other issue, for example, a compilation error or a broken installation. In those cases :func:`pytest.importorskip` +would still silently skip the test, but more often than not users would like to see the unexpected +error so the underlying issue can be fixed. + +In ``8.2`` the ``exc_type`` parameter has been added, giving users the ability of passing :class:`ModuleNotFoundError` +to skip tests only if the module cannot really be found, and not because of some other error. + +Catching only :class:`ModuleNotFoundError` by default (and letting other errors propagate) would be the best solution, +however for backward compatibility, pytest will keep the existing behavior but raise an warning if: + +1. The captured exception is of type :class:`ImportError`, and: +2. The user does not pass ``exc_type`` explicitly. + +If the import attempt raises :class:`ModuleNotFoundError` (the usual case), then the module is skipped and no +warning is emitted. + +This way, the usual cases will keep working the same way, while unexpected errors will now issue a warning, with +users being able to supress the warning by passing ``exc_type=ImportError`` explicitly. + +In ``9.0``, the warning will turn into an error, and in ``9.1`` :func:`pytest.importorskip` will only capture +:class:`ModuleNotFoundError` by default and no warnings will be issued anymore -- but users can still capture +:class:`ImportError` by passing it to ``exc_type``. + + .. _node-ctor-fspath-deprecation: ``fspath`` argument for Node constructors replaced with ``pathlib.Path`` diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index e2a816f5850..76d94accd0d 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -11,6 +11,8 @@ from typing import Type from typing import TypeVar +from .warning_types import PytestDeprecationWarning + class OutcomeException(BaseException): """OutcomeException and its subclass instances indicate and contain info @@ -192,7 +194,11 @@ def xfail(reason: str = "") -> NoReturn: def importorskip( - modname: str, minversion: Optional[str] = None, reason: Optional[str] = None + modname: str, + minversion: Optional[str] = None, + reason: Optional[str] = None, + *, + exc_type: Optional[Type[ImportError]] = None, ) -> Any: """Import and return the requested module ``modname``, or skip the current test if the module cannot be imported. @@ -205,6 +211,18 @@ def importorskip( :param reason: If given, this reason is shown as the message when the module cannot be imported. + :param exc_type: + The exception that should be captured in order to skip modules. + Must be :py:class:`ImportError` or a subclass. + + If the module can be imported but raises :class:`ImportError`, pytest will + issue a warning to the user, as often users expect the module not to be + found (which would raise :class:`ModuleNotFoundError` instead). + + This warning can be suppressed by passing ``exc_type=ImportError`` explicitly. + + See :ref:`import-or-skip-import-error` for details. + :returns: The imported module. This should be assigned to its canonical name. @@ -212,23 +230,62 @@ def importorskip( Example:: docutils = pytest.importorskip("docutils") + + .. versionadded:: 8.2 + + The ``exc_type`` parameter. """ import warnings __tracebackhide__ = True compile(modname, "", "eval") # to catch syntaxerrors + # Until pytest 9.1, we will warn the user if we catch ImportError (instead of ModuleNotFoundError), + # as this might be hiding an installation/environment problem, which is not usually what is intended + # when using importorskip() (#11523). + # In 9.1, to keep the function signature compatible, we just change the code below to: + # 1. Use `exc_type = ModuleNotFoundError` if `exc_type` is not given. + # 2. Remove `warn_on_import` and the warning handling. + if exc_type is None: + exc_type = ImportError + warn_on_import_error = True + else: + warn_on_import_error = False + + skipped: Optional[Skipped] = None + warning: Optional[Warning] = None + with warnings.catch_warnings(): # Make sure to ignore ImportWarnings that might happen because # of existing directories with the same name we're trying to # import but without a __init__.py file. warnings.simplefilter("ignore") + try: __import__(modname) - except ImportError as exc: + except exc_type as exc: + # Do not raise or issue warnings inside the catch_warnings() block. if reason is None: reason = f"could not import {modname!r}: {exc}" - raise Skipped(reason, allow_module_level=True) from None + skipped = Skipped(reason, allow_module_level=True) + + if warn_on_import_error and not isinstance(exc, ModuleNotFoundError): + lines = [ + "", + f"Module '{modname}' was found, but when imported by pytest it raised:", + f" {exc!r}", + "In pytest 9.1 this warning will become an error by default.", + "You can fix the underlying problem, or alternatively overwrite this behavior and silence this " + "warning by passing exc_type=ImportError explicitly.", + "See https://docs.pytest.org/en/stable/deprecations.html#pytest-importorskip-default-behavior-regarding-importerror", + ] + warning = PytestDeprecationWarning("\n".join(lines)) + + if warning: + warnings.warn(warning, stacklevel=2) + if skipped: + raise skipped + mod = sys.modules[modname] if minversion is None: return mod diff --git a/testing/test_runner.py b/testing/test_runner.py index ffac0f2d92b..6e034e94532 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -9,6 +9,7 @@ from typing import List from typing import Tuple from typing import Type +import warnings from _pytest import outcomes from _pytest import reports @@ -762,6 +763,73 @@ def test_importorskip_imports_last_module_part() -> None: assert os.path == ospath +class TestImportOrSkipExcType: + """Tests for #11523.""" + + def test_no_warning(self) -> None: + # An attempt on a module which does not exist will raise ModuleNotFoundError, so it will + # be skipped normally and no warning will be issued. + with warnings.catch_warnings(record=True) as captured: + warnings.simplefilter("always") + + with pytest.raises(pytest.skip.Exception): + pytest.importorskip("TestImportOrSkipExcType_test_no_warning") + + assert captured == [] + + def test_import_error_with_warning(self, pytester: Pytester) -> None: + # Create a module which exists and can be imported, however it raises + # ImportError due to some other problem. In this case we will issue a warning + # about the future behavior change. + fn = pytester.makepyfile("raise ImportError('some specific problem')") + pytester.syspathinsert() + + with warnings.catch_warnings(record=True) as captured: + warnings.simplefilter("always") + + with pytest.raises(pytest.skip.Exception): + pytest.importorskip(fn.stem) + + [warning] = captured + assert warning.category is pytest.PytestDeprecationWarning + + def test_import_error_suppress_warning(self, pytester: Pytester) -> None: + # Same as test_import_error_with_warning, but we can suppress the warning + # by passing ImportError as exc_type. + fn = pytester.makepyfile("raise ImportError('some specific problem')") + pytester.syspathinsert() + + with warnings.catch_warnings(record=True) as captured: + warnings.simplefilter("always") + + with pytest.raises(pytest.skip.Exception): + pytest.importorskip(fn.stem, exc_type=ImportError) + + assert captured == [] + + def test_warning_integration(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + def test_foo(): + pytest.importorskip("warning_integration_module") + """ + ) + pytester.makepyfile( + warning_integration_module=""" + raise ImportError("required library foobar not compiled properly") + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*Module 'warning_integration_module' was found, but when imported by pytest it raised:", + "* ImportError('required library foobar not compiled properly')", + "*1 skipped, 1 warning*", + ] + ) + + def test_importorskip_dev_module(monkeypatch) -> None: try: mod = types.ModuleType("mockmodule") From 93c2cdf6d6c9e0192962e0fd7802379beb45da41 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 26 Apr 2024 15:25:44 -0300 Subject: [PATCH 0604/1271] cherry-pick release-8.1.2 (#12252) (cherry picked from commit 7df3dbc545b4b4deb2148683cd02f774b2d19fd8) --- changelog/12114.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.1.2.rst | 18 ++++++++++++++++++ doc/en/changelog.rst | 9 +++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 8 files changed, 35 insertions(+), 8 deletions(-) delete mode 100644 changelog/12114.bugfix.rst create mode 100644 doc/en/announce/release-8.1.2.rst diff --git a/changelog/12114.bugfix.rst b/changelog/12114.bugfix.rst deleted file mode 100644 index 79849692505..00000000000 --- a/changelog/12114.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed attribute error in pytest.approx for types implicitly convertible to numpy arrays by converting other_side to a numpy array so that np_array_shape != other_side.shape can be properly checked. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 40eccdd748a..bb39eb7e6a1 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.1.2 release-8.1.1 release-8.1.0 release-8.0.2 diff --git a/doc/en/announce/release-8.1.2.rst b/doc/en/announce/release-8.1.2.rst new file mode 100644 index 00000000000..19e41e0f7c5 --- /dev/null +++ b/doc/en/announce/release-8.1.2.rst @@ -0,0 +1,18 @@ +pytest-8.1.2 +======================================= + +pytest 8.1.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index bea4257af0f..fb316e706ba 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,15 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.1.2 (2024-04-26) +========================= + +Bug Fixes +--------- + +- `#12114 `_: Fixed error in :func:`pytest.approx` when used with `numpy` arrays and comparing with other types. + + pytest 8.1.1 (2024-03-08) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index ad17ce0b430..672c7c4457d 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 68737267ef4..c01e685f3f4 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 40632645d16..e96eabbc5e7 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.1.1 + pytest 8.1.2 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 795d2caf50d..ba416ccbc23 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From 1a332802ff8afde3c899df46901f00bde523e4e3 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 27 Apr 2024 01:11:21 +0300 Subject: [PATCH 0605/1271] Avoid slicing `sys.version_info` in version conditionals It is unnecessary, and some static analyzers don't handle it. --- src/_pytest/_code/code.py | 4 ++-- src/_pytest/config/argparsing.py | 2 +- src/_pytest/fixtures.py | 2 +- src/_pytest/runner.py | 2 +- testing/code/test_excinfo.py | 2 +- testing/test_runner.py | 2 +- testing/test_skipping.py | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 3b4a62a4fa0..c65ce79f7e5 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -52,7 +52,7 @@ from _pytest.pathlib import bestrelpath -if sys.version_info[:2] < (3, 11): +if sys.version_info < (3, 11): from exceptiongroup import BaseExceptionGroup _TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] @@ -703,7 +703,7 @@ def _stringify_exception(self, exc: BaseException) -> str: # Workaround for https://github.com/python/cpython/issues/98778 on # Python <= 3.9, and some 3.10 and 3.11 patch versions. HTTPError = getattr(sys.modules.get("urllib.error", None), "HTTPError", ()) - if sys.version_info[:2] <= (3, 11) and isinstance(exc, HTTPError): + if sys.version_info < (3, 12) and isinstance(exc, HTTPError): notes = [] else: raise diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 95dc28d4a16..9006351af72 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -448,7 +448,7 @@ def parse_args( # type: ignore getattr(parsed, FILE_OR_DIR).extend(unrecognized) return parsed - if sys.version_info[:2] < (3, 9): # pragma: no cover + if sys.version_info < (3, 9): # pragma: no cover # Backport of https://github.com/python/cpython/pull/14316 so we can # disable long --argument abbreviations without breaking short flags. def _parse_optional( diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 5303948c4d5..656160ff7dc 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -69,7 +69,7 @@ from _pytest.scope import Scope -if sys.version_info[:2] < (3, 11): +if sys.version_info < (3, 11): from exceptiongroup import BaseExceptionGroup diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 3f706b927c8..9bc544ea742 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -39,7 +39,7 @@ from _pytest.outcomes import TEST_OUTCOME -if sys.version_info[:2] < (3, 11): +if sys.version_info < (3, 11): from exceptiongroup import BaseExceptionGroup if TYPE_CHECKING: diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 419c11abcc0..dd4bd22c8b8 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -28,7 +28,7 @@ if TYPE_CHECKING: from _pytest._code.code import _TracebackStyle -if sys.version_info[:2] < (3, 11): +if sys.version_info < (3, 11): from exceptiongroup import ExceptionGroup diff --git a/testing/test_runner.py b/testing/test_runner.py index 6e034e94532..8b41ec28a38 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -23,7 +23,7 @@ import pytest -if sys.version_info[:2] < (3, 11): +if sys.version_info < (3, 11): from exceptiongroup import ExceptionGroup diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 3f1c83f5bbe..a1511b26d1c 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -1146,7 +1146,7 @@ def test_func(): if pypy_version_info is not None and pypy_version_info < (6,): markline = markline[1:] - if sys.version_info[:2] >= (3, 10): + if sys.version_info >= (3, 10): expected = [ "*ERROR*test_nameerror*", "*asd*", From 80ca255d424da35f8a28216dc25170850779ff93 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 27 Apr 2024 11:03:52 +0300 Subject: [PATCH 0606/1271] pathlib: make `absolutepath` support `os.PathLike[str]` This slightly simplifies a bit of path. --- src/_pytest/nodes.py | 2 +- src/_pytest/pathlib.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 1b91bdb6e43..974d756a2be 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -765,7 +765,7 @@ def location(self) -> Tuple[str, Optional[int], str]: and lineno is a 0-based line number. """ location = self.reportinfo() - path = absolutepath(os.fspath(location[0])) + path = absolutepath(location[0]) relfspath = self.session._node_location_to_relpath(path) assert type(location[2]) is str return (relfspath, location[1], location[2]) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 190d9dd8ce6..e14c2acd328 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -924,13 +924,13 @@ def visit( yield from visit(entry.path, recurse) -def absolutepath(path: Union[Path, str]) -> Path: +def absolutepath(path: "Union[str, os.PathLike[str]]") -> Path: """Convert a path to an absolute path using os.path.abspath. Prefer this over Path.resolve() (see #6523). Prefer this over Path.absolute() (not public, doesn't normalize). """ - return Path(os.path.abspath(str(path))) + return Path(os.path.abspath(path)) def commonpath(path1: Path, path2: Path) -> Optional[Path]: From 530be285751143febe54b8974b234eed5eb8b079 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 14 Mar 2024 20:24:25 +0200 Subject: [PATCH 0607/1271] fixtures: use early return in `_get_active_fixturedef` --- src/_pytest/fixtures.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 656160ff7dc..17d6ddc7fe5 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -570,18 +570,21 @@ def _get_active_fixturedef( self, argname: str ) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]: fixturedef = self._fixture_defs.get(argname) - if fixturedef is None: - try: - fixturedef = self._getnextfixturedef(argname) - except FixtureLookupError: - if argname == "request": - cached_result = (self, [0], None) - return PseudoFixtureDef(cached_result, Scope.Function) - raise - self._compute_fixture_value(fixturedef) - self._fixture_defs[argname] = fixturedef - else: + if fixturedef is not None: self._check_scope(fixturedef, fixturedef._scope) + return fixturedef + + try: + fixturedef = self._getnextfixturedef(argname) + except FixtureLookupError: + if argname == "request": + cached_result = (self, [0], None) + return PseudoFixtureDef(cached_result, Scope.Function) + raise + + self._compute_fixture_value(fixturedef) + + self._fixture_defs[argname] = fixturedef return fixturedef def _get_fixturestack(self) -> List["FixtureDef[Any]"]: From d217d68cde0c34d619862f15c773ecc02ecdaabe Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 14 Mar 2024 20:29:33 +0200 Subject: [PATCH 0608/1271] fixtures: inline `_compute_fixture_value` --- src/_pytest/fixtures.py | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 17d6ddc7fe5..81fbf504f20 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -582,26 +582,7 @@ def _get_active_fixturedef( return PseudoFixtureDef(cached_result, Scope.Function) raise - self._compute_fixture_value(fixturedef) - - self._fixture_defs[argname] = fixturedef - return fixturedef - - def _get_fixturestack(self) -> List["FixtureDef[Any]"]: - values = [request._fixturedef for request in self._iter_chain()] - values.reverse() - return values - - def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: - """Create a SubRequest based on "self" and call the execute method - of the given FixtureDef object. - - If the FixtureDef has cached the result it will do nothing, otherwise it will - setup and run the fixture, cache the value, and schedule a finalizer for it. - """ - # prepare a subrequest object before calling fixture function - # (latter managed by fixturedef) - argname = fixturedef.argname + # Prepare a SubRequest object for calling the fixture. funcitem = self._pyfuncitem try: callspec = funcitem.callspec @@ -627,7 +608,7 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: ) fail(msg, pytrace=False) if has_params: - frame = inspect.stack()[3] + frame = inspect.stack()[2] frameinfo = inspect.getframeinfo(frame[0]) source_path = absolutepath(frameinfo.filename) source_lineno = frameinfo.lineno @@ -658,6 +639,14 @@ def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None: # Make sure the fixture value is cached, running it if it isn't fixturedef.execute(request=subrequest) + self._fixture_defs[argname] = fixturedef + return fixturedef + + def _get_fixturestack(self) -> List["FixtureDef[Any]"]: + values = [request._fixturedef for request in self._iter_chain()] + values.reverse() + return values + @final class TopRequest(FixtureRequest): From 3c77aec1dac0894ec4ca774b71ec91c85cf91dd1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Thu, 14 Mar 2024 20:33:13 +0200 Subject: [PATCH 0609/1271] fixtures: move "request" check early --- src/_pytest/fixtures.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 81fbf504f20..1ff4e173b0e 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -569,18 +569,18 @@ def _iter_chain(self) -> Iterator["SubRequest"]: def _get_active_fixturedef( self, argname: str ) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]: + if argname == "request": + cached_result = (self, [0], None) + return PseudoFixtureDef(cached_result, Scope.Function) + + # If we already finished computing a fixture by this name in this item, + # return it. fixturedef = self._fixture_defs.get(argname) if fixturedef is not None: self._check_scope(fixturedef, fixturedef._scope) return fixturedef - try: - fixturedef = self._getnextfixturedef(argname) - except FixtureLookupError: - if argname == "request": - cached_result = (self, [0], None) - return PseudoFixtureDef(cached_result, Scope.Function) - raise + fixturedef = self._getnextfixturedef(argname) # Prepare a SubRequest object for calling the fixture. funcitem = self._pyfuncitem From acf2971f46a9518b3552d48ea9541a1951c2b207 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 16 Mar 2024 23:56:11 +0200 Subject: [PATCH 0610/1271] fixtures: inline `_getnextfixturedef` into `_get_active_fixturedef` --- src/_pytest/fixtures.py | 70 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 1ff4e173b0e..fbce950ae44 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -410,41 +410,6 @@ def node(self): """Underlying collection node (depends on current request scope).""" raise NotImplementedError() - def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]": - fixturedefs = self._arg2fixturedefs.get(argname, None) - if fixturedefs is None: - # We arrive here because of a dynamic call to - # getfixturevalue(argname) usage which was naturally - # not known at parsing/collection time. - fixturedefs = self._fixturemanager.getfixturedefs(argname, self._pyfuncitem) - if fixturedefs is not None: - self._arg2fixturedefs[argname] = fixturedefs - # No fixtures defined with this name. - if fixturedefs is None: - raise FixtureLookupError(argname, self) - # The are no fixtures with this name applicable for the function. - if not fixturedefs: - raise FixtureLookupError(argname, self) - - # A fixture may override another fixture with the same name, e.g. a - # fixture in a module can override a fixture in a conftest, a fixture in - # a class can override a fixture in the module, and so on. - # An overriding fixture can request its own name (possibly indirectly); - # in this case it gets the value of the fixture it overrides, one level - # up. - # Check how many `argname`s deep we are, and take the next one. - # `fixturedefs` is sorted from furthest to closest, so use negative - # indexing to go in reverse. - index = -1 - for request in self._iter_chain(): - if request.fixturename == argname: - index -= 1 - # If already consumed all of the available levels, fail. - if -index > len(fixturedefs): - raise FixtureLookupError(argname, self) - - return fixturedefs[index] - @property def config(self) -> Config: """The pytest config object associated with this request.""" @@ -580,7 +545,40 @@ def _get_active_fixturedef( self._check_scope(fixturedef, fixturedef._scope) return fixturedef - fixturedef = self._getnextfixturedef(argname) + # Find the appropriate fixturedef. + fixturedefs = self._arg2fixturedefs.get(argname, None) + if fixturedefs is None: + # We arrive here because of a dynamic call to + # getfixturevalue(argname) which was naturally + # not known at parsing/collection time. + fixturedefs = self._fixturemanager.getfixturedefs(argname, self._pyfuncitem) + if fixturedefs is not None: + self._arg2fixturedefs[argname] = fixturedefs + # No fixtures defined with this name. + if fixturedefs is None: + raise FixtureLookupError(argname, self) + # The are no fixtures with this name applicable for the function. + if not fixturedefs: + raise FixtureLookupError(argname, self) + + # A fixture may override another fixture with the same name, e.g. a + # fixture in a module can override a fixture in a conftest, a fixture in + # a class can override a fixture in the module, and so on. + # An overriding fixture can request its own name (possibly indirectly); + # in this case it gets the value of the fixture it overrides, one level + # up. + # Check how many `argname`s deep we are, and take the next one. + # `fixturedefs` is sorted from furthest to closest, so use negative + # indexing to go in reverse. + index = -1 + for request in self._iter_chain(): + if request.fixturename == argname: + index -= 1 + # If already consumed all of the available levels, fail. + if -index > len(fixturedefs): + raise FixtureLookupError(argname, self) + + fixturedef = fixturedefs[index] # Prepare a SubRequest object for calling the fixture. funcitem = self._pyfuncitem From 2e8fb9f1401d727e20f004326752fd1922f9c601 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 17 Mar 2024 00:36:00 +0200 Subject: [PATCH 0611/1271] fixtures: extract a `_check_fixturedef` method This stuff is less interesting when reading `_get_active_fixturedef`. --- src/_pytest/fixtures.py | 73 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index fbce950ae44..87ce5099e8f 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -560,7 +560,6 @@ def _get_active_fixturedef( # The are no fixtures with this name applicable for the function. if not fixturedefs: raise FixtureLookupError(argname, self) - # A fixture may override another fixture with the same name, e.g. a # fixture in a module can override a fixture in a conftest, a fixture in # a class can override a fixture in the module, and so on. @@ -577,13 +576,11 @@ def _get_active_fixturedef( # If already consumed all of the available levels, fail. if -index > len(fixturedefs): raise FixtureLookupError(argname, self) - fixturedef = fixturedefs[index] # Prepare a SubRequest object for calling the fixture. - funcitem = self._pyfuncitem try: - callspec = funcitem.callspec + callspec = self._pyfuncitem.callspec except AttributeError: callspec = None if callspec is not None and argname in callspec.params: @@ -595,41 +592,8 @@ def _get_active_fixturedef( param = NOTSET param_index = 0 scope = fixturedef._scope - - has_params = fixturedef.params is not None - fixtures_not_supported = getattr(funcitem, "nofuncargs", False) - if has_params and fixtures_not_supported: - msg = ( - f"{funcitem.name} does not support fixtures, maybe unittest.TestCase subclass?\n" - f"Node id: {funcitem.nodeid}\n" - f"Function type: {type(funcitem).__name__}" - ) - fail(msg, pytrace=False) - if has_params: - frame = inspect.stack()[2] - frameinfo = inspect.getframeinfo(frame[0]) - source_path = absolutepath(frameinfo.filename) - source_lineno = frameinfo.lineno - try: - source_path_str = str( - source_path.relative_to(funcitem.config.rootpath) - ) - except ValueError: - source_path_str = str(source_path) - location = getlocation(fixturedef.func, funcitem.config.rootpath) - msg = ( - "The requested fixture has no parameter defined for test:\n" - f" {funcitem.nodeid}\n\n" - f"Requested fixture '{fixturedef.argname}' defined in:\n" - f"{location}\n\n" - f"Requested here:\n" - f"{source_path_str}:{source_lineno}" - ) - fail(msg, pytrace=False) - - # Check if a higher-level scoped fixture accesses a lower level one. + self._check_fixturedef_without_param(fixturedef) self._check_scope(fixturedef, scope) - subrequest = SubRequest( self, scope, param, param_index, fixturedef, _ispytest=True ) @@ -640,6 +604,39 @@ def _get_active_fixturedef( self._fixture_defs[argname] = fixturedef return fixturedef + def _check_fixturedef_without_param(self, fixturedef: "FixtureDef[object]") -> None: + """Check that this request is allowed to execute this fixturedef without + a param.""" + funcitem = self._pyfuncitem + has_params = fixturedef.params is not None + fixtures_not_supported = getattr(funcitem, "nofuncargs", False) + if has_params and fixtures_not_supported: + msg = ( + f"{funcitem.name} does not support fixtures, maybe unittest.TestCase subclass?\n" + f"Node id: {funcitem.nodeid}\n" + f"Function type: {type(funcitem).__name__}" + ) + fail(msg, pytrace=False) + if has_params: + frame = inspect.stack()[3] + frameinfo = inspect.getframeinfo(frame[0]) + source_path = absolutepath(frameinfo.filename) + source_lineno = frameinfo.lineno + try: + source_path_str = str(source_path.relative_to(funcitem.config.rootpath)) + except ValueError: + source_path_str = str(source_path) + location = getlocation(fixturedef.func, funcitem.config.rootpath) + msg = ( + "The requested fixture has no parameter defined for test:\n" + f" {funcitem.nodeid}\n\n" + f"Requested fixture '{fixturedef.argname}' defined in:\n" + f"{location}\n\n" + f"Requested here:\n" + f"{source_path_str}:{source_lineno}" + ) + fail(msg, pytrace=False) + def _get_fixturestack(self) -> List["FixtureDef[Any]"]: values = [request._fixturedef for request in self._iter_chain()] values.reverse() From 882c4da2f37702b00bdbd3b6c74e9821d33e0204 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 17 Mar 2024 20:06:29 +0200 Subject: [PATCH 0612/1271] fixtures: inline `fail_fixturefunc` Doesn't add much. --- src/_pytest/fixtures.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 87ce5099e8f..09fd07422fc 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -35,6 +35,7 @@ import _pytest from _pytest import nodes from _pytest._code import getfslineno +from _pytest._code import Source from _pytest._code.code import FormattedExcinfo from _pytest._code.code import TerminalRepr from _pytest._io import TerminalWriter @@ -864,13 +865,6 @@ def toterminal(self, tw: TerminalWriter) -> None: tw.line("%s:%d" % (os.fspath(self.filename), self.firstlineno + 1)) -def fail_fixturefunc(fixturefunc, msg: str) -> NoReturn: - fs, lineno = getfslineno(fixturefunc) - location = f"{fs}:{lineno + 1}" - source = _pytest._code.Source(fixturefunc) - fail(msg + ":\n\n" + str(source.indent()) + "\n" + location, pytrace=False) - - def call_fixture_func( fixturefunc: "_FixtureFunc[FixtureValue]", request: FixtureRequest, kwargs ) -> FixtureValue: @@ -900,7 +894,13 @@ def _teardown_yield_fixture(fixturefunc, it) -> None: except StopIteration: pass else: - fail_fixturefunc(fixturefunc, "fixture function has more than one 'yield'") + fs, lineno = getfslineno(fixturefunc) + fail( + f"fixture function has more than one 'yield':\n\n" + f"{Source(fixturefunc).indent()}\n" + f"{fs}:{lineno + 1}", + pytrace=False, + ) def _eval_scope_callable( From 7e7503c0b015f61d9d21d3b5f55990b7fcd683f7 Mon Sep 17 00:00:00 2001 From: Daniel Miller Date: Sat, 27 Apr 2024 08:49:05 -0400 Subject: [PATCH 0613/1271] unittest: report class cleanup exceptions (#12250) Fixes #11728 --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/11728.improvement.rst | 1 + src/_pytest/unittest.py | 19 +++++++ testing/test_unittest.py | 89 +++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 changelog/11728.improvement.rst diff --git a/AUTHORS b/AUTHORS index d7148acfc51..4f61c05914b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -101,6 +101,7 @@ Cyrus Maden Damian Skrzypczak Daniel Grana Daniel Hahler +Daniel Miller Daniel Nuri Daniel Sánchez Castelló Daniel Valenzuela Zenteno diff --git a/changelog/11728.improvement.rst b/changelog/11728.improvement.rst new file mode 100644 index 00000000000..1e87fc5ed88 --- /dev/null +++ b/changelog/11728.improvement.rst @@ -0,0 +1 @@ +For ``unittest``-based tests, exceptions during class cleanup (as raised by functions registered with :meth:`TestCase.addClassCleanup `) are now reported instead of silently failing. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 5099904fd41..8f1791bf744 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -32,6 +32,9 @@ import pytest +if sys.version_info[:2] < (3, 11): + from exceptiongroup import ExceptionGroup + if TYPE_CHECKING: import unittest @@ -111,6 +114,20 @@ def _register_unittest_setup_class_fixture(self, cls: type) -> None: return None cleanup = getattr(cls, "doClassCleanups", lambda: None) + def process_teardown_exceptions() -> None: + # tearDown_exceptions is a list set in the class containing exc_infos for errors during + # teardown for the class. + exc_infos = getattr(cls, "tearDown_exceptions", None) + if not exc_infos: + return + exceptions = [exc for (_, exc, _) in exc_infos] + # If a single exception, raise it directly as this provides a more readable + # error (hopefully this will improve in #12255). + if len(exceptions) == 1: + raise exceptions[0] + else: + raise ExceptionGroup("Unittest class cleanup errors", exceptions) + def unittest_setup_class_fixture( request: FixtureRequest, ) -> Generator[None, None, None]: @@ -125,6 +142,7 @@ def unittest_setup_class_fixture( # follow this here. except Exception: cleanup() + process_teardown_exceptions() raise yield try: @@ -132,6 +150,7 @@ def unittest_setup_class_fixture( teardown() finally: cleanup() + process_teardown_exceptions() self.session._fixturemanager._register_fixture( # Use a unique name to speed up lookup. diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 9ecb548eeec..d726e74d603 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1500,6 +1500,95 @@ def test_cleanup_called_the_right_number_of_times(): assert passed == 1 +class TestClassCleanupErrors: + """ + Make sure to show exceptions raised during class cleanup function (those registered + via addClassCleanup()). + + See #11728. + """ + + def test_class_cleanups_failure_in_setup(self, pytester: Pytester) -> None: + testpath = pytester.makepyfile( + """ + import unittest + class MyTestCase(unittest.TestCase): + @classmethod + def setUpClass(cls): + def cleanup(n): + raise Exception(f"fail {n}") + cls.addClassCleanup(cleanup, 2) + cls.addClassCleanup(cleanup, 1) + raise Exception("fail 0") + def test(self): + pass + """ + ) + result = pytester.runpytest("-s", testpath) + result.assert_outcomes(passed=0, errors=1) + result.stdout.fnmatch_lines( + [ + "*Unittest class cleanup errors *2 sub-exceptions*", + "*Exception: fail 1", + "*Exception: fail 2", + ] + ) + result.stdout.fnmatch_lines( + [ + "* ERROR at setup of MyTestCase.test *", + "E * Exception: fail 0", + ] + ) + + def test_class_cleanups_failure_in_teardown(self, pytester: Pytester) -> None: + testpath = pytester.makepyfile( + """ + import unittest + class MyTestCase(unittest.TestCase): + @classmethod + def setUpClass(cls): + def cleanup(n): + raise Exception(f"fail {n}") + cls.addClassCleanup(cleanup, 2) + cls.addClassCleanup(cleanup, 1) + def test(self): + pass + """ + ) + result = pytester.runpytest("-s", testpath) + result.assert_outcomes(passed=1, errors=1) + result.stdout.fnmatch_lines( + [ + "*Unittest class cleanup errors *2 sub-exceptions*", + "*Exception: fail 1", + "*Exception: fail 2", + ] + ) + + def test_class_cleanup_1_failure_in_teardown(self, pytester: Pytester) -> None: + testpath = pytester.makepyfile( + """ + import unittest + class MyTestCase(unittest.TestCase): + @classmethod + def setUpClass(cls): + def cleanup(n): + raise Exception(f"fail {n}") + cls.addClassCleanup(cleanup, 1) + def test(self): + pass + """ + ) + result = pytester.runpytest("-s", testpath) + result.assert_outcomes(passed=1, errors=1) + result.stdout.fnmatch_lines( + [ + "*ERROR at teardown of MyTestCase.test*", + "*Exception: fail 1", + ] + ) + + def test_traceback_pruning(pytester: Pytester) -> None: """Regression test for #9610 - doesn't crash during traceback pruning.""" pytester.makepyfile( From fc5c9603041251225a2ddc7caf77e9fb3d013e68 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 28 Apr 2024 01:39:36 +0300 Subject: [PATCH 0614/1271] runner: avoid adding uninteresting entry to tracebacks In these two cases which re-raise an immediately-caught exception, do the re-raising with `raise` instead of `raise exc`, because the `raise exc` adds an uninteresting entry to the exception's traceback (that of itself), while `raise` doesn't. --- src/_pytest/runner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 3f706b927c8..6883a1a5895 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -180,7 +180,7 @@ def pytest_runtest_call(item: Item) -> None: assert e.__traceback__ is not None # Skip *this* frame sys.last_traceback = e.__traceback__.tb_next - raise e + raise def pytest_runtest_teardown(item: Item, nextitem: Optional[Item]) -> None: @@ -512,7 +512,7 @@ def setup(self, item: Item) -> None: col.setup() except TEST_OUTCOME as exc: self.stack[col] = (self.stack[col][0], exc) - raise exc + raise def addfinalizer(self, finalizer: Callable[[], object], node: Node) -> None: """Attach a finalizer to the given node. From 79ca819e59948661c5403dd4aa77c248266a8c76 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 27 Apr 2024 20:35:29 -0300 Subject: [PATCH 0615/1271] Merge pull request #12257 from pytest-dev/release-8.2.0 Prepare release 8.2.0 (cherry picked from commit 69c3bcea36e1cf3468ac3cb92da9cf37038f959d) --- changelog/11523.improvement.rst | 5 -- changelog/11728.improvement.rst | 1 - changelog/11777.improvement.rst | 1 - changelog/11871.feature.rst | 1 - changelog/12065.bugfix.rst | 4 -- changelog/12069.deprecation.rst | 12 ----- changelog/12069.trivial.rst | 1 - changelog/12112.improvement.rst | 1 - changelog/12135.bugfix.rst | 1 - changelog/12167.trivial.rst | 1 - changelog/12194.bugfix.rst | 1 - changelog/1489.bugfix.rst | 1 - changelog/9502.improvement.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.2.0.rst | 43 +++++++++++++++ doc/en/builtin.rst | 30 +++++------ doc/en/changelog.rst | 81 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +-- doc/en/example/pythoncollection.rst | 4 +- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/output.rst | 44 ++++++++++++++-- 22 files changed, 188 insertions(+), 56 deletions(-) delete mode 100644 changelog/11523.improvement.rst delete mode 100644 changelog/11728.improvement.rst delete mode 100644 changelog/11777.improvement.rst delete mode 100644 changelog/11871.feature.rst delete mode 100644 changelog/12065.bugfix.rst delete mode 100644 changelog/12069.deprecation.rst delete mode 100644 changelog/12069.trivial.rst delete mode 100644 changelog/12112.improvement.rst delete mode 100644 changelog/12135.bugfix.rst delete mode 100644 changelog/12167.trivial.rst delete mode 100644 changelog/12194.bugfix.rst delete mode 100644 changelog/1489.bugfix.rst delete mode 100644 changelog/9502.improvement.rst create mode 100644 doc/en/announce/release-8.2.0.rst diff --git a/changelog/11523.improvement.rst b/changelog/11523.improvement.rst deleted file mode 100644 index f7d8ff89df6..00000000000 --- a/changelog/11523.improvement.rst +++ /dev/null @@ -1,5 +0,0 @@ -:func:`pytest.importorskip` will now issue a warning if the module could be found, but raised :class:`ImportError` instead of :class:`ModuleNotFoundError`. - -The warning can be suppressed by passing ``exc_type=ImportError`` to :func:`pytest.importorskip`. - -See :ref:`import-or-skip-import-error` for details. diff --git a/changelog/11728.improvement.rst b/changelog/11728.improvement.rst deleted file mode 100644 index 1e87fc5ed88..00000000000 --- a/changelog/11728.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -For ``unittest``-based tests, exceptions during class cleanup (as raised by functions registered with :meth:`TestCase.addClassCleanup `) are now reported instead of silently failing. diff --git a/changelog/11777.improvement.rst b/changelog/11777.improvement.rst deleted file mode 100644 index fb53c63c10a..00000000000 --- a/changelog/11777.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Text is no longer truncated in the ``short test summary info`` section when ``-vv`` is given. diff --git a/changelog/11871.feature.rst b/changelog/11871.feature.rst deleted file mode 100644 index 530db8c3c6f..00000000000 --- a/changelog/11871.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added support for reading command line arguments from a file using the prefix character ``@``, like e.g.: ``pytest @tests.txt``. The file must have one argument per line. diff --git a/changelog/12065.bugfix.rst b/changelog/12065.bugfix.rst deleted file mode 100644 index ca55b327e13..00000000000 --- a/changelog/12065.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fixed a regression in pytest 8.0.0 where test classes containing ``setup_method`` and tests using ``@staticmethod`` or ``@classmethod`` would crash with ``AttributeError: 'NoneType' object has no attribute 'setup_method'``. - -Now the :attr:`request.instance ` attribute of tests using ``@staticmethod`` and ``@classmethod`` is no longer ``None``, but a fresh instance of the class, like in non-static methods. -Previously it was ``None``, and all fixtures of such tests would share a single ``self``. diff --git a/changelog/12069.deprecation.rst b/changelog/12069.deprecation.rst deleted file mode 100644 index c8798b5ff25..00000000000 --- a/changelog/12069.deprecation.rst +++ /dev/null @@ -1,12 +0,0 @@ -A deprecation warning is now raised when implementations of one of the following hooks request a deprecated ``py.path.local`` parameter instead of the ``pathlib.Path`` parameter which replaced it: - -- :hook:`pytest_ignore_collect` - the ``path`` parameter - use ``collection_path`` instead. -- :hook:`pytest_collect_file` - the ``path`` parameter - use ``file_path`` instead. -- :hook:`pytest_pycollect_makemodule` - the ``path`` parameter - use ``module_path`` instead. -- :hook:`pytest_report_header` - the ``startdir`` parameter - use ``start_path`` instead. -- :hook:`pytest_report_collectionfinish` - the ``startdir`` parameter - use ``start_path`` instead. - -The replacement parameters are available since pytest 7.0.0. -The old parameters will be removed in pytest 9.0.0. - -See :ref:`legacy-path-hooks-deprecated` for more details. diff --git a/changelog/12069.trivial.rst b/changelog/12069.trivial.rst deleted file mode 100644 index 8eb9b0c464a..00000000000 --- a/changelog/12069.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -``pluggy>=1.5.0`` is now required. diff --git a/changelog/12112.improvement.rst b/changelog/12112.improvement.rst deleted file mode 100644 index 3f997b2af65..00000000000 --- a/changelog/12112.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Improve namespace packages detection when :confval:`consider_namespace_packages` is enabled, covering more situations (like editable installs). diff --git a/changelog/12135.bugfix.rst b/changelog/12135.bugfix.rst deleted file mode 100644 index 734733b100d..00000000000 --- a/changelog/12135.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix fixtures adding their finalizer multiple times to fixtures they request, causing unreliable and non-intuitive teardown ordering in some instances. diff --git a/changelog/12167.trivial.rst b/changelog/12167.trivial.rst deleted file mode 100644 index da9363420e6..00000000000 --- a/changelog/12167.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -cache: create cache directory supporting files (``CACHEDIR.TAG``, ``.gitignore``, etc.) in a temporary directory to provide atomic semantics. diff --git a/changelog/12194.bugfix.rst b/changelog/12194.bugfix.rst deleted file mode 100644 index 6983ba35a90..00000000000 --- a/changelog/12194.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a bug with ``--importmode=importlib`` and ``--doctest-modules`` where child modules did not appear as attributes in parent modules. diff --git a/changelog/1489.bugfix.rst b/changelog/1489.bugfix.rst deleted file mode 100644 index 70c5dd1252e..00000000000 --- a/changelog/1489.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix some instances where teardown of higher-scoped fixtures was not happening in the reverse order they were initialized in. diff --git a/changelog/9502.improvement.rst b/changelog/9502.improvement.rst deleted file mode 100644 index 2eaf6a72747..00000000000 --- a/changelog/9502.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added :envvar:`PYTEST_VERSION` environment variable which is defined at the start of the pytest session and undefined afterwards. It contains the value of ``pytest.__version__``, and among other things can be used to easily check if code is running from within a pytest run. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index bb39eb7e6a1..4d0a3ab558e 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.2.0 release-8.1.2 release-8.1.1 release-8.1.0 diff --git a/doc/en/announce/release-8.2.0.rst b/doc/en/announce/release-8.2.0.rst new file mode 100644 index 00000000000..2a63c8d8722 --- /dev/null +++ b/doc/en/announce/release-8.2.0.rst @@ -0,0 +1,43 @@ +pytest-8.2.0 +======================================= + +The pytest team is proud to announce the 8.2.0 release! + +This release contains new features, improvements, and bug fixes, +the full list of changes is available in the changelog: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Daniel Miller +* Florian Bruhin +* HolyMagician03-UMich +* John Litborn +* Levon Saldamli +* Linghao Zhang +* Manuel López-Ibáñez +* Pierre Sassoulas +* Ran Benita +* Ronny Pfannschmidt +* Sebastian Meyer +* Shekhar verma +* Tamir Duberstein +* Tobias Stoeckmann +* dj +* jakkdl +* poulami-sau +* tserg + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 9d49389f190..d5f2e9a1b0f 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:527 + cache -- .../_pytest/cacheprovider.py:542 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1008 + capsysbinary -- .../_pytest/capture.py:1003 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -50,7 +50,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1035 + capfd -- .../_pytest/capture.py:1030 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -67,7 +67,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1062 + capfdbinary -- .../_pytest/capture.py:1057 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -84,7 +84,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - capsys -- .../_pytest/capture.py:981 + capsys -- .../_pytest/capture.py:976 Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsys.readouterr()`` method @@ -101,7 +101,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:737 + doctest_namespace [session scope] -- .../_pytest/doctest.py:738 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -115,7 +115,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1346 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1335 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -125,7 +125,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a if pytestconfig.getoption("verbose") > 0: ... - record_property -- .../_pytest/junitxml.py:283 + record_property -- .../_pytest/junitxml.py:284 Add extra properties to the calling test. User properties become part of the test report and are available to the @@ -139,13 +139,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a def test_function(record_property): record_property("example_key", 1) - record_xml_attribute -- .../_pytest/junitxml.py:306 + record_xml_attribute -- .../_pytest/junitxml.py:307 Add extra xml attributes to the tag for the calling test. The fixture is callable with ``name, value``. The value is automatically XML-encoded. - record_testsuite_property [session scope] -- .../_pytest/junitxml.py:344 + record_testsuite_property [session scope] -- .../_pytest/junitxml.py:345 Record a new ```` tag as child of the root ````. This is suitable to writing global information regarding the entire test @@ -192,7 +192,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:601 + caplog -- .../_pytest/logging.py:602 Access and control log capturing. Captured logs are available through the following properties/methods:: @@ -203,7 +203,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a * caplog.record_tuples -> list of (logger_name, level, message) tuples * caplog.clear() -> clear captured records and formatted log output string - monkeypatch -- .../_pytest/monkeypatch.py:32 + monkeypatch -- .../_pytest/monkeypatch.py:33 A convenient fixture for monkey-patching. The fixture provides these methods to modify objects, dictionaries, or @@ -227,16 +227,16 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a To undo modifications done by the fixture in a contained scope, use :meth:`context() `. - recwarn -- .../_pytest/recwarn.py:31 + recwarn -- .../_pytest/recwarn.py:32 Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information on warning categories. - tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:241 + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:242 Return a :class:`pytest.TempPathFactory` instance for the test session. - tmp_path -- .../_pytest/tmpdir.py:256 + tmp_path -- .../_pytest/tmpdir.py:257 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index fb316e706ba..2630d95cf28 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,87 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.2.0 (2024-04-27) +========================= + +Deprecations +------------ + +- `#12069 `_: A deprecation warning is now raised when implementations of one of the following hooks request a deprecated ``py.path.local`` parameter instead of the ``pathlib.Path`` parameter which replaced it: + + - :hook:`pytest_ignore_collect` - the ``path`` parameter - use ``collection_path`` instead. + - :hook:`pytest_collect_file` - the ``path`` parameter - use ``file_path`` instead. + - :hook:`pytest_pycollect_makemodule` - the ``path`` parameter - use ``module_path`` instead. + - :hook:`pytest_report_header` - the ``startdir`` parameter - use ``start_path`` instead. + - :hook:`pytest_report_collectionfinish` - the ``startdir`` parameter - use ``start_path`` instead. + + The replacement parameters are available since pytest 7.0.0. + The old parameters will be removed in pytest 9.0.0. + + See :ref:`legacy-path-hooks-deprecated` for more details. + + + +Features +-------- + +- `#11871 `_: Added support for reading command line arguments from a file using the prefix character ``@``, like e.g.: ``pytest @tests.txt``. The file must have one argument per line. + + See :ref:`Read arguments from file ` for details. + + + +Improvements +------------ + +- `#11523 `_: :func:`pytest.importorskip` will now issue a warning if the module could be found, but raised :class:`ImportError` instead of :class:`ModuleNotFoundError`. + + The warning can be suppressed by passing ``exc_type=ImportError`` to :func:`pytest.importorskip`. + + See :ref:`import-or-skip-import-error` for details. + + +- `#11728 `_: For ``unittest``-based tests, exceptions during class cleanup (as raised by functions registered with :meth:`TestCase.addClassCleanup `) are now reported instead of silently failing. + + +- `#11777 `_: Text is no longer truncated in the ``short test summary info`` section when ``-vv`` is given. + + +- `#12112 `_: Improved namespace packages detection when :confval:`consider_namespace_packages` is enabled, covering more situations (like editable installs). + + +- `#9502 `_: Added :envvar:`PYTEST_VERSION` environment variable which is defined at the start of the pytest session and undefined afterwards. It contains the value of ``pytest.__version__``, and among other things can be used to easily check if code is running from within a pytest run. + + + +Bug Fixes +--------- + +- `#12065 `_: Fixed a regression in pytest 8.0.0 where test classes containing ``setup_method`` and tests using ``@staticmethod`` or ``@classmethod`` would crash with ``AttributeError: 'NoneType' object has no attribute 'setup_method'``. + + Now the :attr:`request.instance ` attribute of tests using ``@staticmethod`` and ``@classmethod`` is no longer ``None``, but a fresh instance of the class, like in non-static methods. + Previously it was ``None``, and all fixtures of such tests would share a single ``self``. + + +- `#12135 `_: Fixed issue where fixtures adding their finalizer multiple times to fixtures they request would cause unreliable and non-intuitive teardown ordering in some instances. + + +- `#12194 `_: Fixed a bug with ``--importmode=importlib`` and ``--doctest-modules`` where child modules did not appear as attributes in parent modules. + + +- `#1489 `_: Fixed some instances where teardown of higher-scoped fixtures was not happening in the reverse order they were initialized in. + + + +Trivial/Internal Changes +------------------------ + +- `#12069 `_: ``pluggy>=1.5.0`` is now required. + + +- `#12167 `_: :ref:`cache `: create supporting files (``CACHEDIR.TAG``, ``.gitignore``, etc.) in a temporary directory to provide atomic semantics. + + pytest 8.1.2 (2024-04-26) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 672c7c4457d..1bbe2faaad0 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index c01e685f3f4..a383173d07e 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index e96eabbc5e7..5b33e308d13 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.1.2 + pytest 8.2.0 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index ba416ccbc23..72b69a14681 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index 5b47a5c7776..7a4e32edc78 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -294,9 +294,47 @@ Now if we increase verbosity even more: test_verbosity_example.py:19: AssertionError ========================= short test summary info ========================== - FAILED test_verbosity_example.py::test_words_fail - AssertionError: asser... - FAILED test_verbosity_example.py::test_numbers_fail - AssertionError: ass... - FAILED test_verbosity_example.py::test_long_text_fail - AssertionError: a... + FAILED test_verbosity_example.py::test_words_fail - AssertionError: assert ['banana', 'apple', 'grapes', 'melon', 'kiwi'] == ['banana', 'apple', 'orange', 'melon', 'kiwi'] + + At index 2 diff: 'grapes' != 'orange' + + Full diff: + [ + 'banana', + 'apple', + - 'orange', + ? ^ ^^ + + 'grapes', + ? ^ ^ + + 'melon', + 'kiwi', + ] + FAILED test_verbosity_example.py::test_numbers_fail - AssertionError: assert {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4} == {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40} + + Common items: + {'0': 0} + Left contains 4 more items: + {'1': 1, '2': 2, '3': 3, '4': 4} + Right contains 4 more items: + {'10': 10, '20': 20, '30': 30, '40': 40} + + Full diff: + { + '0': 0, + - '10': 10, + ? - - + + '1': 1, + - '20': 20, + ? - - + + '2': 2, + - '30': 30, + ? - - + + '3': 3, + - '40': 40, + ? - - + + '4': 4, + } + FAILED test_verbosity_example.py::test_long_text_fail - AssertionError: assert 'hello world' in 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet ' ======================= 3 failed, 1 passed in 0.12s ======================== Notice now that: From 852df0dc3e384976924041de6273ef4f19a74cf4 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 28 Apr 2024 00:20:56 +0000 Subject: [PATCH 0616/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 136 ++++++++++++++++++------------- 1 file changed, 80 insertions(+), 56 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index e1d1e3ec24a..68d017c31c4 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jan 18, 2024 5 - Production/Stable pytest >=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Apr 22, 2024 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -119,7 +119,7 @@ This list contains 1448 plugins. :pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A :pypi:`pytest-autocap` automatically capture test & fixture stdout/stderr to files May 15, 2022 N/A pytest (<7.2,>=7.1.2) :pypi:`pytest-autochecklog` automatically check condition and log all the checks Apr 25, 2015 4 - Beta N/A - :pypi:`pytest-automation` pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. May 20, 2022 N/A pytest (>=7.0.0) + :pypi:`pytest-automation` pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. Apr 24, 2024 N/A pytest>=7.0.0 :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest @@ -145,7 +145,7 @@ This list contains 1448 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Apr 19, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Apr 26, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -267,6 +267,7 @@ This list contains 1448 plugins. :pypi:`pytest-container` Pytest fixtures for writing container based tests Apr 10, 2024 4 - Beta pytest>=3.10 :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A + :pypi:`pytest-continuous` A pytest plugin to run tests continuously until failure or interruption. Apr 23, 2024 N/A N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Jan 27, 2024 3 - Alpha pytest :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 @@ -301,9 +302,9 @@ This list contains 1448 plugins. :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A - :pypi:`pytest-dashboard` Apr 18, 2024 N/A pytest<8.0.0,>=7.4.3 + :pypi:`pytest-dashboard` Apr 22, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 19, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 21, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -436,14 +437,14 @@ This list contains 1448 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 Apr 04, 2024 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. Apr 09, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Apr 26, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 26, 2024 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) @@ -468,7 +469,7 @@ This list contains 1448 plugins. :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' - :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Apr 20, 2024 4 - Beta pytest<9.0.0,>=8.1.1 + :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Apr 22, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 :pypi:`pytest-exasol-itde` Feb 15, 2024 N/A pytest (>=7,<9) @@ -512,6 +513,7 @@ This list contains 1448 plugins. :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) + :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Apr 22, 2024 N/A N/A :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A :pypi:`pytest-file` Pytest File Mar 18, 2024 1 - Planning N/A @@ -591,7 +593,7 @@ This list contains 1448 plugins. :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Apr 03, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A - :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Jul 22, 2022 4 - Beta pytest + :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Apr 22, 2024 4 - Beta pytest<=8.1.1 :pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest :pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0) @@ -621,7 +623,7 @@ This list contains 1448 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Apr 13, 2024 3 - Alpha pytest==8.1.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 25, 2024 3 - Alpha pytest==8.1.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -652,13 +654,13 @@ This list contains 1448 plugins. :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Apr 12, 2024 3 - Alpha pytest>=7.0.0 + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Apr 22, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Dec 13, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A - :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 08, 2024 5 - Production/Stable pytest>=6.0 + :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 20, 2024 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. Dec 01, 2023 4 - Beta pytest >=3.5.0 @@ -809,7 +811,7 @@ This list contains 1448 plugins. :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Apr 15, 2024 N/A pytest>=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Apr 27, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Mar 07, 2024 N/A pytest >=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A @@ -853,6 +855,7 @@ This list contains 1448 plugins. :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Mar 31, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 + :pypi:`pytest-mypy-runner` Run the mypy static type checker as a pytest test case Apr 23, 2024 N/A pytest>=8.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest @@ -1104,7 +1107,7 @@ This list contains 1448 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-rerunclassfailures` pytest rerun class failures plugin Mar 29, 2024 5 - Production/Stable pytest>=7.2 + :pypi:`pytest-rerunclassfailures` pytest rerun class failures plugin Apr 24, 2024 5 - Production/Stable pytest>=7.2 :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 :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. Feb 08, 2024 4 - Beta pytest @@ -1156,7 +1159,7 @@ This list contains 1448 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 26, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1165,12 +1168,12 @@ This list contains 1448 plugins. :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 Feb 01, 2024 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. Apr 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 26, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A - :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Apr 05, 2024 N/A pytest + :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Apr 25, 2024 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A @@ -1294,7 +1297,7 @@ This list contains 1448 plugins. :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A - :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Dec 10, 2020 5 - Production/Stable N/A + :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Apr 25, 2024 5 - Production/Stable N/A :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) :pypi:`pytest-terra-fixt` Terraform and Terragrunt fixtures for pytest Sep 15, 2022 N/A pytest (==6.2.5) @@ -1454,7 +1457,7 @@ This list contains 1448 plugins. :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Mar 22, 2024 N/A N/A + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Apr 23, 2024 N/A N/A :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Mar 31, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A @@ -1464,7 +1467,7 @@ This list contains 1448 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 Apr 19, 2024 N/A pytest>=7.4.0 + :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Apr 23, 2024 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) @@ -1761,9 +1764,9 @@ This list contains 1448 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Jan 18, 2024, + *last release*: Apr 22, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6 + *requires*: pytest>=6 Plugin for pytest to simplify calling ansible modules from tests or fixtures @@ -2083,9 +2086,9 @@ This list contains 1448 plugins. automatically check condition and log all the checks :pypi:`pytest-automation` - *last release*: May 20, 2022, + *last release*: Apr 24, 2024, *status*: N/A, - *requires*: pytest (>=7.0.0) + *requires*: pytest>=7.0.0 pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. @@ -2265,7 +2268,7 @@ This list contains 1448 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Apr 19, 2024, + *last release*: Apr 26, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3118,6 +3121,13 @@ This list contains 1448 plugins. A plugin to run tests written with the Contexts framework using pytest + :pypi:`pytest-continuous` + *last release*: Apr 23, 2024, + *status*: N/A, + *requires*: N/A + + A pytest plugin to run tests continuously until failure or interruption. + :pypi:`pytest-cookies` *last release*: Mar 22, 2023, *status*: 5 - Production/Stable, @@ -3357,7 +3367,7 @@ This list contains 1448 plugins. pytest fixtures to run dash applications. :pypi:`pytest-dashboard` - *last release*: Apr 18, 2024, + *last release*: Apr 22, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.3 @@ -3371,7 +3381,7 @@ This list contains 1448 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Apr 19, 2024, + *last release*: Apr 21, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4302,56 +4312,56 @@ This list contains 1448 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Apr 09, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Apr 09, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Apr 09, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Apr 09, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Apr 09, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Apr 09, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Apr 09, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Apr 09, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4526,7 +4536,7 @@ This list contains 1448 plugins. Applies eventlet monkey-patch as a pytest plugin. :pypi:`pytest-evm` - *last release*: Apr 20, 2024, + *last release*: Apr 22, 2024, *status*: 4 - Beta, *requires*: pytest<9.0.0,>=8.1.1 @@ -4833,6 +4843,13 @@ This list contains 1448 plugins. py.test plugin that activates the fault handler module for tests (dummy package) + :pypi:`pytest-fauna` + *last release*: Apr 22, 2024, + *status*: N/A, + *requires*: N/A + + A collection of helpful test fixtures for Fauna DB. + :pypi:`pytest-fauxfactory` *last release*: Dec 06, 2017, *status*: 5 - Production/Stable, @@ -5387,9 +5404,9 @@ This list contains 1448 plugins. Utility to select tests that have had its dependencies modified (as identified by git diff) :pypi:`pytest-glamor-allure` - *last release*: Jul 22, 2022, + *last release*: Apr 22, 2024, *status*: 4 - Beta, - *requires*: pytest + *requires*: pytest<=8.1.1 Extends allure-pytest functionality @@ -5597,7 +5614,7 @@ This list contains 1448 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 13, 2024, + *last release*: Apr 25, 2024, *status*: 3 - Alpha, *requires*: pytest==8.1.1 @@ -5814,7 +5831,7 @@ This list contains 1448 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Apr 12, 2024, + *last release*: Apr 22, 2024, *status*: 3 - Alpha, *requires*: pytest>=7.0.0 @@ -5856,7 +5873,7 @@ This list contains 1448 plugins. Pytest plugin for testing function idempotence. :pypi:`pytest-ignore-flaky` - *last release*: Apr 08, 2024, + *last release*: Apr 20, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.0 @@ -6913,7 +6930,7 @@ This list contains 1448 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: Apr 15, 2024, + *last release*: Apr 27, 2024, *status*: N/A, *requires*: pytest>=5.0.0 @@ -7220,6 +7237,13 @@ This list contains 1448 plugins. Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. + :pypi:`pytest-mypy-runner` + *last release*: Apr 23, 2024, + *status*: N/A, + *requires*: pytest>=8.0 + + Run the mypy static type checker as a pytest test case + :pypi:`pytest-mypy-testing` *last release*: Mar 04, 2024, *status*: N/A, @@ -8978,7 +9002,7 @@ This list contains 1448 plugins. Rerun testsuite for a certain time or iterations :pypi:`pytest-rerunclassfailures` - *last release*: Mar 29, 2024, + *last release*: Apr 24, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.2 @@ -9342,7 +9366,7 @@ This list contains 1448 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Apr 14, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9405,7 +9429,7 @@ This list contains 1448 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Apr 14, 2024, + *last release*: Apr 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9440,7 +9464,7 @@ This list contains 1448 plugins. Send pytest execution result email :pypi:`pytest-sentry` - *last release*: Apr 05, 2024, + *last release*: Apr 25, 2024, *status*: N/A, *requires*: pytest @@ -10308,7 +10332,7 @@ This list contains 1448 plugins. py.test plugin to introduce block structure in teamcity build log, if output is not captured :pypi:`pytest-telegram` - *last release*: Dec 10, 2020, + *last release*: Apr 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -11428,7 +11452,7 @@ This list contains 1448 plugins. Extended logging for test and decorators :pypi:`pytest-xlsx` - *last release*: Mar 22, 2024, + *last release*: Apr 23, 2024, *status*: N/A, *requires*: N/A @@ -11498,7 +11522,7 @@ This list contains 1448 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Apr 19, 2024, + *last release*: Apr 23, 2024, *status*: N/A, *requires*: pytest>=7.4.0 From 1a84d233f3a64cab72795b236523bdff95781c81 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 27 Apr 2024 01:41:45 +0300 Subject: [PATCH 0617/1271] terminal: some minor code cleanups No logical changed intended. --- src/_pytest/terminal.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 724d5c54d2f..c0ca97df6c1 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -432,7 +432,7 @@ def hasopt(self, char: str) -> bool: char = {"xfailed": "x", "skipped": "s"}.get(char, char) return char in self.reportchars - def write_fspath_result(self, nodeid: str, res, **markup: bool) -> None: + def write_fspath_result(self, nodeid: str, res: str, **markup: bool) -> None: fspath = self.config.rootpath / nodeid.split("::")[0] if self.currentfspath is None or fspath != self.currentfspath: if self.currentfspath is not None and self._show_progress_info: @@ -565,10 +565,11 @@ def pytest_deselected(self, items: Sequence[Item]) -> None: def pytest_runtest_logstart( self, nodeid: str, location: Tuple[str, Optional[int], str] ) -> None: + fspath, lineno, domain = location # Ensure that the path is printed before the # 1st test of a module starts running. if self.showlongtestinfo: - line = self._locationline(nodeid, *location) + line = self._locationline(nodeid, fspath, lineno, domain) self.write_ensure_prefix(line, "") self.flush() elif self.showfspath: @@ -591,7 +592,6 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: if not letter and not word: # Probably passed setup/teardown. return - running_xdist = hasattr(rep, "node") if markup is None: was_xfail = hasattr(report, "wasxfail") if rep.passed and not was_xfail: @@ -609,6 +609,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: else: self._progress_nodeids_reported.add(rep.nodeid) line = self._locationline(rep.nodeid, *rep.location) + running_xdist = hasattr(rep, "node") if not running_xdist: self.write_ensure_prefix(line, word, **markup) if rep.skipped or hasattr(report, "wasxfail"): @@ -649,38 +650,26 @@ def _is_last_item(self) -> bool: return len(self._progress_nodeids_reported) == self._session.testscollected def pytest_runtest_logfinish(self, nodeid: str) -> None: - assert self._session if ( self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) <= 0 and self._show_progress_info ): - if self._show_progress_info == "count": - num_tests = self._session.testscollected - progress_length = len(f" [{num_tests}/{num_tests}]") - else: - progress_length = len(" [100%]") - self._progress_nodeids_reported.add(nodeid) if self._is_last_item: self._write_progress_information_filling_space() else: - main_color, _ = self._get_main_color() - w = self._width_of_current_line - past_edge = w + progress_length + 1 >= self._screen_width - if past_edge: - msg = self._get_progress_information_message() - self._tw.write(msg + "\n", **{main_color: True}) + self._write_progress_information_if_past_edge() def _get_progress_information_message(self) -> str: assert self._session collected = self._session.testscollected if self._show_progress_info == "count": if collected: - progress = self._progress_nodeids_reported + progress = len(self._progress_nodeids_reported) counter_format = f"{{:{len(str(collected))}d}}" format_string = f" [{counter_format}/{{}}]" - return format_string.format(len(progress), collected) + return format_string.format(progress, collected) return f" [ {collected} / {collected} ]" else: if collected: @@ -689,6 +678,20 @@ def _get_progress_information_message(self) -> str: ) return " [100%]" + def _write_progress_information_if_past_edge(self) -> None: + w = self._width_of_current_line + if self._show_progress_info == "count": + assert self._session + num_tests = self._session.testscollected + progress_length = len(f" [{num_tests}/{num_tests}]") + else: + progress_length = len(" [100%]") + past_edge = w + progress_length + 1 >= self._screen_width + if past_edge: + main_color, _ = self._get_main_color() + msg = self._get_progress_information_message() + self._tw.write(msg + "\n", **{main_color: True}) + def _write_progress_information_filling_space(self) -> None: color, _ = self._get_main_color() msg = self._get_progress_information_message() @@ -937,7 +940,7 @@ def mkrel(nodeid: str) -> str: line += "[".join(values) return line - # collect_fspath comes from testid which has a "/"-normalized path. + # fspath comes from testid which has a "/"-normalized path. if fspath: res = mkrel(nodeid) if self.verbosity >= 2 and nodeid.split("::")[0] != fspath.replace( From 50d1e81713af75ab6d3608d2920ddf21bf53d765 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 27 Apr 2024 13:50:31 +0300 Subject: [PATCH 0618/1271] terminal: fix progress percentages not aligning correctly in xdist Fix #7166 --- changelog/7166.bugfix.rst | 1 + src/_pytest/terminal.py | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 changelog/7166.bugfix.rst diff --git a/changelog/7166.bugfix.rst b/changelog/7166.bugfix.rst new file mode 100644 index 00000000000..98e6821f2ff --- /dev/null +++ b/changelog/7166.bugfix.rst @@ -0,0 +1 @@ +Fixed progress percentages (the ``[ 87%]`` at the edge of the screen) sometimes not aligning correctly when running with pytest-xdist ``-n``. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index c0ca97df6c1..f4b6e9b40ec 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -604,10 +604,18 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: markup = {"yellow": True} else: markup = {} + self._progress_nodeids_reported.add(rep.nodeid) if self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) <= 0: self._tw.write(letter, **markup) + # When running in xdist, the logreport and logfinish of multiple + # items are interspersed, e.g. `logreport`, `logreport`, + # `logfinish`, `logfinish`. To avoid the "past edge" calculation + # from getting confused and overflowing (#7166), do the past edge + # printing here and not in logfinish, except for the 100% which + # should only be printed after all teardowns are finished. + if self._show_progress_info and not self._is_last_item: + self._write_progress_information_if_past_edge() else: - self._progress_nodeids_reported.add(rep.nodeid) line = self._locationline(rep.nodeid, *rep.location) running_xdist = hasattr(rep, "node") if not running_xdist: @@ -649,17 +657,19 @@ def _is_last_item(self) -> bool: assert self._session is not None return len(self._progress_nodeids_reported) == self._session.testscollected - def pytest_runtest_logfinish(self, nodeid: str) -> None: + @hookimpl(wrapper=True) + def pytest_runtestloop(self) -> Generator[None, object, object]: + result = yield + + # Write the final/100% progress -- deferred until the loop is complete. if ( self.config.get_verbosity(Config.VERBOSITY_TEST_CASES) <= 0 and self._show_progress_info + and self._progress_nodeids_reported ): - self._progress_nodeids_reported.add(nodeid) + self._write_progress_information_filling_space() - if self._is_last_item: - self._write_progress_information_filling_space() - else: - self._write_progress_information_if_past_edge() + return result def _get_progress_information_message(self) -> str: assert self._session From 0b91d5e3e869d00c01c614d827745a9ed4cddb43 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 28 Apr 2024 11:44:55 +0300 Subject: [PATCH 0619/1271] fixtures: fix tracebacks for higher-scoped failed fixtures getting longer and longer Fix #12204. --- changelog/12204.bugfix.rst | 4 ++++ src/_pytest/fixtures.py | 11 ++++++----- testing/python/fixtures.py | 22 ++++++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 changelog/12204.bugfix.rst diff --git a/changelog/12204.bugfix.rst b/changelog/12204.bugfix.rst new file mode 100644 index 00000000000..b89a04827f0 --- /dev/null +++ b/changelog/12204.bugfix.rst @@ -0,0 +1,4 @@ +Fix a regression in pytest 8.0 where tracebacks get longer and longer when multiple tests fail due to a shared higher-scope fixture which raised. + +The fix necessitated internal changes which may affect some plugins: +- ``FixtureDef.cached_result[2]`` is now a tuple ``(exc, tb)`` instead of ``exc``. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 09fd07422fc..5f10d565f32 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -8,6 +8,7 @@ import os from pathlib import Path import sys +import types from typing import AbstractSet from typing import Any from typing import Callable @@ -104,8 +105,8 @@ None, # Cache key. object, - # Exception if raised. - BaseException, + # The exception and the original traceback. + Tuple[BaseException, Optional[types.TracebackType]], ], ] @@ -1049,8 +1050,8 @@ def execute(self, request: SubRequest) -> FixtureValue: # numpy arrays (#6497). if my_cache_key is cache_key: if self.cached_result[2] is not None: - exc = self.cached_result[2] - raise exc + exc, exc_tb = self.cached_result[2] + raise exc.with_traceback(exc_tb) else: result = self.cached_result[0] return result @@ -1126,7 +1127,7 @@ def pytest_fixture_setup( # Don't show the fixture as the skip location, as then the user # wouldn't know which test skipped. e._use_item_location = True - fixturedef.cached_result = (None, my_cache_key, e) + fixturedef.cached_result = (None, my_cache_key, (e, e.__traceback__)) raise fixturedef.cached_result = (result, my_cache_key, None) return result diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 12ca6e92630..77914fed75d 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -3397,6 +3397,28 @@ def test_something(): ["*def gen(qwe123):*", "*fixture*qwe123*not found*", "*1 error*"] ) + def test_cached_exception_doesnt_get_longer(self, pytester: Pytester) -> None: + """Regression test for #12204.""" + pytester.makepyfile( + """ + import pytest + @pytest.fixture(scope="session") + def bad(): 1 / 0 + + def test_1(bad): pass + def test_2(bad): pass + def test_3(bad): pass + """ + ) + + result = pytester.runpytest_inprocess("--tb=native") + assert result.ret == ExitCode.TESTS_FAILED + failures = result.reprec.getfailures() # type: ignore[attr-defined] + assert len(failures) == 3 + lines1 = failures[1].longrepr.reprtraceback.reprentries[0].lines + lines2 = failures[2].longrepr.reprtraceback.reprentries[0].lines + assert len(lines1) == len(lines2) + class TestShowFixtures: def test_funcarg_compat(self, pytester: Pytester) -> None: From 3e81cb2f455fa091bc5a78742d190437f8281c68 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 28 Apr 2024 11:47:37 +0300 Subject: [PATCH 0620/1271] runner: fix tracebacks for failed collectors getting longer and longer Refs https://github.com/pytest-dev/pytest/issues/12204#issuecomment-2081239376 --- changelog/12204.bugfix.rst | 3 +++ src/_pytest/runner.py | 14 ++++++++++---- testing/test_runner.py | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/changelog/12204.bugfix.rst b/changelog/12204.bugfix.rst index b89a04827f0..9690f513a38 100644 --- a/changelog/12204.bugfix.rst +++ b/changelog/12204.bugfix.rst @@ -1,4 +1,7 @@ Fix a regression in pytest 8.0 where tracebacks get longer and longer when multiple tests fail due to a shared higher-scope fixture which raised. +Also fix a similar regression in pytest 5.4 for collectors which raise during setup. + The fix necessitated internal changes which may affect some plugins: - ``FixtureDef.cached_result[2]`` is now a tuple ``(exc, tb)`` instead of ``exc``. +- ``SetupState.stack`` failures are now a tuple ``(exc, tb)`` instead of ``exc``. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index a551f715aa8..bf4d9a37f60 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -5,6 +5,7 @@ import dataclasses import os import sys +import types from typing import Callable from typing import cast from typing import Dict @@ -488,8 +489,13 @@ def __init__(self) -> None: Tuple[ # Node's finalizers. List[Callable[[], object]], - # Node's exception, if its setup raised. - Optional[Union[OutcomeException, Exception]], + # Node's exception and original traceback, if its setup raised. + Optional[ + Tuple[ + Union[OutcomeException, Exception], + Optional[types.TracebackType], + ] + ], ], ] = {} @@ -502,7 +508,7 @@ def setup(self, item: Item) -> None: for col, (finalizers, exc) in self.stack.items(): assert col in needed_collectors, "previous item was not torn down properly" if exc: - raise exc + raise exc[0].with_traceback(exc[1]) for col in needed_collectors[len(self.stack) :]: assert col not in self.stack @@ -511,7 +517,7 @@ def setup(self, item: Item) -> None: try: col.setup() except TEST_OUTCOME as exc: - self.stack[col] = (self.stack[col][0], exc) + self.stack[col] = (self.stack[col][0], (exc, exc.__traceback__)) raise def addfinalizer(self, finalizer: Callable[[], object], node: Node) -> None: diff --git a/testing/test_runner.py b/testing/test_runner.py index 8b41ec28a38..ecb98f2ffc2 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -142,6 +142,43 @@ def raiser(exc): assert isinstance(func.exceptions[0], TypeError) # type: ignore assert isinstance(func.exceptions[1], ValueError) # type: ignore + def test_cached_exception_doesnt_get_longer(self, pytester: Pytester) -> None: + """Regression test for #12204 (the "BTW" case).""" + pytester.makepyfile(test="") + # If the collector.setup() raises, all collected items error with this + # exception. + pytester.makeconftest( + """ + import pytest + + class MyItem(pytest.Item): + def runtest(self) -> None: pass + + class MyBadCollector(pytest.Collector): + def collect(self): + return [ + MyItem.from_parent(self, name="one"), + MyItem.from_parent(self, name="two"), + MyItem.from_parent(self, name="three"), + ] + + def setup(self): + 1 / 0 + + def pytest_collect_file(file_path, parent): + if file_path.name == "test.py": + return MyBadCollector.from_parent(parent, name='bad') + """ + ) + + result = pytester.runpytest_inprocess("--tb=native") + assert result.ret == ExitCode.TESTS_FAILED + failures = result.reprec.getfailures() # type: ignore[attr-defined] + assert len(failures) == 3 + lines1 = failures[1].longrepr.reprtraceback.reprentries[0].lines + lines2 = failures[2].longrepr.reprtraceback.reprentries[0].lines + assert len(lines1) == len(lines2) + class BaseFunctionalTests: def test_passfunction(self, pytester: Pytester) -> None: From 85bc9ca9541e83ba6f171edc60daec9503054633 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 28 Apr 2024 17:03:52 +0300 Subject: [PATCH 0621/1271] pre-commit: remove deprecated `fix-encoding-pragma` hook Deprecated by pre-commit. --- .pre-commit-config.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a80edd28cdc..d54c08136f2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,8 +10,6 @@ repos: hooks: - id: trailing-whitespace - id: end-of-file-fixer - - id: fix-encoding-pragma - args: [--remove] - id: check-yaml - id: debug-statements exclude: _pytest/(debugging|hookspec).py From e847b2a5a99d8d9af77c23c625cdb6121c04ad31 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 28 Apr 2024 17:04:27 +0300 Subject: [PATCH 0622/1271] pre-commit: replace `debug-statements` hook with ruff Ruff supports this functionality so we can use it. --- .pre-commit-config.yaml | 3 --- pyproject.toml | 1 + src/_pytest/debugging.py | 1 + src/_pytest/hookspec.py | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d54c08136f2..0225a6a2216 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,9 +11,6 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - - id: debug-statements - exclude: _pytest/(debugging|hookspec).py - language_version: python3 - repo: https://github.com/adamchainz/blacken-docs rev: 1.16.0 hooks: diff --git a/pyproject.toml b/pyproject.toml index 43efacf09f8..2be02ee7e23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -107,6 +107,7 @@ select = [ "PLE", # pylint error "PLW", # pylint warning "PLR1714", # Consider merging multiple comparisons + "T100", # flake8-debugger ] ignore = [ # bugbear ignore diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 6ed0c5c7aee..7beab563ef8 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -1,4 +1,5 @@ # mypy: allow-untyped-defs +# ruff: noqa: T100 """Interactive debugging with PDB, the Python Debugger.""" import argparse diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index acfe7eb9587..01d3b664080 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -1,4 +1,5 @@ # mypy: allow-untyped-defs +# ruff: noqa: T100 """Hook specifications for pytest plugins which are invoked by pytest itself and by builtin plugins.""" From 940b78232e48c34501cfe6e0bfd0ea6d64f4521b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 28 Apr 2024 17:11:11 +0300 Subject: [PATCH 0623/1271] pre-commit: fix misleading indentation --- .pre-commit-config.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0225a6a2216..6cebeeb4617 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -45,13 +45,13 @@ repos: additional_dependencies: ["tox>=4.9"] - repo: local hooks: - - id: pylint - name: pylint - entry: pylint - language: system - types: [python] - args: ["-rn", "-sn", "--fail-on=I"] - stages: [manual] + - id: pylint + name: pylint + entry: pylint + language: system + types: [python] + args: ["-rn", "-sn", "--fail-on=I"] + stages: [manual] - id: rst name: rst entry: rst-lint --encoding utf-8 From 2ede8778d063756663c508f0a39c949d4943e03d Mon Sep 17 00:00:00 2001 From: dj <112573278+dheerajck@users.noreply.github.com> Date: Mon, 29 Apr 2024 00:22:29 +0530 Subject: [PATCH 0624/1271] Document using PYTEST_VERSION to detect if a code is running inside pytest (#12153) Related to #9502 --- changelog/12153.doc.rst | 1 + doc/en/example/simple.rst | 25 +++++-------------------- 2 files changed, 6 insertions(+), 20 deletions(-) create mode 100644 changelog/12153.doc.rst diff --git a/changelog/12153.doc.rst b/changelog/12153.doc.rst new file mode 100644 index 00000000000..ac36becf9a7 --- /dev/null +++ b/changelog/12153.doc.rst @@ -0,0 +1 @@ +Documented using :envvar:`PYTEST_VERSION` to detect if code is running from within a pytest run. diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 7064f61f0e2..dec1bed5f80 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -405,35 +405,20 @@ Detect if running from within a pytest run Usually it is a bad idea to make application code behave differently if called from a test. But if you absolutely must find out if your application code is -running from a test you can do something like this: +running from a test you can do this: .. code-block:: python - # content of your_module.py + import os - _called_from_test = False - -.. code-block:: python - - # content of conftest.py - - - def pytest_configure(config): - your_module._called_from_test = True - -and then check for the ``your_module._called_from_test`` flag: - -.. code-block:: python - - if your_module._called_from_test: - # called from within a test run + if os.environ.get("PYTEST_VERSION") is not None: + # Things you want to to do if your code is called by pytest. ... else: - # called "normally" + # Things you want to to do if your code is not called by pytest. ... -accordingly in your application. Adding info to test report header -------------------------------------------------------------- From cf90008a1a3924f323543bfdfc2e86c65eeae941 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 08:38:05 -0300 Subject: [PATCH 0625/1271] build(deps): Bump peter-evans/create-pull-request from 6.0.4 to 6.0.5 (#12268) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.0.4 to 6.0.5. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/9153d834b60caba6d51c9b9510b087acf9f33f83...6d6857d36972b65feb161a90e484f2984215f83e) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 6943e207608..1015d01c9c6 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -46,7 +46,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request - uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83 + uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From b660596f614f7a67dcf5f6f863345600840df18e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 29 Apr 2024 20:50:34 +0300 Subject: [PATCH 0626/1271] testing: restore integration testing with pytest-bdd The problem was fixed. --- testing/plugins_integration/requirements.txt | 4 +--- tox.ini | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 9e152f1191b..d60bc5d3c08 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,9 +1,7 @@ anyio[curio,trio]==4.3.0 django==5.0.4 pytest-asyncio==0.23.6 -# Temporarily not installed until pytest-bdd is fixed: -# https://github.com/pytest-dev/pytest/pull/11785 -# pytest-bdd==7.0.1 +pytest-bdd==7.1.2 pytest-cov==5.0.0 pytest-django==4.8.0 pytest-flakes==4.0.5 diff --git a/tox.ini b/tox.ini index cb3ca4b8366..4e1ff111966 100644 --- a/tox.ini +++ b/tox.ini @@ -134,11 +134,9 @@ changedir = testing/plugins_integration deps = -rtesting/plugins_integration/requirements.txt setenv = PYTHONPATH=. -# Command temporarily removed until pytest-bdd is fixed: -# https://github.com/pytest-dev/pytest/pull/11785 -# pytest bdd_wallet.py commands = pip check + pytest bdd_wallet.py pytest --cov=. simple_integration.py pytest --ds=django_settings simple_integration.py pytest --html=simple.html simple_integration.py From da53e297807ddf85c74052b8ae32dc45404d1f63 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 29 Apr 2024 22:30:08 +0000 Subject: [PATCH 0627/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.1 → v0.4.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.1...v0.4.2) - [github.com/pre-commit/mirrors-mypy: v1.9.0 → v1.10.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.9.0...v1.10.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6cebeeb4617..c3ebc88501f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.1" + rev: "v0.4.2" hooks: - id: ruff args: ["--fix"] @@ -21,7 +21,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.9.0 + rev: v1.10.0 hooks: - id: mypy files: ^(src/|testing/|scripts/) From 4788165e69d08e10fc6b9c0124083fb358e2e9b0 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 30 Apr 2024 18:06:26 +0200 Subject: [PATCH 0628/1271] [ruff UP031] Fix to use format specifiers instead of percent format --- bench/bench.py | 2 +- doc/en/conf.py | 2 +- extra/get_issues.py | 4 ++-- src/_pytest/_code/code.py | 2 +- src/_pytest/_io/pprint.py | 2 +- src/_pytest/_io/terminalwriter.py | 2 +- src/_pytest/_py/path.py | 6 +++--- src/_pytest/assertion/rewrite.py | 16 +++++++------- src/_pytest/assertion/util.py | 8 +++---- src/_pytest/cacheprovider.py | 10 ++++----- src/_pytest/capture.py | 2 +- src/_pytest/config/__init__.py | 15 +++++++------ src/_pytest/config/argparsing.py | 20 ++++++++++-------- src/_pytest/debugging.py | 3 +-- src/_pytest/doctest.py | 6 +++--- src/_pytest/fixtures.py | 4 ++-- src/_pytest/helpconfig.py | 6 +++--- src/_pytest/junitxml.py | 8 +++---- src/_pytest/mark/__init__.py | 2 +- src/_pytest/mark/structures.py | 4 ++-- src/_pytest/pastebin.py | 4 ++-- src/_pytest/pytester.py | 18 +++++++++------- src/_pytest/python.py | 2 +- src/_pytest/reports.py | 6 +++--- src/_pytest/runner.py | 2 +- src/_pytest/skipping.py | 8 +++---- src/_pytest/terminal.py | 6 ++++-- testing/_py/test_local.py | 8 +++---- testing/acceptance_test.py | 6 +++--- testing/code/test_excinfo.py | 2 +- testing/freeze/tox_run.py | 2 +- testing/io/test_saferepr.py | 2 +- testing/python/collect.py | 4 ++-- testing/python/fixtures.py | 5 ++--- testing/test_assertion.py | 6 +++--- testing/test_assertrewrite.py | 6 ++---- testing/test_cacheprovider.py | 2 +- testing/test_capture.py | 9 ++++---- testing/test_collection.py | 13 ++++++------ testing/test_config.py | 28 ++++++++++++------------- testing/test_conftest.py | 14 ++++++------- testing/test_debugging.py | 29 +++++++++++++------------ testing/test_doctest.py | 2 +- testing/test_faulthandler.py | 2 +- testing/test_junitxml.py | 35 +++++++++++++++---------------- testing/test_legacypath.py | 2 +- testing/test_monkeypatch.py | 2 +- testing/test_pastebin.py | 2 +- testing/test_skipping.py | 25 +++++++++------------- testing/test_terminal.py | 12 +++++------ testing/test_tmpdir.py | 6 +++--- testing/test_warnings.py | 20 +++++++++--------- 52 files changed, 202 insertions(+), 212 deletions(-) diff --git a/bench/bench.py b/bench/bench.py index 437d3259d83..0bb13c75a15 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -8,7 +8,7 @@ import pytest # noqa: F401 script = sys.argv[1:] if len(sys.argv) > 1 else ["empty.py"] - cProfile.run("pytest.cmdline.main(%r)" % script, "prof") + cProfile.run(f"pytest.cmdline.main({script!r})", "prof") p = pstats.Stats("prof") p.strip_dirs() p.sort_stats("cumulative") diff --git a/doc/en/conf.py b/doc/en/conf.py index 32ecaa17435..af54b468996 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -236,7 +236,7 @@ html_title = "pytest documentation" # A shorter title for the navigation bar. Default is the same as html_title. -html_short_title = "pytest-%s" % release +html_short_title = f"pytest-{release}" # The name of an image file (relative to this directory) to place at the top # of the sidebar. diff --git a/extra/get_issues.py b/extra/get_issues.py index 716233ccba1..a0c2f19adfa 100644 --- a/extra/get_issues.py +++ b/extra/get_issues.py @@ -60,7 +60,7 @@ def report(issues): kind = _get_kind(issue) status = issue["state"] number = issue["number"] - link = "https://github.com/pytest-dev/pytest/issues/%s/" % number + link = f"https://github.com/pytest-dev/pytest/issues/{number}/" print("----") print(status, kind, link) print(title) @@ -69,7 +69,7 @@ def report(issues): # print("\n".join(lines[:3])) # if len(lines) > 3 or len(body) > 240: # print("...") - print("\n\nFound %s open issues" % len(issues)) + print(f"\n\nFound {len(issues)} open issues") if __name__ == "__main__": diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index c65ce79f7e5..b80d53ca5f9 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -940,7 +940,7 @@ def repr_traceback_entry( s = self.get_source(source, line_index, excinfo, short=short) lines.extend(s) if short: - message = "in %s" % (entry.name) + message = f"in {entry.name}" else: message = excinfo and excinfo.typename or "" entry_path = entry.path diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 75e9a7123b5..e637eec59e1 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -616,7 +616,7 @@ def _safe_repr( vrepr = self._safe_repr(v, context, maxlevels, level) append(f"{krepr}: {vrepr}") context.remove(objid) - return "{%s}" % ", ".join(components) + return "{{{}}}".format(", ".join(components)) if (issubclass(typ, list) and r is list.__repr__) or ( issubclass(typ, tuple) and r is tuple.__repr__ diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index deb6ecc3c94..5bcd0592778 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -104,7 +104,7 @@ def markup(self, text: str, **markup: bool) -> str: if self.hasmarkup: esc = [self._esctable[name] for name, on in markup.items() if on] if esc: - text = "".join("\x1b[%sm" % cod for cod in esc) + text + "\x1b[0m" + text = "".join(f"\x1b[{cod}m" for cod in esc) + text + "\x1b[0m" return text def sep( diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 7bb3693f938..27b115cfd87 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -659,7 +659,7 @@ def new(self, **kw): ) if "basename" in kw: if "purebasename" in kw or "ext" in kw: - raise ValueError("invalid specification %r" % kw) + raise ValueError(f"invalid specification {kw!r}") else: pb = kw.setdefault("purebasename", purebasename) try: @@ -705,7 +705,7 @@ def _getbyspec(self, spec: str) -> list[str]: elif name == "ext": res.append(ext) else: - raise ValueError("invalid part specification %r" % name) + raise ValueError(f"invalid part specification {name!r}") return res def dirpath(self, *args, **kwargs): @@ -1026,7 +1026,7 @@ def atime(self): return self.stat().atime def __repr__(self): - return "local(%r)" % self.strpath + return f"local({self.strpath!r})" def __str__(self): """Return string representation of the Path.""" diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 678471ee992..b6f14aa9294 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -101,7 +101,7 @@ def find_spec( state = self.config.stash[assertstate_key] if self._early_rewrite_bailout(name, state): return None - state.trace("find_module called for: %s" % name) + state.trace(f"find_module called for: {name}") # Type ignored because mypy is confused about the `self` binding here. spec = self._find_spec(name, path) # type: ignore @@ -273,7 +273,7 @@ def _warn_already_imported(self, name: str) -> None: self.config.issue_config_time_warning( PytestAssertRewriteWarning( - "Module already imported so cannot be rewritten: %s" % name + f"Module already imported so cannot be rewritten: {name}" ), stacklevel=5, ) @@ -374,21 +374,21 @@ def _read_pyc( return None # Check for invalid or out of date pyc file. if len(data) != (16): - trace("_read_pyc(%s): invalid pyc (too short)" % source) + trace(f"_read_pyc({source}): invalid pyc (too short)") return None if data[:4] != importlib.util.MAGIC_NUMBER: - trace("_read_pyc(%s): invalid pyc (bad magic number)" % source) + trace(f"_read_pyc({source}): invalid pyc (bad magic number)") return None if data[4:8] != b"\x00\x00\x00\x00": - trace("_read_pyc(%s): invalid pyc (unsupported flags)" % source) + trace(f"_read_pyc({source}): invalid pyc (unsupported flags)") return None mtime_data = data[8:12] if int.from_bytes(mtime_data, "little") != mtime & 0xFFFFFFFF: - trace("_read_pyc(%s): out of date" % source) + trace(f"_read_pyc({source}): out of date") return None size_data = data[12:16] if int.from_bytes(size_data, "little") != size & 0xFFFFFFFF: - trace("_read_pyc(%s): invalid pyc (incorrect size)" % source) + trace(f"_read_pyc({source}): invalid pyc (incorrect size)") return None try: co = marshal.load(fp) @@ -396,7 +396,7 @@ def _read_pyc( trace(f"_read_pyc({source}): marshal.load error {e}") return None if not isinstance(co, types.CodeType): - trace("_read_pyc(%s): not a code object" % source) + trace(f"_read_pyc({source}): not a code object") return None return co diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index cb671641041..008eabf9a1f 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -292,7 +292,7 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]: if i > 42: i -= 10 # Provide some context explanation = [ - "Skipping %s identical leading characters in diff, use -v to show" % i + f"Skipping {i} identical leading characters in diff, use -v to show" ] left = left[i:] right = right[i:] @@ -493,7 +493,7 @@ def _compare_eq_dict( common = set_left.intersection(set_right) same = {k: left[k] for k in common if left[k] == right[k]} if same and verbose < 2: - explanation += ["Omitting %s identical items, use -vv to show" % len(same)] + explanation += [f"Omitting {len(same)} identical items, use -vv to show"] elif same: explanation += ["Common items:"] explanation += highlighter(pprint.pformat(same)).splitlines() @@ -560,7 +560,7 @@ def _compare_eq_cls( if same or diff: explanation += [""] if same and verbose < 2: - explanation.append("Omitting %s identical items, use -vv to show" % len(same)) + explanation.append(f"Omitting {len(same)} identical items, use -vv to show") elif same: explanation += ["Matching attributes:"] explanation += highlighter(pprint.pformat(same)).splitlines() @@ -590,7 +590,7 @@ def _notin_text(term: str, text: str, verbose: int = 0) -> List[str]: tail = text[index + len(term) :] correct_text = head + tail diff = _diff_text(text, correct_text, verbose) - newdiff = ["%s is contained here:" % saferepr(term, maxsize=42)] + newdiff = [f"{saferepr(term, maxsize=42)} is contained here:"] for line in diff: if line.startswith("Skipping"): continue diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index e9f66f1f44f..4593e2a8172 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -332,7 +332,7 @@ def get_last_failed_paths(self) -> Set[Path]: def pytest_report_collectionfinish(self) -> Optional[str]: if self.active and self.config.getoption("verbose") >= 0: - return "run-last-failure: %s" % self._report_status + return f"run-last-failure: {self._report_status}" return None def pytest_runtest_logreport(self, report: TestReport) -> None: @@ -588,21 +588,21 @@ def cacheshow(config: Config, session: Session) -> int: dummy = object() basedir = config.cache._cachedir vdir = basedir / Cache._CACHE_PREFIX_VALUES - tw.sep("-", "cache values for %r" % glob) + tw.sep("-", f"cache values for {glob!r}") for valpath in sorted(x for x in vdir.rglob(glob) if x.is_file()): key = str(valpath.relative_to(vdir)) val = config.cache.get(key, dummy) if val is dummy: - tw.line("%s contains unreadable content, will be ignored" % key) + tw.line(f"{key} contains unreadable content, will be ignored") else: - tw.line("%s contains:" % key) + tw.line(f"{key} contains:") for line in pformat(val).splitlines(): tw.line(" " + line) ddir = basedir / Cache._CACHE_PREFIX_DIRS if ddir.is_dir(): contents = sorted(ddir.rglob(glob)) - tw.sep("-", "cache directories for %r" % glob) + tw.sep("-", f"cache directories for {glob!r}") for p in contents: # if p.is_dir(): # print("%s/" % p.relative_to(basedir)) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 3f6a2510348..198d4195020 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -738,7 +738,7 @@ def is_capturing(self) -> Union[str, bool]: if self.is_globally_capturing(): return "global" if self._capture_fixture: - return "fixture %s" % self._capture_fixture.request.fixturename + return f"fixture {self._capture_fixture.request.fixturename}" return False # Global capturing control diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 306b14cce28..c8e8e7d29dd 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -798,7 +798,7 @@ def consider_pluginarg(self, arg: str) -> None: if arg.startswith("no:"): name = arg[3:] if name in essential_plugins: - raise UsageError("plugin %s cannot be disabled" % name) + raise UsageError(f"plugin {name} cannot be disabled") # PR #4304: remove stepwise if cacheprovider is blocked. if name == "cacheprovider": @@ -847,9 +847,9 @@ def import_plugin(self, modname: str, consider_entry_points: bool = False) -> No # "terminal" or "capture". Those plugins are registered under their # basename for historic purposes but must be imported with the # _pytest prefix. - assert isinstance(modname, str), ( - "module name as text required, got %r" % modname - ) + assert isinstance( + modname, str + ), f"module name as text required, got {modname!r}" if self.is_blocked(modname) or self.get_plugin(modname) is not None: return @@ -892,8 +892,7 @@ def _get_plugin_specs_as_list( if isinstance(specs, collections.abc.Sequence): return list(specs) raise UsageError( - "Plugins may be specified as a sequence or a ','-separated string of plugin names. Got: %r" - % specs + f"Plugins may be specified as a sequence or a ','-separated string of plugin names. Got: {specs!r}" ) @@ -1185,7 +1184,7 @@ def notify_exception( res = self.hook.pytest_internalerror(excrepr=excrepr, excinfo=excinfo) if not any(res): for line in str(excrepr).split("\n"): - sys.stderr.write("INTERNALERROR> %s\n" % line) + sys.stderr.write(f"INTERNALERROR> {line}\n") sys.stderr.flush() def cwd_relative_nodeid(self, nodeid: str) -> str: @@ -1435,7 +1434,7 @@ def _checkversion(self) -> None: if not isinstance(minver, str): raise pytest.UsageError( - "%s: 'minversion' must be a single value" % self.inipath + f"{self.inipath}: 'minversion' must be a single value" ) if Version(minver) > Version(pytest.__version__): diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 9006351af72..f270b864c6a 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -313,23 +313,23 @@ def _set_opt_strings(self, opts: Sequence[str]) -> None: for opt in opts: if len(opt) < 2: raise ArgumentError( - "invalid option string %r: " - "must be at least two characters long" % opt, + f"invalid option string {opt!r}: " + "must be at least two characters long", self, ) elif len(opt) == 2: if not (opt[0] == "-" and opt[1] != "-"): raise ArgumentError( - "invalid short option string %r: " - "must be of the form -x, (x any non-dash char)" % opt, + f"invalid short option string {opt!r}: " + "must be of the form -x, (x any non-dash char)", self, ) self._short_opts.append(opt) else: if not (opt[0:2] == "--" and opt[2] != "-"): raise ArgumentError( - "invalid long option string %r: " - "must start with --, followed by non-dash" % opt, + f"invalid long option string {opt!r}: " + "must start with --, followed by non-dash", self, ) self._long_opts.append(opt) @@ -383,7 +383,7 @@ def addoption(self, *opts: str, **attrs: Any) -> None: name for opt in self.options for name in opt.names() ) if conflict: - raise ValueError("option names %s already added" % conflict) + raise ValueError(f"option names {conflict} already added") option = Argument(*opts, **attrs) self._addoption_instance(option, shortupper=False) @@ -441,7 +441,9 @@ def parse_args( # type: ignore if unrecognized: for arg in unrecognized: if arg and arg[0] == "-": - lines = ["unrecognized arguments: %s" % (" ".join(unrecognized))] + lines = [ + "unrecognized arguments: {}".format(" ".join(unrecognized)) + ] for k, v in sorted(self.extra_info.items()): lines.append(f" {k}: {v}") self.error("\n".join(lines)) @@ -520,7 +522,7 @@ def _format_action_invocation(self, action: argparse.Action) -> str: continue if not option.startswith("--"): raise ArgumentError( - 'long optional argument without "--": [%s]' % (option), option + f'long optional argument without "--": [{option}]', option ) xxoption = option[2:] shortened = xxoption.replace("-", "") diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 7beab563ef8..1338ef9f22c 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -181,8 +181,7 @@ def do_continue(self, arg): else: tw.sep( ">", - "PDB continue (IO-capturing resumed for %s)" - % capturing, + f"PDB continue (IO-capturing resumed for {capturing})", ) assert capman is not None capman.resume() diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 7fff99f37b5..35a13676222 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -374,7 +374,7 @@ def repr_failure( # type: ignore[override] ).split("\n") else: inner_excinfo = ExceptionInfo.from_exc_info(failure.exc_info) - lines += ["UNEXPECTED EXCEPTION: %s" % repr(inner_excinfo.value)] + lines += [f"UNEXPECTED EXCEPTION: {inner_excinfo.value!r}"] lines += [ x.strip("\n") for x in traceback.format_exception(*failure.exc_info) ] @@ -382,7 +382,7 @@ def repr_failure( # type: ignore[override] return ReprFailDoctest(reprlocation_lines) def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: - return self.path, self.dtest.lineno, "[doctest] %s" % self.name + return self.path, self.dtest.lineno, f"[doctest] {self.name}" def _get_flag_lookup() -> Dict[str, int]: @@ -563,7 +563,7 @@ def _from_module(self, module, object): module = self.obj except Collector.CollectError: if self.config.getvalue("doctest_ignore_import_errors"): - skip("unable to import module %r" % self.path) + skip(f"unable to import module {self.path!r}") else: raise diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 5f10d565f32..5a290718fe4 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -675,7 +675,7 @@ def node(self): return self._pyfuncitem def __repr__(self) -> str: - return "" % (self.node) + return f"" def _fillfixtures(self) -> None: item = self._pyfuncitem @@ -1897,7 +1897,7 @@ def _showfixtures_main(config: Config, session: "Session") -> None: continue tw.write(f"{argname}", green=True) if fixturedef.scope != "function": - tw.write(" [%s scope]" % fixturedef.scope, cyan=True) + tw.write(f" [{fixturedef.scope} scope]", cyan=True) tw.write(f" -- {prettypath}", yellow=True) tw.write("\n") doc = inspect.getdoc(fixturedef.func) diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 37fbdf04d7e..68e0bd881a7 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -121,11 +121,11 @@ def pytest_cmdline_parse() -> Generator[None, Config, Config]: ) config.trace.root.setwriter(debugfile.write) undo_tracing = config.pluginmanager.enable_tracing() - sys.stderr.write("writing pytest debug information to %s\n" % path) + sys.stderr.write(f"writing pytest debug information to {path}\n") def unset_tracing() -> None: debugfile.close() - sys.stderr.write("wrote pytest debug information to %s\n" % debugfile.name) + sys.stderr.write(f"wrote pytest debug information to {debugfile.name}\n") config.trace.root.setwriter(None) undo_tracing() @@ -185,7 +185,7 @@ def showhelp(config: Config) -> None: if help is None: raise TypeError(f"help argument cannot be None for {name}") spec = f"{name} ({type}):" - tw.write(" %s" % spec) + tw.write(f" {spec}") spec_len = len(spec) if spec_len > (indent_len - 3): # Display help starting at a new line. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 13fc9277aec..011af6100e9 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -53,9 +53,9 @@ def bin_xml_escape(arg: object) -> str: def repl(matchobj: Match[str]) -> str: i = ord(matchobj.group()) if i <= 0xFF: - return "#x%02X" % i + return f"#x{i:02X}" else: - return "#x%04X" % i + return f"#x{i:04X}" # The spec range of valid chars is: # Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] @@ -149,7 +149,7 @@ def record_testreport(self, testreport: TestReport) -> None: self.attrs = temp_attrs def to_xml(self) -> ET.Element: - testcase = ET.Element("testcase", self.attrs, time="%.3f" % self.duration) + testcase = ET.Element("testcase", self.attrs, time=f"{self.duration:.3f}") properties = self.make_properties_node() if properties is not None: testcase.append(properties) @@ -670,7 +670,7 @@ def pytest_sessionfinish(self) -> None: failures=str(self.stats["failure"]), skipped=str(self.stats["skipped"]), tests=str(numtests), - time="%.3f" % suite_time_delta, + time=f"{suite_time_delta:.3f}", timestamp=datetime.fromtimestamp(self.suite_start_time).isoformat(), hostname=platform.node(), ) diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index 77dabd95dec..f5276d8fbda 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -122,7 +122,7 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: parts = line.split(":", 1) name = parts[0] rest = parts[1] if len(parts) == 2 else "" - tw.write("@pytest.mark.%s:" % name, bold=True) + tw.write(f"@pytest.mark.{name}:", bold=True) tw.line(rest) tw.line() config._ensure_unconfigure() diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index a6503bf1d46..3567142a6d9 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -552,9 +552,9 @@ def __getattr__(self, name: str) -> MarkDecorator: fail(f"Unknown '{name}' mark, did you mean 'parametrize'?") warnings.warn( - "Unknown pytest.mark.%s - is this a typo? You can register " + f"Unknown pytest.mark.{name} - is this a typo? You can register " "custom marks to avoid this warning - for details, see " - "https://docs.pytest.org/en/stable/how-to/mark.html" % name, + "https://docs.pytest.org/en/stable/how-to/mark.html", PytestUnknownMarkWarning, 2, ) diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 533d78c9a2a..20cb8ca83c3 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -65,7 +65,7 @@ def pytest_unconfigure(config: Config) -> None: # Write summary. tr.write_sep("=", "Sending information to Paste Service") pastebinurl = create_new_paste(sessionlog) - tr.write_line("pastebin session-log: %s\n" % pastebinurl) + tr.write_line(f"pastebin session-log: {pastebinurl}\n") def create_new_paste(contents: Union[str, bytes]) -> str: @@ -85,7 +85,7 @@ def create_new_paste(contents: Union[str, bytes]) -> str: urlopen(url, data=urlencode(params).encode("ascii")).read().decode("utf-8") ) except OSError as exc_info: # urllib errors - return "bad response: %s" % exc_info + return f"bad response: {exc_info}" m = re.search(r'href="/raw/(\w+)"', response) if m: return f"{url}/show/{m.group(1)}" diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 23f44da69ca..31c6de78195 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -182,13 +182,13 @@ def pytest_runtest_protocol(self, item: Item) -> Generator[None, object, object] leaked_files = [t for t in lines2 if t[0] in new_fds] if leaked_files: error = [ - "***** %s FD leakage detected" % len(leaked_files), + f"***** {len(leaked_files)} FD leakage detected", *(str(f) for f in leaked_files), "*** Before:", *(str(f) for f in lines1), "*** After:", *(str(f) for f in lines2), - "***** %s FD leakage detected" % len(leaked_files), + f"***** {len(leaked_files)} FD leakage detected", "*** function {}:{}: {} ".format(*item.location), "See issue #2366", ] @@ -313,7 +313,7 @@ def popcall(self, name: str) -> RecordedHookCall: del self.calls[i] return call lines = [f"could not find call {name!r}, in:"] - lines.extend([" %s" % x for x in self.calls]) + lines.extend([f" {x}" for x in self.calls]) fail("\n".join(lines)) def getcall(self, name: str) -> RecordedHookCall: @@ -1204,7 +1204,9 @@ def _ensure_basetemp( if str(x).startswith("--basetemp"): break else: - new_args.append("--basetemp=%s" % self.path.parent.joinpath("basetemp")) + new_args.append( + "--basetemp={}".format(self.path.parent.joinpath("basetemp")) + ) return new_args def parseconfig(self, *args: Union[str, "os.PathLike[str]"]) -> Config: @@ -1485,7 +1487,7 @@ def runpytest_subprocess( """ __tracebackhide__ = True p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700) - args = ("--basetemp=%s" % p, *args) + args = (f"--basetemp={p}", *args) plugins = [x for x in self.plugins if isinstance(x, str)] if plugins: args = ("-p", plugins[0], *args) @@ -1593,7 +1595,7 @@ def _match_lines_random( self._log("matched: ", repr(line)) break else: - msg = "line %r not found in output" % line + msg = f"line {line!r} not found in output" self._log(msg) self._fail(msg) @@ -1605,7 +1607,7 @@ def get_lines_after(self, fnline: str) -> Sequence[str]: for i, line in enumerate(self.lines): if fnline == line or fnmatch(line, fnline): return self.lines[i + 1 :] - raise ValueError("line %r not found in output" % fnline) + raise ValueError(f"line {fnline!r} not found in output") def _log(self, *args) -> None: self._log_output.append(" ".join(str(x) for x in args)) @@ -1690,7 +1692,7 @@ def _match_lines( started = True break elif match_func(nextline, line): - self._log("%s:" % match_nickname, repr(line)) + self._log(f"{match_nickname}:", repr(line)) self._log( "{:>{width}}".format("with:", width=wnick), repr(nextline) ) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 5e059f2c4e6..68eceb7f4f3 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -224,7 +224,7 @@ def pytest_pycollect_makeitem( filename, lineno = getfslineno(obj) warnings.warn_explicit( message=PytestCollectionWarning( - "cannot collect %r because it is not a function." % name + f"cannot collect {name!r} because it is not a function." ), category=None, filename=str(filename), diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 70f3212ce7b..2064183d0f7 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -232,10 +232,10 @@ def _report_unserialization_failure( url = "https://github.com/pytest-dev/pytest/issues" stream = StringIO() pprint("-" * 100, stream=stream) - pprint("INTERNALERROR: Unknown entry type returned: %s" % type_name, stream=stream) - pprint("report_name: %s" % report_class, stream=stream) + pprint(f"INTERNALERROR: Unknown entry type returned: {type_name}", stream=stream) + pprint(f"report_name: {report_class}", stream=stream) pprint(reportdict, stream=stream) - pprint("Please report this bug at %s" % url, stream=stream) + pprint(f"Please report this bug at {url}", stream=stream) pprint("-" * 100, stream=stream) raise RuntimeError(stream.getvalue()) diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index bf4d9a37f60..eb444f2e322 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -90,7 +90,7 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None: if not durations: tr.write_sep("=", "slowest durations") else: - tr.write_sep("=", "slowest %s durations" % durations) + tr.write_sep("=", f"slowest {durations} durations") dlist = dlist[:durations] for i, rep in enumerate(dlist): diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 188dcae3f1c..54500b2851b 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -117,7 +117,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool, result = eval(condition_code, globals_) except SyntaxError as exc: msglines = [ - "Error evaluating %r condition" % mark.name, + f"Error evaluating {mark.name!r} condition", " " + condition, " " + " " * (exc.offset or 0) + "^", "SyntaxError: invalid syntax", @@ -125,7 +125,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool, fail("\n".join(msglines), pytrace=False) except Exception as exc: msglines = [ - "Error evaluating %r condition" % mark.name, + f"Error evaluating {mark.name!r} condition", " " + condition, *traceback.format_exception_only(type(exc), exc), ] @@ -137,7 +137,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool, result = bool(condition) except Exception as exc: msglines = [ - "Error evaluating %r condition as a boolean" % mark.name, + f"Error evaluating {mark.name!r} condition as a boolean", *traceback.format_exception_only(type(exc), exc), ] fail("\n".join(msglines), pytrace=False) @@ -149,7 +149,7 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool, else: # XXX better be checked at collection time msg = ( - "Error evaluating %r: " % mark.name + f"Error evaluating {mark.name!r}: " + "you need to specify reason=STRING when using booleans as conditions." ) fail(msg, pytrace=False) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index f4b6e9b40ec..d05eb7e3dce 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -640,7 +640,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: self._write_progress_information_filling_space() else: self.ensure_newline() - self._tw.write("[%s]" % rep.node.gateway.id) + self._tw.write(f"[{rep.node.gateway.id}]") if self._show_progress_info: self._tw.write( self._get_progress_information_message() + " ", cyan=True @@ -818,7 +818,9 @@ def pytest_report_header(self, config: Config) -> List[str]: plugininfo = config.pluginmanager.list_plugin_distinfo() if plugininfo: - result.append("plugins: %s" % ", ".join(_plugin_nameversions(plugininfo))) + result.append( + "plugins: {}".format(", ".join(_plugin_nameversions(plugininfo))) + ) return result def pytest_collection_finish(self, session: "Session") -> None: diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index ad2526571e6..243219babc9 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -551,7 +551,7 @@ def batch_make_numbered_dirs(rootdir, repeats): for i in range(repeats): dir_ = local.make_numbered_dir(prefix="repro-", rootdir=rootdir) file_ = dir_.join("foo") - file_.write_text("%s" % i, encoding="utf-8") + file_.write_text(f"{i}", encoding="utf-8") actual = int(file_.read_text(encoding="utf-8")) assert ( actual == i @@ -563,9 +563,9 @@ def batch_make_numbered_dirs(rootdir, repeats): class TestLocalPath(CommonFSTests): def test_join_normpath(self, tmpdir): assert tmpdir.join(".") == tmpdir - p = tmpdir.join("../%s" % tmpdir.basename) + p = tmpdir.join(f"../{tmpdir.basename}") assert p == tmpdir - p = tmpdir.join("..//%s/" % tmpdir.basename) + p = tmpdir.join(f"..//{tmpdir.basename}/") assert p == tmpdir @skiponwin32 @@ -722,7 +722,7 @@ def test_write_and_ensure(self, path1): @pytest.mark.parametrize("bin", (False, True)) def test_dump(self, tmpdir, bin): - path = tmpdir.join("dumpfile%s" % int(bin)) + path = tmpdir.join(f"dumpfile{int(bin)}") try: d = {"answer": 42} path.dump(d, bin=bin) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 8f001bc2401..ac7fab3d27a 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -400,7 +400,7 @@ def test_docstring_on_hookspec(self) -> None: for name, value in vars(hookspec).items(): if name.startswith("pytest_"): - assert value.__doc__, "no docstring for %s" % name + assert value.__doc__, f"no docstring for {name}" def test_initialization_error_issue49(self, pytester: Pytester) -> None: pytester.makeconftest( @@ -973,7 +973,7 @@ def test_calls_showall(self, pytester: Pytester, mock_timing) -> None: for x in tested: for y in ("call",): # 'setup', 'call', 'teardown': for line in result.stdout.lines: - if ("test_%s" % x) in line and y in line: + if (f"test_{x}") in line and y in line: break else: raise AssertionError(f"not found {x} {y}") @@ -986,7 +986,7 @@ def test_calls_showall_verbose(self, pytester: Pytester, mock_timing) -> None: for x in "123": for y in ("call",): # 'setup', 'call', 'teardown': for line in result.stdout.lines: - if ("test_%s" % x) in line and y in line: + if (f"test_{x}") in line and y in line: break else: raise AssertionError(f"not found {x} {y}") diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index dd4bd22c8b8..f2c689a137e 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1406,7 +1406,7 @@ def g(): mod.f() # emulate the issue described in #1984 - attr = "__%s__" % reason + attr = f"__{reason}__" getattr(excinfo.value, attr).__traceback__ = None r = excinfo.getrepr() diff --git a/testing/freeze/tox_run.py b/testing/freeze/tox_run.py index 7fd63cf1218..1230fcce140 100644 --- a/testing/freeze/tox_run.py +++ b/testing/freeze/tox_run.py @@ -10,4 +10,4 @@ executable = os.path.join(os.getcwd(), "dist", "runtests_script", "runtests_script") if sys.platform.startswith("win"): executable += ".exe" - sys.exit(os.system("%s tests" % executable)) + sys.exit(os.system(f"{executable} tests")) diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index 5d270f1756c..f627434c4e9 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -144,7 +144,7 @@ def test_big_repr(): def test_repr_on_newstyle() -> None: class Function: def __repr__(self): - return "<%s>" % (self.name) # type: ignore[attr-defined] + return f"<{self.name}>" # type: ignore[attr-defined] assert saferepr(Function()) diff --git a/testing/python/collect.py b/testing/python/collect.py index 745550f0775..a1a7dc8978d 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -36,9 +36,9 @@ def test_import_duplicate(self, pytester: Pytester) -> None: [ "*import*mismatch*", "*imported*test_whatever*", - "*%s*" % p1, + f"*{p1}*", "*not the same*", - "*%s*" % p2, + f"*{p2}*", "*HINT*", ] ) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 77914fed75d..aec0deb99a1 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2268,18 +2268,17 @@ def test_override_parametrized_fixture_issue_979( This was a regression introduced in the fix for #736. """ pytester.makepyfile( - """ + f""" import pytest @pytest.fixture(params=[1, 2]) def fixt(request): return request.param - @pytest.mark.parametrize(%s, [(3, 'x'), (4, 'x')]) + @pytest.mark.parametrize({param_args}, [(3, 'x'), (4, 'x')]) def test_foo(fixt, val): pass """ - % param_args ) reprec = pytester.inline_run() reprec.assertoutcome(passed=2) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index ef4e36644d9..a8960436b55 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -101,7 +101,7 @@ def test(check_first): """, } pytester.makepyfile(**contents) - result = pytester.runpytest_subprocess("--assert=%s" % mode) + result = pytester.runpytest_subprocess(f"--assert={mode}") if mode == "plain": expected = "E AssertionError" elif mode == "rewrite": @@ -163,7 +163,7 @@ def test_foo(check_first): """, } pytester.makepyfile(**contents) - result = pytester.runpytest_subprocess("--assert=%s" % mode) + result = pytester.runpytest_subprocess(f"--assert={mode}") if mode == "plain": expected = "E AssertionError" elif mode == "rewrite": @@ -280,7 +280,7 @@ def test2(check_first2): } pytester.makepyfile(**contents) result = pytester.run( - sys.executable, "mainwrapper.py", "-s", "--assert=%s" % mode + sys.executable, "mainwrapper.py", "-s", f"--assert={mode}" ) if mode == "plain": expected = "E AssertionError" diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 7acc8cdf1d9..bedf6e27606 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -308,9 +308,7 @@ def test_foo(): ) result = pytester.runpytest() assert result.ret == 1 - result.stdout.fnmatch_lines( - ["*AssertionError*%s*" % repr((1, 2)), "*assert 1 == 2*"] - ) + result.stdout.fnmatch_lines([f"*AssertionError*{(1, 2)!r}*", "*assert 1 == 2*"]) def test_assertion_message_expr(self, pytester: Pytester) -> None: pytester.makepyfile( @@ -908,7 +906,7 @@ def test_optimized(): assert test_optimized.__doc__ is None""" ) p = make_numbered_dir(root=Path(pytester.path), prefix="runpytest-") - tmp = "--basetemp=%s" % p + tmp = f"--basetemp={p}" with monkeypatch.context() as mp: mp.setenv("PYTHONOPTIMIZE", "2") mp.delenv("PYTHONDONTWRITEBYTECODE", raising=False) diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 304e5414abc..6c18c358a80 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -191,7 +191,7 @@ def test_cache_reportheader( monkeypatch.delenv("TOX_ENV_DIR", raising=False) expected = ".pytest_cache" result = pytester.runpytest("-v") - result.stdout.fnmatch_lines(["cachedir: %s" % expected]) + result.stdout.fnmatch_lines([f"cachedir: {expected}"]) def test_cache_reportheader_external_abspath( diff --git a/testing/test_capture.py b/testing/test_capture.py index 0521c3b6b04..b6c206ec47c 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -103,16 +103,15 @@ def test_init_capturing(self): def test_capturing_unicode(pytester: Pytester, method: str) -> None: obj = "'b\u00f6y'" pytester.makepyfile( - """\ + f"""\ # taken from issue 227 from nosetests def test_unicode(): import sys print(sys.stdout) - print(%s) + print({obj}) """ - % obj ) - result = pytester.runpytest("--capture=%s" % method) + result = pytester.runpytest(f"--capture={method}") result.stdout.fnmatch_lines(["*1 passed*"]) @@ -124,7 +123,7 @@ def test_unicode(): print('b\\u00f6y') """ ) - result = pytester.runpytest("--capture=%s" % method) + result = pytester.runpytest(f"--capture={method}") result.stdout.fnmatch_lines(["*1 passed*"]) diff --git a/testing/test_collection.py b/testing/test_collection.py index 1491ec85990..9caca622c90 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -275,14 +275,14 @@ def test_testpaths_ini(self, pytester: Pytester, monkeypatch: MonkeyPatch) -> No # collects the tests for dirname in ("a", "b", "c"): items, reprec = pytester.inline_genitems(tmp_path.joinpath(dirname)) - assert [x.name for x in items] == ["test_%s" % dirname] + assert [x.name for x in items] == [f"test_{dirname}"] # changing cwd to each subdirectory and running pytest without # arguments collects the tests in that directory normally for dirname in ("a", "b", "c"): monkeypatch.chdir(pytester.path.joinpath(dirname)) items, reprec = pytester.inline_genitems() - assert [x.name for x in items] == ["test_%s" % dirname] + assert [x.name for x in items] == [f"test_{dirname}"] class TestCollectPluginHookRelay: @@ -572,7 +572,7 @@ def test_method(self): def test_collect_custom_nodes_multi_id(self, pytester: Pytester) -> None: p = pytester.makepyfile("def test_func(): pass") pytester.makeconftest( - """ + f""" import pytest class SpecialItem(pytest.Item): def runtest(self): @@ -581,10 +581,9 @@ class SpecialFile(pytest.File): def collect(self): return [SpecialItem.from_parent(name="check", parent=self)] def pytest_collect_file(file_path, parent): - if file_path.name == %r: + if file_path.name == {p.name!r}: return SpecialFile.from_parent(path=file_path, parent=parent) """ - % p.name ) id = p.name @@ -862,7 +861,7 @@ def runtest(self): result = pytester.runpytest() assert result.ret == 0 result.stdout.fnmatch_lines(["*2 passed*"]) - res = pytester.runpytest("%s::item2" % p.name) + res = pytester.runpytest(f"{p.name}::item2") res.stdout.fnmatch_lines(["*1 passed*"]) @@ -1444,7 +1443,7 @@ def test_nodeid(request): symlink_to_sub = out_of_tree.joinpath("symlink_to_sub") symlink_or_skip(sub, symlink_to_sub) os.chdir(sub) - result = pytester.runpytest("-vs", "--rootdir=%s" % sub, symlink_to_sub) + result = pytester.runpytest("-vs", f"--rootdir={sub}", symlink_to_sub) result.stdout.fnmatch_lines( [ # Should not contain "sub/"! diff --git a/testing/test_config.py b/testing/test_config.py index 147c2cb851c..776c8424a1a 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -67,13 +67,12 @@ def test_setupcfg_uses_toolpytest_with_pytest(self, pytester: Pytester) -> None: p1 = pytester.makepyfile("def test(): pass") pytester.makefile( ".cfg", - setup=""" + setup=f""" [tool:pytest] - testpaths=%s + testpaths={p1.name} [pytest] testpaths=ignored - """ - % p1.name, + """, ) result = pytester.runpytest() result.stdout.fnmatch_lines(["configfile: setup.cfg", "* 1 passed in *"]) @@ -838,11 +837,10 @@ def pytest_addoption(parser): ) if str_val != "no-ini": pytester.makeini( - """ + f""" [pytest] - strip=%s + strip={str_val} """ - % str_val ) config = pytester.parseconfig() assert config.getini("strip") is bool_val @@ -1290,8 +1288,8 @@ def test_invalid_options_show_extra_information(pytester: Pytester) -> None: result.stderr.fnmatch_lines( [ "*error: unrecognized arguments: --invalid-option*", - "* inifile: %s*" % pytester.path.joinpath("tox.ini"), - "* rootdir: %s*" % pytester.path, + "* inifile: {}*".format(pytester.path.joinpath("tox.ini")), + f"* rootdir: {pytester.path}*", ] ) @@ -1423,8 +1421,8 @@ def pytest_load_initial_conftests(self): def test_get_plugin_specs_as_list() -> None: def exp_match(val: object) -> str: return ( - "Plugins may be specified as a sequence or a ','-separated string of plugin names. Got: %s" - % re.escape(repr(val)) + f"Plugins may be specified as a sequence or a ','-separated string " + f"of plugin names. Got: {re.escape(repr(val))}" ) with pytest.raises(pytest.UsageError, match=exp_match({"foo"})): @@ -1837,10 +1835,10 @@ def test_addopts_before_initini( self, monkeypatch: MonkeyPatch, _config_for_test, _sys_snapshot ) -> None: cache_dir = ".custom_cache" - monkeypatch.setenv("PYTEST_ADDOPTS", "-o cache_dir=%s" % cache_dir) + monkeypatch.setenv("PYTEST_ADDOPTS", f"-o cache_dir={cache_dir}") config = _config_for_test config._preparse([], addopts=True) - assert config._override_ini == ["cache_dir=%s" % cache_dir] + assert config._override_ini == [f"cache_dir={cache_dir}"] def test_addopts_from_env_not_concatenated( self, monkeypatch: MonkeyPatch, _config_for_test @@ -2048,7 +2046,7 @@ class DummyPlugin: ) def test_config_blocked_default_plugins(pytester: Pytester, plugin: str) -> None: p = pytester.makepyfile("def test(): pass") - result = pytester.runpytest(str(p), "-pno:%s" % plugin) + result = pytester.runpytest(str(p), f"-pno:{plugin}") if plugin == "python": assert result.ret == ExitCode.USAGE_ERROR @@ -2065,7 +2063,7 @@ def test_config_blocked_default_plugins(pytester: Pytester, plugin: str) -> None result.stdout.fnmatch_lines(["* 1 passed in *"]) p = pytester.makepyfile("def test(): assert 0") - result = pytester.runpytest(str(p), "-pno:%s" % plugin) + result = pytester.runpytest(str(p), f"-pno:{plugin}") assert result.ret == ExitCode.TESTS_FAILED if plugin != "terminal": result.stdout.fnmatch_lines(["* 1 failed in *"]) diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 3116dfe2584..a3ebcbb7862 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -280,7 +280,7 @@ def pytest_addoption(parser): ), encoding="utf-8", ) - result = pytester.runpytest("-h", "--confcutdir=%s" % x, x) + result = pytester.runpytest("-h", f"--confcutdir={x}", x) result.stdout.fnmatch_lines(["*--xyz*"]) result.stdout.no_fnmatch_line("*warning: could not load initial*") @@ -380,7 +380,7 @@ def fixture(): """ ), } - pytester.makepyfile(**{"real/%s" % k: v for k, v in source.items()}) + pytester.makepyfile(**{f"real/{k}": v for k, v in source.items()}) # Create a build directory that contains symlinks to actual files # but doesn't symlink actual directories. @@ -402,7 +402,7 @@ def test_conftest_badcase(pytester: Pytester) -> None: """Check conftest.py loading when directory casing is wrong (#5792).""" pytester.path.joinpath("JenkinsRoot/test").mkdir(parents=True) source = {"setup.py": "", "test/__init__.py": "", "test/conftest.py": ""} - pytester.makepyfile(**{"JenkinsRoot/%s" % k: v for k, v in source.items()}) + pytester.makepyfile(**{f"JenkinsRoot/{k}": v for k, v in source.items()}) os.chdir(pytester.path.joinpath("jenkinsroot/test")) result = pytester.runpytest() @@ -638,9 +638,9 @@ def test_parsefactories_relative_node_ids( ) -> None: """#616""" dirs = self._setup_tree(pytester) - print("pytest run in cwd: %s" % (dirs[chdir].relative_to(pytester.path))) - print("pytestarg : %s" % testarg) - print("expected pass : %s" % expect_ntests_passed) + print(f"pytest run in cwd: {dirs[chdir].relative_to(pytester.path)}") + print(f"pytestarg : {testarg}") + print(f"expected pass : {expect_ntests_passed}") os.chdir(dirs[chdir]) reprec = pytester.inline_run( testarg, @@ -699,7 +699,7 @@ def out_of_reach(): pass args = [str(src)] if confcutdir: - args = ["--confcutdir=%s" % root.joinpath(confcutdir)] + args = [f"--confcutdir={root.joinpath(confcutdir)}"] result = pytester.runpytest(*args) match = "" if passed: diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 53ebadbdba4..a99336c75a6 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -221,7 +221,7 @@ def test_not_called_due_to_quit(): pass """ ) - child = pytester.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest(f"--pdb {p1}") child.expect("captured stdout") child.expect("get rekt") child.expect("captured stderr") @@ -246,7 +246,7 @@ def test_1(): assert False """ ) - child = pytester.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest(f"--pdb {p1}") child.expect("Pdb") output = child.before.decode("utf8") child.sendeof() @@ -283,7 +283,7 @@ def test_1(): assert False """ ) - child = pytester.spawn_pytest("--show-capture=all --pdb -p no:logging %s" % p1) + child = pytester.spawn_pytest(f"--show-capture=all --pdb -p no:logging {p1}") child.expect("get rekt") output = child.before.decode("utf8") assert "captured log" not in output @@ -303,7 +303,7 @@ def test_1(): pytest.raises(ValueError, globalfunc) """ ) - child = pytester.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest(f"--pdb {p1}") child.expect(".*def test_1") child.expect(".*pytest.raises.*globalfunc") child.expect("Pdb") @@ -320,7 +320,7 @@ def test_pdb_interaction_on_collection_issue181(self, pytester: Pytester) -> Non xxx """ ) - child = pytester.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest(f"--pdb {p1}") # child.expect(".*import pytest.*") child.expect("Pdb") child.sendline("c") @@ -335,7 +335,7 @@ def pytest_runtest_protocol(): """ ) p1 = pytester.makepyfile("def test_func(): pass") - child = pytester.spawn_pytest("--pdb %s" % p1) + child = pytester.spawn_pytest(f"--pdb {p1}") child.expect("Pdb") # INTERNALERROR is only displayed once via terminal reporter. @@ -461,7 +461,7 @@ def test_1(capsys, caplog): assert 0 """ ) - child = pytester.spawn_pytest("--pdb %s" % str(p1)) + child = pytester.spawn_pytest(f"--pdb {p1!s}") child.send("caplog.record_tuples\n") child.expect_exact( "[('test_pdb_with_caplog_on_pdb_invocation', 30, 'some_warning')]" @@ -501,7 +501,7 @@ def function_1(): ''' """ ) - child = pytester.spawn_pytest("--doctest-modules --pdb %s" % p1) + child = pytester.spawn_pytest(f"--doctest-modules --pdb {p1}") child.expect("Pdb") assert "UNEXPECTED EXCEPTION: AssertionError()" in child.before.decode("utf8") @@ -528,7 +528,7 @@ def function_1(): ) # NOTE: does not use pytest.set_trace, but Python's patched pdb, # therefore "-s" is required. - child = pytester.spawn_pytest("--doctest-modules --pdb -s %s" % p1) + child = pytester.spawn_pytest(f"--doctest-modules --pdb -s {p1}") child.expect("Pdb") child.sendline("q") rest = child.read().decode("utf8") @@ -621,7 +621,7 @@ def test_1(): pytest.fail("expected_failure") """ ) - child = pytester.spawn_pytest("--pdbcls=mytest:CustomPdb %s" % str(p1)) + child = pytester.spawn_pytest(f"--pdbcls=mytest:CustomPdb {p1!s}") child.expect(r"PDB set_trace \(IO-capturing turned off\)") child.expect(r"\n\(Pdb") child.sendline("debug foo()") @@ -658,7 +658,7 @@ def test_1(): pytest.set_trace() """ ) - child = pytester.spawn_pytest("-s %s" % p1) + child = pytester.spawn_pytest(f"-s {p1}") child.expect(r">>> PDB set_trace >>>") child.expect("Pdb") child.sendline("c") @@ -914,7 +914,7 @@ def test_foo(): """ ) monkeypatch.setenv("PYTHONPATH", str(pytester.path)) - child = pytester.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1)) + child = pytester.spawn_pytest(f"--pdbcls=custom_pdb:CustomPdb {p1!s}") child.expect("__init__") child.expect("custom set_trace>") @@ -1208,8 +1208,7 @@ def test_inner({fixture}): child.expect("Pdb") before = child.before.decode("utf8") assert ( - "> PDB set_trace (IO-capturing turned off for fixture %s) >" % (fixture) - in before + f"> PDB set_trace (IO-capturing turned off for fixture {fixture}) >" in before ) # Test that capturing is really suspended. @@ -1225,7 +1224,7 @@ def test_inner({fixture}): TestPDB.flush(child) assert child.exitstatus == 0 assert "= 1 passed in" in rest - assert "> PDB continue (IO-capturing resumed for fixture %s) >" % (fixture) in rest + assert f"> PDB continue (IO-capturing resumed for fixture {fixture}) >" in rest def test_pdbcls_via_local_module(pytester: Pytester) -> None: diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 58fce244f45..de5d1353163 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1160,7 +1160,7 @@ def makeit(doctest): pytester.maketxtfile(doctest) else: assert mode == "module" - pytester.makepyfile('"""\n%s"""' % doctest) + pytester.makepyfile(f'"""\n{doctest}"""') return makeit diff --git a/testing/test_faulthandler.py b/testing/test_faulthandler.py index a3363de9816..e5016976130 100644 --- a/testing/test_faulthandler.py +++ b/testing/test_faulthandler.py @@ -101,7 +101,7 @@ def test_timeout(): result = pytester.runpytest_subprocess(*args) tb_output = "most recent call first" if enabled: - result.stderr.fnmatch_lines(["*%s*" % tb_output]) + result.stderr.fnmatch_lines([f"*{tb_output}*"]) else: assert tb_output not in result.stderr.str() result.stdout.fnmatch_lines(["*1 passed*"]) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 3b92d65bdb9..f8742dc2e3c 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -44,7 +44,7 @@ def __call__( if family: args = ("-o", "junit_family=" + family, *args) xml_path = self.pytester.path.joinpath("junit.xml") - result = self.pytester.runpytest("--junitxml=%s" % xml_path, *args) + result = self.pytester.runpytest(f"--junitxml={xml_path}", *args) if family == "xunit2": with xml_path.open(encoding="utf-8") as f: self.schema.validate(f) @@ -520,7 +520,7 @@ def test_fail(): ) result, dom = run_and_parse( - "-o", "junit_logging=%s" % junit_logging, family=xunit_family + "-o", f"junit_logging={junit_logging}", family=xunit_family ) assert result.ret, "Expected ret > 0" node = dom.find_first_by_tag("testsuite") @@ -605,11 +605,11 @@ def test_func(arg1): for index, char in enumerate("<&'"): tnode = node.find_nth_by_tag("testcase", index) tnode.assert_attr( - classname="test_failure_escape", name="test_func[%s]" % char + classname="test_failure_escape", name=f"test_func[{char}]" ) sysout = tnode.find_first_by_tag("system-out") text = sysout.text - assert "%s\n" % char in text + assert f"{char}\n" in text @parametrize_families def test_junit_prefixing( @@ -694,7 +694,7 @@ def test_fail(): assert 0 """ ) - result, dom = run_and_parse("-o", "junit_logging=%s" % junit_logging) + result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") node = dom.find_first_by_tag("testsuite") tnode = node.find_first_by_tag("testcase") if junit_logging in ["system-err", "out-err", "all"]: @@ -764,13 +764,12 @@ def test_collect_error( def test_unicode(self, pytester: Pytester, run_and_parse: RunAndParse) -> None: value = "hx\xc4\x85\xc4\x87\n" pytester.makepyfile( - """\ + f"""\ # coding: latin1 def test_hello(): - print(%r) + print({value!r}) assert 0 """ - % value ) result, dom = run_and_parse() assert result.ret == 1 @@ -805,7 +804,7 @@ def test_pass(): print('hello-stdout') """ ) - result, dom = run_and_parse("-o", "junit_logging=%s" % junit_logging) + result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": @@ -829,7 +828,7 @@ def test_pass(): sys.stderr.write('hello-stderr') """ ) - result, dom = run_and_parse("-o", "junit_logging=%s" % junit_logging) + result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": @@ -858,7 +857,7 @@ def test_function(arg): pass """ ) - result, dom = run_and_parse("-o", "junit_logging=%s" % junit_logging) + result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": @@ -888,7 +887,7 @@ def test_function(arg): pass """ ) - result, dom = run_and_parse("-o", "junit_logging=%s" % junit_logging) + result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": @@ -919,7 +918,7 @@ def test_function(arg): sys.stdout.write('hello-stdout call') """ ) - result, dom = run_and_parse("-o", "junit_logging=%s" % junit_logging) + result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": @@ -1013,7 +1012,7 @@ def test_print_nullbyte(): """ ) xmlf = pytester.path.joinpath("junit.xml") - pytester.runpytest("--junitxml=%s" % xmlf, "-o", "junit_logging=%s" % junit_logging) + pytester.runpytest(f"--junitxml={xmlf}", "-o", f"junit_logging={junit_logging}") text = xmlf.read_text(encoding="utf-8") assert "\x00" not in text if junit_logging == "system-out": @@ -1035,7 +1034,7 @@ def test_print_nullbyte(): """ ) xmlf = pytester.path.joinpath("junit.xml") - pytester.runpytest("--junitxml=%s" % xmlf, "-o", "junit_logging=%s" % junit_logging) + pytester.runpytest(f"--junitxml={xmlf}", "-o", f"junit_logging={junit_logging}") text = xmlf.read_text(encoding="utf-8") if junit_logging == "system-out": assert "#x0" in text @@ -1071,9 +1070,9 @@ def test_invalid_xml_escape() -> None: for i in invalid: got = bin_xml_escape(chr(i)) if i <= 0xFF: - expected = "#x%02X" % i + expected = f"#x{i:02X}" else: - expected = "#x%04X" % i + expected = f"#x{i:04X}" assert got == expected for i in valid: assert chr(i) == bin_xml_escape(chr(i)) @@ -1748,7 +1747,7 @@ def test_func(): """ ) result, dom = run_and_parse( - "-o", "junit_logging=%s" % junit_logging, family=xunit_family + "-o", f"junit_logging={junit_logging}", family=xunit_family ) assert result.ret == 1 node = dom.find_first_by_tag("testcase") diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index 49e620c1138..f7f45dbf02e 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -79,7 +79,7 @@ def test_1(tmpdir): assert os.path.realpath(str(tmpdir)) == str(tmpdir) """ ) - result = pytester.runpytest("-s", p, "--basetemp=%s/bt" % linktemp) + result = pytester.runpytest("-s", p, f"--basetemp={linktemp}/bt") assert not result.ret diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 12be774beca..2ad3ccc4ddc 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -442,7 +442,7 @@ def test_syspath_prepend_with_namespace_packages( lib = ns.joinpath(dirname) lib.mkdir() lib.joinpath("__init__.py").write_text( - "def check(): return %r" % dirname, encoding="utf-8" + f"def check(): return {dirname!r}", encoding="utf-8" ) monkeypatch.syspath_prepend("hello") diff --git a/testing/test_pastebin.py b/testing/test_pastebin.py index 651a04da84a..9ca0da8f69d 100644 --- a/testing/test_pastebin.py +++ b/testing/test_pastebin.py @@ -171,7 +171,7 @@ def test_create_new_paste(self, pastebin, mocked_urlopen) -> None: assert type(data) is bytes lexer = "text" assert url == "https://bpa.st" - assert "lexer=%s" % lexer in data.decode() + assert f"lexer={lexer}" in data.decode() assert "code=full-paste-contents" in data.decode() assert "expiry=1week" in data.decode() diff --git a/testing/test_skipping.py b/testing/test_skipping.py index a1511b26d1c..459216a6d6b 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -297,13 +297,12 @@ class TestXFail: @pytest.mark.parametrize("strict", [True, False]) def test_xfail_simple(self, pytester: Pytester, strict: bool) -> None: item = pytester.getitem( - """ + f""" import pytest - @pytest.mark.xfail(strict=%s) + @pytest.mark.xfail(strict={strict}) def test_func(): assert 0 """ - % strict ) reports = runtestprotocol(item, log=False) assert len(reports) == 3 @@ -630,15 +629,14 @@ def test_foo(): @pytest.mark.parametrize("strict", [True, False]) def test_strict_xfail(self, pytester: Pytester, strict: bool) -> None: p = pytester.makepyfile( - """ + f""" import pytest - @pytest.mark.xfail(reason='unsupported feature', strict=%s) + @pytest.mark.xfail(reason='unsupported feature', strict={strict}) def test_foo(): with open('foo_executed', 'w', encoding='utf-8'): pass # make sure test executes """ - % strict ) result = pytester.runpytest(p, "-rxX") if strict: @@ -658,14 +656,13 @@ def test_foo(): @pytest.mark.parametrize("strict", [True, False]) def test_strict_xfail_condition(self, pytester: Pytester, strict: bool) -> None: p = pytester.makepyfile( - """ + f""" import pytest - @pytest.mark.xfail(False, reason='unsupported feature', strict=%s) + @pytest.mark.xfail(False, reason='unsupported feature', strict={strict}) def test_foo(): pass """ - % strict ) result = pytester.runpytest(p, "-rxX") result.stdout.fnmatch_lines(["*1 passed*"]) @@ -674,14 +671,13 @@ def test_foo(): @pytest.mark.parametrize("strict", [True, False]) def test_xfail_condition_keyword(self, pytester: Pytester, strict: bool) -> None: p = pytester.makepyfile( - """ + f""" import pytest - @pytest.mark.xfail(condition=False, reason='unsupported feature', strict=%s) + @pytest.mark.xfail(condition=False, reason='unsupported feature', strict={strict}) def test_foo(): pass """ - % strict ) result = pytester.runpytest(p, "-rxX") result.stdout.fnmatch_lines(["*1 passed*"]) @@ -692,11 +688,10 @@ def test_strict_xfail_default_from_file( self, pytester: Pytester, strict_val ) -> None: pytester.makeini( - """ + f""" [pytest] - xfail_strict = %s + xfail_strict = {strict_val} """ - % strict_val ) p = pytester.makepyfile( """ diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 170f1efcf91..dd5fa4bf679 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1421,7 +1421,7 @@ def test_opt(arg): s = result.stdout.str() assert "arg = 42" not in s assert "x = 0" not in s - result.stdout.fnmatch_lines(["*%s:8*" % p.name, " assert x", "E assert*"]) + result.stdout.fnmatch_lines([f"*{p.name}:8*", " assert x", "E assert*"]) result = pytester.runpytest() s = result.stdout.str() assert "x = 0" in s @@ -1497,8 +1497,8 @@ def test_func(): """ ) for tbopt in ["long", "short", "no"]: - print("testing --tb=%s..." % tbopt) - result = pytester.runpytest("-rN", "--tb=%s" % tbopt) + print(f"testing --tb={tbopt}...") + result = pytester.runpytest("-rN", f"--tb={tbopt}") s = result.stdout.str() if tbopt == "long": assert "print(6*7)" in s @@ -1528,7 +1528,7 @@ def test_func2(): result = pytester.runpytest("--tb=line") bn = p.name result.stdout.fnmatch_lines( - ["*%s:3: IndexError*" % bn, "*%s:8: AssertionError: hello*" % bn] + [f"*{bn}:3: IndexError*", f"*{bn}:8: AssertionError: hello*"] ) s = result.stdout.str() assert "def test_func2" not in s @@ -1544,7 +1544,7 @@ def test_func1(): result = pytester.runpytest("--tb=line") result.stdout.str() bn = p.name - result.stdout.fnmatch_lines(["*%s:3: Failed: test_func1" % bn]) + result.stdout.fnmatch_lines([f"*{bn}:3: Failed: test_func1"]) def test_pytest_report_header(self, pytester: Pytester, option) -> None: pytester.makeconftest( @@ -1945,7 +1945,7 @@ class fake_session: # Reset cache. tr._main_color = None - print("Based on stats: %s" % stats_arg) + print(f"Based on stats: {stats_arg}") print(f'Expect summary: "{exp_line}"; with color "{exp_color}"') (line, color) = tr.build_summary_stats_line() print(f'Actually got: "{line}"; with color "{color}"') diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 331ee7da6c7..f424998e50f 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -87,11 +87,11 @@ def test_1(tmp_path): pass """ ) - pytester.runpytest(p, "--basetemp=%s" % mytemp) + pytester.runpytest(p, f"--basetemp={mytemp}") assert mytemp.exists() mytemp.joinpath("hello").touch() - pytester.runpytest(p, "--basetemp=%s" % mytemp) + pytester.runpytest(p, f"--basetemp={mytemp}") assert mytemp.exists() assert not mytemp.joinpath("hello").exists() @@ -248,7 +248,7 @@ def test_abs_path(tmp_path_factory): """ ) - result = pytester.runpytest(p, "--basetemp=%s" % mytemp) + result = pytester.runpytest(p, f"--basetemp={mytemp}") if is_ok: assert result.ret == 0 assert mytemp.joinpath(basename).exists() diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 3ef0cd3b546..770454e83df 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -44,7 +44,7 @@ def test_normal_flow(pytester: Pytester, pyfile_with_warnings) -> None: result = pytester.runpytest(pyfile_with_warnings) result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", "test_normal_flow.py::test_func", "*normal_flow_module.py:3: UserWarning: user warning", '* warnings.warn(UserWarning("user warning"))', @@ -75,7 +75,7 @@ def test_func(fix): result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", "*test_setup_teardown_warnings.py:6: UserWarning: warning during setup", '*warnings.warn(UserWarning("warning during setup"))', "*test_setup_teardown_warnings.py:8: UserWarning: warning during teardown", @@ -143,7 +143,7 @@ def test_func(fix): result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", "*test_unicode.py:7: UserWarning: \u6d4b\u8bd5*", "* 1 passed, 1 warning*", ] @@ -315,7 +315,7 @@ def test_foo(): result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", " *collection_warnings.py:3: UserWarning: collection warning", ' warnings.warn(UserWarning("collection warning"))', "* 1 passed, 1 warning*", @@ -374,7 +374,7 @@ def test_bar(): else: result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", "*test_hide_pytest_internal_warnings.py:4: PytestWarning: some internal warning", "* 1 passed, 1 warning *", ] @@ -461,7 +461,7 @@ def test_shown_by_default(self, pytester: Pytester, customize_filters) -> None: result = pytester.runpytest_subprocess() result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", "*test_shown_by_default.py:3: DeprecationWarning: collection", "*test_shown_by_default.py:7: PendingDeprecationWarning: test run", "* 1 passed, 2 warnings*", @@ -492,7 +492,7 @@ def test_hidden_by_mark(self, pytester: Pytester) -> None: result = pytester.runpytest_subprocess() result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", "*test_hidden_by_mark.py:3: DeprecationWarning: collection", "* 1 passed, 1 warning*", ] @@ -555,7 +555,7 @@ def test(): class TestAssertionWarnings: @staticmethod def assert_result_warns(result, msg) -> None: - result.stdout.fnmatch_lines(["*PytestAssertRewriteWarning: %s*" % msg]) + result.stdout.fnmatch_lines([f"*PytestAssertRewriteWarning: {msg}*"]) def test_tuple_warning(self, pytester: Pytester) -> None: pytester.makepyfile( @@ -585,7 +585,7 @@ def test_group_warnings_by_message(pytester: Pytester) -> None: result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", "test_group_warnings_by_message.py::test_foo[[]0[]]", "test_group_warnings_by_message.py::test_foo[[]1[]]", "test_group_warnings_by_message.py::test_foo[[]2[]]", @@ -617,7 +617,7 @@ def test_group_warnings_by_message_summary(pytester: Pytester) -> None: result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "*== %s ==*" % WARNINGS_SUMMARY_HEADER, + f"*== {WARNINGS_SUMMARY_HEADER} ==*", "test_1.py: 21 warnings", "test_2.py: 1 warning", " */test_1.py:8: UserWarning: foo", From 2b6c946a2bdcf4bb6bf9b04fadf8e24160aa631f Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 30 Apr 2024 18:11:06 +0200 Subject: [PATCH 0629/1271] [mypy 1.10.0] Remove 'type: ignore' that became useless --- src/_pytest/python_api.py | 2 +- src/_pytest/runner.py | 4 ++-- testing/test_runner.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 7d89fdd809e..9b17e5cb786 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -454,7 +454,7 @@ def __eq__(self, actual) -> bool: return False # Return true if the two numbers are within the tolerance. - result: bool = abs(self.expected - actual) <= self.tolerance # type: ignore[arg-type] + result: bool = abs(self.expected - actual) <= self.tolerance return result # Ignore type because of https://github.com/python/mypy/issues/4266. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index eb444f2e322..5b7cd3e1dad 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -167,7 +167,7 @@ def pytest_runtest_call(item: Item) -> None: del sys.last_value del sys.last_traceback if sys.version_info >= (3, 12, 0): - del sys.last_exc # type: ignore[attr-defined] + del sys.last_exc except AttributeError: pass try: @@ -177,7 +177,7 @@ def pytest_runtest_call(item: Item) -> None: sys.last_type = type(e) sys.last_value = e if sys.version_info >= (3, 12, 0): - sys.last_exc = e # type: ignore[attr-defined] + sys.last_exc = e assert e.__traceback__ is not None # Skip *this* frame sys.last_traceback = e.__traceback__.tb_next diff --git a/testing/test_runner.py b/testing/test_runner.py index ecb98f2ffc2..6bd4a045db6 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1032,7 +1032,7 @@ def runtest(self): assert sys.last_type is IndexError assert isinstance(sys.last_value, IndexError) if sys.version_info >= (3, 12, 0): - assert isinstance(sys.last_exc, IndexError) # type: ignore[attr-defined] + assert isinstance(sys.last_exc, IndexError) assert sys.last_value.args[0] == "TEST" assert sys.last_traceback From 65d7d6135e86125ef22973806cf6ab2cf2752841 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 30 Apr 2024 18:13:04 +0200 Subject: [PATCH 0630/1271] [ruff] Add change to format in the git blame ignore file --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index bce64a374be..d6aac5c425d 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -31,3 +31,5 @@ c9df77cbd6a365dcb73c39618e4842711817e871 4546d5445aaefe6a03957db028c263521dfb5c4b # Migration to ruff / ruff format 4588653b2497ed25976b7aaff225b889fb476756 +# Use format specifiers instead of percent format +4788165e69d08e10fc6b9c0124083fb358e2e9b0 From 4c5298c3954efa71436364efaf531d3851a6aeb4 Mon Sep 17 00:00:00 2001 From: Ben Brown Date: Thu, 2 May 2024 03:42:31 -0400 Subject: [PATCH 0631/1271] Add back "Fix teardown error reporting when --maxfail=1 (#11721)" (#12279) Closes #11706. Originally fixed in #11721, but then reverted in #12022 due to a regression in pytest-xdist. The regression was fixed on the pytest-xdist side in pytest-dev/pytest-xdist#1026. --- changelog/11706.bugfix.rst | 4 +++ src/_pytest/runner.py | 4 +++ testing/test_runner.py | 50 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 changelog/11706.bugfix.rst diff --git a/changelog/11706.bugfix.rst b/changelog/11706.bugfix.rst new file mode 100644 index 00000000000..a86db5ef66a --- /dev/null +++ b/changelog/11706.bugfix.rst @@ -0,0 +1,4 @@ +Fix reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`. + +Originally added in pytest 8.0.0, but reverted in 8.0.2 due to a regression in pytest-xdist. +This regression was fixed in pytest-xdist 3.6.1. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 5b7cd3e1dad..dfefa73b72d 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -134,6 +134,10 @@ def runtestprotocol( show_test_item(item) if not item.config.getoption("setuponly", False): reports.append(call_and_report(item, "call", log)) + # If the session is about to fail or stop, teardown everything - this is + # necessary to correctly report fixture teardown errors (see #11706) + if item.session.shouldfail or item.session.shouldstop: + nextitem = None reports.append(call_and_report(item, "teardown", log, nextitem=nextitem)) # After all teardown hooks have been called # want funcargs and request info to go away. diff --git a/testing/test_runner.py b/testing/test_runner.py index 6bd4a045db6..436ce2f1062 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1216,3 +1216,53 @@ def test(): result = pytester.runpytest_inprocess() assert result.ret == ExitCode.OK assert os.environ["PYTEST_VERSION"] == "old version" + + +def test_teardown_session_failed(pytester: Pytester) -> None: + """Test that higher-scoped fixture teardowns run in the context of the last + item after the test session bails early due to --maxfail. + + Regression test for #11706. + """ + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="module") + def baz(): + yield + pytest.fail("This is a failing teardown") + + def test_foo(baz): + pytest.fail("This is a failing test") + + def test_bar(): pass + """ + ) + result = pytester.runpytest("--maxfail=1") + result.assert_outcomes(failed=1, errors=1) + + +def test_teardown_session_stopped(pytester: Pytester) -> None: + """Test that higher-scoped fixture teardowns run in the context of the last + item after the test session bails early due to --stepwise. + + Regression test for #11706. + """ + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="module") + def baz(): + yield + pytest.fail("This is a failing teardown") + + def test_foo(baz): + pytest.fail("This is a failing test") + + def test_bar(): pass + """ + ) + result = pytester.runpytest("--stepwise") + result.assert_outcomes(failed=1, errors=1) From 97610067acf220b13cc4c6fca34e5aac4834b04d Mon Sep 17 00:00:00 2001 From: Anita Hammer <166057949+anitahammer@users.noreply.github.com> Date: Thu, 2 May 2024 12:59:09 +0100 Subject: [PATCH 0632/1271] Handle KeyboardInterrupt and SystemExit at collection time (#12191) --- AUTHORS | 1 + changelog/12191.bugfix.rst | 1 + src/_pytest/runner.py | 4 +++- testing/test_collection.py | 31 +++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 changelog/12191.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 4f61c05914b..4619cf1bc44 100644 --- a/AUTHORS +++ b/AUTHORS @@ -36,6 +36,7 @@ Andrey Paramonov Andrzej Klajnert Andrzej Ostrowski Andy Freeland +Anita Hammer Anthon van der Neut Anthony Shaw Anthony Sottile diff --git a/changelog/12191.bugfix.rst b/changelog/12191.bugfix.rst new file mode 100644 index 00000000000..5102d469814 --- /dev/null +++ b/changelog/12191.bugfix.rst @@ -0,0 +1 @@ +Keyboard interrupts and system exits are now properly handled during the test collection. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index dfefa73b72d..e5af60e388b 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -393,7 +393,9 @@ def collect() -> List[Union[Item, Collector]]: return list(collector.collect()) - call = CallInfo.from_call(collect, "collect") + call = CallInfo.from_call( + collect, "collect", reraise=(KeyboardInterrupt, SystemExit) + ) longrepr: Union[None, Tuple[str, int, str], str, TerminalRepr] = None if not call.excinfo: outcome: Literal["passed", "skipped", "failed"] = "passed" diff --git a/testing/test_collection.py b/testing/test_collection.py index 9caca622c90..995e2999bbe 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -7,6 +7,7 @@ import tempfile import textwrap from typing import List +from typing import Type from _pytest.assertion.util import running_on_ci from _pytest.config import ExitCode @@ -1856,3 +1857,33 @@ def test_do_not_collect_symlink_siblings( # Ensure we collect it only once if we pass the symlinked directory. result = pytester.runpytest(symlink_path, "-sv") result.assert_outcomes(passed=1) + + +@pytest.mark.parametrize( + "exception_class, msg", + [ + (KeyboardInterrupt, "*!!! KeyboardInterrupt !!!*"), + (SystemExit, "INTERNALERROR> SystemExit"), + ], +) +def test_respect_system_exceptions( + pytester: Pytester, + exception_class: Type[BaseException], + msg: str, +): + head = "Before exception" + tail = "After exception" + ensure_file(pytester.path / "test_eggs.py").write_text( + f"print('{head}')", encoding="UTF-8" + ) + ensure_file(pytester.path / "test_ham.py").write_text( + f"raise {exception_class.__name__}()", encoding="UTF-8" + ) + ensure_file(pytester.path / "test_spam.py").write_text( + f"print('{tail}')", encoding="UTF-8" + ) + + result = pytester.runpytest_subprocess("-s") + result.stdout.fnmatch_lines([f"*{head}*"]) + result.stdout.fnmatch_lines([msg]) + result.stdout.no_fnmatch_line(f"*{tail}*") From 3d09c85df0e5e6d4cf2a7ad087fe15618d61cdb2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 4 May 2024 21:26:09 -0300 Subject: [PATCH 0633/1271] [automated] Update plugin list (#12286) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 128 ++++++++++++++++--------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 68d017c31c4..2a68f9e49a6 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =5.0.0,<6.0.0) :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 18, 2024 N/A pytest>=7.0.0 - :pypi:`pytest-checkdocs` check the README when running tests Mar 31, 2024 5 - Production/Stable pytest>=6; extra == "testing" + :pypi:`pytest-checkdocs` check the README when running tests Apr 30, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A @@ -356,6 +356,7 @@ This list contains 1451 plugins. :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 :pypi:`pytest-discover` Pytest plugin to record discovered tests in a file Mar 26, 2024 N/A pytest + :pypi:`pytest-ditto` May 04, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-django` A Django plugin for pytest. Jan 30, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest @@ -437,14 +438,14 @@ This list contains 1451 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 Apr 04, 2024 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. Apr 26, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 26, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 26, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 26, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 26, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 26, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 26, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Apr 30, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 30, 2024 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) @@ -518,7 +519,7 @@ This list contains 1451 plugins. :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A :pypi:`pytest-file` Pytest File Mar 18, 2024 1 - Planning N/A :pypi:`pytest-filecov` A pytest plugin to detect unused files Jun 27, 2021 4 - Beta pytest - :pypi:`pytest-filedata` easily load data from files Jan 17, 2019 4 - Beta N/A + :pypi:`pytest-filedata` easily load test data from files Apr 29, 2024 5 - Production/Stable N/A :pypi:`pytest-filemarker` A pytest plugin that runs marked tests when files change. Dec 01, 2020 N/A pytest :pypi:`pytest-file-watcher` Pytest-File-Watcher is a CLI tool that watches for changes in your code and runs pytest on the changed files. Mar 23, 2023 N/A pytest :pypi:`pytest-filter-case` run test cases filter by mark Nov 05, 2020 N/A N/A @@ -593,7 +594,7 @@ This list contains 1451 plugins. :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Apr 03, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A - :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Apr 22, 2024 4 - Beta pytest<=8.1.1 + :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Apr 30, 2024 4 - Beta pytest<=8.2.0 :pypi:`pytest-gnupg-fixtures` Pytest fixtures for testing with gnupg. Mar 04, 2021 4 - Beta pytest :pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0) @@ -623,7 +624,7 @@ This list contains 1451 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Apr 25, 2024 3 - Alpha pytest==8.1.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 04, 2024 3 - Alpha pytest==8.1.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -671,7 +672,7 @@ This list contains 1451 plugins. :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A :pypi:`pytest-infrastructure` pytest stack validation prior to testing executing Apr 12, 2020 4 - Beta N/A :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A - :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 14, 2024 N/A pytest<9.0.0,>=8.1.1 + :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :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. Dec 13, 2023 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 02, 2024 5 - Production/Stable N/A @@ -703,7 +704,7 @@ This list contains 1451 plugins. :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 12, 2024 3 - Alpha N/A + :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 30, 2024 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Mar 27, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) @@ -795,7 +796,7 @@ This list contains 1451 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to make a test results report with Markdown table format. Feb 04, 2024 4 - Beta pytest !=6.0.0,<9,>=3.3.2 + :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. May 03, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Feb 15, 2024 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A @@ -858,10 +859,10 @@ This list contains 1451 plugins. :pypi:`pytest-mypy-runner` Run the mypy static type checker as a pytest test case Apr 23, 2024 N/A pytest>=8.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 - :pypi:`pytest-ndb` pytest notebook debugger Oct 15, 2023 N/A pytest + :pypi:`pytest-ndb` pytest notebook debugger Apr 28, 2024 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-neos` Pytest plugin for neos Apr 15, 2024 1 - Planning N/A + :pypi:`pytest-neos` Pytest plugin for neos May 01, 2024 1 - Planning N/A :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Mar 07, 2024 N/A pytest <7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest @@ -1020,7 +1021,7 @@ This list contains 1451 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 Dec 09, 2023 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Apr 30, 2024 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) @@ -1135,14 +1136,14 @@ This list contains 1451 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 29, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them May 03, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Mar 10, 2024 4 - Beta pytest (>=5) + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. May 02, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest @@ -1159,7 +1160,7 @@ This list contains 1451 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 03, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1168,7 +1169,7 @@ This list contains 1451 plugins. :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 Feb 01, 2024 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. Apr 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 03, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1398,7 +1399,7 @@ This list contains 1451 plugins. :pypi:`pytest-ui-failed-screenshot` UI自动测试失败时自动截图,并将截图加入到测试报告中 Dec 06, 2022 N/A N/A :pypi:`pytest-ui-failed-screenshot-allure` UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 Dec 06, 2022 N/A N/A :pypi:`pytest-uncollect-if` A plugin to uncollect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-unflakable` Unflakable plugin for PyTest Nov 12, 2023 4 - Beta pytest >=6.2.0 + :pypi:`pytest-unflakable` Unflakable plugin for PyTest Apr 30, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) @@ -1448,7 +1449,7 @@ This list contains 1451 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 Mar 18, 2024 5 - Production/Stable pytest >=7.0.0 - :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Apr 19, 2024 5 - Production/Stable pytest >=6.2.0 + :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Apr 28, 2024 5 - Production/Stable pytest>=7.0.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) @@ -2268,7 +2269,7 @@ This list contains 1451 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Apr 26, 2024, + *last release*: May 03, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2723,9 +2724,9 @@ This list contains 1451 plugins. A pytest plugin that allows multiple failures per test. :pypi:`pytest-checkdocs` - *last release*: Mar 31, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, - *requires*: pytest>=6; extra == "testing" + *requires*: pytest!=8.1.*,>=6; extra == "testing" check the README when running tests @@ -3744,6 +3745,13 @@ This list contains 1451 plugins. Pytest plugin to record discovered tests in a file + :pypi:`pytest-ditto` + *last release*: May 04, 2024, + *status*: 4 - Beta, + *requires*: pytest>=3.5.0 + + + :pypi:`pytest-django` *last release*: Jan 30, 2024, *status*: 5 - Production/Stable, @@ -4312,56 +4320,56 @@ This list contains 1451 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Apr 26, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Apr 26, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Apr 26, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Apr 26, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Apr 26, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Apr 26, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Apr 26, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Apr 26, 2024, + *last release*: Apr 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4879,11 +4887,11 @@ This list contains 1451 plugins. A pytest plugin to detect unused files :pypi:`pytest-filedata` - *last release*: Jan 17, 2019, - *status*: 4 - Beta, + *last release*: Apr 29, 2024, + *status*: 5 - Production/Stable, *requires*: N/A - easily load data from files + easily load test data from files :pypi:`pytest-filemarker` *last release*: Dec 01, 2020, @@ -5404,9 +5412,9 @@ This list contains 1451 plugins. Utility to select tests that have had its dependencies modified (as identified by git diff) :pypi:`pytest-glamor-allure` - *last release*: Apr 22, 2024, + *last release*: Apr 30, 2024, *status*: 4 - Beta, - *requires*: pytest<=8.1.1 + *requires*: pytest<=8.2.0 Extends allure-pytest functionality @@ -5614,7 +5622,7 @@ This list contains 1451 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 25, 2024, + *last release*: May 04, 2024, *status*: 3 - Alpha, *requires*: pytest==8.1.1 @@ -5950,7 +5958,7 @@ This list contains 1451 plugins. Reuse pytest.ini to store env variables :pypi:`pytest-initry` - *last release*: Apr 14, 2024, + *last release*: Apr 30, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.1.1 @@ -6174,7 +6182,7 @@ This list contains 1451 plugins. A plugin to generate customizable jinja-based HTML reports in pytest :pypi:`pytest-jira` - *last release*: Apr 12, 2024, + *last release*: Apr 30, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -6818,11 +6826,11 @@ This list contains 1451 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: Feb 04, 2024, + *last release*: May 03, 2024, *status*: 4 - Beta, - *requires*: pytest !=6.0.0,<9,>=3.3.2 + *requires*: pytest!=6.0.0,<9,>=3.3.2 - A pytest plugin to make a test results report with Markdown table format. + A pytest plugin to generate test outcomes reports with markdown table format. :pypi:`pytest-meilisearch` *last release*: Feb 15, 2024, @@ -7259,7 +7267,7 @@ This list contains 1451 plugins. MySQL process and client fixtures for pytest :pypi:`pytest-ndb` - *last release*: Oct 15, 2023, + *last release*: Apr 28, 2024, *status*: N/A, *requires*: pytest @@ -7280,7 +7288,7 @@ This list contains 1451 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-neos` - *last release*: Apr 15, 2024, + *last release*: May 01, 2024, *status*: 1 - Planning, *requires*: N/A @@ -8393,7 +8401,7 @@ This list contains 1451 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Dec 09, 2023, + *last release*: Apr 30, 2024, *status*: N/A, *requires*: pytest @@ -9198,7 +9206,7 @@ This list contains 1451 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Mar 29, 2024, + *last release*: May 03, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9247,9 +9255,9 @@ This list contains 1451 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Mar 10, 2024, + *last release*: May 02, 2024, *status*: 4 - Beta, - *requires*: pytest (>=5) + *requires*: pytest>=5 pytest plugin to check ruff requirements. @@ -9366,7 +9374,7 @@ This list contains 1451 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Apr 26, 2024, + *last release*: May 03, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9429,7 +9437,7 @@ This list contains 1451 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Apr 26, 2024, + *last release*: May 03, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -11039,9 +11047,9 @@ This list contains 1451 plugins. A plugin to uncollect pytests tests rather than using skipif :pypi:`pytest-unflakable` - *last release*: Nov 12, 2023, + *last release*: Apr 30, 2024, *status*: 4 - Beta, - *requires*: pytest >=6.2.0 + *requires*: pytest>=6.2.0 Unflakable plugin for PyTest @@ -11389,9 +11397,9 @@ This list contains 1451 plugins. A pytest plugin for configuring workflow/pipeline tests using YAML files :pypi:`pytest-xdist` - *last release*: Apr 19, 2024, + *last release*: Apr 28, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6.2.0 + *requires*: pytest>=7.0.0 pytest xdist plugin for distributed testing, most importantly across multiple CPUs From 84e59af8c829de659efb339d5a9c7cec98eee719 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 5 May 2024 19:53:16 -0300 Subject: [PATCH 0634/1271] Document exceptions raised by exit, skip, xfail, fail, and importorskip (#12285) As commented on: https://github.com/pytest-dev/pytest/issues/7469#issuecomment-2094104215 --- doc/en/reference/reference.rst | 19 ++++++++++++++++++- src/_pytest/outcomes.py | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 39317497ebd..e46478da02b 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -59,11 +59,19 @@ pytest.fail .. autofunction:: pytest.fail(reason, [pytrace=True, msg=None]) +.. class:: pytest.fail.Exception + + The exception raised by :func:`pytest.fail`. + pytest.skip ~~~~~~~~~~~ .. autofunction:: pytest.skip(reason, [allow_module_level=False, msg=None]) +.. class:: pytest.skip.Exception + + The exception raised by :func:`pytest.skip`. + .. _`pytest.importorskip ref`: pytest.importorskip @@ -76,11 +84,19 @@ pytest.xfail .. autofunction:: pytest.xfail +.. class:: pytest.xfail.Exception + + The exception raised by :func:`pytest.xfail`. + pytest.exit ~~~~~~~~~~~ .. autofunction:: pytest.exit(reason, [returncode=None, msg=None]) +.. class:: pytest.exit.Exception + + The exception raised by :func:`pytest.exit`. + pytest.main ~~~~~~~~~~~ @@ -246,9 +262,10 @@ Marks a test function as *expected to fail*. to specify ``reason`` (see :ref:`condition string `). :keyword str reason: Reason why the test function is marked as xfail. - :keyword Type[Exception] raises: + :keyword raises: Exception class (or tuple of classes) expected to be raised by the test function; other exceptions will fail the test. Note that subclasses of the classes passed will also result in a match (similar to how the ``except`` statement works). + :type raises: Type[:py:exc:`Exception`] :keyword bool run: Whether the test function should actually be executed. If ``False``, the function will always xfail and will diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 76d94accd0d..f953dabe03d 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -114,6 +114,9 @@ def exit( :param returncode: Return code to be used when exiting pytest. None means the same as ``0`` (no error), same as :func:`sys.exit`. + + :raises pytest.exit.Exception: + The exception that is raised. """ __tracebackhide__ = True raise Exit(reason, returncode) @@ -142,6 +145,9 @@ def skip( Defaults to False. + :raises pytest.skip.Exception: + The exception that is raised. + .. note:: It is better to use the :ref:`pytest.mark.skipif ref` marker when possible to declare a test to be skipped under certain conditions @@ -163,6 +169,9 @@ def fail(reason: str = "", pytrace: bool = True) -> NoReturn: :param pytrace: If False, msg represents the full failure information and no python traceback will be reported. + + :raises pytest.fail.Exception: + The exception that is raised. """ __tracebackhide__ = True raise Failed(msg=reason, pytrace=pytrace) @@ -188,6 +197,9 @@ def xfail(reason: str = "") -> NoReturn: It is better to use the :ref:`pytest.mark.xfail ref` marker when possible to declare a test to be xfailed under certain conditions like known bugs or missing features. + + :raises pytest.xfail.Exception: + The exception that is raised. """ __tracebackhide__ = True raise XFailed(reason) @@ -227,6 +239,9 @@ def importorskip( :returns: The imported module. This should be assigned to its canonical name. + :raises pytest.skip.Exception: + If the module cannot be imported. + Example:: docutils = pytest.importorskip("docutils") From 4080459f041f02c66356777001d18155d2796ee7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 07:28:34 +0200 Subject: [PATCH 0635/1271] [pre-commit.ci] pre-commit autoupdate (#12292) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.2 → v0.4.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.2...v0.4.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c3ebc88501f..b83ae969661 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.2" + rev: "v0.4.3" hooks: - id: ruff args: ["--fix"] From 8efbefb2d7968e44ea3e220ab102872c0f96ccff Mon Sep 17 00:00:00 2001 From: Brian Okken <1568356+okken@users.noreply.github.com> Date: Tue, 7 May 2024 10:37:00 -0700 Subject: [PATCH 0636/1271] New --xfail-tb flag (#12280) Fix #12231 --- changelog/12231.feature.rst | 11 +++++ src/_pytest/terminal.py | 25 +++++++++--- testing/test_terminal.py | 81 ++++++++++++++++++++++++------------- 3 files changed, 83 insertions(+), 34 deletions(-) create mode 100644 changelog/12231.feature.rst diff --git a/changelog/12231.feature.rst b/changelog/12231.feature.rst new file mode 100644 index 00000000000..dad04bc20c1 --- /dev/null +++ b/changelog/12231.feature.rst @@ -0,0 +1,11 @@ +Added `--xfail-tb` flag, which turns on traceback output for XFAIL results. + +* If the `--xfail-tb` flag is not sent, tracebacks for XFAIL results are NOT shown. +* The style of traceback for XFAIL is set with `--tb`, and can be `auto|long|short|line|native|no`. +* Note: Even if you have `--xfail-tb` set, you won't see them if `--tb=no`. + +Some history: + +With pytest 8.0, `-rx` or `-ra` would not only turn on summary reports for xfail, but also report the tracebacks for xfail results. This caused issues with some projects that utilize xfail, but don't want to see all of the xfail tracebacks. + +This change detaches xfail tracebacks from `-rx`, and now we turn on xfail tracebacks with `--xfail-tb`. With this, the default `-rx`/ `-ra` behavior is identical to pre-8.0 with respect to xfail tracebacks. While this is a behavior change, it brings default behavior back to pre-8.0.0 behavior, which ultimately was considered the better course of action. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index d05eb7e3dce..2eef8d1f227 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -216,6 +216,13 @@ def pytest_addoption(parser: Parser) -> None: choices=["auto", "long", "short", "no", "line", "native"], help="Traceback print mode (auto/long/short/line/native/no)", ) + group._addoption( + "--xfail-tb", + action="store_true", + dest="xfail_tb", + default=False, + help="Show tracebacks for xfail (as long as --tb != no)", + ) group._addoption( "--show-capture", action="store", @@ -1086,21 +1093,29 @@ def print_teardown_sections(self, rep: TestReport) -> None: self._tw.line(content) def summary_failures(self) -> None: - self.summary_failures_combined("failed", "FAILURES") + style = self.config.option.tbstyle + self.summary_failures_combined("failed", "FAILURES", style=style) def summary_xfailures(self) -> None: - self.summary_failures_combined("xfailed", "XFAILURES", "x") + show_tb = self.config.option.xfail_tb + style = self.config.option.tbstyle if show_tb else "no" + self.summary_failures_combined("xfailed", "XFAILURES", style=style) def summary_failures_combined( - self, which_reports: str, sep_title: str, needed_opt: Optional[str] = None + self, + which_reports: str, + sep_title: str, + *, + style: str, + needed_opt: Optional[str] = None, ) -> None: - if self.config.option.tbstyle != "no": + if style != "no": if not needed_opt or self.hasopt(needed_opt): reports: List[BaseReport] = self.getreports(which_reports) if not reports: return self.write_sep("=", sep_title) - if self.config.option.tbstyle == "line": + if style == "line": for rep in reports: line = self._getcrashline(rep) self.write_line(line) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index dd5fa4bf679..19848e7cbaf 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2909,54 +2909,77 @@ def test_xfail_reason(): assert result.stdout.lines.count(expect2) == 1 -def test_summary_xfail_tb(pytester: Pytester) -> None: - pytester.makepyfile( +@pytest.fixture() +def xfail_testfile(pytester: Pytester) -> Path: + return pytester.makepyfile( """ import pytest - @pytest.mark.xfail - def test_xfail(): + def test_fail(): a, b = 1, 2 assert a == b + + @pytest.mark.xfail + def test_xfail(): + c, d = 3, 4 + assert c == d """ ) - result = pytester.runpytest("-rx") + + +def test_xfail_tb_default(xfail_testfile, pytester: Pytester) -> None: + result = pytester.runpytest(xfail_testfile) + + # test_fail, show traceback result.stdout.fnmatch_lines( [ + "*= FAILURES =*", + "*_ test_fail _*", + "*def test_fail():*", + "* a, b = 1, 2*", + "*> assert a == b*", + "*E assert 1 == 2*", + ] + ) + + # test_xfail, don't show traceback + result.stdout.no_fnmatch_line("*= XFAILURES =*") + + +def test_xfail_tb_true(xfail_testfile, pytester: Pytester) -> None: + result = pytester.runpytest(xfail_testfile, "--xfail-tb") + + # both test_fail and test_xfail, show traceback + result.stdout.fnmatch_lines( + [ + "*= FAILURES =*", + "*_ test_fail _*", + "*def test_fail():*", + "* a, b = 1, 2*", + "*> assert a == b*", + "*E assert 1 == 2*", "*= XFAILURES =*", "*_ test_xfail _*", - "* @pytest.mark.xfail*", - "* def test_xfail():*", - "* a, b = 1, 2*", - "> *assert a == b*", - "E *assert 1 == 2*", - "test_summary_xfail_tb.py:6: AssertionError*", - "*= short test summary info =*", - "XFAIL test_summary_xfail_tb.py::test_xfail", - "*= 1 xfailed in * =*", + "*def test_xfail():*", + "* c, d = 3, 4*", + "*> assert c == d*", + "*E assert 3 == 4*", + "*short test summary info*", ] ) -def test_xfail_tb_line(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import pytest +def test_xfail_tb_line(xfail_testfile, pytester: Pytester) -> None: + result = pytester.runpytest(xfail_testfile, "--xfail-tb", "--tb=line") - @pytest.mark.xfail - def test_xfail(): - a, b = 1, 2 - assert a == b - """ - ) - result = pytester.runpytest("-rx", "--tb=line") + # both test_fail and test_xfail, show line result.stdout.fnmatch_lines( [ + "*= FAILURES =*", + "*test_xfail_tb_line.py:5: assert 1 == 2", "*= XFAILURES =*", - "*test_xfail_tb_line.py:6: assert 1 == 2", - "*= short test summary info =*", - "XFAIL test_xfail_tb_line.py::test_xfail", - "*= 1 xfailed in * =*", + "*test_xfail_tb_line.py:10: assert 3 == 4", + "*short test summary info*", ] ) From d49f1fc4dbf9e04da016335d9e82527423d9ad1f Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 8 May 2024 15:13:30 +0200 Subject: [PATCH 0637/1271] doc: update sprint repo link (#12296) --- doc/en/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 67501c0530c..83eb27b0a53 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -5,7 +5,7 @@ - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training): * **June 11th to 13th 2024**, Remote * **March 4th to 6th 2025**, Leipzig, Germany / Remote - - `pytest development sprint `_, **June 17th -- 22nd 2024** + - `pytest development sprint `_, **June 17th -- 22nd 2024** - pytest tips and tricks for a better testsuite, `Europython 2024 `_, **July 8th -- 14th 2024** (3h), Prague Also see :doc:`previous talks and blogposts `. From 5af46f3d4e8264c50ffd635dbb395199670e70b7 Mon Sep 17 00:00:00 2001 From: Yutian Li Date: Thu, 9 May 2024 14:04:58 -0400 Subject: [PATCH 0638/1271] Fix crashing under squashfuse_ll read-only mounts (#12301) Fixes #12300 --- AUTHORS | 1 + changelog/12300.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 5 ++++- testing/test_assertrewrite.py | 5 +++++ 4 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 changelog/12300.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 4619cf1bc44..54ed85fc732 100644 --- a/AUTHORS +++ b/AUTHORS @@ -441,6 +441,7 @@ Yao Xiao Yoav Caspi Yuliang Shao Yusuke Kadowaki +Yutian Li Yuval Shimon Zac Hatfield-Dodds Zachary Kneupper diff --git a/changelog/12300.bugfix.rst b/changelog/12300.bugfix.rst new file mode 100644 index 00000000000..6c162482022 --- /dev/null +++ b/changelog/12300.bugfix.rst @@ -0,0 +1 @@ +Fixed handling of 'Function not implemented' error under squashfuse_ll, which is a different way to say that the mountpoint is read-only. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index b6f14aa9294..3d5df0d6c34 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -1171,7 +1171,10 @@ def try_makedirs(cache_dir: Path) -> bool: return False except OSError as e: # as of now, EROFS doesn't have an equivalent OSError-subclass - if e.errno == errno.EROFS: + # + # squashfuse_ll returns ENOSYS "OSError: [Errno 38] Function not + # implemented" for a read-only error + if e.errno in {errno.EROFS, errno.ENOSYS}: return False raise return True diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index bedf6e27606..82c7055b968 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1972,6 +1972,11 @@ def fake_mkdir(p, exist_ok=False, *, exc): monkeypatch.setattr(os, "makedirs", partial(fake_mkdir, exc=err)) assert not try_makedirs(p) + err = OSError() + err.errno = errno.ENOSYS + monkeypatch.setattr(os, "makedirs", partial(fake_mkdir, exc=err)) + assert not try_makedirs(p) + # unhandled OSError should raise err = OSError() err.errno = errno.ECHILD From e20a08565f6ecdd7953589e6da11b998e94c1948 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 12 May 2024 00:21:02 +0000 Subject: [PATCH 0639/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 126 ++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 43 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 2a68f9e49a6..d03861ccfd1 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A + :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 10, 2024 4 - Beta pytest :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Feb 02, 2024 N/A pytest (>=8.0.0,<9.0.0) :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) @@ -136,6 +137,7 @@ This list contains 1452 plugins. :pypi:`pytest-bandit` A bandit plugin for pytest Feb 23, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 :pypi:`pytest-bdd` BDD for pytest Mar 17, 2024 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 @@ -145,7 +147,7 @@ This list contains 1452 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 03, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 08, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -169,6 +171,7 @@ This list contains 1452 plugins. :pypi:`pytest-boost-xml` Plugin for pytest to generate boost xml reports Nov 30, 2022 4 - Beta N/A :pypi:`pytest-bootstrap` Mar 04, 2022 N/A N/A :pypi:`pytest-bpdb` A py.test plug-in to enable drop to bpdb debugger on test failure. Jan 19, 2015 2 - Pre-Alpha N/A + :pypi:`pytest-bq` BigQuery fixtures and fixture factories for Pytest. May 08, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-bravado` Pytest-bravado automatically generates from OpenAPI specification client fixtures. Feb 15, 2022 N/A N/A :pypi:`pytest-breakword` Use breakword with pytest Aug 04, 2021 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-breed-adapter` A simple plugin to connect with breed-server Nov 07, 2018 4 - Beta pytest (>=3.5.0) @@ -238,7 +241,7 @@ This list contains 1452 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Mar 18, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest May 06, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 @@ -356,7 +359,7 @@ This list contains 1452 plugins. :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 :pypi:`pytest-discover` Pytest plugin to record discovered tests in a file Mar 26, 2024 N/A pytest - :pypi:`pytest-ditto` May 04, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. May 07, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-django` A Django plugin for pytest. Jan 30, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest @@ -479,7 +482,7 @@ This list contains 1452 plugins. :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest :pypi:`pytest-executable` pytest plugin for testing executables Oct 07, 2023 N/A pytest <8,>=5 :pypi:`pytest-execution-timer` A timer for the phases of Pytest's execution. Dec 24, 2021 4 - Beta N/A - :pypi:`pytest-exit-code` A pytest plugin that overrides the built-in exit codes to retain more information about the test results. Feb 23, 2024 4 - Beta pytest >=6.2.0 + :pypi:`pytest-exit-code` A pytest plugin that overrides the built-in exit codes to retain more information about the test results. May 06, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-expect` py.test plugin to store test expectations and mark tests based on them Apr 21, 2016 4 - Beta N/A :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-expecter` Better testing with expecter and pytest. Sep 18, 2022 5 - Production/Stable N/A @@ -612,19 +615,19 @@ This list contains 1452 plugins. :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Mar 16, 2024 5 - Production/Stable N/A :pypi:`pytest-helm-chart` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Jun 15, 2020 4 - Beta pytest (>=5.4.2,<6.0.0) :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Feb 07, 2024 4 - Beta pytest (>=8.0.0,<9.0.0) - :pypi:`pytest-helm-templates` Pytest fixtures for unit testing the output of helm templates Apr 05, 2024 N/A pytest~=7.4.0; extra == "dev" + :pypi:`pytest-helm-templates` Pytest fixtures for unit testing the output of helm templates May 08, 2024 N/A pytest~=7.4.0; extra == "dev" :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-henry` Aug 29, 2023 N/A N/A :pypi:`pytest-hidecaptured` Hide captured output May 04, 2018 4 - Beta pytest (>=2.8.5) - :pypi:`pytest-himark` A plugin that will filter pytest's test collection using a json file. It will read a json file provided with a --json argument in pytest command line (or in pytest.ini), search the markers key and automatically add -m option to the command line for filtering out the tests marked with disabled markers. Apr 14, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-himark` This plugin aims to create markers automatically based on a json configuration. May 10, 2024 4 - Beta pytest>=6.2.0 :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 Jan 14, 2024 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 May 04, 2024 3 - Alpha pytest==8.1.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 11, 2024 3 - Alpha pytest==8.1.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -648,7 +651,7 @@ This list contains 1452 plugins. :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 24, 2024 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 24, 2023 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-httptesting` http_testing framework on top of pytest May 08, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-httpx` Send responses to httpx. Feb 21, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest @@ -676,7 +679,7 @@ This list contains 1452 plugins. :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. Dec 13, 2023 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Apr 15, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules May 10, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest @@ -729,6 +732,7 @@ This list contains 1452 plugins. :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A :pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A + :pypi:`pytest-kookit` Your simple but kooky integration testing with pytest May 06, 2024 N/A N/A :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) @@ -845,7 +849,7 @@ This list contains 1452 plugins. :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Feb 14, 2024 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Mar 31, 2024 4 - Beta pytest<8; extra == "test" + :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT May 08, 2024 4 - Beta pytest<9; extra == "test" :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A @@ -964,8 +968,8 @@ This list contains 1452 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Feb 02, 2024 N/A pytest (<9.0.0,>=6.2.4) - :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Feb 25, 2024 N/A N/A + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers May 06, 2024 N/A N/A + :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright May 04, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A @@ -1028,7 +1032,7 @@ This list contains 1452 plugins. :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report Feb 03, 2024 N/A pytest + :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report May 05, 2024 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Jan 26, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Jan 02, 2024 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 @@ -1049,7 +1053,7 @@ This list contains 1452 plugins. :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) :pypi:`pytest_quickify` Run test suites with pytest-quickify. Jun 14, 2019 N/A pytest - :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Jul 05, 2023 5 - Production/Stable pytest (>=6.2) + :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest May 08, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-race` Race conditions tester for pytest Jun 07, 2022 4 - Beta N/A :pypi:`pytest-rage` pytest plugin to implement PEP712 Oct 21, 2011 3 - Alpha N/A :pypi:`pytest-rail` pytest plugin for creating TestRail runs and adding results May 02, 2022 N/A pytest (>=3.6) @@ -1062,7 +1066,7 @@ This list contains 1452 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Mar 18, 2024 4 - Beta pytest >=7.4.3 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection May 10, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Mar 14, 2024 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 @@ -1156,6 +1160,7 @@ This list contains 1452 plugins. :pypi:`pytest-salt-factories` Pytest Salt Plugin Mar 22, 2024 5 - Production/Stable pytest>=7.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-sample-argvalues` A utility function to help choose a random sample from your argvalues in pytest. May 07, 2024 N/A pytest :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 @@ -1178,7 +1183,7 @@ This list contains 1452 plugins. :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Mar 19, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-servers` pytest servers May 09, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1246,7 +1251,7 @@ This list contains 1452 plugins. :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 Apr 19, 2024 N/A pytest (>5.4.0,<8) - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 26, 2024 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX May 10, 2024 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 @@ -2135,6 +2140,13 @@ This list contains 1452 plugins. pytest plugin for testing AWS resource configurations + :pypi:`pytest-aws-apigateway` + *last release*: May 10, 2024, + *status*: 4 - Beta, + *requires*: pytest + + pytest plugin for AWS ApiGateway + :pypi:`pytest-aws-config` *last release*: May 28, 2021, *status*: N/A, @@ -2205,6 +2217,13 @@ This list contains 1452 plugins. pytest plugin for URL based testing + :pypi:`pytest-batch-regression` + *last release*: May 08, 2024, + *status*: N/A, + *requires*: pytest>=6.0.0 + + A pytest plugin to repeat the entire test suite in batches. + :pypi:`pytest-bdd` *last release*: Mar 17, 2024, *status*: 6 - Mature, @@ -2269,7 +2288,7 @@ This list contains 1452 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: May 03, 2024, + *last release*: May 08, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2436,6 +2455,13 @@ This list contains 1452 plugins. A py.test plug-in to enable drop to bpdb debugger on test failure. + :pypi:`pytest-bq` + *last release*: May 08, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=6.2 + + BigQuery fixtures and fixture factories for Pytest. + :pypi:`pytest-bravado` *last release*: Feb 15, 2022, *status*: N/A, @@ -2920,7 +2946,7 @@ This list contains 1452 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Mar 18, 2024, + *last release*: May 06, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3746,11 +3772,11 @@ This list contains 1452 plugins. Pytest plugin to record discovered tests in a file :pypi:`pytest-ditto` - *last release*: May 04, 2024, + *last release*: May 07, 2024, *status*: 4 - Beta, *requires*: pytest>=3.5.0 - + Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. :pypi:`pytest-django` *last release*: Jan 30, 2024, @@ -4607,9 +4633,9 @@ This list contains 1452 plugins. A timer for the phases of Pytest's execution. :pypi:`pytest-exit-code` - *last release*: Feb 23, 2024, + *last release*: May 06, 2024, *status*: 4 - Beta, - *requires*: pytest >=6.2.0 + *requires*: pytest>=6.2.0 A pytest plugin that overrides the built-in exit codes to retain more information about the test results. @@ -5538,7 +5564,7 @@ This list contains 1452 plugins. A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. :pypi:`pytest-helm-templates` - *last release*: Apr 05, 2024, + *last release*: May 08, 2024, *status*: N/A, *requires*: pytest~=7.4.0; extra == "dev" @@ -5580,11 +5606,11 @@ This list contains 1452 plugins. Hide captured output :pypi:`pytest-himark` - *last release*: Apr 14, 2024, + *last release*: May 10, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 - A plugin that will filter pytest's test collection using a json file. It will read a json file provided with a --json argument in pytest command line (or in pytest.ini), search the markers key and automatically add -m option to the command line for filtering out the tests marked with disabled markers. + This plugin aims to create markers automatically based on a json configuration. :pypi:`pytest-historic` *last release*: Apr 08, 2020, @@ -5622,7 +5648,7 @@ This list contains 1452 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 04, 2024, + *last release*: May 11, 2024, *status*: 3 - Alpha, *requires*: pytest==8.1.1 @@ -5790,9 +5816,9 @@ This list contains 1452 plugins. pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: Jul 24, 2023, + *last release*: May 08, 2024, *status*: N/A, - *requires*: pytest (>=7.2.0,<8.0.0) + *requires*: pytest<9.0.0,>=8.2.0 http_testing framework on top of pytest @@ -5986,7 +6012,7 @@ This list contains 1452 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Apr 15, 2024, + *last release*: May 10, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6356,6 +6382,13 @@ This list contains 1452 plugins. Run Konira DSL tests with py.test + :pypi:`pytest-kookit` + *last release*: May 06, 2024, + *status*: N/A, + *requires*: N/A + + Your simple but kooky integration testing with pytest + :pypi:`pytest-koopmans` *last release*: Nov 21, 2022, *status*: 4 - Beta, @@ -7169,9 +7202,9 @@ This list contains 1452 plugins. low-startup-overhead, scalable, distributed-testing pytest plugin :pypi:`pytest-mqtt` - *last release*: Mar 31, 2024, + *last release*: May 08, 2024, *status*: 4 - Beta, - *requires*: pytest<8; extra == "test" + *requires*: pytest<9; extra == "test" pytest-mqtt supports testing systems based on MQTT @@ -8002,14 +8035,14 @@ This list contains 1452 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Feb 02, 2024, + *last release*: May 06, 2024, *status*: N/A, - *requires*: pytest (<9.0.0,>=6.2.4) + *requires*: N/A A pytest wrapper with fixtures for Playwright to automate web browsers :pypi:`pytest_playwright_async` - *last release*: Feb 25, 2024, + *last release*: May 04, 2024, *status*: N/A, *requires*: N/A @@ -8450,7 +8483,7 @@ This list contains 1452 plugins. Pyramid server fixture for py.test :pypi:`pytest-pyreport` - *last release*: Feb 03, 2024, + *last release*: May 05, 2024, *status*: N/A, *requires*: pytest @@ -8597,9 +8630,9 @@ This list contains 1452 plugins. Run test suites with pytest-quickify. :pypi:`pytest-rabbitmq` - *last release*: Jul 05, 2023, + *last release*: May 08, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2) + *requires*: pytest>=6.2 RabbitMQ process and client fixtures for pytest @@ -8688,9 +8721,9 @@ This list contains 1452 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-ranking` - *last release*: Mar 18, 2024, + *last release*: May 10, 2024, *status*: 4 - Beta, - *requires*: pytest >=7.4.3 + *requires*: pytest>=7.4.3 A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection @@ -9345,6 +9378,13 @@ This list contains 1452 plugins. Simple PyTest Plugin For Salt's Test Suite Specifically + :pypi:`pytest-sample-argvalues` + *last release*: May 07, 2024, + *status*: N/A, + *requires*: pytest + + A utility function to help choose a random sample from your argvalues in pytest. + :pypi:`pytest-sanic` *last release*: Oct 25, 2021, *status*: N/A, @@ -9500,7 +9540,7 @@ This list contains 1452 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Mar 19, 2024, + *last release*: May 09, 2024, *status*: 3 - Alpha, *requires*: pytest>=6.2 @@ -9976,7 +10016,7 @@ This list contains 1452 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Mar 26, 2024, + *last release*: May 10, 2024, *status*: N/A, *requires*: N/A From 90a3ef2f36f6c282d1175ce0c13149ce57d1362d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 12 May 2024 22:28:49 +0300 Subject: [PATCH 0640/1271] python: add workaround for permission error crashes from non-selected directories Fix #12120. --- changelog/12120.bugfix.rst | 1 + src/_pytest/python.py | 7 ++++++- testing/test_collection.py | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 changelog/12120.bugfix.rst diff --git a/changelog/12120.bugfix.rst b/changelog/12120.bugfix.rst new file mode 100644 index 00000000000..b1ca4913b37 --- /dev/null +++ b/changelog/12120.bugfix.rst @@ -0,0 +1 @@ +Fix `PermissionError` crashes arising from directories which are not selected on the command-line. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 68eceb7f4f3..8efaf80787a 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -176,7 +176,12 @@ def pytest_collect_directory( path: Path, parent: nodes.Collector ) -> Optional[nodes.Collector]: pkginit = path / "__init__.py" - if pkginit.is_file(): + try: + has_pkginit = pkginit.is_file() + except PermissionError: + # See https://github.com/pytest-dev/pytest/issues/12120#issuecomment-2106349096. + return None + if has_pkginit: return Package.from_parent(parent, path=path) return None diff --git a/testing/test_collection.py b/testing/test_collection.py index 995e2999bbe..8ff38a334f4 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -285,6 +285,23 @@ def test_testpaths_ini(self, pytester: Pytester, monkeypatch: MonkeyPatch) -> No items, reprec = pytester.inline_genitems() assert [x.name for x in items] == [f"test_{dirname}"] + def test_missing_permissions_on_unselected_directory_doesnt_crash( + self, pytester: Pytester + ) -> None: + """Regression test for #12120.""" + test = pytester.makepyfile(test="def test(): pass") + bad = pytester.mkdir("bad") + try: + bad.chmod(0) + + result = pytester.runpytest(test) + finally: + bad.chmod(750) + bad.rmdir() + + assert result.ret == ExitCode.OK + result.assert_outcomes(passed=1) + class TestCollectPluginHookRelay: def test_pytest_collect_file(self, pytester: Pytester) -> None: From eea04c289108749ba96ed42b410baaae5932708d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 05:56:16 +0200 Subject: [PATCH 0641/1271] build(deps): Bump django in /testing/plugins_integration (#12314) Bumps [django](https://github.com/django/django) from 5.0.4 to 5.0.6. - [Commits](https://github.com/django/django/compare/5.0.4...5.0.6) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d60bc5d3c08..d4d0fc633c0 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.3.0 -django==5.0.4 +django==5.0.6 pytest-asyncio==0.23.6 pytest-bdd==7.1.2 pytest-cov==5.0.0 From 37489d3c6c81bc3f1badf7c50e568d4fffe6deb9 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 13 May 2024 12:27:20 +0300 Subject: [PATCH 0642/1271] python,unittest: don't collect abstract classes Fix #12275. --- changelog/12275.bugfix.rst | 1 + src/_pytest/python.py | 6 +++++- src/_pytest/unittest.py | 8 +++++++- testing/python/collect.py | 26 ++++++++++++++++++++++++++ testing/test_unittest.py | 28 ++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 changelog/12275.bugfix.rst diff --git a/changelog/12275.bugfix.rst b/changelog/12275.bugfix.rst new file mode 100644 index 00000000000..2d040a3a063 --- /dev/null +++ b/changelog/12275.bugfix.rst @@ -0,0 +1 @@ +Fix collection error upon encountering an :mod:`abstract ` class, including abstract `unittest.TestCase` subclasses. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 68eceb7f4f3..5196b9fe891 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -368,7 +368,11 @@ def istestfunction(self, obj: object, name: str) -> bool: return False def istestclass(self, obj: object, name: str) -> bool: - return self.classnamefilter(name) or self.isnosetest(obj) + if not (self.classnamefilter(name) or self.isnosetest(obj)): + return False + if inspect.isabstract(obj): + return False + return True def _matches_prefix_or_glob_option(self, option_name: str, name: str) -> bool: """Check if the given name matches the prefix or glob-pattern defined diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 8f1791bf744..919b497c295 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs """Discover and run std-library "unittest" style tests.""" +import inspect import sys import traceback import types @@ -49,14 +50,19 @@ def pytest_pycollect_makeitem( collector: Union[Module, Class], name: str, obj: object ) -> Optional["UnitTestCase"]: - # Has unittest been imported and is obj a subclass of its TestCase? try: + # Has unittest been imported? ut = sys.modules["unittest"] + # Is obj a subclass of unittest.TestCase? # Type ignored because `ut` is an opaque module. if not issubclass(obj, ut.TestCase): # type: ignore return None except Exception: return None + # Is obj a concrete class? + # Abstract classes can't be instantiated so no point collecting them. + if inspect.isabstract(obj): + return None # Yes, so let's collect it. return UnitTestCase.from_parent(collector, name=name, obj=obj) diff --git a/testing/python/collect.py b/testing/python/collect.py index a1a7dc8978d..843fa3c0e6b 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -262,6 +262,32 @@ def prop(self): result = pytester.runpytest() assert result.ret == ExitCode.NO_TESTS_COLLECTED + def test_abstract_class_is_not_collected(self, pytester: Pytester) -> None: + """Regression test for #12275 (non-unittest version).""" + pytester.makepyfile( + """ + import abc + + class TestBase(abc.ABC): + @abc.abstractmethod + def abstract1(self): pass + + @abc.abstractmethod + def abstract2(self): pass + + def test_it(self): pass + + class TestPartial(TestBase): + def abstract1(self): pass + + class TestConcrete(TestPartial): + def abstract2(self): pass + """ + ) + result = pytester.runpytest() + assert result.ret == ExitCode.OK + result.assert_outcomes(passed=1) + class TestFunction: def test_getmodulecollector(self, pytester: Pytester) -> None: diff --git a/testing/test_unittest.py b/testing/test_unittest.py index d726e74d603..f73e083be78 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1640,3 +1640,31 @@ def test_it2(self): pass assert skipped == 1 assert failed == 0 assert reprec.ret == ExitCode.NO_TESTS_COLLECTED + + +def test_abstract_testcase_is_not_collected(pytester: Pytester) -> None: + """Regression test for #12275.""" + pytester.makepyfile( + """ + import abc + import unittest + + class TestBase(unittest.TestCase, abc.ABC): + @abc.abstractmethod + def abstract1(self): pass + + @abc.abstractmethod + def abstract2(self): pass + + def test_it(self): pass + + class TestPartial(TestBase): + def abstract1(self): pass + + class TestConcrete(TestPartial): + def abstract2(self): pass + """ + ) + result = pytester.runpytest() + assert result.ret == ExitCode.OK + result.assert_outcomes(passed=1) From ebe2e8eac9db5a662cf60c9058e0c5ba480d3ad0 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 13 May 2024 22:11:40 +0300 Subject: [PATCH 0643/1271] changelog: document unittest 8.2 change as breaking --- doc/en/changelog.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 2630d95cf28..fb276a93839 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,24 @@ with advance notice in the **Deprecations** section of releases. pytest 8.2.0 (2024-04-27) ========================= +Breaking Changes +---------------- + +- `#12089 `_: pytest now requires that :class:`unittest.TestCase` subclasses can be instantiated freely using ``MyTestCase('runTest')``. + + If the class doesn't allow this, you may see an error during collection such as ``AttributeError: 'MyTestCase' object has no attribute 'runTest'``. + + Classes which do not override ``__init__``, or do not access the test method in ``__init__`` using ``getattr`` or similar, are unaffected. + + Classes which do should take care to not crash when ``"runTest"`` is given, as is shown in `unittest.TestCases's implementation `_. + Alternatively, consider using :meth:`setUp ` instead of ``__init__``. + + If you run into this issue using ``tornado.AsyncTestCase``, please see `issue 12263 `_. + + If you run into this issue using an abstract ``TestCase`` subclass, please see `issue 12275 `_. + + Historical note: the effect of this change on custom TestCase implementations was not properly considered initially, this is why it was done in a minor release. We apologize for the inconvenience. + Deprecations ------------ From 3a64c47f1f713fbc154d04960fe8382ecf94bdc4 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 14 May 2024 23:26:15 +0300 Subject: [PATCH 0644/1271] cacheprovider: fix `.pytest_cache` not being world-readable Fix #12308. --- changelog/12308.bugfix.rst | 1 + src/_pytest/cacheprovider.py | 7 +++++++ testing/test_cacheprovider.py | 15 +++++++++++++++ 3 files changed, 23 insertions(+) create mode 100644 changelog/12308.bugfix.rst diff --git a/changelog/12308.bugfix.rst b/changelog/12308.bugfix.rst new file mode 100644 index 00000000000..07995427a1a --- /dev/null +++ b/changelog/12308.bugfix.rst @@ -0,0 +1 @@ +Fix a regression in pytest 8.2.0 where the permissions of automatically-created ``.pytest_cache`` directories became ``rwx------`` instead of the expected ``rwxr-xr-x``. diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 4593e2a8172..06def557e41 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -213,6 +213,13 @@ def _ensure_cache_dir_and_supporting_files(self) -> None: dir=self._cachedir.parent, ) as newpath: path = Path(newpath) + + # Reset permissions to the default, see #12308. + # Note: there's no way to get the current umask atomically, eek. + umask = os.umask(0o022) + os.umask(umask) + path.chmod(0o777 - umask) + with open(path.joinpath("README.md"), "xt", encoding="UTF-8") as f: f.write(README_CONTENT) with open(path.joinpath(".gitignore"), "xt", encoding="UTF-8") as f: diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 6c18c358a80..c85c1d04cc7 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -31,6 +31,21 @@ def test_config_cache_mkdir(self, pytester: Pytester) -> None: p = config.cache.mkdir("name") assert p.is_dir() + def test_cache_dir_permissions(self, pytester: Pytester) -> None: + """The .pytest_cache directory should have world-readable permissions + (depending on umask). + + Regression test for #12308. + """ + pytester.makeini("[pytest]") + config = pytester.parseconfigure() + assert config.cache is not None + p = config.cache.mkdir("name") + assert p.is_dir() + # Instead of messing with umask, make sure .pytest_cache has the same + # permissions as the default that `mkdir` gives `p`. + assert (p.parent.stat().st_mode & 0o777) == (p.stat().st_mode & 0o777) + def test_config_cache_dataerror(self, pytester: Pytester) -> None: pytester.makeini("[pytest]") config = pytester.parseconfigure() From 1acf56d033e801f34ddc78d1124d818d96ba31b7 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 15 May 2024 17:11:26 +0300 Subject: [PATCH 0645/1271] fixtures: fix non-working package-scope parametrization reordering The `.parent` was incorrectly removed in a21fb87a90974189c1b8b26189959507189bb3a1, but it was actually correct (well, it assumes that Module.path.parent == Package.path, which I'm not sure is always correct, but that's a different matter). Restore it. Fix #12328. --- changelog/12328.bugfix.rst | 1 + src/_pytest/fixtures.py | 3 ++- testing/python/fixtures.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 changelog/12328.bugfix.rst diff --git a/changelog/12328.bugfix.rst b/changelog/12328.bugfix.rst new file mode 100644 index 00000000000..f334425850b --- /dev/null +++ b/changelog/12328.bugfix.rst @@ -0,0 +1 @@ +Fix a regression in pytest 8.0.0 where package-scoped parameterized items were not correctly reordered to minimize setups/teardowns in some cases. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 5a290718fe4..a271f947d45 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -187,7 +187,8 @@ def get_parametrized_fixture_keys( if scope is Scope.Session: scoped_item_path = None elif scope is Scope.Package: - scoped_item_path = item.path + # Package key = module's directory. + scoped_item_path = item.path.parent elif scope is Scope.Module: scoped_item_path = item.path elif scope is Scope.Class: diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index aec0deb99a1..13ab4904c1a 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4274,6 +4274,39 @@ def test_func(self, f2, f1, m2): request = TopRequest(items[0], _ispytest=True) assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split() + def test_parametrized_package_scope_reordering(self, pytester: Pytester) -> None: + """A paramaterized package-scoped fixture correctly reorders items to + minimize setups & teardowns. + + Regression test for #12328. + """ + pytester.makepyfile( + __init__="", + conftest=""" + import pytest + @pytest.fixture(scope="package", params=["a", "b"]) + def fix(request): + return request.param + """, + test_1="def test1(fix): pass", + test_2="def test2(fix): pass", + ) + + result = pytester.runpytest("--setup-plan") + assert result.ret == ExitCode.OK + result.stdout.fnmatch_lines( + [ + " SETUP P fix['a']", + " test_1.py::test1[a] (fixtures used: fix, request)", + " test_2.py::test2[a] (fixtures used: fix, request)", + " TEARDOWN P fix['a']", + " SETUP P fix['b']", + " test_1.py::test1[b] (fixtures used: fix, request)", + " test_2.py::test2[b] (fixtures used: fix, request)", + " TEARDOWN P fix['b']", + ], + ) + def test_multiple_packages(self, pytester: Pytester) -> None: """Complex test involving multiple package fixtures. Make sure teardowns are executed in order. From 8d0081182266a38cf7e4abd1d3cebb74a622469a Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 15 May 2024 12:49:34 -0400 Subject: [PATCH 0646/1271] Spelling and minor changes (#12122) --- doc/en/announce/release-2.0.0.rst | 4 +-- doc/en/announce/release-2.2.2.rst | 2 +- doc/en/announce/release-2.4.0.rst | 2 +- doc/en/announce/release-2.5.0.rst | 2 +- doc/en/announce/release-2.6.0.rst | 2 +- doc/en/announce/release-2.7.0.rst | 2 +- doc/en/announce/sprint2016.rst | 2 +- doc/en/changelog.rst | 38 +++++++++++----------- doc/en/deprecations.rst | 2 +- doc/en/example/customdirectory/conftest.py | 2 +- doc/en/getting-started.rst | 2 +- doc/en/naming20.rst | 2 +- doc/en/reference/fixtures.rst | 2 +- doc/en/reference/reference.rst | 2 +- src/_pytest/_py/error.py | 2 +- src/_pytest/_py/path.py | 4 +-- src/_pytest/assertion/rewrite.py | 2 +- src/_pytest/assertion/util.py | 4 +-- src/_pytest/cacheprovider.py | 2 +- src/_pytest/compat.py | 2 +- src/_pytest/config/__init__.py | 6 ++-- src/_pytest/fixtures.py | 4 +-- src/_pytest/hookspec.py | 6 ++-- src/_pytest/legacypath.py | 4 +-- src/_pytest/mark/__init__.py | 2 +- src/_pytest/pathlib.py | 4 +-- src/_pytest/stepwise.py | 2 +- testing/_py/test_local.py | 4 +-- testing/code/test_excinfo.py | 2 +- testing/code/test_source.py | 2 +- testing/logging/test_fixture.py | 31 ++++++++++-------- testing/python/fixtures.py | 2 +- testing/python/integration.py | 4 +-- testing/test_cacheprovider.py | 2 +- testing/test_compat.py | 2 +- testing/test_config.py | 4 +-- testing/test_conftest.py | 4 +-- testing/test_debugging.py | 4 +-- testing/test_doctest.py | 6 ++-- testing/test_junitxml.py | 2 +- testing/test_legacypath.py | 2 +- testing/test_mark_expression.py | 2 +- testing/test_pluginmanager.py | 4 +-- testing/test_runner.py | 2 +- testing/test_terminal.py | 2 +- testing/test_unittest.py | 6 ++-- 46 files changed, 100 insertions(+), 97 deletions(-) diff --git a/doc/en/announce/release-2.0.0.rst b/doc/en/announce/release-2.0.0.rst index ecb1a1db988..c2a9f6da4d5 100644 --- a/doc/en/announce/release-2.0.0.rst +++ b/doc/en/announce/release-2.0.0.rst @@ -62,7 +62,7 @@ New Features - new "-q" option which decreases verbosity and prints a more nose/unittest-style "dot" output. -- many many more detailed improvements details +- many, many, more detailed improvements details Fixes ----------------------- @@ -109,7 +109,7 @@ Important Notes in conftest.py files. They will cause nothing special. - removed support for calling the pre-1.0 collection API of "run()" and "join" - removed reading option values from conftest.py files or env variables. - This can now be done much much better and easier through the ini-file + This can now be done much, much, better and easier through the ini-file mechanism and the "addopts" entry in particular. - removed the "disabled" attribute in test classes. Use the skipping and pytestmark mechanism to skip or xfail a test class. diff --git a/doc/en/announce/release-2.2.2.rst b/doc/en/announce/release-2.2.2.rst index 22ef0bc7a16..510b35ee1d0 100644 --- a/doc/en/announce/release-2.2.2.rst +++ b/doc/en/announce/release-2.2.2.rst @@ -4,7 +4,7 @@ pytest-2.2.2: bug fixes pytest-2.2.2 (updated to 2.2.3 to fix packaging issues) is a minor backward-compatible release of the versatile py.test testing tool. It contains bug fixes and a few refinements particularly to reporting with -"--collectonly", see below for betails. +"--collectonly", see below for details. For general information see here: diff --git a/doc/en/announce/release-2.4.0.rst b/doc/en/announce/release-2.4.0.rst index 138cc89576c..9b864329674 100644 --- a/doc/en/announce/release-2.4.0.rst +++ b/doc/en/announce/release-2.4.0.rst @@ -181,7 +181,7 @@ Bug fixes: partially failed (finalizers would not always be called before) - fix issue320 - fix class scope for fixtures when mixed with - module-level functions. Thanks Anatloy Bubenkoff. + module-level functions. Thanks Anatoly Bubenkoff. - you can specify "-q" or "-qq" to get different levels of "quieter" reporting (thanks Katarzyna Jachim) diff --git a/doc/en/announce/release-2.5.0.rst b/doc/en/announce/release-2.5.0.rst index c6cdcdd8a83..fe64f1b8668 100644 --- a/doc/en/announce/release-2.5.0.rst +++ b/doc/en/announce/release-2.5.0.rst @@ -83,7 +83,7 @@ holger krekel Thanks Ralph Schmitt for the precise failure example. - fix issue244 by implementing special index for parameters to only use - indices for paramentrized test ids + indices for parametrized test ids - fix issue287 by running all finalizers but saving the exception from the first failing finalizer and re-raising it so teardown will diff --git a/doc/en/announce/release-2.6.0.rst b/doc/en/announce/release-2.6.0.rst index 56fbd6cc1e4..c00df585738 100644 --- a/doc/en/announce/release-2.6.0.rst +++ b/doc/en/announce/release-2.6.0.rst @@ -73,7 +73,7 @@ holger krekel - cleanup setup.py a bit and specify supported versions. Thanks Jurko Gospodnetic for the PR. -- change XPASS colour to yellow rather then red when tests are run +- change XPASS colour to yellow rather than red when tests are run with -v. - fix issue473: work around mock putting an unbound method into a class diff --git a/doc/en/announce/release-2.7.0.rst b/doc/en/announce/release-2.7.0.rst index 2840178a07f..83cddb34157 100644 --- a/doc/en/announce/release-2.7.0.rst +++ b/doc/en/announce/release-2.7.0.rst @@ -55,7 +55,7 @@ holger krekel github. See https://pytest.org/en/stable/contributing.html . Thanks to Anatoly for pushing and initial work on this. -- fix issue650: new option ``--docttest-ignore-import-errors`` which +- fix issue650: new option ``--doctest-ignore-import-errors`` which will turn import errors in doctests into skips. Thanks Charles Cloud for the complete PR. diff --git a/doc/en/announce/sprint2016.rst b/doc/en/announce/sprint2016.rst index 8e706589876..8d47a205c71 100644 --- a/doc/en/announce/sprint2016.rst +++ b/doc/en/announce/sprint2016.rst @@ -49,7 +49,7 @@ place on 20th, 21st, 22nd, 24th and 25th. On the 23rd we took a break day for some hot hiking in the Black Forest. Sprint activity was organised heavily around pairing, with plenty of group -discusssions to take advantage of the high bandwidth, and lightning talks +discussions to take advantage of the high bandwidth, and lightning talks as well. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index fb276a93839..d5cde498859 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -168,7 +168,7 @@ Improvements - `#11311 `_: When using ``--override-ini`` for paths in invocations without a configuration file defined, the current working directory is used as the relative directory. - Previoulsy this would raise an :class:`AssertionError`. + Previously this would raise an :class:`AssertionError`. - `#11475 `_: :ref:`--import-mode=importlib ` now tries to import modules using the standard import mechanism (but still without changing :py:data:`sys.path`), falling back to importing modules directly only if that fails. @@ -1411,7 +1411,7 @@ Deprecations ``__init__`` method, they should take ``**kwargs``. See :ref:`uncooperative-constructors-deprecated` for details. - Note that a deprection warning is only emitted when there is a conflict in the + Note that a deprecation warning is only emitted when there is a conflict in the arguments pytest expected to pass. This deprecation was already part of pytest 7.0.0rc1 but wasn't documented. @@ -1453,7 +1453,7 @@ Breaking Changes - `#7259 `_: The :ref:`Node.reportinfo() ` function first return value type has been expanded from `py.path.local | str` to `os.PathLike[str] | str`. Most plugins which refer to `reportinfo()` only define it as part of a custom :class:`pytest.Item` implementation. - Since `py.path.local` is an `os.PathLike[str]`, these plugins are unaffacted. + Since `py.path.local` is an `os.PathLike[str]`, these plugins are unaffected. Plugins and users which call `reportinfo()`, use the first return value and interact with it as a `py.path.local`, would need to adjust by calling `py.path.local(fspath)`. Although preferably, avoid the legacy `py.path.local` and use `pathlib.Path`, or use `item.location` or `item.path`, instead. @@ -1961,7 +1961,7 @@ Bug Fixes the ``tmp_path``/``tmpdir`` fixture). Now the directories are created with private permissions. - pytest used to silently use a pre-existing ``/tmp/pytest-of-`` directory, + pytest used to silently use a preexisting ``/tmp/pytest-of-`` directory, even if owned by another user. This means another user could pre-create such a directory and gain control of another user's temporary directory. Now such a condition results in an error. @@ -2688,7 +2688,7 @@ Features also changes ``sys.modules`` as a side-effect), which works but has a number of drawbacks, like requiring test modules that don't live in packages to have unique names (as they need to reside under a unique name in ``sys.modules``). - ``--import-mode=importlib`` uses more fine grained import mechanisms from ``importlib`` which don't + ``--import-mode=importlib`` uses more fine-grained import mechanisms from ``importlib`` which don't require pytest to change ``sys.path`` or ``sys.modules`` at all, eliminating much of the drawbacks of the previous mode. @@ -2705,7 +2705,7 @@ Improvements ------------ - :issue:`4375`: The ``pytest`` command now suppresses the ``BrokenPipeError`` error message that - is printed to stderr when the output of ``pytest`` is piped and and the pipe is + is printed to stderr when the output of ``pytest`` is piped and the pipe is closed by the piped-to program (common examples are ``less`` and ``head``). @@ -3007,7 +3007,7 @@ Breaking Changes This hook has been marked as deprecated and not been even called by pytest for over 10 years now. -- :issue:`6673`: Reversed / fix meaning of "+/-" in error diffs. "-" means that sth. expected is missing in the result and "+" means that there are unexpected extras in the result. +- :issue:`6673`: Reversed / fix meaning of "+/-" in error diffs. "-" means that something expected is missing in the result and "+" means that there are unexpected extras in the result. - :issue:`6737`: The ``cached_result`` attribute of ``FixtureDef`` is now set to ``None`` when @@ -4612,7 +4612,7 @@ Bug Fixes Improved Documentation ---------------------- -- :issue:`4974`: Update docs for ``pytest_cmdline_parse`` hook to note availability liminations +- :issue:`4974`: Update docs for ``pytest_cmdline_parse`` hook to note availability limitations @@ -6470,7 +6470,7 @@ Features Bug Fixes --------- -- Fix hanging pexpect test on MacOS by using flush() instead of wait(). +- Fix hanging pexpect test on macOS by using flush() instead of wait(). (:issue:`2022`) - Fix restoring Python state after in-process pytest runs with the @@ -6518,7 +6518,7 @@ Trivial/Internal Changes ------------------------ - Show a simple and easy error when keyword expressions trigger a syntax error - (for example, ``"-k foo and import"`` will show an error that you can not use + (for example, ``"-k foo and import"`` will show an error that you cannot use the ``import`` keyword in expressions). (:issue:`2953`) - Change parametrized automatic test id generation to use the ``__name__`` @@ -8294,7 +8294,7 @@ time or change existing behaviors in order to make them less surprising/more use one will also have a "reprec" attribute with the recorded events/reports. - fix monkeypatch.setattr("x.y", raising=False) to actually not raise - if "y" is not a pre-existing attribute. Thanks Florian Bruhin. + if "y" is not a preexisting attribute. Thanks Florian Bruhin. - fix issue741: make running output from testdir.run copy/pasteable Thanks Bruno Oliveira. @@ -8350,7 +8350,7 @@ time or change existing behaviors in order to make them less surprising/more use - fix issue854: autouse yield_fixtures defined as class members of unittest.TestCase subclasses now work as expected. - Thannks xmo-odoo for the report and Bruno Oliveira for the PR. + Thanks xmo-odoo for the report and Bruno Oliveira for the PR. - fix issue833: --fixtures now shows all fixtures of collected test files, instead of just the fixtures declared on the first one. @@ -8454,7 +8454,7 @@ time or change existing behaviors in order to make them less surprising/more use github. See https://pytest.org/en/stable/contributing.html . Thanks to Anatoly for pushing and initial work on this. -- fix issue650: new option ``--docttest-ignore-import-errors`` which +- fix issue650: new option ``--doctest-ignore-import-errors`` which will turn import errors in doctests into skips. Thanks Charles Cloud for the complete PR. @@ -8642,7 +8642,7 @@ time or change existing behaviors in order to make them less surprising/more use - cleanup setup.py a bit and specify supported versions. Thanks Jurko Gospodnetic for the PR. -- change XPASS colour to yellow rather then red when tests are run +- change XPASS colour to yellow rather than red when tests are run with -v. - fix issue473: work around mock putting an unbound method into a class @@ -8815,7 +8815,7 @@ time or change existing behaviors in order to make them less surprising/more use Thanks Ralph Schmitt for the precise failure example. - fix issue244 by implementing special index for parameters to only use - indices for paramentrized test ids + indices for parametrized test ids - fix issue287 by running all finalizers but saving the exception from the first failing finalizer and re-raising it so teardown will @@ -8823,7 +8823,7 @@ time or change existing behaviors in order to make them less surprising/more use it might be the cause for other finalizers to fail. - fix ordering when mock.patch or other standard decorator-wrappings - are used with test methods. This fixues issue346 and should + are used with test methods. This fixes issue346 and should help with random "xdist" collection failures. Thanks to Ronny Pfannschmidt and Donald Stufft for helping to isolate it. @@ -9080,7 +9080,7 @@ Bug fixes: partially failed (finalizers would not always be called before) - fix issue320 - fix class scope for fixtures when mixed with - module-level functions. Thanks Anatloy Bubenkoff. + module-level functions. Thanks Anatoly Bubenkoff. - you can specify "-q" or "-qq" to get different levels of "quieter" reporting (thanks Katarzyna Jachim) @@ -9502,7 +9502,7 @@ Bug fixes: unexpected exceptions - fix issue47: timing output in junitxml for test cases is now correct - fix issue48: typo in MarkInfo repr leading to exception -- fix issue49: avoid confusing error when initizaliation partially fails +- fix issue49: avoid confusing error when initialization partially fails - fix issue44: env/username expansion for junitxml file path - show releaselevel information in test runs for pypy - reworked doc pages for better navigation and PDF generation @@ -9627,7 +9627,7 @@ Bug fixes: collection-before-running semantics were not setup as with pytest 1.3.4. Note, however, that the recommended and much cleaner way to do test - parametraization remains the "pytest_generate_tests" + parameterization remains the "pytest_generate_tests" mechanism, see the docs. 2.0.0 (2010-11-25) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 5ac93f15144..a65ea331663 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -462,7 +462,7 @@ Now :class:`~pytest.Class` collects the test methods directly. Most plugins which reference ``Instance`` do so in order to ignore or skip it, using a check such as ``if isinstance(node, Instance): return``. Such plugins should simply remove consideration of ``Instance`` on pytest>=7. -However, to keep such uses working, a dummy type has been instanted in ``pytest.Instance`` and ``_pytest.python.Instance``, +However, to keep such uses working, a dummy type has been instanced in ``pytest.Instance`` and ``_pytest.python.Instance``, and importing it emits a deprecation warning. This was removed in pytest 8. diff --git a/doc/en/example/customdirectory/conftest.py b/doc/en/example/customdirectory/conftest.py index 350893cab43..b2f68dba41a 100644 --- a/doc/en/example/customdirectory/conftest.py +++ b/doc/en/example/customdirectory/conftest.py @@ -21,7 +21,7 @@ def collect(self): @pytest.hookimpl def pytest_collect_directory(path, parent): - # Use our custom collector for directories containing a `mainfest.json` file. + # Use our custom collector for directories containing a `manifest.json` file. if path.joinpath("manifest.json").is_file(): return ManifestDirectory.from_parent(parent=parent, path=path) # Otherwise fallback to the standard behavior. diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 5b33e308d13..468de3654d9 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -274,7 +274,7 @@ Continue reading Check out additional pytest resources to help you customize tests for your unique workflow: * ":ref:`usage`" for command line invocation examples -* ":ref:`existingtestsuite`" for working with pre-existing tests +* ":ref:`existingtestsuite`" for working with preexisting tests * ":ref:`mark`" for information on the ``pytest.mark`` mechanism * ":ref:`fixtures`" for providing a functional baseline to your tests * ":ref:`plugins`" for managing and writing plugins diff --git a/doc/en/naming20.rst b/doc/en/naming20.rst index 5a81df2698d..11213066384 100644 --- a/doc/en/naming20.rst +++ b/doc/en/naming20.rst @@ -8,7 +8,7 @@ If you used older version of the ``py`` distribution (which included the py.test command line tool and Python name space) you accessed helpers and possibly collection classes through the ``py.test`` Python namespaces. The new ``pytest`` -Python module flaty provides the same objects, following +Python module flatly provides the same objects, following these renaming rules:: py.test.XYZ -> pytest.XYZ diff --git a/doc/en/reference/fixtures.rst b/doc/en/reference/fixtures.rst index 8ba59395e3e..dff93a035ef 100644 --- a/doc/en/reference/fixtures.rst +++ b/doc/en/reference/fixtures.rst @@ -39,7 +39,7 @@ Built-in fixtures Store and retrieve values across pytest runs. :fixture:`doctest_namespace` - Provide a dict injected into the docstests namespace. + Provide a dict injected into the doctests namespace. :fixture:`monkeypatch` Temporarily modify classes, functions, dictionaries, diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index e46478da02b..4036b7d9912 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1940,7 +1940,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: general: -k EXPRESSION Only run tests which match the given substring - expression. An expression is a Python evaluatable + expression. An expression is a Python evaluable expression where all names are substring-matched against test names and their parent classes. Example: -k 'test_method or test_other' matches all diff --git a/src/_pytest/_py/error.py b/src/_pytest/_py/error.py index 68f1eed7ec0..ab3a4ed318e 100644 --- a/src/_pytest/_py/error.py +++ b/src/_pytest/_py/error.py @@ -41,7 +41,7 @@ def __str__(self) -> str: 3: errno.ENOENT, 17: errno.EEXIST, 18: errno.EXDEV, - 13: errno.EBUSY, # empty cd drive, but ENOMEDIUM seems unavailiable + 13: errno.EBUSY, # empty cd drive, but ENOMEDIUM seems unavailable 22: errno.ENOTDIR, 20: errno.ENOTDIR, 267: errno.ENOTDIR, diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index 27b115cfd87..bcb05ac34cd 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -836,7 +836,7 @@ def mtime(self) -> float: def copy(self, target, mode=False, stat=False): """Copy path to target. - If mode is True, will copy copy permission from path to target. + If mode is True, will copy permission from path to target. If stat is True, copy permission, last modification time, last access time, and flags from path to target. """ @@ -1047,7 +1047,7 @@ def chmod(self, mode, rec=0): def pypkgpath(self): """Return the Python package path by looking for the last directory upwards which still contains an __init__.py. - Return None if a pkgpath can not be determined. + Return None if a pkgpath cannot be determined. """ pkgpath = None for parent in self.parts(reverse=True): diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 3d5df0d6c34..928c4f5e3b2 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -584,7 +584,7 @@ def _write_and_reset() -> None: # multi-line assert with message elif lineno in seen_lines: lines[-1] = lines[-1][:offset] - # multi line assert with escapd newline before message + # multi line assert with escaped newline before message else: lines.append(line[:offset]) _write_and_reset() diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 008eabf9a1f..a118befcc16 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -325,7 +325,7 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]: def _compare_eq_iterable( left: Iterable[Any], right: Iterable[Any], - highligher: _HighlightFunc, + highlighter: _HighlightFunc, verbose: int = 0, ) -> List[str]: if verbose <= 0 and not running_on_ci(): @@ -340,7 +340,7 @@ def _compare_eq_iterable( # "right" is the expected base against which we compare "left", # see https://github.com/pytest-dev/pytest/issues/3333 explanation.extend( - highligher( + highlighter( "\n".join( line.rstrip() for line in difflib.ndiff(right_formatting, left_formatting) diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 06def557e41..5aa8f483522 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -251,7 +251,7 @@ def pytest_make_collect_report( # Sort any lf-paths to the beginning. lf_paths = self.lfplugin._last_failed_paths - # Use stable sort to priorize last failed. + # Use stable sort to prioritize last failed. def sort_key(node: Union[nodes.Item, nodes.Collector]) -> bool: return node.path in lf_paths diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 9d9411818ac..614848e0dba 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -53,7 +53,7 @@ def iscoroutinefunction(func: object) -> bool: def syntax, and doesn't contain yield), or a function decorated with @asyncio.coroutine. - Note: copied and modified from Python 3.5's builtin couroutines.py to avoid + Note: copied and modified from Python 3.5's builtin coroutines.py to avoid importing asyncio directly, which in turns also initializes the "logging" module as a side-effect (see issue #8). """ diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index c8e8e7d29dd..c698ea9a777 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -462,7 +462,7 @@ def parse_hookimpl_opts( # (see issue #1073). if not name.startswith("pytest_"): return None - # Ignore names which can not be hooks. + # Ignore names which cannot be hooks. if name == "pytest_plugins": return None @@ -574,8 +574,8 @@ def _set_initial_conftests( self._noconftest = noconftest self._using_pyargs = pyargs foundanchor = False - for intitial_path in args: - path = str(intitial_path) + for initial_path in args: + path = str(initial_path) # remove node-id syntax i = path.find("::") if i != -1: diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 5a290718fe4..3ce8b3fb4c0 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -326,7 +326,7 @@ def prune_dependency_tree(self) -> None: working_set = set(self.initialnames) while working_set: argname = working_set.pop() - # Argname may be smth not included in the original names_closure, + # Argname may be something not included in the original names_closure, # in which case we ignore it. This currently happens with pseudo # FixtureDefs which wrap 'get_direct_param_fixture_func(request)'. # So they introduce the new dependency 'request' which might have @@ -1702,7 +1702,7 @@ def parsefactories( If `node_or_object` is a collection node (with an underlying Python object), the node's object is traversed and the node's nodeid is used to - determine the fixtures' visibilty. `nodeid` must not be specified in + determine the fixtures' visibility. `nodeid` must not be specified in this case. If `node_or_object` is an object (e.g. a plugin), the object is diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 01d3b664080..8a38ff4fb43 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -651,7 +651,7 @@ def pytest_runtest_protocol( - ``pytest_runtest_logreport(report)`` - ``pytest_exception_interact(call, report)`` if an interactive exception occurred - - Call phase, if the the setup passed and the ``setuponly`` pytest option is not set: + - Call phase, if the setup passed and the ``setuponly`` pytest option is not set: - ``call = pytest_runtest_call(item)`` (wrapped in ``CallInfo(when="call")``) - ``report = pytest_runtest_makereport(item, call)`` - ``pytest_runtest_logreport(report)`` @@ -861,7 +861,7 @@ def pytest_fixture_setup( ) -> Optional[object]: """Perform fixture setup execution. - :param fixturdef: + :param fixturedef: The fixture definition object. :param request: The fixture request object. @@ -891,7 +891,7 @@ def pytest_fixture_post_finalizer( the fixture result ``fixturedef.cached_result`` is still available (not ``None``). - :param fixturdef: + :param fixturedef: The fixture definition object. :param request: The fixture request object. diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index b28c89767fe..d9de65b1a53 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -384,7 +384,7 @@ def Config_inifile(self: Config) -> Optional[LEGACY_PATH]: return legacy_path(str(self.inipath)) if self.inipath else None -def Session_stardir(self: Session) -> LEGACY_PATH: +def Session_startdir(self: Session) -> LEGACY_PATH: """The path from which pytest was invoked. Prefer to use ``startpath`` which is a :class:`pathlib.Path`. @@ -439,7 +439,7 @@ def pytest_load_initial_conftests(early_config: Config) -> None: mp.setattr(Config, "inifile", property(Config_inifile), raising=False) # Add Session.startdir property. - mp.setattr(Session, "startdir", property(Session_stardir), raising=False) + mp.setattr(Session, "startdir", property(Session_startdir), raising=False) # Add pathlist configuration type. mp.setattr(Config, "_getini_unknown_type", Config__getini_unknown_type) diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index f5276d8fbda..950a6959ec9 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -78,7 +78,7 @@ def pytest_addoption(parser: Parser) -> None: default="", metavar="EXPRESSION", help="Only run tests which match the given substring expression. " - "An expression is a Python evaluatable expression " + "An expression is a Python evaluable expression " "where all names are substring-matched against test names " "and their parent classes. Example: -k 'test_method or test_" "other' matches all test functions and classes whose name " diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index e14c2acd328..b11eea4e7ef 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -173,7 +173,7 @@ def rm_rf(path: Path) -> None: def find_prefixed(root: Path, prefix: str) -> Iterator["os.DirEntry[str]"]: - """Find all elements in root that begin with the prefix, case insensitive.""" + """Find all elements in root that begin with the prefix, case-insensitive.""" l_prefix = prefix.lower() for x in os.scandir(root): if x.name.lower().startswith(l_prefix): @@ -776,7 +776,7 @@ def resolve_package_path(path: Path) -> Optional[Path]: """Return the Python package path by looking for the last directory upwards which still contains an __init__.py. - Returns None if it can not be determined. + Returns None if it cannot be determined. """ result = None for parent in itertools.chain((path,), path.parents): diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index 3ebebc288f8..92d3a297e0d 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -40,7 +40,7 @@ def pytest_addoption(parser: Parser) -> None: @pytest.hookimpl def pytest_configure(config: Config) -> None: if config.option.stepwise_skip: - # allow --stepwise-skip to work on it's own merits. + # allow --stepwise-skip to work on its own merits. config.option.stepwise = True if config.getoption("stepwise"): config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin") diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 243219babc9..ea5794b251b 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -667,7 +667,7 @@ def test_tilde_expansion(self, monkeypatch, tmpdir): assert p == os.path.expanduser("~") @pytest.mark.skipif( - not sys.platform.startswith("win32"), reason="case insensitive only on windows" + not sys.platform.startswith("win32"), reason="case-insensitive only on windows" ) def test_eq_hash_are_case_insensitive_on_windows(self): a = local("/some/path") @@ -898,7 +898,7 @@ def test_sysfind_bat_exe_before(self, tmpdir, monkeypatch): class TestExecution: pytestmark = skiponwin32 - def test_sysfind_no_permisson_ignored(self, monkeypatch, tmpdir): + def test_sysfind_no_permission_ignored(self, monkeypatch, tmpdir): noperm = tmpdir.ensure("noperm", dir=True) monkeypatch.setenv("PATH", str(noperm), prepend=":") noperm.chmod(0) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index f2c689a137e..86e30dc4830 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1515,7 +1515,7 @@ def test(tmp_path): result.stderr.no_fnmatch_line("*INTERNALERROR*") -def test_regression_nagative_line_index(pytester: Pytester) -> None: +def test_regression_negative_line_index(pytester: Pytester) -> None: """ With Python 3.10 alphas, there was an INTERNALERROR reported in https://github.com/pytest-dev/pytest/pull/8227 diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 12ea27b3517..2fa85205795 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -255,7 +255,7 @@ def g(): assert str(g_source).strip() == "def g():\n pass # pragma: no cover" -def test_getfuncsource_with_multine_string() -> None: +def test_getfuncsource_with_multiline_string() -> None: def f(): c = """while True: pass diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index 2e16913f099..c1cfff632af 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -117,7 +117,7 @@ def test2(caplog): result.stdout.no_fnmatch_line("*log from test2*") -def test_change_level_undos_handler_level(pytester: Pytester) -> None: +def test_change_level_undoes_handler_level(pytester: Pytester) -> None: """Ensure that 'set_level' is undone after the end of the test (handler). Issue #7569. Tests the handler level specifically. @@ -302,7 +302,15 @@ def logging_during_setup_and_teardown( assert [x.message for x in caplog.get_records("teardown")] == ["a_teardown_log"] -def test_caplog_captures_for_all_stages( +def private_assert_caplog_records_is_setup_call( + caplog: pytest.LogCaptureFixture, +) -> None: + # This reaches into private API, don't use this type of thing in real tests! + caplog_records = caplog._item.stash[caplog_records_key] + assert set(caplog_records) == {"setup", "call"} + + +def test_captures_for_all_stages( caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None ) -> None: assert not caplog.records @@ -312,9 +320,7 @@ def test_caplog_captures_for_all_stages( assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - # This reaches into private API, don't use this type of thing in real tests! - caplog_records = caplog._item.stash[caplog_records_key] - assert set(caplog_records) == {"setup", "call"} + private_assert_caplog_records_is_setup_call(caplog) def test_clear_for_call_stage( @@ -323,21 +329,18 @@ def test_clear_for_call_stage( logger.info("a_call_log") assert [x.message for x in caplog.get_records("call")] == ["a_call_log"] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - caplog_records = caplog._item.stash[caplog_records_key] - assert set(caplog_records) == {"setup", "call"} + private_assert_caplog_records_is_setup_call(caplog) caplog.clear() assert caplog.get_records("call") == [] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - caplog_records = caplog._item.stash[caplog_records_key] - assert set(caplog_records) == {"setup", "call"} + private_assert_caplog_records_is_setup_call(caplog) logging.info("a_call_log_after_clear") assert [x.message for x in caplog.get_records("call")] == ["a_call_log_after_clear"] assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"] - caplog_records = caplog._item.stash[caplog_records_key] - assert set(caplog_records) == {"setup", "call"} + private_assert_caplog_records_is_setup_call(caplog) def test_ini_controls_global_log_level(pytester: Pytester) -> None: @@ -363,11 +366,11 @@ def test_log_level_override(request, caplog): ) result = pytester.runpytest() - # make sure that that we get a '0' exit code for the testsuite + # make sure that we get a '0' exit code for the testsuite assert result.ret == 0 -def test_caplog_can_override_global_log_level(pytester: Pytester) -> None: +def test_can_override_global_log_level(pytester: Pytester) -> None: pytester.makepyfile( """ import pytest @@ -406,7 +409,7 @@ def test_log_level_override(request, caplog): assert result.ret == 0 -def test_caplog_captures_despite_exception(pytester: Pytester) -> None: +def test_captures_despite_exception(pytester: Pytester) -> None: pytester.makepyfile( """ import pytest diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index aec0deb99a1..15d7c33b215 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -933,7 +933,7 @@ def test_request_subrequest_addfinalizer_exceptions( ) -> None: """ Ensure exceptions raised during teardown by finalizers are suppressed - until all finalizers are called, then re-reaised together in an + until all finalizers are called, then re-raised together in an exception group (#2440) """ pytester.makepyfile( diff --git a/testing/python/integration.py b/testing/python/integration.py index 219ebf9cec8..c20aaeed839 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -163,7 +163,7 @@ def mock_basename(path): @mock.patch("os.path.abspath") @mock.patch("os.path.normpath") @mock.patch("os.path.basename", new=mock_basename) - def test_someting(normpath, abspath, tmp_path): + def test_something(normpath, abspath, tmp_path): abspath.return_value = "this" os.path.normpath(os.path.abspath("hello")) normpath.assert_any_call("this") @@ -176,7 +176,7 @@ def test_someting(normpath, abspath, tmp_path): funcnames = [ call.report.location[2] for call in calls if call.report.when == "call" ] - assert funcnames == ["T.test_hello", "test_someting"] + assert funcnames == ["T.test_hello", "test_something"] def test_mock_sorting(self, pytester: Pytester) -> None: pytest.importorskip("mock", "1.0.1") diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index c85c1d04cc7..d7815f77b9a 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -58,7 +58,7 @@ def test_config_cache_dataerror(self, pytester: Pytester) -> None: assert val == -2 @pytest.mark.filterwarnings("ignore:could not create cache path") - def test_cache_writefail_cachfile_silent(self, pytester: Pytester) -> None: + def test_cache_writefail_cachefile_silent(self, pytester: Pytester) -> None: pytester.makeini("[pytest]") pytester.path.joinpath(".pytest_cache").write_text( "gone wrong", encoding="utf-8" diff --git a/testing/test_compat.py b/testing/test_compat.py index c898af7c531..73ac1bad858 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -94,7 +94,7 @@ def foo(x): assert get_real_func(partial(foo)) is foo -@pytest.mark.skipif(sys.version_info >= (3, 11), reason="couroutine removed") +@pytest.mark.skipif(sys.version_info >= (3, 11), reason="coroutine removed") def test_is_generator_asyncio(pytester: Pytester) -> None: pytester.makepyfile( """ diff --git a/testing/test_config.py b/testing/test_config.py index 776c8424a1a..1cb31fed06d 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -216,7 +216,7 @@ def test_toml_parse_error(self, pytester: Pytester) -> None: def test_confcutdir_default_without_configfile(self, pytester: Pytester) -> None: # If --confcutdir is not specified, and there is no configfile, default - # to the roothpath. + # to the rootpath. sub = pytester.mkdir("sub") os.chdir(sub) config = pytester.parseconfigure() @@ -1738,7 +1738,7 @@ def pytest_addoption(parser): ) pytester.makepyfile( r""" - def test_overriden(pytestconfig): + def test_overridden(pytestconfig): config_paths = pytestconfig.getini("paths") print(config_paths) for cpf in config_paths: diff --git a/testing/test_conftest.py b/testing/test_conftest.py index a3ebcbb7862..eb3ebecdc98 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -70,7 +70,7 @@ def test_basic_init(self, basedir: Path) -> None: ) assert conftest._rget_with_confmod("a", p)[1] == 1 - def test_immediate_initialiation_and_incremental_are_the_same( + def test_immediate_initialization_and_incremental_are_the_same( self, basedir: Path ) -> None: conftest = PytestPluginManager() @@ -396,7 +396,7 @@ def fixture(): @pytest.mark.skipif( os.path.normcase("x") != os.path.normcase("X"), - reason="only relevant for case insensitive file systems", + reason="only relevant for case-insensitive file systems", ) def test_conftest_badcase(pytester: Pytester) -> None: """Check conftest.py loading when directory casing is wrong (#5792).""" diff --git a/testing/test_debugging.py b/testing/test_debugging.py index a99336c75a6..1f3422947de 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -1122,7 +1122,7 @@ def test_func_kw(myparam, request, func="func_kw"): def test_trace_after_runpytest(pytester: Pytester) -> None: - """Test that debugging's pytest_configure is re-entrant.""" + """Test that debugging's pytest_configure is reentrant.""" p1 = pytester.makepyfile( """ from _pytest.debugging import pytestPDB @@ -1153,7 +1153,7 @@ def test_inner(): def test_quit_with_swallowed_SystemExit(pytester: Pytester) -> None: - """Test that debugging's pytest_configure is re-entrant.""" + """Test that debugging's pytest_configure is reentrant.""" p1 = pytester.makepyfile( """ def call_pdb_set_trace(): diff --git a/testing/test_doctest.py b/testing/test_doctest.py index de5d1353163..d731121795d 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -396,7 +396,7 @@ def some_property(self): ] ) - def test_doctest_no_linedata_on_overriden_property(self, pytester: Pytester): + def test_doctest_no_linedata_on_overridden_property(self, pytester: Pytester): pytester.makepyfile( """ class Sample(object): @@ -414,7 +414,7 @@ def some_property(self): result.stdout.fnmatch_lines( [ "*= FAILURES =*", - "*_ [[]doctest[]] test_doctest_no_linedata_on_overriden_property.Sample.some_property _*", + "*_ [[]doctest[]] test_doctest_no_linedata_on_overridden_property.Sample.some_property _*", "EXAMPLE LOCATION UNKNOWN, not showing all tests of that example", "[?][?][?] >>> Sample().some_property", "Expected:", @@ -422,7 +422,7 @@ def some_property(self): "Got:", " 'something'", "", - "*/test_doctest_no_linedata_on_overriden_property.py:None: DocTestFailure", + "*/test_doctest_no_linedata_on_overridden_property.py:None: DocTestFailure", "*= 1 failed in *", ] ) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index f8742dc2e3c..1ebc3ed3a51 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1001,7 +1001,7 @@ def repr_failure(self, excinfo): @pytest.mark.parametrize("junit_logging", ["no", "system-out"]) def test_nullbyte(pytester: Pytester, junit_logging: str) -> None: - # A null byte can not occur in XML (see section 2.2 of the spec) + # A null byte cannot occur in XML (see section 2.2 of the spec) pytester.makepyfile( """ import sys diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index f7f45dbf02e..d2b33b4fb8b 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -155,7 +155,7 @@ def pytest_addoption(parser): ) pytester.makepyfile( r""" - def test_overriden(pytestconfig): + def test_overridden(pytestconfig): config_paths = pytestconfig.getini("paths") print(config_paths) for cpf in config_paths: diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index a7a9cf3044a..07c89f90838 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -61,7 +61,7 @@ def test_basic(expr: str, expected: bool) -> None: ("not not not not not true", False), ), ) -def test_syntax_oddeties(expr: str, expected: bool) -> None: +def test_syntax_oddities(expr: str, expected: bool) -> None: matcher = {"true": True, "false": False}.__getitem__ assert evaluate(expr, matcher) is expected diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index da43364f643..99b003b66ed 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -420,7 +420,7 @@ def test_consider_conftest_deps( pytestpm.consider_conftest(mod, registration_name="unused") -class TestPytestPluginManagerBootstrapming: +class TestPytestPluginManagerBootstrapping: def test_preparse_args(self, pytestpm: PytestPluginManager) -> None: pytest.raises( ImportError, lambda: pytestpm.consider_preparse(["xyz", "-p", "hello123"]) @@ -446,7 +446,7 @@ def test_plugin_prevent_register(self, pytestpm: PytestPluginManager) -> None: assert len(l2) == len(l1) assert 42 not in l2 - def test_plugin_prevent_register_unregistered_alredy_registered( + def test_plugin_prevent_register_unregistered_already_registered( self, pytestpm: PytestPluginManager ) -> None: pytestpm.register(42, name="abc") diff --git a/testing/test_runner.py b/testing/test_runner.py index 436ce2f1062..3ec5678274e 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -446,7 +446,7 @@ def test_func(): # assert rep.outcome.when == "setup" # assert rep.outcome.where.lineno == 3 # assert rep.outcome.where.path.basename == "test_func.py" - # assert instanace(rep.failed.failurerepr, PythonFailureRepr) + # assert isinstance(rep.failed.failurerepr, PythonFailureRepr) def test_systemexit_does_not_bail_out(self, pytester: Pytester) -> None: try: diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 19848e7cbaf..6cd4a1827d2 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -926,7 +926,7 @@ def test_header(self, pytester: Pytester) -> None: def test_header_absolute_testpath( self, pytester: Pytester, monkeypatch: MonkeyPatch ) -> None: - """Regresstion test for #7814.""" + """Regression test for #7814.""" tests = pytester.path.joinpath("tests") tests.mkdir() pytester.makepyprojecttoml( diff --git a/testing/test_unittest.py b/testing/test_unittest.py index f73e083be78..003a74d3849 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -299,7 +299,7 @@ def test_func2(self): @classmethod def tearDownClass(cls): cls.x -= 1 - def test_teareddown(): + def test_torn_down(): assert MyTestCase.x == 0 """ ) @@ -346,7 +346,7 @@ def test_func2(self): assert self.x == 1 def teardown_class(cls): cls.x -= 1 - def test_teareddown(): + def test_torn_down(): assert MyTestCase.x == 0 """ ) @@ -881,7 +881,7 @@ def test_method1(self): def tearDownClass(cls): cls.x = 1 - def test_not_teareddown(): + def test_not_torn_down(): assert TestFoo.x == 0 """ From 635fbe2bff805c86c0df1db463f4c5eea087aec6 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 17 May 2024 08:19:13 -0300 Subject: [PATCH 0647/1271] Attest package provenance (#12333) Use the new build provenance support added in [build-and-inspect-python-package 2.5.0](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md#250---2024-05-13). More information: https://github.blog/2024-05-02-introducing-artifact-attestations-now-in-public-beta/ Tested also in https://github.com/pytest-dev/pytest-mock/pull/431. Note: even though it is technically necessary only for the `deploy` workflow, as the `test` workflow does not publish its packages, decided to always attest the provenance in both cases to avoid any surprises related to this (say a misconfiguration) when deploying. --- .github/workflows/deploy.yml | 9 ++++++++- .github/workflows/test.yml | 2 +- changelog/12333.trivial.rst | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 changelog/12333.trivial.rst diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cc0e6331d45..20a72270fde 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -19,6 +19,11 @@ jobs: SETUPTOOLS_SCM_PRETEND_VERSION: ${{ github.event.inputs.version }} timeout-minutes: 10 + # Required by attest-build-provenance-github. + permissions: + id-token: write + attestations: write + steps: - uses: actions/checkout@v4 with: @@ -26,7 +31,9 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.4.0 + uses: hynek/build-and-inspect-python-package@v2.5.0 + with: + attest-build-provenance-github: 'true' deploy: if: github.repository == 'pytest-dev/pytest' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4434740675e..df801864fd8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.4.0 + uses: hynek/build-and-inspect-python-package@v2.5.0 build: needs: [package] diff --git a/changelog/12333.trivial.rst b/changelog/12333.trivial.rst new file mode 100644 index 00000000000..32c4c5771a7 --- /dev/null +++ b/changelog/12333.trivial.rst @@ -0,0 +1 @@ +pytest releases are now attested using the recent `Artifact Attestation ` support from GitHub, allowing users to verify the provenance of pytest's sdist and wheel artifacts. From ee9ea703f98df811738e7ea58bffe6c1bc660371 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 18 May 2024 12:07:06 -0400 Subject: [PATCH 0648/1271] Fix new typing issues in AST code (#12337) python/typeshed#11880 adds more precise types for AST nodes. I'm submitting some changes to adapt pytest to these changes. --- src/_pytest/assertion/rewrite.py | 12 ++++++------ testing/test_assertrewrite.py | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 928c4f5e3b2..b29a254f5f7 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -835,7 +835,7 @@ def pop_format_context(self, expl_expr: ast.expr) -> ast.Name: current = self.stack.pop() if self.stack: self.explanation_specifiers = self.stack[-1] - keys = [ast.Constant(key) for key in current.keys()] + keys: List[Optional[ast.expr]] = [ast.Constant(key) for key in current.keys()] format_dict = ast.Dict(keys, list(current.values())) form = ast.BinOp(expl_expr, ast.Mod(), format_dict) name = "@py_format" + str(next(self.variable_counter)) @@ -926,13 +926,13 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: [*self.expl_stmts, hook_call_pass], [], ) - statements_pass = [hook_impl_test] + statements_pass: List[ast.stmt] = [hook_impl_test] # Test for assertion condition main_test = ast.If(negation, statements_fail, statements_pass) self.statements.append(main_test) if self.format_variables: - variables = [ + variables: List[ast.expr] = [ ast.Name(name, ast.Store()) for name in self.format_variables ] clear_format = ast.Assign(variables, ast.Constant(None)) @@ -1114,11 +1114,11 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: if isinstance(comp.left, (ast.Compare, ast.BoolOp)): left_expl = f"({left_expl})" res_variables = [self.variable() for i in range(len(comp.ops))] - load_names = [ast.Name(v, ast.Load()) for v in res_variables] + load_names: List[ast.expr] = [ast.Name(v, ast.Load()) for v in res_variables] store_names = [ast.Name(v, ast.Store()) for v in res_variables] it = zip(range(len(comp.ops)), comp.ops, comp.comparators) - expls = [] - syms = [] + expls: List[ast.expr] = [] + syms: List[ast.expr] = [] results = [left_res] for i, op, next_operand in it: if ( diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 82c7055b968..8db9dbbe5ff 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -130,6 +130,7 @@ def test_location_is_set(self) -> None: if isinstance(node, ast.Import): continue for n in [node, *ast.iter_child_nodes(node)]: + assert isinstance(n, (ast.stmt, ast.expr)) assert n.lineno == 3 assert n.col_offset == 0 assert n.end_lineno == 6 From dbee3fa34a9fb3712742f28ba15676274e68121d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 17 May 2024 11:22:53 +0300 Subject: [PATCH 0649/1271] testing: remove conditionals for Python 3.11 beta releases No need to support beta releases of an older version anymore. Ref: 09b2c9532090db84daa3aa1a243f90dc8709fc00 --- testing/test_doctest.py | 6 ------ testing/test_main.py | 17 +---------------- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index d731121795d..c6f156b0e2d 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,7 +1,6 @@ # mypy: allow-untyped-defs import inspect from pathlib import Path -import sys import textwrap from typing import Callable from typing import Optional @@ -224,11 +223,6 @@ def test_doctest_unexpected_exception(self, pytester: Pytester): "Traceback (most recent call last):", ' File "*/doctest.py", line *, in __run', " *", - *( - (" *^^^^*",) - if (3, 11, 0, "beta", 4) > sys.version_info >= (3, 11) - else () - ), ' File "", line 1, in ', "ZeroDivisionError: division by zero", "*/test_doctest_unexpected_exception.txt:2: UnexpectedException", diff --git a/testing/test_main.py b/testing/test_main.py index 345aa1e62cf..6294f66b360 100644 --- a/testing/test_main.py +++ b/testing/test_main.py @@ -3,7 +3,6 @@ import os from pathlib import Path import re -import sys from typing import Optional from _pytest.config import ExitCode @@ -45,32 +44,18 @@ def pytest_internalerror(excrepr, excinfo): assert result.ret == ExitCode.INTERNAL_ERROR assert result.stdout.lines[0] == "INTERNALERROR> Traceback (most recent call last):" - end_lines = ( - result.stdout.lines[-4:] - if (3, 11, 0, "beta", 4) > sys.version_info >= (3, 11) - else result.stdout.lines[-3:] - ) + end_lines = result.stdout.lines[-3:] if exc == SystemExit: assert end_lines == [ f'INTERNALERROR> File "{c1}", line 4, in pytest_sessionstart', 'INTERNALERROR> raise SystemExit("boom")', - *( - ("INTERNALERROR> ^^^^^^^^^^^^^^^^^^^^^^^^",) - if (3, 11, 0, "beta", 4) > sys.version_info >= (3, 11) - else () - ), "INTERNALERROR> SystemExit: boom", ] else: assert end_lines == [ f'INTERNALERROR> File "{c1}", line 4, in pytest_sessionstart', 'INTERNALERROR> raise ValueError("boom")', - *( - ("INTERNALERROR> ^^^^^^^^^^^^^^^^^^^^^^^^",) - if (3, 11, 0, "beta", 4) > sys.version_info >= (3, 11) - else () - ), "INTERNALERROR> ValueError: boom", ] if returncode is False: From cb732bbfb0a2dd8d7acbc703ce485bd2f631cf92 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 19 May 2024 00:21:06 +0000 Subject: [PATCH 0650/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 148 +++++++++++++++++++------------ 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index d03861ccfd1..43c4748ea03 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =2.7.3) :pypi:`pytest-allure-collection` pytest plugin to collect allure markers without running any tests Apr 13, 2023 N/A pytest :pypi:`pytest-allure-dsl` pytest plugin to test case doc string dls instructions Oct 25, 2020 4 - Beta pytest + :pypi:`pytest-allure-id2history` Overwrite allure history id with testcase full name and testcase id if testcase has id, exclude parameters. May 14, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) @@ -126,7 +127,7 @@ This list contains 1457 plugins. :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A - :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 10, 2024 4 - Beta pytest + :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 18, 2024 4 - Beta pytest :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Feb 02, 2024 N/A pytest (>=8.0.0,<9.0.0) :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) @@ -147,7 +148,7 @@ This list contains 1457 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 08, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 17, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -232,6 +233,7 @@ This list contains 1457 plugins. :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) + :pypi:`pytest-cleanslate` Collects and executes pytest tests separately May 15, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Apr 19, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -241,7 +243,7 @@ This list contains 1457 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest May 06, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest May 12, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 @@ -357,7 +359,7 @@ This list contains 1457 plugins. :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. Oct 18, 2023 4 - Beta pytest !=6.0.0,<8,>=3.3.2 + :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. May 11, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 :pypi:`pytest-discover` Pytest plugin to record discovered tests in a file Mar 26, 2024 N/A pytest :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. May 07, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-django` A Django plugin for pytest. Jan 30, 2024 5 - Production/Stable pytest >=7.0.0 @@ -553,7 +555,7 @@ This list contains 1457 plugins. :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest - :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jun 26, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd May 15, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-fly` pytest observer Apr 14, 2024 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest @@ -621,13 +623,13 @@ This list contains 1457 plugins. :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-henry` Aug 29, 2023 N/A N/A :pypi:`pytest-hidecaptured` Hide captured output May 04, 2018 4 - Beta pytest (>=2.8.5) - :pypi:`pytest-himark` This plugin aims to create markers automatically based on a json configuration. May 10, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-himark` This plugin aims to create markers automatically based on a json configuration. May 15, 2024 4 - Beta pytest>=6.2.0 :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 Jan 14, 2024 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 May 11, 2024 3 - Alpha pytest==8.1.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 18, 2024 3 - Alpha pytest==8.1.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -708,7 +710,7 @@ This list contains 1457 plugins. :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 30, 2024 3 - Alpha N/A - :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 19, 2023 N/A pytest (>=7.2.0) + :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked May 16, 2024 N/A pytest>=7.2.0 :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Mar 27, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest @@ -732,7 +734,7 @@ This list contains 1457 plugins. :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A :pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A - :pypi:`pytest-kookit` Your simple but kooky integration testing with pytest May 06, 2024 N/A N/A + :pypi:`pytest-kookit` Your simple but kooky integration testing with pytest May 16, 2024 N/A N/A :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) @@ -764,7 +766,7 @@ This list contains 1457 plugins. :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 + :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests May 17, 2024 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lock` pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. Feb 03, 2024 N/A pytest (>=7.4.3,<8.0.0) @@ -800,7 +802,7 @@ This list contains 1457 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. May 03, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 + :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. May 18, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Feb 15, 2024 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A @@ -875,7 +877,7 @@ This list contains 1457 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Feb 16, 2024 N/A pytest (>=6.2.5,<7.0.0) + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies May 17, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Apr 11, 2024 N/A N/A @@ -975,7 +977,7 @@ This list contains 1457 plugins. :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A - :pypi:`pytest-plone` Pytest plugin to test Plone addons Jan 05, 2023 3 - Alpha pytest + :pypi:`pytest-plone` Pytest plugin to test Plone addons May 15, 2024 3 - Alpha pytest<8.0.0 :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Mar 26, 2024 5 - Production/Stable pytest>=7.4.2 @@ -1013,6 +1015,7 @@ This list contains 1457 plugins. :pypi:`pytest-prysk` Pytest plugin for prysk Mar 12, 2024 4 - Beta pytest (>=7.3.2) :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) + :pypi:`pytest-pt` pytest plugin to use \*.pt files as tests May 15, 2024 4 - Beta pytest :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-pudb` Pytest PuDB debugger integration Oct 25, 2018 3 - Alpha pytest (>=2.0) :pypi:`pytest-pumpkin-spice` A pytest plugin that makes your test reporting pumpkin-spiced Sep 18, 2022 4 - Beta N/A @@ -1039,6 +1042,7 @@ This list contains 1457 plugins. :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) :pypi:`pytest-pythonhashseed` Pytest plugin to set PYTHONHASHSEED env var. Feb 25, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) + :pypi:`pytest-python-test-engineer-sort` Sort plugin for Pytest May 13, 2024 N/A pytest>=6.2.0 :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 @@ -1066,7 +1070,7 @@ This list contains 1457 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection May 10, 2024 4 - Beta pytest>=7.4.3 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection May 12, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Mar 14, 2024 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 @@ -1116,7 +1120,7 @@ This list contains 1457 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 :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. Feb 08, 2024 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Apr 03, 2024 N/A pytest~=4.6; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest May 17, 2024 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 @@ -1128,7 +1132,7 @@ This list contains 1457 plugins. :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Feb 04, 2024 N/A pytest >=7.0.0 + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments May 14, 2024 N/A pytest>=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest @@ -1140,7 +1144,7 @@ This list contains 1457 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them May 03, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them May 18, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1165,7 +1169,7 @@ This list contains 1457 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 03, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 16, 2024 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 Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 @@ -1174,7 +1178,7 @@ This list contains 1457 plugins. :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 Feb 01, 2024 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. May 03, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 16, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1184,6 +1188,7 @@ This list contains 1457 plugins. :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A :pypi:`pytest-servers` pytest servers May 09, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-service` May 11, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1250,7 +1255,7 @@ This list contains 1457 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 Apr 19, 2024 N/A pytest (>5.4.0,<8) + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons May 16, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX May 10, 2024 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 @@ -1423,7 +1428,6 @@ This list contains 1457 plugins. :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 Nov 23, 2023 4 - Beta pytest - :pypi:`pytest-ver` Pytest module with Verification Protocol, Verification Report and Trace Matrix Feb 07, 2024 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 @@ -1463,7 +1467,7 @@ This list contains 1457 plugins. :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Apr 23, 2024 N/A N/A + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Apr 23, 2024 N/A pytest~=7.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Mar 31, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A @@ -1720,6 +1724,13 @@ This list contains 1457 plugins. pytest plugin to test case doc string dls instructions + :pypi:`pytest-allure-id2history` + *last release*: May 14, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + Overwrite allure history id with testcase full name and testcase id if testcase has id, exclude parameters. + :pypi:`pytest-allure-intersection` *last release*: Oct 27, 2022, *status*: N/A, @@ -2141,7 +2152,7 @@ This list contains 1457 plugins. pytest plugin for testing AWS resource configurations :pypi:`pytest-aws-apigateway` - *last release*: May 10, 2024, + *last release*: May 18, 2024, *status*: 4 - Beta, *requires*: pytest @@ -2288,7 +2299,7 @@ This list contains 1457 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: May 08, 2024, + *last release*: May 17, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2882,6 +2893,13 @@ This list contains 1457 plugins. Easy quality control for CLDF datasets using pytest + :pypi:`pytest-cleanslate` + *last release*: May 15, 2024, + *status*: N/A, + *requires*: pytest + + Collects and executes pytest tests separately + :pypi:`pytest_cleanup` *last release*: Jan 28, 2020, *status*: N/A, @@ -2946,7 +2964,7 @@ This list contains 1457 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: May 06, 2024, + *last release*: May 12, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3758,9 +3776,9 @@ This list contains 1457 plugins. Disable plugins per test :pypi:`pytest-discord` - *last release*: Oct 18, 2023, + *last release*: May 11, 2024, *status*: 4 - Beta, - *requires*: pytest !=6.0.0,<8,>=3.3.2 + *requires*: pytest!=6.0.0,<9,>=3.3.2 A pytest plugin to notify test results to a Discord channel. @@ -5130,9 +5148,9 @@ This list contains 1457 plugins. :pypi:`pytest-fluent` - *last release*: Jun 26, 2023, + *last release*: May 15, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.0.0) + *requires*: pytest>=7.0.0 A pytest plugin in order to provide logs via fluentd @@ -5606,7 +5624,7 @@ This list contains 1457 plugins. Hide captured output :pypi:`pytest-himark` - *last release*: May 10, 2024, + *last release*: May 15, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -5648,7 +5666,7 @@ This list contains 1457 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 11, 2024, + *last release*: May 18, 2024, *status*: 3 - Alpha, *requires*: pytest==8.1.1 @@ -6215,9 +6233,9 @@ This list contains 1457 plugins. py.test JIRA integration plugin, using markers :pypi:`pytest-jira-xfail` - *last release*: Jun 19, 2023, + *last release*: May 16, 2024, *status*: N/A, - *requires*: pytest (>=7.2.0) + *requires*: pytest>=7.2.0 Plugin skips (xfail) tests if unresolved Jira issue(s) linked @@ -6383,7 +6401,7 @@ This list contains 1457 plugins. Run Konira DSL tests with py.test :pypi:`pytest-kookit` - *last release*: May 06, 2024, + *last release*: May 16, 2024, *status*: N/A, *requires*: N/A @@ -6607,7 +6625,7 @@ This list contains 1457 plugins. Generate local badges (shields) reporting your test suite status. :pypi:`pytest-localftpserver` - *last release*: Oct 14, 2023, + *last release*: May 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -6859,7 +6877,7 @@ This list contains 1457 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: May 03, 2024, + *last release*: May 18, 2024, *status*: 4 - Beta, *requires*: pytest!=6.0.0,<9,>=3.3.2 @@ -7384,9 +7402,9 @@ This list contains 1457 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Feb 16, 2024, + *last release*: May 17, 2024, *status*: N/A, - *requires*: pytest (>=6.2.5,<7.0.0) + *requires*: pytest<9.0.0,>=8.2.0 Pytest plugin accessing NHSDigital's APIM proxies @@ -8084,9 +8102,9 @@ This list contains 1457 plugins. A pytest fixture for visual testing with Playwright :pypi:`pytest-plone` - *last release*: Jan 05, 2023, + *last release*: May 15, 2024, *status*: 3 - Alpha, - *requires*: pytest + *requires*: pytest<8.0.0 Pytest plugin to test Plone addons @@ -8349,6 +8367,13 @@ This list contains 1457 plugins. pytest plugin for testing applications that use psqlgraph + :pypi:`pytest-pt` + *last release*: May 15, 2024, + *status*: 4 - Beta, + *requires*: pytest + + pytest plugin to use \*.pt files as tests + :pypi:`pytest-ptera` *last release*: Mar 01, 2022, *status*: N/A, @@ -8531,6 +8556,13 @@ This list contains 1457 plugins. pytest plugin for adding to the PYTHONPATH from command line or configs. + :pypi:`pytest-python-test-engineer-sort` + *last release*: May 13, 2024, + *status*: N/A, + *requires*: pytest>=6.2.0 + + Sort plugin for Pytest + :pypi:`pytest-pytorch` *last release*: May 25, 2021, *status*: 4 - Beta, @@ -8721,7 +8753,7 @@ This list contains 1457 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-ranking` - *last release*: May 10, 2024, + *last release*: May 12, 2024, *status*: 4 - Beta, *requires*: pytest>=7.4.3 @@ -9071,7 +9103,7 @@ This list contains 1457 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Apr 03, 2024, + *last release*: May 17, 2024, *status*: N/A, *requires*: pytest~=4.6; python_version == "2.7" @@ -9155,9 +9187,9 @@ This list contains 1457 plugins. A RethinkDB plugin for pytest. :pypi:`pytest-retry` - *last release*: Feb 04, 2024, + *last release*: May 14, 2024, *status*: N/A, - *requires*: pytest >=7.0.0 + *requires*: pytest>=7.0.0 Adds the ability to retry flaky tests in CI environments @@ -9239,7 +9271,7 @@ This list contains 1457 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: May 03, 2024, + *last release*: May 18, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9414,7 +9446,7 @@ This list contains 1457 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: May 03, 2024, + *last release*: May 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9477,7 +9509,7 @@ This list contains 1457 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: May 03, 2024, + *last release*: May 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9546,6 +9578,13 @@ This list contains 1457 plugins. pytest servers + :pypi:`pytest-service` + *last release*: May 11, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=6.0.0 + + + :pypi:`pytest-services` *last release*: Oct 30, 2020, *status*: 6 - Mature, @@ -10009,9 +10048,9 @@ This list contains 1457 plugins. :pypi:`pytest-splunk-addon` - *last release*: Apr 19, 2024, + *last release*: May 16, 2024, *status*: N/A, - *requires*: pytest (>5.4.0,<8) + *requires*: pytest<8,>5.4.0 A Dynamic test tool for Splunk Apps and Add-ons @@ -11219,13 +11258,6 @@ This list contains 1457 plugins. py.test fixture for creating a virtual environment - :pypi:`pytest-ver` - *last release*: Feb 07, 2024, - *status*: 4 - Beta, - *requires*: pytest - - Pytest module with Verification Protocol, Verification Report and Trace Matrix - :pypi:`pytest-verbose-parametrize` *last release*: May 28, 2019, *status*: 5 - Production/Stable, @@ -11502,7 +11534,7 @@ This list contains 1457 plugins. :pypi:`pytest-xlsx` *last release*: Apr 23, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest~=7.0 pytest plugin for generating test cases by xlsx(excel) From 1cb704ff2c6f6d4e8abd45734d05e9a3f326348b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 17 May 2024 09:59:29 +0300 Subject: [PATCH 0651/1271] Add Python 3.13 (beta1) support --- .github/workflows/test.yml | 22 +++++++++++++++++++--- changelog/12334.improvement.rst | 1 + pyproject.toml | 1 + src/_pytest/_code/code.py | 7 +++---- src/_pytest/pytester.py | 6 +++++- testing/code/test_excinfo.py | 8 ++++++-- testing/code/test_source.py | 6 +++++- testing/test_cacheprovider.py | 2 +- testing/test_doctest.py | 4 +++- tox.ini | 1 + 10 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 changelog/12334.improvement.rst diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index df801864fd8..09d37aaa2c8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -55,6 +55,7 @@ jobs: "windows-py310", "windows-py311", "windows-py312", + "windows-py313", "ubuntu-py38", "ubuntu-py38-pluggy", @@ -63,12 +64,14 @@ jobs: "ubuntu-py310", "ubuntu-py311", "ubuntu-py312", + "ubuntu-py313", "ubuntu-pypy3", "macos-py38", "macos-py39", "macos-py310", "macos-py312", + "macos-py313", "doctesting", "plugins", @@ -97,9 +100,13 @@ jobs: os: windows-latest tox_env: "py311" - name: "windows-py312" - python: "3.12-dev" + python: "3.12" os: windows-latest tox_env: "py312" + - name: "windows-py313" + python: "3.13-dev" + os: windows-latest + tox_env: "py313" - name: "ubuntu-py38" python: "3.8" @@ -128,10 +135,15 @@ jobs: tox_env: "py311" use_coverage: true - name: "ubuntu-py312" - python: "3.12-dev" + python: "3.12" os: ubuntu-latest tox_env: "py312" use_coverage: true + - name: "ubuntu-py313" + python: "3.13-dev" + os: ubuntu-latest + tox_env: "py313" + use_coverage: true - name: "ubuntu-pypy3" python: "pypy-3.8" os: ubuntu-latest @@ -151,9 +163,13 @@ jobs: os: macos-latest tox_env: "py310-xdist" - name: "macos-py312" - python: "3.12-dev" + python: "3.12" os: macos-latest tox_env: "py312-xdist" + - name: "macos-py313" + python: "3.13-dev" + os: macos-latest + tox_env: "py313-xdist" - name: "plugins" python: "3.12" diff --git a/changelog/12334.improvement.rst b/changelog/12334.improvement.rst new file mode 100644 index 00000000000..7fd52e9dbb8 --- /dev/null +++ b/changelog/12334.improvement.rst @@ -0,0 +1 @@ +Support for Python 3.13 (beta1 at the time of writing). diff --git a/pyproject.toml b/pyproject.toml index 2be02ee7e23..b85f39d856c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing", "Topic :: Utilities", diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index b80d53ca5f9..cfa226bb749 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -424,15 +424,14 @@ def recursionindex(self) -> Optional[int]: # which generates code objects that have hash/value equality # XXX needs a test key = entry.frame.code.path, id(entry.frame.code.raw), entry.lineno - # print "checking for recursion at", key values = cache.setdefault(key, []) + # Since Python 3.13 f_locals is a proxy, freeze it. + loc = dict(entry.frame.f_locals) if values: - f = entry.frame - loc = f.f_locals for otherloc in values: if otherloc == loc: return i - values.append(entry.frame.f_locals) + values.append(loc) return None diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 31c6de78195..f9ab007a4d1 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -289,7 +289,8 @@ def assert_contains(self, entries: Sequence[Tuple[str, str]]) -> None: __tracebackhide__ = True i = 0 entries = list(entries) - backlocals = sys._getframe(1).f_locals + # Since Python 3.13, f_locals is not a dict, but eval requires a dict. + backlocals = dict(sys._getframe(1).f_locals) while entries: name, check = entries.pop(0) for ind, call in enumerate(self.calls[i:]): @@ -760,6 +761,9 @@ def _makefile( ) -> Path: items = list(files.items()) + if ext is None: + raise TypeError("ext must not be None") + if ext and not ext.startswith("."): raise ValueError( f"pytester.makefile expects a file extension, try .{ext} instead of {ext}" diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 86e30dc4830..b5474512987 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs from __future__ import annotations +import fnmatch import importlib import io import operator @@ -237,7 +238,7 @@ def f(n): n += 1 f(n) - excinfo = pytest.raises(RuntimeError, f, 8) + excinfo = pytest.raises(RecursionError, f, 8) traceback = excinfo.traceback recindex = traceback.recursionindex() assert recindex == 3 @@ -373,7 +374,10 @@ def test_excinfo_no_sourcecode(): except ValueError: excinfo = _pytest._code.ExceptionInfo.from_current() s = str(excinfo.traceback[-1]) - assert s == " File '':1 in \n ???\n" + # TODO: Since Python 3.13b1 under pytest-xdist, the * is `import + # sys;exec(eval(sys.stdin.readline()))` (execnet bootstrap code) + # instead of `???` like before. Is this OK? + fnmatch.fnmatch(s, " File '':1 in \n *\n") def test_excinfo_no_python_sourcecode(tmp_path: Path) -> None: diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 2fa85205795..a00259976c4 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -370,7 +370,11 @@ class B: pass B.__name__ = B.__qualname__ = "B2" - assert getfslineno(B)[1] == -1 + # Since Python 3.13 this started working. + if sys.version_info >= (3, 13): + assert getfslineno(B)[1] != -1 + else: + assert getfslineno(B)[1] == -1 def test_code_of_object_instance_with_call() -> None: diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index d7815f77b9a..8728ae84fdc 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -194,7 +194,7 @@ def test_custom_cache_dir_with_env_var( assert pytester.path.joinpath("custom_cache_dir").is_dir() -@pytest.mark.parametrize("env", ((), ("TOX_ENV_DIR", "/tox_env_dir"))) +@pytest.mark.parametrize("env", ((), ("TOX_ENV_DIR", "mydir/tox-env"))) def test_cache_reportheader( env: Sequence[str], pytester: Pytester, monkeypatch: MonkeyPatch ) -> None: diff --git a/testing/test_doctest.py b/testing/test_doctest.py index c6f156b0e2d..9b33d641a14 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs import inspect from pathlib import Path +import sys import textwrap from typing import Callable from typing import Optional @@ -223,6 +224,7 @@ def test_doctest_unexpected_exception(self, pytester: Pytester): "Traceback (most recent call last):", ' File "*/doctest.py", line *, in __run', " *", + *((" *^^^^*", " *", " *") if sys.version_info >= (3, 13) else ()), ' File "", line 1, in ', "ZeroDivisionError: division by zero", "*/test_doctest_unexpected_exception.txt:2: UnexpectedException", @@ -379,7 +381,7 @@ def some_property(self): "*= FAILURES =*", "*_ [[]doctest[]] test_doctest_linedata_on_property.Sample.some_property _*", "004 ", - "005 >>> Sample().some_property", + "005 *>>> Sample().some_property", "Expected:", " 'another thing'", "Got:", diff --git a/tox.ini b/tox.ini index 4e1ff111966..0a3f0acf5b8 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,7 @@ envlist = py310 py311 py312 + py313 pypy3 py38-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} doctesting From 32baa0b93d770a7acb9f7b59eb2d3382e6b9b78e Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 19 May 2024 16:43:40 +0000 Subject: [PATCH 0652/1271] Prepare release version 8.2.1 (cherry picked from commit 66ff8dffdf9eee9b3dd6686de34542c49ff80dcd) --- changelog/12120.bugfix.rst | 1 - changelog/12191.bugfix.rst | 1 - changelog/12300.bugfix.rst | 1 - changelog/12308.bugfix.rst | 1 - changelog/12333.trivial.rst | 1 - changelog/12334.improvement.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.2.1.rst | 19 +++++++++++++++++ doc/en/builtin.rst | 2 +- doc/en/changelog.rst | 32 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 14 files changed, 60 insertions(+), 14 deletions(-) delete mode 100644 changelog/12120.bugfix.rst delete mode 100644 changelog/12191.bugfix.rst delete mode 100644 changelog/12300.bugfix.rst delete mode 100644 changelog/12308.bugfix.rst delete mode 100644 changelog/12333.trivial.rst delete mode 100644 changelog/12334.improvement.rst create mode 100644 doc/en/announce/release-8.2.1.rst diff --git a/changelog/12120.bugfix.rst b/changelog/12120.bugfix.rst deleted file mode 100644 index b1ca4913b37..00000000000 --- a/changelog/12120.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix `PermissionError` crashes arising from directories which are not selected on the command-line. diff --git a/changelog/12191.bugfix.rst b/changelog/12191.bugfix.rst deleted file mode 100644 index 5102d469814..00000000000 --- a/changelog/12191.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Keyboard interrupts and system exits are now properly handled during the test collection. diff --git a/changelog/12300.bugfix.rst b/changelog/12300.bugfix.rst deleted file mode 100644 index 6c162482022..00000000000 --- a/changelog/12300.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed handling of 'Function not implemented' error under squashfuse_ll, which is a different way to say that the mountpoint is read-only. diff --git a/changelog/12308.bugfix.rst b/changelog/12308.bugfix.rst deleted file mode 100644 index 07995427a1a..00000000000 --- a/changelog/12308.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.2.0 where the permissions of automatically-created ``.pytest_cache`` directories became ``rwx------`` instead of the expected ``rwxr-xr-x``. diff --git a/changelog/12333.trivial.rst b/changelog/12333.trivial.rst deleted file mode 100644 index 32c4c5771a7..00000000000 --- a/changelog/12333.trivial.rst +++ /dev/null @@ -1 +0,0 @@ -pytest releases are now attested using the recent `Artifact Attestation ` support from GitHub, allowing users to verify the provenance of pytest's sdist and wheel artifacts. diff --git a/changelog/12334.improvement.rst b/changelog/12334.improvement.rst deleted file mode 100644 index 7fd52e9dbb8..00000000000 --- a/changelog/12334.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Support for Python 3.13 (beta1 at the time of writing). diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 4d0a3ab558e..8a33f7fb57d 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.2.1 release-8.2.0 release-8.1.2 release-8.1.1 diff --git a/doc/en/announce/release-8.2.1.rst b/doc/en/announce/release-8.2.1.rst new file mode 100644 index 00000000000..4452edec110 --- /dev/null +++ b/doc/en/announce/release-8.2.1.rst @@ -0,0 +1,19 @@ +pytest-8.2.1 +======================================= + +pytest 8.2.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index d5f2e9a1b0f..458253fabbb 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:542 + cache -- .../_pytest/cacheprovider.py:549 Return a cache object that can persist state between testing sessions. cache.get(key, default) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index d5cde498859..f69b9782bbc 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,38 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.2.1 (2024-05-19) +========================= + +Improvements +------------ + +- `#12334 `_: Support for Python 3.13 (beta1 at the time of writing). + + + +Bug Fixes +--------- + +- `#12120 `_: Fix `PermissionError` crashes arising from directories which are not selected on the command-line. + + +- `#12191 `_: Keyboard interrupts and system exits are now properly handled during the test collection. + + +- `#12300 `_: Fixed handling of 'Function not implemented' error under squashfuse_ll, which is a different way to say that the mountpoint is read-only. + + +- `#12308 `_: Fix a regression in pytest 8.2.0 where the permissions of automatically-created ``.pytest_cache`` directories became ``rwx------`` instead of the expected ``rwxr-xr-x``. + + + +Trivial/Internal Changes +------------------------ + +- `#12333 `_: pytest releases are now attested using the recent `Artifact Attestation ` support from GitHub, allowing users to verify the provenance of pytest's sdist and wheel artifacts. + + pytest 8.2.0 (2024-04-27) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 1bbe2faaad0..03f6852e5c0 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index a383173d07e..aa9d05d7227 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 468de3654d9..94e0d80e656 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.2.0 + pytest 8.2.1 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 72b69a14681..6cc20c8c3e4 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From d4f827d86b1c15a4628c1a41bdea57e577d71784 Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Sun, 19 May 2024 17:14:45 -0400 Subject: [PATCH 0653/1271] Fix link in changelog (#12343) --- doc/en/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index f69b9782bbc..ca7f5b999bd 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -57,7 +57,7 @@ Bug Fixes Trivial/Internal Changes ------------------------ -- `#12333 `_: pytest releases are now attested using the recent `Artifact Attestation ` support from GitHub, allowing users to verify the provenance of pytest's sdist and wheel artifacts. +- `#12333 `_: pytest releases are now attested using the recent `Artifact Attestation `_ support from GitHub, allowing users to verify the provenance of pytest's sdist and wheel artifacts. pytest 8.2.0 (2024-04-27) From 00be7c07390fa5b85882bb19bbb246732a5d84cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 07:11:04 +0200 Subject: [PATCH 0654/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#12345) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.6 to 0.23.7. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.6...v0.23.7) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d4d0fc633c0..458cc2f9743 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.3.0 django==5.0.6 -pytest-asyncio==0.23.6 +pytest-asyncio==0.23.7 pytest-bdd==7.1.2 pytest-cov==5.0.0 pytest-django==4.8.0 From 807c01451867cb107900a5a9ce0d07f261770d99 Mon Sep 17 00:00:00 2001 From: polkapolka <7219835+polkapolka@users.noreply.github.com> Date: Mon, 20 May 2024 22:14:51 +0000 Subject: [PATCH 0655/1271] changed warning raised by async def to error --- src/_pytest/config/exceptions.py | 4 ---- src/_pytest/python.py | 16 ++++++++++++++-- src/_pytest/warning_types.py | 2 +- testing/acceptance_test.py | 31 +++++++++++-------------------- testing/test_unittest.py | 2 +- 5 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/_pytest/config/exceptions.py b/src/_pytest/config/exceptions.py index 4031ea732f3..95c412734be 100644 --- a/src/_pytest/config/exceptions.py +++ b/src/_pytest/config/exceptions.py @@ -1,7 +1,3 @@ -from typing import final - - -@final class UsageError(Exception): """Error in pytest usage or invocation.""" diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 4887614de3b..bf20ca31d13 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -54,6 +54,7 @@ from _pytest.config import Config from _pytest.config import hookimpl from _pytest.config.argparsing import Parser +from _pytest.config.exceptions import UsageError from _pytest.deprecated import check_ispytest from _pytest.fixtures import FixtureDef from _pytest.fixtures import FixtureRequest @@ -77,7 +78,6 @@ from _pytest.stash import StashKey from _pytest.warning_types import PytestCollectionWarning from _pytest.warning_types import PytestReturnNotNoneWarning -from _pytest.warning_types import PytestUnhandledCoroutineWarning if TYPE_CHECKING: @@ -138,6 +138,16 @@ def pytest_configure(config: Config) -> None: ) +@final +class PytestUnhandledCoroutineError(UsageError): + """An unraisable exception resulted in an error. + + Unraisable exceptions are exceptions raised in :meth:`__del__ ` + implementations and similar situations when the exception cannot be raised + as normal. + """ + + def async_warn_and_skip(nodeid: str) -> None: msg = "async def functions are not natively supported and have been skipped.\n" msg += ( @@ -148,7 +158,9 @@ def async_warn_and_skip(nodeid: str) -> None: msg += " - pytest-tornasync\n" msg += " - pytest-trio\n" msg += " - pytest-twisted" - warnings.warn(PytestUnhandledCoroutineWarning(msg.format(nodeid))) + raise PytestUnhandledCoroutineError( + msg.format(nodeid) + ) # TODO: This is the warning to look at skip(reason="async def function and no async plugin installed (see warnings)") diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index a5884f29582..d2e542651fe 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -77,7 +77,7 @@ def simple(cls, apiname: str) -> "PytestExperimentalApiWarning": @final -class PytestUnhandledCoroutineWarning(PytestReturnNotNoneWarning): +class PytestUnhandledCoroutineWarning(PytestReturnNotNoneWarning): # TODO: look at this """Warning emitted for an unhandled coroutine. A coroutine was encountered when collecting test functions, but was not diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index ac7fab3d27a..12c8a50dd98 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1233,7 +1233,7 @@ def test_usage_error_code(pytester: Pytester) -> None: assert result.ret == ExitCode.USAGE_ERROR -def test_warn_on_async_function(pytester: Pytester) -> None: +def test_error_on_async_function(pytester: Pytester) -> None: # TODO: Change this # In the below we .close() the coroutine only to avoid # "RuntimeWarning: coroutine 'test_2' was never awaited" # which messes with other tests. @@ -1249,23 +1249,19 @@ def test_3(): return coro """ ) - result = pytester.runpytest("-Wdefault") + result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "test_async.py::test_1", - "test_async.py::test_2", - "test_async.py::test_3", + "*test_async.py::test_1*", + "*test_async.py::test_2*", + "*test_async.py::test_3*", "*async def functions are not natively supported*", - "*3 skipped, 3 warnings in*", ] ) - # ensure our warning message appears only once - assert ( - result.stdout.str().count("async def functions are not natively supported") == 1 - ) + result.assert_outcomes(failed=3) -def test_warn_on_async_gen_function(pytester: Pytester) -> None: +def test_error_on_async_gen_function(pytester: Pytester) -> None: # TODO: Change this pytester.makepyfile( test_async=""" async def test_1(): @@ -1276,20 +1272,15 @@ def test_3(): return test_2() """ ) - result = pytester.runpytest("-Wdefault") + result = pytester.runpytest() result.stdout.fnmatch_lines( [ - "test_async.py::test_1", - "test_async.py::test_2", - "test_async.py::test_3", + "*test_async.py::test_1*", + "*test_async.py::test_2*", + "*test_async.py::test_3*", "*async def functions are not natively supported*", - "*3 skipped, 3 warnings in*", ] ) - # ensure our warning message appears only once - assert ( - result.stdout.str().count("async def functions are not natively supported") == 1 - ) def test_pdb_can_be_rewritten(pytester: Pytester) -> None: diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 003a74d3849..e2a2904a3ba 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1309,7 +1309,7 @@ def test_1(self): assert tracked == [] -def test_async_support(pytester: Pytester) -> None: +def test_async_support(pytester: Pytester) -> None: # TODO: Change this pytest.importorskip("unittest.async_case") pytester.copy_example("unittest/test_unittest_asyncio.py") From 5d5c9dc85850f64621190e62bd20d4b190bdbdb6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 07:04:09 +0000 Subject: [PATCH 0656/1271] [pre-commit.ci] pre-commit autoupdate (#12321) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.3 → v0.4.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.3...v0.4.4) - [github.com/tox-dev/pyproject-fmt: 1.8.0 → 2.1.3](https://github.com/tox-dev/pyproject-fmt/compare/1.8.0...2.1.3) Also fix the comment following autofix Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 4 +- pyproject.toml | 274 +++++++++++++++++++++------------------- 2 files changed, 148 insertions(+), 130 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b83ae969661..f20f61761e0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.3" + rev: "v0.4.4" hooks: - id: ruff args: ["--fix"] @@ -38,7 +38,7 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "1.8.0" + rev: "2.1.3" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version diff --git a/pyproject.toml b/pyproject.toml index b85f39d856c..e3c64b3e9d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,10 @@ +[build-system] +build-backend = "setuptools.build_meta" +requires = [ + "setuptools>=61", + "setuptools-scm[toml]>=6.2.3", +] + [project] name = "pytest" description = "pytest: simple powerful testing with Python" @@ -6,15 +13,15 @@ keywords = [ "test", "unittest", ] -license = {text = "MIT"} +license = { text = "MIT" } authors = [ - {name = "Holger Krekel"}, - {name = "Bruno Oliveira"}, - {name = "Ronny Pfannschmidt"}, - {name = "Floris Bruynooghe"}, - {name = "Brianna Laugher"}, - {name = "Florian Bruhin"}, - {name = "Others (See AUTHORS)"}, + { name = "Holger Krekel" }, + { name = "Bruno Oliveira" }, + { name = "Ronny Pfannschmidt" }, + { name = "Floris Bruynooghe" }, + { name = "Brianna Laugher" }, + { name = "Florian Bruhin" }, + { name = "Others (See AUTHORS)" }, ] requires-python = ">=3.8" classifiers = [ @@ -31,7 +38,6 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing", "Topic :: Utilities", @@ -40,15 +46,14 @@ dynamic = [ "version", ] dependencies = [ - 'colorama; sys_platform == "win32"', - 'exceptiongroup>=1.0.0rc8; python_version < "3.11"', + "colorama; sys_platform=='win32'", + "exceptiongroup>=1.0.0rc8; python_version<'3.11'", "iniconfig", "packaging", - "pluggy<2.0,>=1.5", - 'tomli>=1; python_version < "3.11"', + "pluggy<2,>=1.5", + "tomli>=1; python_version<'3.11'", ] -[project.optional-dependencies] -dev = [ +optional-dependencies.dev = [ "argcomplete", "attrs>=19.2", "hypothesis>=3.56", @@ -58,59 +63,54 @@ dev = [ "setuptools", "xmlschema", ] -[project.urls] -Changelog = "https://docs.pytest.org/en/stable/changelog.html" -Homepage = "https://docs.pytest.org/en/latest/" -Source = "https://github.com/pytest-dev/pytest" -Tracker = "https://github.com/pytest-dev/pytest/issues" -Twitter = "https://twitter.com/pytestdotorg" -[project.scripts] -"py.test" = "pytest:console_main" -pytest = "pytest:console_main" - -[build-system] -build-backend = "setuptools.build_meta" -requires = [ - "setuptools>=61", - "setuptools-scm[toml]>=6.2.3", -] +urls.Changelog = "https://docs.pytest.org/en/stable/changelog.html" +urls.Homepage = "https://docs.pytest.org/en/latest/" +urls.Source = "https://github.com/pytest-dev/pytest" +urls.Tracker = "https://github.com/pytest-dev/pytest/issues" +urls.Twitter = "https://twitter.com/pytestdotorg" +scripts."py.test" = "pytest:console_main" +scripts.pytest = "pytest:console_main" [tool.setuptools.package-data] -"_pytest" = ["py.typed"] -"pytest" = ["py.typed"] +"_pytest" = [ + "py.typed", +] +"pytest" = [ + "py.typed", +] [tool.setuptools_scm] write_to = "src/_pytest/_version.py" [tool.black] -target-version = ['py38'] +target-version = [ + 'py38', +] [tool.ruff] -src = ["src"] line-length = 88 - -[tool.ruff.format] -docstring-code-format = true - -[tool.ruff.lint] -select = [ - "B", # bugbear - "D", # pydocstyle - "E", # pycodestyle - "F", # pyflakes - "I", # isort - "PYI", # flake8-pyi - "UP", # pyupgrade - "RUF", # ruff - "W", # pycodestyle - "PIE", # flake8-pie - "PGH004", # pygrep-hooks - Use specific rule codes when using noqa - "PLE", # pylint error - "PLW", # pylint warning +src = [ + "src", +] +format.docstring-code-format = true +lint.select = [ + "B", # bugbear + "D", # pydocstyle + "E", # pycodestyle + "F", # pyflakes + "I", # isort + "PGH004", # pygrep-hooks - Use specific rule codes when using noqa + "PIE", # flake8-pie + "PLE", # pylint error "PLR1714", # Consider merging multiple comparisons - "T100", # flake8-debugger + "PLW", # pylint warning + "PYI", # flake8-pyi + "RUF", # ruff + "T100", # flake8-debugger + "UP", # pyupgrade + "W", # pycodestyle ] -ignore = [ +lint.ignore = [ # bugbear ignore "B004", # Using `hasattr(x, "__call__")` to test if x is callable is unreliable. "B007", # Loop control variable `i` not used within loop body @@ -118,10 +118,6 @@ ignore = [ "B010", # [*] Do not call `setattr` with a constant attribute value. "B011", # Do not `assert False` (`python -O` removes these calls) "B028", # No explicit `stacklevel` keyword argument found - # pycodestyle ignore - # pytest can do weird low-level things, and we usually know - # what we're doing when we use type(..) is ... - "E721", # Do not compare types, use `isinstance()` # pydocstyle ignore "D100", # Missing docstring in public module "D101", # Missing docstring in public class @@ -131,46 +127,51 @@ ignore = [ "D105", # Missing docstring in magic method "D106", # Missing docstring in public nested class "D107", # Missing docstring in `__init__` - "D209", # [*] Multi-line docstring closing quotes should be on a separate line "D205", # 1 blank line required between summary line and description + "D209", # [*] Multi-line docstring closing quotes should be on a separate line "D400", # First line should end with a period "D401", # First line of docstring should be in imperative mood "D402", # First line should not be the function's signature "D404", # First word of the docstring should not be "This" "D415", # First line should end with a period, question mark, or exclamation point + # pytest can do weird low-level things, and we usually know + # what we're doing when we use type(..) is ... + "E721", # Do not compare types, use `isinstance()` + # pylint ignore + "PLR5501", # Use `elif` instead of `else` then `if` + "PLW0120", # remove the else and dedent its contents + "PLW0603", # Using the global statement + "PLW2901", # for loop variable overwritten by assignment target # ruff ignore "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - # pylint ignore - "PLW0603", # Using the global statement - "PLW0120", # remove the else and dedent its contents - "PLW2901", # for loop variable overwritten by assignment target - "PLR5501", # Use `elif` instead of `else` then `if` ] - -[tool.ruff.lint.pycodestyle] +lint.per-file-ignores."src/_pytest/_py/**/*.py" = [ + "B", + "PYI", +] +lint.per-file-ignores."src/_pytest/_version.py" = [ + "I001", +] +lint.per-file-ignores."testing/python/approx.py" = [ + "B015", +] +lint.isort.combine-as-imports = true +lint.isort.force-single-line = true +lint.isort.force-sort-within-sections = true +lint.isort.known-local-folder = [ + "pytest", + "_pytest", +] +lint.isort.lines-after-imports = 2 +lint.isort.order-by-type = false # In order to be able to format for 88 char in ruff format -max-line-length = 120 - -[tool.ruff.lint.pydocstyle] -convention = "pep257" - -[tool.ruff.lint.isort] -force-single-line = true -combine-as-imports = true -force-sort-within-sections = true -order-by-type = false -known-local-folder = ["pytest", "_pytest"] -lines-after-imports = 2 - -[tool.ruff.lint.per-file-ignores] -"src/_pytest/_py/**/*.py" = ["B", "PYI"] -"src/_pytest/_version.py" = ["I001"] -"testing/python/approx.py" = ["B015"] +lint.pycodestyle.max-line-length = 120 +lint.pydocstyle.convention = "pep257" [tool.pylint.main] # Maximum number of characters on a single line. max-line-length = 120 -disable= [ +disable = [ "abstract-method", "arguments-differ", "arguments-renamed", @@ -291,16 +292,27 @@ indent = 4 [tool.pytest.ini_options] minversion = "2.0" addopts = "-rfEX -p pytester --strict-markers" -python_files = ["test_*.py", "*_test.py", "testing/python/*.py"] -python_classes = ["Test", "Acceptance"] -python_functions = ["test"] +python_files = [ + "test_*.py", + "*_test.py", + "testing/python/*.py", +] +python_classes = [ + "Test", + "Acceptance", +] +python_functions = [ + "test", +] # NOTE: "doc" is not included here, but gets tested explicitly via "doctesting". -testpaths = ["testing"] +testpaths = [ + "testing", +] norecursedirs = [ - "testing/example_scripts", - ".*", - "build", - "dist", + "testing/example_scripts", + ".*", + "build", + "dist", ] xfail_strict = true filterwarnings = [ @@ -355,49 +367,55 @@ directory = "changelog/" title_format = "pytest {version} ({project_date})" template = "changelog/_template.rst" - [[tool.towncrier.type]] - directory = "breaking" - name = "Breaking Changes" - showcontent = true +[[tool.towncrier.type]] +directory = "breaking" +name = "Breaking Changes" +showcontent = true - [[tool.towncrier.type]] - directory = "deprecation" - name = "Deprecations" - showcontent = true +[[tool.towncrier.type]] +directory = "deprecation" +name = "Deprecations" +showcontent = true - [[tool.towncrier.type]] - directory = "feature" - name = "Features" - showcontent = true +[[tool.towncrier.type]] +directory = "feature" +name = "Features" +showcontent = true - [[tool.towncrier.type]] - directory = "improvement" - name = "Improvements" - showcontent = true +[[tool.towncrier.type]] +directory = "improvement" +name = "Improvements" +showcontent = true - [[tool.towncrier.type]] - directory = "bugfix" - name = "Bug Fixes" - showcontent = true +[[tool.towncrier.type]] +directory = "bugfix" +name = "Bug Fixes" +showcontent = true - [[tool.towncrier.type]] - directory = "vendor" - name = "Vendored Libraries" - showcontent = true +[[tool.towncrier.type]] +directory = "vendor" +name = "Vendored Libraries" +showcontent = true - [[tool.towncrier.type]] - directory = "doc" - name = "Improved Documentation" - showcontent = true +[[tool.towncrier.type]] +directory = "doc" +name = "Improved Documentation" +showcontent = true - [[tool.towncrier.type]] - directory = "trivial" - name = "Trivial/Internal Changes" - showcontent = true +[[tool.towncrier.type]] +directory = "trivial" +name = "Trivial/Internal Changes" +showcontent = true [tool.mypy] -files = ["src", "testing", "scripts"] -mypy_path = ["src"] +files = [ + "src", + "testing", + "scripts", +] +mypy_path = [ + "src", +] check_untyped_defs = true disallow_any_generics = true disallow_untyped_defs = true From cbf6bd9dd28d8464f7eebe32e51b398e2a5e3039 Mon Sep 17 00:00:00 2001 From: Sam Jirovec <47160720+samjirovec@users.noreply.github.com> Date: Tue, 21 May 2024 08:56:18 -0500 Subject: [PATCH 0657/1271] Issue #12290 - Docs using Furo Theme W/ Dark Mode (#12326) * furo theme for docs site * removing duplicate tocs from deprecations and reference pages * removing pallets references in code and config * reverting trainings to sidebar * removed sphinx style and unpinned packaging version * updated styles --- AUTHORS | 1 + CONTRIBUTING.rst | 4 ---- changelog/12290.doc.rst | 1 + doc/en/{img => _static}/pytest1.png | Bin doc/en/_templates/sidebar/brand.html | 7 ++++++ doc/en/_templates/slim_searchbox.html | 14 ------------ doc/en/_templates/style.html | 7 ++++++ doc/en/conf.py | 30 ++++++++++---------------- doc/en/deprecations.rst | 4 ---- doc/en/index.rst | 17 +++++++-------- doc/en/reference/reference.rst | 3 --- doc/en/requirements.txt | 4 ++-- 12 files changed, 37 insertions(+), 55 deletions(-) create mode 100644 changelog/12290.doc.rst rename doc/en/{img => _static}/pytest1.png (100%) create mode 100644 doc/en/_templates/sidebar/brand.html delete mode 100644 doc/en/_templates/slim_searchbox.html create mode 100644 doc/en/_templates/style.html diff --git a/AUTHORS b/AUTHORS index 54ed85fc732..cc53ce10d4f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -358,6 +358,7 @@ Sadra Barikbin Saiprasad Kale Samuel Colvin Samuel Dion-Girardeau +Samuel Jirovec Samuel Searles-Bryant Samuel Therrien (Avasam) Samuele Pedroni diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index d7da59c812d..0bf440da261 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -5,10 +5,6 @@ Contribution getting started Contributions are highly welcomed and appreciated. Every little bit of help counts, so do not hesitate! -.. contents:: - :depth: 2 - :backlinks: none - .. _submitfeedback: diff --git a/changelog/12290.doc.rst b/changelog/12290.doc.rst new file mode 100644 index 00000000000..07fe3babc66 --- /dev/null +++ b/changelog/12290.doc.rst @@ -0,0 +1 @@ +Updated Sphinx theme to use Furo instead of Flask, enabling Dark mode theme. diff --git a/doc/en/img/pytest1.png b/doc/en/_static/pytest1.png similarity index 100% rename from doc/en/img/pytest1.png rename to doc/en/_static/pytest1.png diff --git a/doc/en/_templates/sidebar/brand.html b/doc/en/_templates/sidebar/brand.html new file mode 100644 index 00000000000..f997c4cca5f --- /dev/null +++ b/doc/en/_templates/sidebar/brand.html @@ -0,0 +1,7 @@ + + + diff --git a/doc/en/_templates/slim_searchbox.html b/doc/en/_templates/slim_searchbox.html deleted file mode 100644 index f088ff8d312..00000000000 --- a/doc/en/_templates/slim_searchbox.html +++ /dev/null @@ -1,14 +0,0 @@ -{# - basic/searchbox.html with heading removed. -#} -{%- if pagename != "search" and builder != "singlehtml" %} - - -{%- endif %} diff --git a/doc/en/_templates/style.html b/doc/en/_templates/style.html new file mode 100644 index 00000000000..400cb75ff97 --- /dev/null +++ b/doc/en/_templates/style.html @@ -0,0 +1,7 @@ + diff --git a/doc/en/conf.py b/doc/en/conf.py index af54b468996..e64931ae5c8 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -15,9 +15,7 @@ # # The full version, including alpha/beta/rc tags. # The short X.Y version. -import os import shutil -import sys from textwrap import dedent from typing import TYPE_CHECKING @@ -65,7 +63,6 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ - "pallets_sphinx_themes", "pygments_pytest", "sphinx.ext.autodoc", "sphinx.ext.autosummary", @@ -140,10 +137,6 @@ # output. They are ignored by default. # show_authors = False -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = "sphinx" - - # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] @@ -216,12 +209,9 @@ # -- Options for HTML output --------------------------------------------------- -sys.path.append(os.path.abspath("_themes")) -html_theme_path = ["_themes"] - # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = "flask" +html_theme = "furo" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -266,18 +256,24 @@ html_sidebars = { "index": [ - "slim_searchbox.html", + "sidebar/brand.html", + "sidebar/search.html", + "sidebar/scroll-start.html", "sidebarintro.html", "globaltoc.html", "links.html", - "sourcelink.html", + "sidebar/scroll-end.html", + "style.html", ], "**": [ - "slim_searchbox.html", + "sidebar/brand.html", + "sidebar/search.html", + "sidebar/scroll-start.html", "globaltoc.html", "relations.html", "links.html", - "sourcelink.html", + "sidebar/scroll-end.html", + "style.html", ], } @@ -337,10 +333,6 @@ ) ] -# The name of an image file (relative to this directory) to place at the top of -# the title page. -latex_logo = "img/pytest1.png" - # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index a65ea331663..bf6268a4980 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -7,10 +7,6 @@ This page lists all pytest features that are currently deprecated or have been r The objective is to give users a clear rationale why a certain feature has been removed, and what alternatives should be used instead. -.. contents:: - :depth: 3 - :local: - Deprecated Features ------------------- diff --git a/doc/en/index.rst b/doc/en/index.rst index 83eb27b0a53..2aebb0d6b9c 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -1,16 +1,16 @@ :orphan: -.. sidebar:: Next Open Trainings and Events +.. _features: - - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training): - * **June 11th to 13th 2024**, Remote - * **March 4th to 6th 2025**, Leipzig, Germany / Remote - - `pytest development sprint `_, **June 17th -- 22nd 2024** - - pytest tips and tricks for a better testsuite, `Europython 2024 `_, **July 8th -- 14th 2024** (3h), Prague +.. sidebar:: **Next Open Trainings and Events** - Also see :doc:`previous talks and blogposts `. + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training): + * **June 11th to 13th 2024**, Remote + * **March 4th to 6th 2025**, Leipzig, Germany / Remote + - `pytest development sprint `_, **June 17th -- 22nd 2024** + - pytest tips and tricks for a better testsuite, `Europython 2024 `_, **July 8th -- 14th 2024** (3h), Prague -.. _features: + Also see :doc:`previous talks and blogposts ` pytest: helps you write better programs ======================================= @@ -25,7 +25,6 @@ scale to support complex functional testing for applications and libraries. **PyPI package name**: :pypi:`pytest` - A quick example --------------- diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 4036b7d9912..3675c7cb2ee 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -7,9 +7,6 @@ API Reference This page contains the full reference to pytest's API. -.. contents:: - :depth: 3 - :local: Constants --------- diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 974988c8cf4..6e7221d645a 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -1,4 +1,3 @@ -pallets-sphinx-themes pluggy>=1.5.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 @@ -8,4 +7,5 @@ sphinxcontrib-svg2pdfconverter # Pin packaging because it no longer handles 'latest' version, which # is the version that is assigned to the docs. # See https://github.com/pytest-dev/pytest/pull/10578#issuecomment-1348249045. -packaging <22 +packaging +furo From 889d9b28d786c75b66f4d1acb80123bdb341639c Mon Sep 17 00:00:00 2001 From: Nathan Goldbaum Date: Fri, 24 May 2024 05:16:44 -0600 Subject: [PATCH 0658/1271] Add thread safety section to flaky test docs (#12359) Closes #12356 --- AUTHORS | 1 + changelog/12356.doc.rst | 2 ++ doc/en/explanation/flaky.rst | 22 +++++++++++++++++++--- 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 changelog/12356.doc.rst diff --git a/AUTHORS b/AUTHORS index cc53ce10d4f..18c60750e30 100644 --- a/AUTHORS +++ b/AUTHORS @@ -289,6 +289,7 @@ Mike Lundy Milan Lesnek Miro Hrončok mrbean-bremen +Nathan Goldbaum Nathaniel Compton Nathaniel Waisbrot Ned Batchelder diff --git a/changelog/12356.doc.rst b/changelog/12356.doc.rst new file mode 100644 index 00000000000..312c26d3298 --- /dev/null +++ b/changelog/12356.doc.rst @@ -0,0 +1,2 @@ +Added a subsection to the documentation for debugging flaky tests to mention +lack of thread safety in pytest as a possible source of flakyness. diff --git a/doc/en/explanation/flaky.rst b/doc/en/explanation/flaky.rst index 41cbe847989..cb6c3983424 100644 --- a/doc/en/explanation/flaky.rst +++ b/doc/en/explanation/flaky.rst @@ -18,7 +18,7 @@ System state Broadly speaking, a flaky test indicates that the test relies on some system state that is not being appropriately controlled - the test environment is not sufficiently isolated. Higher level tests are more likely to be flaky as they rely on more state. -Flaky tests sometimes appear when a test suite is run in parallel (such as use of pytest-xdist). This can indicate a test is reliant on test ordering. +Flaky tests sometimes appear when a test suite is run in parallel (such as use of `pytest-xdist`_). This can indicate a test is reliant on test ordering. - Perhaps a different test is failing to clean up after itself and leaving behind data which causes the flaky test to fail. - The flaky test is reliant on data from a previous test that doesn't clean up after itself, and in parallel runs that previous test is not always present @@ -30,9 +30,22 @@ Overly strict assertion Overly strict assertions can cause problems with floating point comparison as well as timing issues. :func:`pytest.approx` is useful here. +Thread safety +~~~~~~~~~~~~~ -Pytest features -^^^^^^^^^^^^^^^ +pytest is single-threaded, executing its tests always in the same thread, sequentially, never spawning any threads itself. + +Even in case of plugins which run tests in parallel, for example `pytest-xdist`_, usually work by spawning multiple *processes* and running tests in batches, without using multiple threads. + +It is of course possible (and common) for tests and fixtures to spawn threads themselves as part of their testing workflow (for example, a fixture that starts a server thread in the background, or a test which executes production code that spawns threads), but some care must be taken: + +* Make sure to eventually wait on any spawned threads -- for example at the end of a test, or during the teardown of a fixture. +* Avoid using primitives provided by pytest (:func:`pytest.warns`, :func:`pytest.raises`, etc) from multiple threads, as they are not thread-safe. + +If your test suite uses threads and your are seeing flaky test results, do not discount the possibility that the test is implicitly using global state in pytest itself. + +Related features +^^^^^^^^^^^^^^^^ Xfail strict ~~~~~~~~~~~~ @@ -123,3 +136,6 @@ Resources * `Flaky Tests at Google and How We Mitigate Them `_ by John Micco, 2016 * `Where do Google's flaky tests come from? `_ by Jeff Listfield, 2017 + + +.. _pytest-xdist: https://github.com/pytest-dev/pytest-xdist From b83dd34ce19da60486155ea9be81bfeb5c1b86b9 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 26 May 2024 00:21:28 +0000 Subject: [PATCH 0659/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 196 +++++++++++++++++-------------- 1 file changed, 110 insertions(+), 86 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 43c4748ea03..5d2a9349320 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio May 19, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 25, 2024 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) @@ -127,7 +127,7 @@ This list contains 1461 plugins. :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A - :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 18, 2024 4 - Beta pytest + :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 24, 2024 4 - Beta pytest :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Feb 02, 2024 N/A pytest (>=8.0.0,<9.0.0) :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) @@ -142,13 +142,13 @@ This list contains 1461 plugins. :pypi:`pytest-bdd` BDD for pytest Mar 17, 2024 6 - Mature pytest (>=6.2.0) :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 - :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Feb 19, 2024 N/A pytest >=7.1.3 + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports May 20, 2024 N/A pytest >=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 17, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 21, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -233,7 +233,7 @@ This list contains 1461 plugins. :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) - :pypi:`pytest-cleanslate` Collects and executes pytest tests separately May 15, 2024 N/A pytest + :pypi:`pytest-cleanslate` Collects and executes pytest tests separately May 20, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Apr 19, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -258,6 +258,7 @@ This list contains 1461 plugins. :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-interface-info-plugin` Get executed interface information in pytest interface automation framework Sep 25, 2023 4 - Beta N/A + :pypi:`pytest-collect-jmeter-report-tests` A simple plugin to use with pytest May 20, 2024 4 - Beta pytest>=7.2.1 :pypi:`pytest-collector` Python package for collecting pytest. Aug 02, 2022 N/A pytest (>=7.0,<8.0) :pypi:`pytest-collect-pytest-interinfo` A simple plugin to use with pytest Sep 26, 2023 4 - Beta N/A :pypi:`pytest-colordots` Colorizes the progress indicators Oct 06, 2017 5 - Production/Stable N/A @@ -309,7 +310,7 @@ This list contains 1461 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` Apr 22, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 21, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. May 25, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -368,7 +369,7 @@ This list contains 1461 plugins. :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A :pypi:`pytest-django-class` A pytest plugin for running django in class-scoped fixtures Aug 08, 2023 4 - Beta N/A - :pypi:`pytest-django-docker-pg` Jan 30, 2024 5 - Production/Stable pytest <8.0.0,>=7.0.0 + :pypi:`pytest-django-docker-pg` May 21, 2024 5 - Production/Stable pytest<9.0.0,>=7.0.0 :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) :pypi:`pytest-django-factories` Factories for your Django models that can be used as Pytest fixtures. Nov 12, 2020 4 - Beta N/A :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 @@ -443,14 +444,14 @@ This list contains 1461 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 Apr 04, 2024 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. Apr 30, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 30, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 30, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 30, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 30, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 30, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 30, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. May 23, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. May 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. May 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. May 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. May 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. May 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. May 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. May 23, 2024 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) @@ -645,7 +646,7 @@ This list contains 1461 plugins. :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Jan 17, 2024 5 - Production/Stable N/A :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A - :pypi:`pytest-html-report-merger` Oct 23, 2023 N/A N/A + :pypi:`pytest-html-report-merger` May 22, 2024 N/A N/A :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' @@ -680,7 +681,7 @@ This list contains 1461 plugins. :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :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. Dec 13, 2023 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package May 24, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules May 10, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A @@ -716,11 +717,13 @@ This list contains 1461 plugins. :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-json` Generate JSON test reports Jan 18, 2016 4 - Beta N/A + :pypi:`pytest-json-ctrf` Pytest plugin to generate json report in CTRF (Common Test Report Format) May 21, 2024 N/A pytest>6.0.0 :pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Mar 14, 2023 4 - Beta N/A :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-jtl-collector` A simple plugin to use with pytest May 20, 2024 4 - Beta pytest>=7.2.1 :pypi:`pytest-jtr` pytest plugin supporting json test report output Apr 15, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest @@ -766,7 +769,7 @@ This list contains 1461 plugins. :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 May 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests May 19, 2024 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lock` pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. Feb 03, 2024 N/A pytest (>=7.4.3,<8.0.0) @@ -779,11 +782,11 @@ This list contains 1461 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Mar 30, 2024 5 - Production/Stable pytest==8.1.1 + :pypi:`pytest-logikal` Common testing environment May 23, 2024 5 - Production/Stable pytest==8.2.1 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest - :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Feb 07, 2024 3 - Alpha pytest + :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers May 22, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) @@ -818,7 +821,7 @@ This list contains 1461 plugins. :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Apr 27, 2024 N/A pytest>=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions May 19, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Mar 07, 2024 N/A pytest >=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A @@ -864,7 +867,7 @@ This list contains 1461 plugins. :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-runner` Run the mypy static type checker as a pytest test case Apr 23, 2024 N/A pytest>=8.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 - :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Oct 30, 2023 5 - Production/Stable pytest >=6.2 + :pypi:`pytest-mysql` MySQL process and client fixtures for pytest May 23, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-ndb` pytest notebook debugger Apr 28, 2024 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) @@ -877,7 +880,7 @@ This list contains 1461 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies May 17, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies May 20, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Apr 11, 2024 N/A N/A @@ -929,7 +932,6 @@ This list contains 1461 plugins. :pypi:`pytest-parallelize-tests` pytest plugin that parallelizes test execution across multiple hosts Jan 27, 2023 4 - Beta N/A :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) - :pypi:`pytest-parameterize-from-files` A pytest plugin that parameterizes tests from data files. Feb 15, 2024 4 - Beta pytest>=7.2.0 :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest @@ -949,12 +951,12 @@ This list contains 1461 plugins. :pypi:`pytest-pep8` pytest plugin to check PEP8 requirements Apr 27, 2014 N/A N/A :pypi:`pytest-percent` Change the exit code of pytest test sessions when a required percent of tests pass. May 21, 2020 N/A pytest (>=5.2.0) :pypi:`pytest-percents` Mar 16, 2024 N/A N/A - :pypi:`pytest-perf` Run performance tests against the mainline code. Jan 28, 2024 5 - Production/Stable pytest >=6 ; extra == 'testing' + :pypi:`pytest-perf` Run performance tests against the mainline code. May 20, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-performancetotal` A performance plugin for pytest Mar 19, 2024 4 - Beta N/A - :pypi:`pytest-persistence` Pytest tool for persistent objects Jul 04, 2023 N/A N/A + :pypi:`pytest-persistence` Pytest tool for persistent objects May 23, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Mar 27, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker Apr 03, 2024 5 - Production/Stable pytest>=6.0.0 + :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-picked` Run the tests related to the changed files Jul 27, 2023 N/A pytest (>=3.7.0) @@ -971,7 +973,7 @@ This list contains 1461 plugins. :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers May 06, 2024 N/A N/A - :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright May 04, 2024 N/A N/A + :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright May 24, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A @@ -982,7 +984,7 @@ This list contains 1461 plugins. :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Mar 26, 2024 5 - Production/Stable pytest>=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A - :pypi:`pytest-pogo` Pytest plugin for pogo-migrate Mar 11, 2024 1 - Planning pytest (>=7,<9) + :pypi:`pytest-pogo` Pytest plugin for pogo-migrate May 22, 2024 1 - Planning pytest<9,>=7 :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A :pypi:`pytest-pokie` Pokie plugin for pytest Oct 19, 2023 5 - Production/Stable N/A :pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A @@ -1046,7 +1048,7 @@ This list contains 1461 plugins. :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Sep 12, 2023 4 - Beta pytest (>=7.2.2,<8.0.0) + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 22, 2024 4 - Beta pytest<9.0.0,>=7.2.2 :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 Nov 29, 2023 5 - Production/Stable pytest >=6.0 @@ -1119,7 +1121,7 @@ This list contains 1461 plugins. :pypi:`pytest-rerunclassfailures` pytest rerun class failures plugin Apr 24, 2024 5 - Production/Stable pytest>=7.2 :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 :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. Feb 08, 2024 4 - Beta pytest + :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. May 23, 2024 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest May 17, 2024 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) @@ -1144,7 +1146,7 @@ This list contains 1461 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them May 18, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them May 24, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1171,6 +1173,7 @@ This list contains 1461 plugins. :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 16, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A + :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :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 Feb 16, 2024 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 @@ -1260,7 +1263,7 @@ This list contains 1461 plugins. :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 - :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Mar 15, 2023 3 - Alpha pytest (>=2.0) + :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock May 21, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 19, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) @@ -1312,7 +1315,7 @@ This list contains 1461 plugins. :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) :pypi:`pytest-terra-fixt` Terraform and Terragrunt fixtures for pytest Sep 15, 2022 N/A pytest (==6.2.5) - :pypi:`pytest-terraform` A pytest plugin for using terraform fixtures Jun 20, 2023 N/A pytest (>=6.0) + :pypi:`pytest-terraform` A pytest plugin for using terraform fixtures May 21, 2024 N/A pytest>=6.0 :pypi:`pytest-terraform-fixture` generate terraform resources to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A :pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0) @@ -1469,7 +1472,7 @@ This list contains 1461 plugins. :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Apr 23, 2024 N/A pytest~=7.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest - :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. Mar 31, 2024 4 - Beta pytest>=2.8 + :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. May 19, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) @@ -2026,9 +2029,9 @@ This list contains 1461 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Mar 19, 2024, + *last release*: May 19, 2024, *status*: 4 - Beta, - *requires*: pytest <9,>=7.0.0 + *requires*: pytest<9,>=7.0.0 Pytest support for asyncio @@ -2152,7 +2155,7 @@ This list contains 1461 plugins. pytest plugin for testing AWS resource configurations :pypi:`pytest-aws-apigateway` - *last release*: May 18, 2024, + *last release*: May 24, 2024, *status*: 4 - Beta, *requires*: pytest @@ -2257,7 +2260,7 @@ This list contains 1461 plugins. BDD for pytest :pypi:`pytest-bdd-report` - *last release*: Feb 19, 2024, + *last release*: May 20, 2024, *status*: N/A, *requires*: pytest >=7.1.3 @@ -2299,7 +2302,7 @@ This list contains 1461 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: May 17, 2024, + *last release*: May 21, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2894,7 +2897,7 @@ This list contains 1461 plugins. Easy quality control for CLDF datasets using pytest :pypi:`pytest-cleanslate` - *last release*: May 15, 2024, + *last release*: May 20, 2024, *status*: N/A, *requires*: pytest @@ -3068,6 +3071,13 @@ This list contains 1461 plugins. Get executed interface information in pytest interface automation framework + :pypi:`pytest-collect-jmeter-report-tests` + *last release*: May 20, 2024, + *status*: 4 - Beta, + *requires*: pytest>=7.2.1 + + A simple plugin to use with pytest + :pypi:`pytest-collector` *last release*: Aug 02, 2022, *status*: N/A, @@ -3426,7 +3436,7 @@ This list contains 1461 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Apr 21, 2024, + *last release*: May 25, 2024, *status*: 4 - Beta, *requires*: pytest @@ -3839,9 +3849,9 @@ This list contains 1461 plugins. A pytest plugin for running django in class-scoped fixtures :pypi:`pytest-django-docker-pg` - *last release*: Jan 30, 2024, + *last release*: May 21, 2024, *status*: 5 - Production/Stable, - *requires*: pytest <8.0.0,>=7.0.0 + *requires*: pytest<9.0.0,>=7.0.0 @@ -4364,56 +4374,56 @@ This list contains 1461 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Apr 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Apr 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Apr 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Apr 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Apr 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Apr 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Apr 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Apr 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5778,7 +5788,7 @@ This list contains 1461 plugins. Generates a static html report based on pytest framework :pypi:`pytest-html-report-merger` - *last release*: Oct 23, 2023, + *last release*: May 22, 2024, *status*: N/A, *requires*: N/A @@ -6023,7 +6033,7 @@ This list contains 1461 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Apr 02, 2024, + *last release*: May 24, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6274,6 +6284,13 @@ This list contains 1461 plugins. Generate JSON test reports + :pypi:`pytest-json-ctrf` + *last release*: May 21, 2024, + *status*: N/A, + *requires*: pytest>6.0.0 + + Pytest plugin to generate json report in CTRF (Common Test Report Format) + :pypi:`pytest-json-fixtures` *last release*: Mar 14, 2023, *status*: 4 - Beta, @@ -6309,6 +6326,13 @@ This list contains 1461 plugins. A pytest plugin to perform JSONSchema validations + :pypi:`pytest-jtl-collector` + *last release*: May 20, 2024, + *status*: 4 - Beta, + *requires*: pytest>=7.2.1 + + A simple plugin to use with pytest + :pypi:`pytest-jtr` *last release*: Apr 15, 2024, *status*: N/A, @@ -6625,7 +6649,7 @@ This list contains 1461 plugins. Generate local badges (shields) reporting your test suite status. :pypi:`pytest-localftpserver` - *last release*: May 17, 2024, + *last release*: May 19, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -6716,9 +6740,9 @@ This list contains 1461 plugins. :pypi:`pytest-logikal` - *last release*: Mar 30, 2024, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, - *requires*: pytest==8.1.1 + *requires*: pytest==8.2.1 Common testing environment @@ -6744,7 +6768,7 @@ This list contains 1461 plugins. pytest plugin for looping tests :pypi:`pytest-lsp` - *last release*: Feb 07, 2024, + *last release*: May 22, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -6989,7 +7013,7 @@ This list contains 1461 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: Apr 27, 2024, + *last release*: May 19, 2024, *status*: N/A, *requires*: pytest>=5.0.0 @@ -7311,9 +7335,9 @@ This list contains 1461 plugins. Pytest plugin to check mypy output. :pypi:`pytest-mysql` - *last release*: Oct 30, 2023, + *last release*: May 23, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6.2 + *requires*: pytest>=6.2 MySQL process and client fixtures for pytest @@ -7402,7 +7426,7 @@ This list contains 1461 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: May 17, 2024, + *last release*: May 20, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -7765,13 +7789,6 @@ This list contains 1461 plugins. Configure pytest fixtures using a combination of"parametrize" and markers - :pypi:`pytest-parameterize-from-files` - *last release*: Feb 15, 2024, - *status*: 4 - Beta, - *requires*: pytest>=7.2.0 - - A pytest plugin that parameterizes tests from data files. - :pypi:`pytest-parametrization` *last release*: May 22, 2022, *status*: 5 - Production/Stable, @@ -7906,9 +7923,9 @@ This list contains 1461 plugins. :pypi:`pytest-perf` - *last release*: Jan 28, 2024, + *last release*: May 20, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6 ; extra == 'testing' + *requires*: pytest!=8.1.*,>=6; extra == "testing" Run performance tests against the mainline code. @@ -7927,7 +7944,7 @@ This list contains 1461 plugins. A performance plugin for pytest :pypi:`pytest-persistence` - *last release*: Jul 04, 2023, + *last release*: May 23, 2024, *status*: N/A, *requires*: N/A @@ -7941,7 +7958,7 @@ This list contains 1461 plugins. Pytest pexpect plugin. :pypi:`pytest-pg` - *last release*: Apr 03, 2024, + *last release*: May 21, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.0.0 @@ -8060,7 +8077,7 @@ This list contains 1461 plugins. A pytest wrapper with fixtures for Playwright to automate web browsers :pypi:`pytest_playwright_async` - *last release*: May 04, 2024, + *last release*: May 24, 2024, *status*: N/A, *requires*: N/A @@ -8137,9 +8154,9 @@ This list contains 1461 plugins. :pypi:`pytest-pogo` - *last release*: Mar 11, 2024, + *last release*: May 22, 2024, *status*: 1 - Planning, - *requires*: pytest (>=7,<9) + *requires*: pytest<9,>=7 Pytest plugin for pogo-migrate @@ -8585,9 +8602,9 @@ This list contains 1461 plugins. Pytest-pyvista package :pypi:`pytest-qaseio` - *last release*: Sep 12, 2023, + *last release*: May 22, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.2.2,<8.0.0) + *requires*: pytest<9.0.0,>=7.2.2 Pytest plugin for Qase.io integration @@ -9096,7 +9113,7 @@ This list contains 1461 plugins. pytest plugin to re-run tests to eliminate flaky failures :pypi:`pytest-reserial` - *last release*: Feb 08, 2024, + *last release*: May 23, 2024, *status*: 4 - Beta, *requires*: pytest @@ -9271,7 +9288,7 @@ This list contains 1461 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: May 18, 2024, + *last release*: May 24, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9459,6 +9476,13 @@ This list contains 1461 plugins. pytest plugin for test scenarios + :pypi:`pytest-scenario-files` + *last release*: May 19, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=7.2.0 + + A pytest plugin that generates unit test scenarios from data files. + :pypi:`pytest-schedule` *last release*: Jan 07, 2023, *status*: 5 - Production/Stable, @@ -10083,9 +10107,9 @@ This list contains 1461 plugins. pytest plugin with sqlalchemy related fixtures :pypi:`pytest-sqlalchemy-mock` - *last release*: Mar 15, 2023, + *last release*: May 21, 2024, *status*: 3 - Alpha, - *requires*: pytest (>=2.0) + *requires*: pytest>=7.0.0 pytest sqlalchemy plugin for mock @@ -10447,9 +10471,9 @@ This list contains 1461 plugins. Terraform and Terragrunt fixtures for pytest :pypi:`pytest-terraform` - *last release*: Jun 20, 2023, + *last release*: May 21, 2024, *status*: N/A, - *requires*: pytest (>=6.0) + *requires*: pytest>=6.0 A pytest plugin for using terraform fixtures @@ -11546,7 +11570,7 @@ This list contains 1461 plugins. An extended parametrizing plugin of pytest. :pypi:`pytest-xprocess` - *last release*: Mar 31, 2024, + *last release*: May 19, 2024, *status*: 4 - Beta, *requires*: pytest>=2.8 From c3c51037f0a18e65d49aac093d9bd7a2e924f0a2 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 25 May 2024 22:02:28 +0300 Subject: [PATCH 0660/1271] unittest: fix class instances no longer released on test teardown since pytest 8.2.0 Fix #12367. --- changelog/12367.bugfix.rst | 1 + src/_pytest/unittest.py | 3 ++- testing/test_unittest.py | 36 ++++++++++++++++++++---------------- 3 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 changelog/12367.bugfix.rst diff --git a/changelog/12367.bugfix.rst b/changelog/12367.bugfix.rst new file mode 100644 index 00000000000..e8bf2e4f155 --- /dev/null +++ b/changelog/12367.bugfix.rst @@ -0,0 +1 @@ +Fix a regression in pytest 8.2.0 where unittest class instances (a fresh one is created for each test) were not released promptly on test teardown but only on session teardown. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 919b497c295..643443f08c6 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -218,11 +218,12 @@ def setup(self) -> None: super().setup() def teardown(self) -> None: - super().teardown() if self._explicit_tearDown is not None: self._explicit_tearDown() self._explicit_tearDown = None self._obj = None + self._instance = None + super().teardown() def startTest(self, testcase: "unittest.TestCase") -> None: pass diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 003a74d3849..c359715dc2e 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1,5 +1,4 @@ # mypy: allow-untyped-defs -import gc import sys from typing import List @@ -192,30 +191,35 @@ def test_check(self): def test_teardown_issue1649(pytester: Pytester) -> None: """ Are TestCase objects cleaned up? Often unittest TestCase objects set - attributes that are large and expensive during setUp. + attributes that are large and expensive during test run or setUp. The TestCase will not be cleaned up if the test fails, because it would then exist in the stackframe. + + Regression test for #1649 (see also #12367). """ - testpath = pytester.makepyfile( + pytester.makepyfile( """ import unittest - class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase): - def setUp(self): - self.an_expensive_object = 1 - def test_demo(self): - pass + import gc - """ + class TestCaseObjectsShouldBeCleanedUp(unittest.TestCase): + def test_expensive(self): + self.an_expensive_obj = object() + + def test_is_it_still_alive(self): + gc.collect() + for obj in gc.get_objects(): + if type(obj).__name__ == "TestCaseObjectsShouldBeCleanedUp": + assert not hasattr(obj, "an_expensive_obj") + break + else: + assert False, "Could not find TestCaseObjectsShouldBeCleanedUp instance" + """ ) - pytester.inline_run("-s", testpath) - gc.collect() - - # Either already destroyed, or didn't run setUp. - for obj in gc.get_objects(): - if type(obj).__name__ == "TestCaseObjectsShouldBeCleanedUp": - assert not hasattr(obj, "an_expensive_obj") + result = pytester.runpytest() + assert result.ret == ExitCode.OK def test_unittest_skip_issue148(pytester: Pytester) -> None: From 020db7ec046a7e84c431db7dbe5163887732602e Mon Sep 17 00:00:00 2001 From: James Frost Date: Sun, 26 May 2024 11:21:30 +0100 Subject: [PATCH 0661/1271] Add html_baseurl to sphinx conf.py (#12364) This is used to set the tag that points to the canonical version of the webpage. Including this indicates to search engines which version to include in their indexes, and should prevent older versions showing up. Fixes #12363 --- AUTHORS | 1 + changelog/12363.doc.rst | 1 + doc/en/conf.py | 3 +++ 3 files changed, 5 insertions(+) create mode 100644 changelog/12363.doc.rst diff --git a/AUTHORS b/AUTHORS index 18c60750e30..748b9bae2c8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -192,6 +192,7 @@ Jake VanderPlas Jakob van Santen Jakub Mitoraj James Bourbeau +James Frost Jan Balster Janne Vanhala Jason R. Coombs diff --git a/changelog/12363.doc.rst b/changelog/12363.doc.rst new file mode 100644 index 00000000000..c657281babf --- /dev/null +++ b/changelog/12363.doc.rst @@ -0,0 +1 @@ +The documentation webpages now links to a canonical version to reduce outdated documentation in search engine results. diff --git a/doc/en/conf.py b/doc/en/conf.py index e64931ae5c8..738d07dc2f1 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -312,6 +312,9 @@ # Output file base name for HTML help builder. htmlhelp_basename = "pytestdoc" +# The base URL which points to the root of the HTML documentation. It is used +# to indicate the location of document using the canonical link relation (#12363). +html_baseurl = "https://docs.pytest.org/en/stable/" # -- Options for LaTeX output -------------------------------------------------- From 24abe4eb03f64bfed301e6d70dfcf4f0c6a8cc0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 06:43:30 +0200 Subject: [PATCH 0662/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#12374) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 4.3.0 to 4.4.0. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.3.0...4.4.0) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 458cc2f9743..cf6e4763dc5 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==4.3.0 +anyio[curio,trio]==4.4.0 django==5.0.6 pytest-asyncio==0.23.7 pytest-bdd==7.1.2 From 88fae23bdddef9db9dba771080e220cfea65356a Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 27 May 2024 21:18:03 +0200 Subject: [PATCH 0663/1271] [pylint] Fixes all ``use-maxplit-args``, ``consider-using-enumerate`` (#12172) * [pylint 'use-maxsplit-arg'] Do not split more than necessary when using the first element * [pylint 'consider-using-enumerate'] Use zip when iterating on two iterators * [pylint] 'cell-var-from-loop' and 'disallowed-name' permanent disable * [pylint] Disable 'possibly-used-before-assignment' following 3.2.0 release --- pyproject.toml | 7 +++---- src/_pytest/fixtures.py | 9 +++++++-- testing/test_reports.py | 12 ++++++------ testing/test_warnings.py | 6 ++---- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e3c64b3e9d8..11590a90e9d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -181,13 +181,12 @@ disable = [ "bad-mcs-method-argument", "broad-exception-caught", "broad-exception-raised", - "cell-var-from-loop", + "cell-var-from-loop", # B023 from ruff / flake8-bugbear "comparison-of-constants", "comparison-with-callable", "comparison-with-itself", "condition-evals-to-constant", "consider-using-dict-items", - "consider-using-enumerate", "consider-using-from-import", "consider-using-f-string", "consider-using-in", @@ -195,7 +194,7 @@ disable = [ "consider-using-ternary", "consider-using-with", "cyclic-import", - "disallowed-name", + "disallowed-name", # foo / bar are used often in tests "duplicate-code", "eval-used", "exec-used", @@ -229,6 +228,7 @@ disable = [ "pointless-exception-statement", "pointless-statement", "pointless-string-statement", + "possibly-used-before-assignment", "protected-access", "raise-missing-from", "redefined-argument-from-local", @@ -276,7 +276,6 @@ disable = [ "useless-else-on-loop", "useless-import-alias", "useless-return", - "use-maxsplit-arg", "using-constant-test", "wrong-import-order", ] diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 06da52aeda3..b7a58081ba8 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1821,7 +1821,10 @@ def write_fixture(fixture_def: FixtureDef[object]) -> None: fixture_doc = inspect.getdoc(fixture_def.func) if fixture_doc: write_docstring( - tw, fixture_doc.split("\n\n")[0] if verbose <= 0 else fixture_doc + tw, + fixture_doc.split("\n\n", maxsplit=1)[0] + if verbose <= 0 + else fixture_doc, ) else: tw.line(" no docstring available", red=True) @@ -1903,7 +1906,9 @@ def _showfixtures_main(config: Config, session: "Session") -> None: tw.write("\n") doc = inspect.getdoc(fixturedef.func) if doc: - write_docstring(tw, doc.split("\n\n")[0] if verbose <= 0 else doc) + write_docstring( + tw, doc.split("\n\n", maxsplit=1)[0] if verbose <= 0 else doc + ) else: tw.line(" no docstring available", red=True) tw.line() diff --git a/testing/test_reports.py b/testing/test_reports.py index c6baeebc9dd..7987b401771 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -100,14 +100,13 @@ def test_repr_entry(): rep_entries = rep.longrepr.reprtraceback.reprentries a_entries = a.longrepr.reprtraceback.reprentries - for i in range(len(a_entries)): - rep_entry = rep_entries[i] + assert len(rep_entries) == len(a_entries) # python < 3.10 zip(strict=True) + for a_entry, rep_entry in zip(a_entries, rep_entries): assert isinstance(rep_entry, ReprEntry) assert rep_entry.reprfileloc is not None assert rep_entry.reprfuncargs is not None assert rep_entry.reprlocals is not None - a_entry = a_entries[i] assert isinstance(a_entry, ReprEntry) assert a_entry.reprfileloc is not None assert a_entry.reprfuncargs is not None @@ -146,9 +145,10 @@ def test_repr_entry_native(): rep_entries = rep.longrepr.reprtraceback.reprentries a_entries = a.longrepr.reprtraceback.reprentries - for i in range(len(a_entries)): - assert isinstance(rep_entries[i], ReprEntryNative) - assert rep_entries[i].lines == a_entries[i].lines + assert len(rep_entries) == len(a_entries) # python < 3.10 zip(strict=True) + for rep_entry, a_entry in zip(rep_entries, a_entries): + assert isinstance(rep_entry, ReprEntryNative) + assert rep_entry.lines == a_entry.lines def test_itemreport_outcomes(self, pytester: Pytester) -> None: # This test came originally from test_remote.py in xdist (ca03269). diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 770454e83df..73c8c1b3231 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -280,10 +280,8 @@ def pytest_warning_recorded(self, warning_message, when, nodeid, location): ("call warning", "runtest", "test_warning_recorded_hook.py::test_func"), ("teardown warning", "runtest", "test_warning_recorded_hook.py::test_func"), ] - for index in range(len(expected)): - collected_result = collected[index] - expected_result = expected[index] - + assert len(collected) == len(expected) # python < 3.10 zip(strict=True) + for collected_result, expected_result in zip(collected, expected): assert collected_result[0] == expected_result[0], str(collected) assert collected_result[1] == expected_result[1], str(collected) assert collected_result[2] == expected_result[2], str(collected) From 48cb8a2b329d0e8beaf30804c503eddb5e531385 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 22:31:18 +0000 Subject: [PATCH 0664/1271] [pre-commit.ci] pre-commit autoupdate (#12380) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.4 → v0.4.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.4...v0.4.5) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- src/_pytest/_code/code.py | 4 ++-- src/_pytest/config/__init__.py | 2 +- src/_pytest/doctest.py | 2 +- src/_pytest/threadexception.py | 4 ++-- src/_pytest/unraisableexception.py | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f20f61761e0..64bdbb36a94 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.4" + rev: "v0.4.5" hooks: - id: ruff args: ["--fix"] diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index cfa226bb749..4fb686a86e5 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -199,8 +199,8 @@ def __init__( rawentry: TracebackType, repr_style: Optional['Literal["short", "long"]'] = None, ) -> None: - self._rawentry: "Final" = rawentry - self._repr_style: "Final" = repr_style + self._rawentry: Final = rawentry + self._repr_style: Final = repr_style def with_repr_style( self, repr_style: Optional['Literal["short", "long"]'] diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index c698ea9a777..f3d3b3062b5 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1913,7 +1913,7 @@ def parse_warning_filter( parts.append("") action_, message, category_, module, lineno_ = (s.strip() for s in parts) try: - action: "warnings._ActionKind" = warnings._getaction(action_) # type: ignore[attr-defined] + action: warnings._ActionKind = warnings._getaction(action_) # type: ignore[attr-defined] except warnings._OptionError as e: raise UsageError(error_template.format(error=str(e))) from None try: diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 35a13676222..2d7453b4ee0 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -298,7 +298,7 @@ def setup(self) -> None: def runtest(self) -> None: _check_all_skipped(self.dtest) self._disable_output_capturing_for_darwin() - failures: List["doctest.DocTestFailure"] = [] + failures: List[doctest.DocTestFailure] = [] # Type ignored because we change the type of `out` from what # doctest expects. self.runner.run(self.dtest, out=failures) # type: ignore[arg-type] diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index 09faf661b91..603a1777c92 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -34,8 +34,8 @@ class catch_threading_exception: """ def __init__(self) -> None: - self.args: Optional["threading.ExceptHookArgs"] = None - self._old_hook: Optional[Callable[["threading.ExceptHookArgs"], Any]] = None + self.args: Optional[threading.ExceptHookArgs] = None + self._old_hook: Optional[Callable[[threading.ExceptHookArgs], Any]] = None def _hook(self, args: "threading.ExceptHookArgs") -> None: self.args = args diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index f649267abf1..50b121e8811 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -34,8 +34,8 @@ class catch_unraisable_exception: """ def __init__(self) -> None: - self.unraisable: Optional["sys.UnraisableHookArgs"] = None - self._old_hook: Optional[Callable[["sys.UnraisableHookArgs"], Any]] = None + self.unraisable: Optional[sys.UnraisableHookArgs] = None + self._old_hook: Optional[Callable[[sys.UnraisableHookArgs], Any]] = None def _hook(self, unraisable: "sys.UnraisableHookArgs") -> None: # Storing unraisable.object can resurrect an object which is being From 9f121e85a78310e50acde71082dc0df3e5ce895c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 28 May 2024 13:47:00 -0300 Subject: [PATCH 0665/1271] Clarify pytest_ignore_collect docs (#12385) Fixes #12383 Co-authored-by: Ran Benita --- src/_pytest/hookspec.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 8a38ff4fb43..c7f9d036c33 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -311,7 +311,12 @@ def pytest_collection_finish(session: "Session") -> None: def pytest_ignore_collect( collection_path: Path, path: "LEGACY_PATH", config: "Config" ) -> Optional[bool]: - """Return True to prevent considering this path for collection. + """Return ``True`` to ignore this path for collection. + + Return ``None`` to let other plugins ignore the path for collection. + + Returning ``False`` will forcefully *not* ignore this path for collection, + without giving a chance for other plugins to ignore this path. This hook is consulted for all files and directories prior to calling more specific hooks. From 383659d0be02e8ce5cb47f70961877dcec943018 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 13:39:29 +0200 Subject: [PATCH 0666/1271] build(deps): Bump hynek/build-and-inspect-python-package (#12373) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.5.0...v2.6.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 20a72270fde..640a0f1c281 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.5.0 + uses: hynek/build-and-inspect-python-package@v2.6.0 with: attest-build-provenance-github: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 09d37aaa2c8..45e9c918a57 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,7 +35,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.5.0 + uses: hynek/build-and-inspect-python-package@v2.6.0 build: needs: [package] From db67d5c8749273ebed23788526ad511e342d8b8d Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 27 May 2024 22:18:59 +0200 Subject: [PATCH 0667/1271] [pylint 'use-yield-from'] Fix all occurences in existing code --- src/_pytest/_py/path.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index bcb05ac34cd..c7ab1182f4a 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -161,15 +161,13 @@ def gen(self, path): ) if not self.breadthfirst: for subdir in dirs: - for p in self.gen(subdir): - yield p + yield from self.gen(subdir) for p in self.optsort(entries): if self.fil is None or self.fil(p): yield p if self.breadthfirst: for subdir in dirs: - for p in self.gen(subdir): - yield p + yield from self.gen(subdir) class FNMatcher: From c45afde35d3a81ff27b6ae6c31c515b12d499338 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 27 May 2024 22:34:02 +0200 Subject: [PATCH 0668/1271] [pylint 'consider-using-sys-exit'] Fix all occurences in existing code --- extra/get_issues.py | 3 ++- pyproject.toml | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/get_issues.py b/extra/get_issues.py index a0c2f19adfa..64e859e0c12 100644 --- a/extra/get_issues.py +++ b/extra/get_issues.py @@ -1,5 +1,6 @@ import json from pathlib import Path +import sys import requests @@ -17,7 +18,7 @@ def get_issues(): if r.status_code == 403: # API request limit exceeded print(data["message"]) - exit(1) + sys.exit(1) issues.extend(data) # Look for next page diff --git a/pyproject.toml b/pyproject.toml index 11590a90e9d..4594595e2fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -190,7 +190,6 @@ disable = [ "consider-using-from-import", "consider-using-f-string", "consider-using-in", - "consider-using-sys-exit", "consider-using-ternary", "consider-using-with", "cyclic-import", From 0d33cdf02a2b742a63be75cbb2309803ea51c525 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 27 May 2024 23:12:29 +0200 Subject: [PATCH 0669/1271] [pylint] Disable the only 'misplaced-bare-raise' --- pyproject.toml | 3 +-- src/_pytest/logging.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4594595e2fb..3e01d048e0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -211,10 +211,9 @@ disable = [ "keyword-arg-before-vararg", "line-too-long", "method-hidden", - "misplaced-bare-raise", "missing-docstring", "missing-timeout", - "multiple-statements", + "multiple-statements", # multiple-statements-on-one-line-colon (E701) from ruff "no-else-break", "no-else-continue", "no-else-raise", diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index af5e443ced1..c9139d369ef 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -401,7 +401,7 @@ def handleError(self, record: logging.LogRecord) -> None: # The default behavior of logging is to print "Logging error" # to stderr with the call stack and some extra details. # pytest wants to make such mistakes visible during testing. - raise + raise # pylint: disable=misplaced-bare-raise @final From 908e112999c62307c891603bb509cf691ea66f66 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 31 Mar 2024 23:59:08 +0200 Subject: [PATCH 0670/1271] [pylint 'implicit-str-concat'] fix existing unwanted implicit str concat --- pyproject.toml | 1 - testing/_py/test_local.py | 2 +- testing/test_cacheprovider.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3e01d048e0c..0627c94c732 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -200,7 +200,6 @@ disable = [ "expression-not-assigned", "fixme", "global-statement", - "implicit-str-concat", "import-error", "import-outside-toplevel", "inconsistent-return-statements", diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index ea5794b251b..0215aba9695 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -207,7 +207,7 @@ def test_visit_norecurse(self, path1): @pytest.mark.parametrize( "fil", - ["*dir", "*dir", pytest.mark.skip("sys.version_info <" " (3,6)")(b"*dir")], + ["*dir", "*dir", pytest.mark.skip("sys.version_info < (3,6)")(b"*dir")], ) def test_visit_filterfunc_is_string(self, path1, fil): lst = [] diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 8728ae84fdc..08158f6191a 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -1163,7 +1163,7 @@ def test_1(): assert 1 ) p1.write_text( - "def test_1(): assert 1\n" "def test_2(): assert 1\n", encoding="utf-8" + "def test_1(): assert 1\ndef test_2(): assert 1\n", encoding="utf-8" ) os.utime(p1, ns=(p1.stat().st_atime_ns, int(1e9))) From 10c6db2df2f6c40b212785ef00fc834cc5eb3288 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 30 May 2024 16:48:37 +0200 Subject: [PATCH 0671/1271] doc: Update trainings/events (#12401) --- doc/en/index.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 2aebb0d6b9c..58527ea7331 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -4,11 +4,10 @@ .. sidebar:: **Next Open Trainings and Events** - - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training): - * **June 11th to 13th 2024**, Remote - * **March 4th to 6th 2025**, Leipzig, Germany / Remote - - `pytest development sprint `_, **June 17th -- 22nd 2024** - - pytest tips and tricks for a better testsuite, `Europython 2024 `_, **July 8th -- 14th 2024** (3h), Prague + - `pytest development sprint `_, **June 17th -- 22nd 2024**, Klaus (AT) / Remote + - `pytest tips and tricks for a better testsuite `_, at `Europython 2024 `_, **July 8th -- 14th 2024** (3h), Prague (CZ) + - `pytest: Professionelles Testen (nicht nur) für Python `_, at `CH Open Workshoptage `_, **September 2nd 2024**, HSLU Rotkreuz (CH) + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Leipzig (DE) / Remote Also see :doc:`previous talks and blogposts ` From 98021838fd97e10e1c9095fcbd0abbb6432a83cb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 2 Jun 2024 09:31:40 -0300 Subject: [PATCH 0672/1271] [automated] Update plugin list (#12405) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 192 ++++++++++++++++++++----------- 1 file changed, 124 insertions(+), 68 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 5d2a9349320..0f116277997 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7; extra == "pytest" - :pypi:`nuts` Network Unit Testing System Aug 11, 2023 N/A pytest (>=7.3.0,<8.0.0) + :pypi:`nuts` Network Unit Testing System May 28, 2024 N/A pytest<8,>=7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Feb 10, 2024 N/A pytest (>=6) @@ -124,6 +124,7 @@ This list contains 1464 plugins. :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest + :pypi:`pytest-aux` templates/examples and aux for pytest May 31, 2024 N/A N/A :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -148,7 +149,7 @@ This list contains 1464 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 21, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 31, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -171,6 +172,7 @@ This list contains 1464 plugins. :pypi:`pytest-board` Local continuous test runner with pytest and watchdog. Jan 20, 2019 N/A N/A :pypi:`pytest-boost-xml` Plugin for pytest to generate boost xml reports Nov 30, 2022 4 - Beta N/A :pypi:`pytest-bootstrap` Mar 04, 2022 N/A N/A + :pypi:`pytest-boto-mock` Thin-wrapper around the mock package for easier use with pytest May 27, 2024 5 - Production/Stable pytest>=8.2.0 :pypi:`pytest-bpdb` A py.test plug-in to enable drop to bpdb debugger on test failure. Jan 19, 2015 2 - Pre-Alpha N/A :pypi:`pytest-bq` BigQuery fixtures and fixture factories for Pytest. May 08, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-bravado` Pytest-bravado automatically generates from OpenAPI specification client fixtures. Feb 15, 2022 N/A N/A @@ -233,7 +235,7 @@ This list contains 1464 plugins. :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) - :pypi:`pytest-cleanslate` Collects and executes pytest tests separately May 20, 2024 N/A pytest + :pypi:`pytest-cleanslate` Collects and executes pytest tests separately May 30, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Apr 19, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -243,7 +245,7 @@ This list contains 1464 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest May 12, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest May 31, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 @@ -302,13 +304,14 @@ This list contains 1464 plugins. :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A :pypi:`pytest-custom-exit-code` Exit pytest test session with custom exit code in different scenarios Aug 07, 2019 4 - Beta pytest (>=4.0.2) :pypi:`pytest-custom-nodeid` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 07, 2021 N/A N/A + :pypi:`pytest-custom-outputs` A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail May 30, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A :pypi:`pytest-cython` A plugin for testing Cython extension modules Apr 05, 2024 5 - Production/Stable pytest>=8 :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A - :pypi:`pytest-dashboard` Apr 22, 2024 N/A pytest<8.0.0,>=7.4.3 + :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A :pypi:`pytest-databases` Reusable database fixtures for any and all databases. May 25, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest @@ -362,7 +365,8 @@ This list contains 1464 plugins. :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. May 11, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 :pypi:`pytest-discover` Pytest plugin to record discovered tests in a file Mar 26, 2024 N/A pytest - :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. May 07, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. May 29, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-ditto-pandas` pytest-ditto plugin for pandas snapshots. May 29, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-django` A Django plugin for pytest. Jan 30, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest @@ -444,13 +448,13 @@ This list contains 1464 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 Apr 04, 2024 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. May 23, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. May 31, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. May 23, 2024 5 - Production/Stable N/A :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. May 23, 2024 5 - Production/Stable N/A :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. May 23, 2024 5 - Production/Stable N/A :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. May 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. May 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. May 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. May 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. May 31, 2024 5 - Production/Stable N/A :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. May 23, 2024 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) @@ -480,6 +484,7 @@ This list contains 1464 plugins. :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 :pypi:`pytest-exasol-itde` Feb 15, 2024 N/A pytest (>=7,<9) + :pypi:`pytest-exasol-saas` May 27, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -520,7 +525,7 @@ This list contains 1464 plugins. :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) - :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Apr 22, 2024 N/A N/A + :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. May 30, 2024 N/A N/A :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A :pypi:`pytest-file` Pytest File Mar 18, 2024 1 - Planning N/A @@ -616,7 +621,6 @@ This list contains 1464 plugins. :pypi:`pytest-hardware-test-report` A simple plugin to use with pytest Apr 01, 2024 4 - Beta pytest<9.0.0,>=8.0.0 :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Mar 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-helm-chart` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Jun 15, 2020 4 - Beta pytest (>=5.4.2,<6.0.0) :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Feb 07, 2024 4 - Beta pytest (>=8.0.0,<9.0.0) :pypi:`pytest-helm-templates` Pytest fixtures for unit testing the output of helm templates May 08, 2024 N/A pytest~=7.4.0; extra == "dev" :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A @@ -630,7 +634,7 @@ This list contains 1464 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 May 18, 2024 3 - Alpha pytest==8.1.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 31, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -743,7 +747,7 @@ This list contains 1464 plugins. :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-kuunda` pytest plugin to help with test data setup for PySpark tests Feb 25, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-kwparametrize` Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks Jan 22, 2021 N/A pytest (>=6) - :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. Aug 20, 2022 3 - Alpha pytest (>=3.6,<8) + :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. May 27, 2024 5 - Production/Stable pytest<9,>=3.6 :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A :pypi:`pytest-langchain` Pytest-style test runner for langchain agents Feb 26, 2023 N/A pytest :pypi:`pytest-lark` Create fancy and clear HTML test reports. Nov 05, 2023 N/A N/A @@ -817,13 +821,13 @@ This list contains 1464 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 Feb 12, 2024 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 Mar 14, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin May 28, 2024 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions May 19, 2024 N/A pytest>=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions May 26, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Mar 07, 2024 N/A pytest >=7.0 + :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests May 28, 2024 N/A pytest>=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Mar 21, 2024 5 - Production/Stable pytest>=6.2.5 @@ -839,7 +843,6 @@ This list contains 1464 plugins. :pypi:`pytest-modalt` Massively distributed pytest runs using modal.com Feb 27, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-modified-env` Pytest plugin to fail a test if it leaves modified \`os.environ\` afterwards. Jan 29, 2022 4 - Beta N/A :pypi:`pytest-modifyjunit` Utility for adding additional properties to junit xml for IDM QE Jan 10, 2019 N/A N/A - :pypi:`pytest-modifyscope` pytest plugin to modify fixture scope Apr 12, 2020 N/A pytest :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Mar 13, 2024 5 - Production/Stable pytest >=6.2 @@ -907,7 +910,7 @@ This list contains 1464 plugins. :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) :pypi:`pytest-ogsm-plugin` 针对特定项目定制化插件,优化了pytest报告展示方式,并添加了项目所需特定参数 May 16, 2023 N/A N/A :pypi:`pytest-ok` The ultimate pytest output plugin Apr 01, 2019 4 - Beta N/A - :pypi:`pytest-only` Use @pytest.mark.only to run a single test Mar 09, 2024 5 - Production/Stable pytest (<7.1) ; python_full_version <= "3.6.0" + :pypi:`pytest-only` Use @pytest.mark.only to run a single test May 27, 2024 5 - Production/Stable pytest<9,>=3.6.0 :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 11, 2023 4 - Beta N/A :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) @@ -1019,6 +1022,7 @@ This list contains 1464 plugins. :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-pt` pytest plugin to use \*.pt files as tests May 15, 2024 4 - Beta pytest :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) + :pypi:`pytest-publish` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-pudb` Pytest PuDB debugger integration Oct 25, 2018 3 - Alpha pytest (>=2.0) :pypi:`pytest-pumpkin-spice` A pytest plugin that makes your test reporting pumpkin-spiced Sep 18, 2022 4 - Beta N/A :pypi:`pytest-purkinje` py.test plugin for purkinje test runner Oct 28, 2017 2 - Pre-Alpha N/A @@ -1048,7 +1052,8 @@ This list contains 1464 plugins. :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 22, 2024 4 - Beta pytest<9.0.0,>=7.2.2 + :pypi:`pytest-qanova` A pytest plugin to collect test information May 26, 2024 3 - Alpha pytest + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 30, 2024 4 - Beta pytest<9.0.0,>=7.2.2 :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 Nov 29, 2023 5 - Production/Stable pytest >=6.0 @@ -1146,7 +1151,7 @@ This list contains 1464 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them May 24, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them May 29, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1258,7 +1263,7 @@ This list contains 1464 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 May 16, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons May 27, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX May 10, 2024 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 @@ -1281,7 +1286,7 @@ This list contains 1464 plugins. :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-structlog` Structured logging assertions Mar 13, 2024 N/A pytest + :pypi:`pytest-structlog` Structured logging assertions May 30, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) @@ -1323,7 +1328,7 @@ This list contains 1464 plugins. :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A - :pypi:`pytest-testinfra` Test infrastructures Feb 15, 2024 5 - Production/Stable pytest >=6 + :pypi:`pytest-testinfra` Test infrastructures May 26, 2024 5 - Production/Stable pytest>=6 :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) @@ -1352,6 +1357,7 @@ This list contains 1464 plugins. :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A + :pypi:`pytest-tf` Test your OpenTofu and Terraform config using a PyTest plugin May 29, 2024 N/A pytest<9.0.0,>=8.2.1 :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A :pypi:`pytest-thawgun` Pytest plugin for time travel May 26, 2020 3 - Alpha N/A :pypi:`pytest-thread` Jul 07, 2023 N/A N/A @@ -1453,7 +1459,7 @@ This list contains 1464 plugins. :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 13, 2023 N/A pytest >= 7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable Mar 22, 2024 N/A pytest>=7.3.1 + :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 28, 2024 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -1477,6 +1483,7 @@ This list contains 1464 plugins. :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A + :pypi:`pytest-xstress` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 :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 @@ -1518,9 +1525,9 @@ This list contains 1464 plugins. Test whether your code is logging correctly 🪵 :pypi:`nuts` - *last release*: Aug 11, 2023, + *last release*: May 28, 2024, *status*: N/A, - *requires*: pytest (>=7.3.0,<8.0.0) + *requires*: pytest<8,>=7 Network Unit Testing System @@ -2133,6 +2140,13 @@ This list contains 1464 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. + :pypi:`pytest-aux` + *last release*: May 31, 2024, + *status*: N/A, + *requires*: N/A + + templates/examples and aux for pytest + :pypi:`pytest-aviator` *last release*: Nov 04, 2022, *status*: 4 - Beta, @@ -2302,7 +2316,7 @@ This list contains 1464 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: May 21, 2024, + *last release*: May 31, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2462,6 +2476,13 @@ This list contains 1464 plugins. + :pypi:`pytest-boto-mock` + *last release*: May 27, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=8.2.0 + + Thin-wrapper around the mock package for easier use with pytest + :pypi:`pytest-bpdb` *last release*: Jan 19, 2015, *status*: 2 - Pre-Alpha, @@ -2897,7 +2918,7 @@ This list contains 1464 plugins. Easy quality control for CLDF datasets using pytest :pypi:`pytest-cleanslate` - *last release*: May 20, 2024, + *last release*: May 30, 2024, *status*: N/A, *requires*: pytest @@ -2967,7 +2988,7 @@ This list contains 1464 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: May 12, 2024, + *last release*: May 31, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3379,6 +3400,13 @@ This list contains 1464 plugins. Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report + :pypi:`pytest-custom-outputs` + *last release*: May 30, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail + :pypi:`pytest-custom-report` *last release*: Jan 30, 2019, *status*: N/A, @@ -3422,7 +3450,7 @@ This list contains 1464 plugins. pytest fixtures to run dash applications. :pypi:`pytest-dashboard` - *last release*: Apr 22, 2024, + *last release*: May 30, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.3 @@ -3800,12 +3828,19 @@ This list contains 1464 plugins. Pytest plugin to record discovered tests in a file :pypi:`pytest-ditto` - *last release*: May 07, 2024, + *last release*: May 29, 2024, *status*: 4 - Beta, *requires*: pytest>=3.5.0 Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. + :pypi:`pytest-ditto-pandas` + *last release*: May 29, 2024, + *status*: 4 - Beta, + *requires*: pytest>=3.5.0 + + pytest-ditto plugin for pandas snapshots. + :pypi:`pytest-django` *last release*: Jan 30, 2024, *status*: 5 - Production/Stable, @@ -4374,7 +4409,7 @@ This list contains 1464 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: May 23, 2024, + *last release*: May 31, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -4409,14 +4444,14 @@ This list contains 1464 plugins. Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: May 23, 2024, + *last release*: May 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: May 23, 2024, + *last release*: May 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4625,6 +4660,13 @@ This list contains 1464 plugins. + :pypi:`pytest-exasol-saas` + *last release*: May 27, 2024, + *status*: N/A, + *requires*: pytest<9,>=7 + + + :pypi:`pytest-excel` *last release*: Sep 14, 2023, *status*: 5 - Production/Stable, @@ -4906,7 +4948,7 @@ This list contains 1464 plugins. py.test plugin that activates the fault handler module for tests (dummy package) :pypi:`pytest-fauna` - *last release*: Apr 22, 2024, + *last release*: May 30, 2024, *status*: N/A, *requires*: N/A @@ -5577,13 +5619,6 @@ This list contains 1464 plugins. Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. - :pypi:`pytest-helm-chart` - *last release*: Jun 15, 2020, - *status*: 4 - Beta, - *requires*: pytest (>=5.4.2,<6.0.0) - - A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. - :pypi:`pytest-helm-charts` *last release*: Feb 07, 2024, *status*: 4 - Beta, @@ -5676,9 +5711,9 @@ This list contains 1464 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 18, 2024, + *last release*: May 31, 2024, *status*: 3 - Alpha, - *requires*: pytest==8.1.1 + *requires*: pytest==8.2.0 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -6467,9 +6502,9 @@ This list contains 1464 plugins. Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks :pypi:`pytest-lambda` - *last release*: Aug 20, 2022, - *status*: 3 - Alpha, - *requires*: pytest (>=3.6,<8) + *last release*: May 27, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest<9,>=3.6 Define pytest fixtures with lambda functions. @@ -6985,7 +7020,7 @@ This list contains 1464 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Mar 14, 2024, + *last release*: May 28, 2024, *status*: N/A, *requires*: pytest @@ -7013,7 +7048,7 @@ This list contains 1464 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: May 19, 2024, + *last release*: May 26, 2024, *status*: N/A, *requires*: pytest>=5.0.0 @@ -7027,9 +7062,9 @@ This list contains 1464 plugins. Pytest plugin that creates missing fixtures :pypi:`pytest-mitmproxy` - *last release*: Mar 07, 2024, + *last release*: May 28, 2024, *status*: N/A, - *requires*: pytest >=7.0 + *requires*: pytest>=7.0 pytest plugin for mitmproxy tests @@ -7138,13 +7173,6 @@ This list contains 1464 plugins. Utility for adding additional properties to junit xml for IDM QE - :pypi:`pytest-modifyscope` - *last release*: Apr 12, 2020, - *status*: N/A, - *requires*: pytest - - pytest plugin to modify fixture scope - :pypi:`pytest-molecule` *last release*: Mar 29, 2022, *status*: 5 - Production/Stable, @@ -7615,9 +7643,9 @@ This list contains 1464 plugins. The ultimate pytest output plugin :pypi:`pytest-only` - *last release*: Mar 09, 2024, + *last release*: May 27, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (<7.1) ; python_full_version <= "3.6.0" + *requires*: pytest<9,>=3.6.0 Use @pytest.mark.only to run a single test @@ -8398,6 +8426,13 @@ This list contains 1464 plugins. Use ptera probes in tests + :pypi:`pytest-publish` + *last release*: Jun 01, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.0.0 + + + :pypi:`pytest-pudb` *last release*: Oct 25, 2018, *status*: 3 - Alpha, @@ -8601,8 +8636,15 @@ This list contains 1464 plugins. Pytest-pyvista package + :pypi:`pytest-qanova` + *last release*: May 26, 2024, + *status*: 3 - Alpha, + *requires*: pytest + + A pytest plugin to collect test information + :pypi:`pytest-qaseio` - *last release*: May 22, 2024, + *last release*: May 30, 2024, *status*: 4 - Beta, *requires*: pytest<9.0.0,>=7.2.2 @@ -9288,7 +9330,7 @@ This list contains 1464 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: May 24, 2024, + *last release*: May 29, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -10072,7 +10114,7 @@ This list contains 1464 plugins. :pypi:`pytest-splunk-addon` - *last release*: May 16, 2024, + *last release*: May 27, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10233,7 +10275,7 @@ This list contains 1464 plugins. A Pytest plugin that allows you to loop tests for a user defined amount of time. :pypi:`pytest-structlog` - *last release*: Mar 13, 2024, + *last release*: May 30, 2024, *status*: N/A, *requires*: pytest @@ -10527,9 +10569,9 @@ This list contains 1464 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-testinfra` - *last release*: Feb 15, 2024, + *last release*: May 26, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6 + *requires*: pytest>=6 Test infrastructures @@ -10729,6 +10771,13 @@ This list contains 1464 plugins. pytest-ligo + :pypi:`pytest-tf` + *last release*: May 29, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.2.1 + + Test your OpenTofu and Terraform config using a PyTest plugin + :pypi:`pytest-th2-bdd` *last release*: May 13, 2022, *status*: N/A, @@ -11437,7 +11486,7 @@ This list contains 1464 plugins. Welian API Automation test framework pytest plugin :pypi:`pytest-when` - *last release*: Mar 22, 2024, + *last release*: May 28, 2024, *status*: N/A, *requires*: pytest>=7.3.1 @@ -11604,6 +11653,13 @@ This list contains 1464 plugins. A package to prevent Dependency Confusion attacks against Yandex. + :pypi:`pytest-xstress` + *last release*: Jun 01, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.0.0 + + + :pypi:`pytest-xvfb` *last release*: May 29, 2023, *status*: 4 - Beta, From 17065cb008caaf26a48128fec1721c7f3d92b4c2 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 2 Jun 2024 16:57:50 +0300 Subject: [PATCH 0673/1271] cacheprovider: fix "Directory not empty" crash from cache directory creation Fix #12381 Test plan: It's possible to write a deterministic test case for this, but somewhat of a hassle so I tested it manually. I reproduced by removing existing `.pytest_cache`, adding a sleep before the rename and running two pytests. I verified that it doesn't reproduce after the fix. --- changelog/12381.bugfix.rst | 1 + src/_pytest/cacheprovider.py | 27 +++++++++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) create mode 100644 changelog/12381.bugfix.rst diff --git a/changelog/12381.bugfix.rst b/changelog/12381.bugfix.rst new file mode 100644 index 00000000000..02233cd4a84 --- /dev/null +++ b/changelog/12381.bugfix.rst @@ -0,0 +1 @@ +Fix possible "Directory not empty" crashes arising from concurent cache dir (``.pytest_cache``) creation. Regressed in pytest 8.2.0. diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 5aa8f483522..7e00135a4c1 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -4,6 +4,7 @@ # This plugin was not named "cache" to avoid conflicts with the external # pytest-cache version. import dataclasses +import errno import json import os from pathlib import Path @@ -227,14 +228,24 @@ def _ensure_cache_dir_and_supporting_files(self) -> None: with open(path.joinpath("CACHEDIR.TAG"), "xb") as f: f.write(CACHEDIR_TAG_CONTENT) - path.rename(self._cachedir) - # Create a directory in place of the one we just moved so that `TemporaryDirectory`'s - # cleanup doesn't complain. - # - # TODO: pass ignore_cleanup_errors=True when we no longer support python < 3.10. See - # https://github.com/python/cpython/issues/74168. Note that passing delete=False would - # do the wrong thing in case of errors and isn't supported until python 3.12. - path.mkdir() + try: + path.rename(self._cachedir) + except OSError as e: + # If 2 concurrent pytests both race to the rename, the loser + # gets "Directory not empty" from the rename. In this case, + # everything is handled so just continue (while letting the + # temporary directory be cleaned up). + if e.errno != errno.ENOTEMPTY: + raise + else: + # Create a directory in place of the one we just moved so that + # `TemporaryDirectory`'s cleanup doesn't complain. + # + # TODO: pass ignore_cleanup_errors=True when we no longer support python < 3.10. + # See https://github.com/python/cpython/issues/74168. Note that passing + # delete=False would do the wrong thing in case of errors and isn't supported + # until python 3.12. + path.mkdir() class LFPluginCollWrapper: From 1eee63a891d3598e6d3178c3c793eecdd5940b5c Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 27 May 2024 00:44:05 +0300 Subject: [PATCH 0674/1271] fixtures: minor cleanups to reorder_items This makes some minor clarity and performance improvements to the code. --- src/_pytest/fixtures.py | 125 +++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 60 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index b7a58081ba8..37fc44ff9c9 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -21,6 +21,7 @@ from typing import Iterable from typing import Iterator from typing import List +from typing import Mapping from typing import MutableMapping from typing import NoReturn from typing import Optional @@ -161,6 +162,12 @@ def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]: ) +# Algorithm for sorting on a per-parametrized resource setup basis. +# It is called for Session scope first and performs sorting +# down to the lower scopes such as to minimize number of "high scope" +# setups and teardowns. + + @dataclasses.dataclass(frozen=True) class FixtureArgKey: argname: str @@ -169,97 +176,91 @@ class FixtureArgKey: item_cls: Optional[type] -def get_parametrized_fixture_keys( +_V = TypeVar("_V") +OrderedSet = Dict[_V, None] + + +def get_parametrized_fixture_argkeys( item: nodes.Item, scope: Scope ) -> Iterator[FixtureArgKey]: """Return list of keys for all parametrized arguments which match the specified scope.""" assert scope is not Scope.Function + try: callspec: CallSpec2 = item.callspec # type: ignore[attr-defined] except AttributeError: return + + item_cls = None + if scope is Scope.Session: + scoped_item_path = None + elif scope is Scope.Package: + # Package key = module's directory. + scoped_item_path = item.path.parent + elif scope is Scope.Module: + scoped_item_path = item.path + elif scope is Scope.Class: + scoped_item_path = item.path + item_cls = item.cls # type: ignore[attr-defined] + else: + assert_never(scope) + for argname in callspec.indices: if callspec._arg2scope[argname] != scope: continue - - item_cls = None - if scope is Scope.Session: - scoped_item_path = None - elif scope is Scope.Package: - # Package key = module's directory. - scoped_item_path = item.path.parent - elif scope is Scope.Module: - scoped_item_path = item.path - elif scope is Scope.Class: - scoped_item_path = item.path - item_cls = item.cls # type: ignore[attr-defined] - else: - assert_never(scope) - param_index = callspec.indices[argname] yield FixtureArgKey(argname, param_index, scoped_item_path, item_cls) -# Algorithm for sorting on a per-parametrized resource setup basis. -# It is called for Session scope first and performs sorting -# down to the lower scopes such as to minimize number of "high scope" -# setups and teardowns. - - def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]: - argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]] = {} + argkeys_by_item: Dict[Scope, Dict[nodes.Item, OrderedSet[FixtureArgKey]]] = {} items_by_argkey: Dict[Scope, Dict[FixtureArgKey, Deque[nodes.Item]]] = {} for scope in HIGH_SCOPES: - scoped_argkeys_cache = argkeys_cache[scope] = {} + scoped_argkeys_by_item = argkeys_by_item[scope] = {} scoped_items_by_argkey = items_by_argkey[scope] = defaultdict(deque) for item in items: - keys = dict.fromkeys(get_parametrized_fixture_keys(item, scope), None) - if keys: - scoped_argkeys_cache[item] = keys - for key in keys: - scoped_items_by_argkey[key].append(item) - items_dict = dict.fromkeys(items, None) + argkeys = dict.fromkeys(get_parametrized_fixture_argkeys(item, scope)) + if argkeys: + scoped_argkeys_by_item[item] = argkeys + for argkey in argkeys: + scoped_items_by_argkey[argkey].append(item) + + items_set = dict.fromkeys(items) return list( - reorder_items_atscope(items_dict, argkeys_cache, items_by_argkey, Scope.Session) + reorder_items_atscope( + items_set, argkeys_by_item, items_by_argkey, Scope.Session + ) ) -def fix_cache_order( - item: nodes.Item, - argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]], - items_by_argkey: Dict[Scope, Dict[FixtureArgKey, "Deque[nodes.Item]"]], -) -> None: - for scope in HIGH_SCOPES: - for key in argkeys_cache[scope].get(item, []): - items_by_argkey[scope][key].appendleft(item) - - def reorder_items_atscope( - items: Dict[nodes.Item, None], - argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]], - items_by_argkey: Dict[Scope, Dict[FixtureArgKey, "Deque[nodes.Item]"]], + items: OrderedSet[nodes.Item], + argkeys_by_item: Mapping[Scope, Mapping[nodes.Item, OrderedSet[FixtureArgKey]]], + items_by_argkey: Mapping[Scope, Mapping[FixtureArgKey, "Deque[nodes.Item]"]], scope: Scope, -) -> Dict[nodes.Item, None]: +) -> OrderedSet[nodes.Item]: if scope is Scope.Function or len(items) < 3: return items - ignore: Set[Optional[FixtureArgKey]] = set() - items_deque = deque(items) - items_done: Dict[nodes.Item, None] = {} + scoped_items_by_argkey = items_by_argkey[scope] - scoped_argkeys_cache = argkeys_cache[scope] + scoped_argkeys_by_item = argkeys_by_item[scope] + + ignore: Set[FixtureArgKey] = set() + items_deque = deque(items) + items_done: OrderedSet[nodes.Item] = {} while items_deque: - no_argkey_group: Dict[nodes.Item, None] = {} + no_argkey_items: OrderedSet[nodes.Item] = {} slicing_argkey = None while items_deque: item = items_deque.popleft() - if item in items_done or item in no_argkey_group: + if item in items_done or item in no_argkey_items: continue argkeys = dict.fromkeys( - (k for k in scoped_argkeys_cache.get(item, []) if k not in ignore), None + k for k in scoped_argkeys_by_item.get(item, ()) if k not in ignore ) if not argkeys: - no_argkey_group[item] = None + no_argkey_items[item] = None else: slicing_argkey, _ = argkeys.popitem() # We don't have to remove relevant items from later in the @@ -268,16 +269,20 @@ def reorder_items_atscope( i for i in scoped_items_by_argkey[slicing_argkey] if i in items ] for i in reversed(matching_items): - fix_cache_order(i, argkeys_cache, items_by_argkey) items_deque.appendleft(i) + # Fix items_by_argkey order. + for other_scope in HIGH_SCOPES: + other_scoped_items_by_argkey = items_by_argkey[other_scope] + for argkey in argkeys_by_item[other_scope].get(i, ()): + other_scoped_items_by_argkey[argkey].appendleft(i) break - if no_argkey_group: - no_argkey_group = reorder_items_atscope( - no_argkey_group, argkeys_cache, items_by_argkey, scope.next_lower() + if no_argkey_items: + reordered_no_argkey_items = reorder_items_atscope( + no_argkey_items, argkeys_by_item, items_by_argkey, scope.next_lower() ) - for item in no_argkey_group: - items_done[item] = None - ignore.add(slicing_argkey) + items_done.update(reordered_no_argkey_items) + if slicing_argkey is not None: + ignore.add(slicing_argkey) return items_done From 7be95f9b30ffd418483bdb57112f9339465d4695 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 3 Jun 2024 14:11:41 +0200 Subject: [PATCH 0675/1271] code: do not truncate args when running with -vvv (#12241) Related to #2871. --- AUTHORS | 1 + changelog/2871.improvement.rst | 1 + src/_pytest/_code/code.py | 12 +++++++++++- src/_pytest/nodes.py | 3 +++ testing/code/test_excinfo.py | 24 ++++++++++++++++++++++++ testing/test_assertion.py | 33 +++++++++++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 changelog/2871.improvement.rst diff --git a/AUTHORS b/AUTHORS index 748b9bae2c8..0560caf721b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -279,6 +279,7 @@ Michael Droettboom Michael Goerz Michael Krebs Michael Seifert +Michael Vogt Michal Wajszczuk Michał Górny Michał Zięba diff --git a/changelog/2871.improvement.rst b/changelog/2871.improvement.rst new file mode 100644 index 00000000000..1ba399550c7 --- /dev/null +++ b/changelog/2871.improvement.rst @@ -0,0 +1 @@ +Do not truncate arguments to functions in output when running with `-vvv`. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 4fb686a86e5..b1ef9fe227c 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -635,6 +635,7 @@ def getrepr( ] = True, funcargs: bool = False, truncate_locals: bool = True, + truncate_args: bool = True, chain: bool = True, ) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]: """Return str()able representation of this exception info. @@ -665,6 +666,9 @@ def getrepr( :param bool truncate_locals: With ``showlocals==True``, make sure locals can be safely represented as strings. + :param bool truncate_args: + With ``showargs==True``, make sure args can be safely represented as strings. + :param bool chain: If chained exceptions in Python 3 should be shown. @@ -691,6 +695,7 @@ def getrepr( tbfilter=tbfilter, funcargs=funcargs, truncate_locals=truncate_locals, + truncate_args=truncate_args, chain=chain, ) return fmt.repr_excinfo(self) @@ -809,6 +814,7 @@ class FormattedExcinfo: tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True funcargs: bool = False truncate_locals: bool = True + truncate_args: bool = True chain: bool = True astcache: Dict[Union[str, Path], ast.AST] = dataclasses.field( default_factory=dict, init=False, repr=False @@ -839,7 +845,11 @@ def repr_args(self, entry: TracebackEntry) -> Optional["ReprFuncArgs"]: if self.funcargs: args = [] for argname, argvalue in entry.frame.getargs(var=True): - args.append((argname, saferepr(argvalue))) + if self.truncate_args: + str_repr = saferepr(argvalue) + else: + str_repr = saferepr(argvalue, maxsize=None) + args.append((argname, str_repr)) return ReprFuncArgs(args) return None diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 974d756a2be..e731019715c 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -448,6 +448,8 @@ def _repr_failure_py( else: truncate_locals = True + truncate_args = False if self.config.getoption("verbose", 0) > 2 else True + # excinfo.getrepr() formats paths relative to the CWD if `abspath` is False. # It is possible for a fixture/test to change the CWD while this code runs, which # would then result in the user seeing confusing paths in the failure message. @@ -466,6 +468,7 @@ def _repr_failure_py( style=style, tbfilter=tbfilter, truncate_locals=truncate_locals, + truncate_args=truncate_args, ) def repr_failure( diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index b5474512987..f7f780e98f8 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -11,6 +11,7 @@ import sys import textwrap from typing import Any +from typing import cast from typing import TYPE_CHECKING import _pytest._code @@ -712,6 +713,29 @@ def test_repr_local_truncated(self) -> None: assert full_reprlocals.lines assert full_reprlocals.lines[0] == "l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" + def test_repr_args_not_truncated(self, importasmod) -> None: + mod = importasmod( + """ + def func1(m): + raise ValueError("hello\\nworld") + """ + ) + excinfo = pytest.raises(ValueError, mod.func1, "m" * 500) + excinfo.traceback = excinfo.traceback.filter(excinfo) + entry = excinfo.traceback[-1] + p = FormattedExcinfo(funcargs=True, truncate_args=True) + reprfuncargs = p.repr_args(entry) + assert reprfuncargs is not None + arg1 = cast(str, reprfuncargs.args[0][1]) + assert len(arg1) < 500 + assert "..." in arg1 + # again without truncate + p = FormattedExcinfo(funcargs=True, truncate_args=False) + reprfuncargs = p.repr_args(entry) + assert reprfuncargs is not None + assert reprfuncargs.args[0] == ("m", repr("m" * 500)) + assert "..." not in cast(str, reprfuncargs.args[0][1]) + def test_repr_tracebackentry_lines(self, importasmod) -> None: mod = importasmod( """ diff --git a/testing/test_assertion.py b/testing/test_assertion.py index a8960436b55..726235999b4 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -2045,3 +2045,36 @@ def test_long_text_fail(): f"E AssertionError: assert 'hello world' in '{long_text}'", ] ) + + +def test_full_output_vvv(pytester: Pytester) -> None: + pytester.makepyfile( + r""" + def crash_helper(m): + assert 1 == 2 + def test_vvv(): + crash_helper(500 * "a") + """ + ) + result = pytester.runpytest("") + # without -vvv, the passed args are truncated + expected_non_vvv_arg_line = "m = 'aaaaaaaaaaaaaaa*..aaaaaaaaaaaa*" + result.stdout.fnmatch_lines( + [ + expected_non_vvv_arg_line, + "test_full_output_vvv.py:2: AssertionError", + ], + ) + # double check that the untruncated part is not in the output + expected_vvv_arg_line = "m = '{}'".format(500 * "a") + result.stdout.no_fnmatch_line(expected_vvv_arg_line) + + # but with "-vvv" the args are not truncated + result = pytester.runpytest("-vvv") + result.stdout.fnmatch_lines( + [ + expected_vvv_arg_line, + "test_full_output_vvv.py:2: AssertionError", + ] + ) + result.stdout.no_fnmatch_line(expected_non_vvv_arg_line) From 3433c7adf52a79592438d7af0637ae905657ee56 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 09:06:33 +0200 Subject: [PATCH 0676/1271] [pre-commit.ci] pre-commit autoupdate (#12413) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.5 → v0.4.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.5...v0.4.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 64bdbb36a94..6a9fde6a511 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.5" + rev: "v0.4.7" hooks: - id: ruff args: ["--fix"] From e89d23b24741c001e8651a77303992cfa41c1664 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 2 Jun 2024 17:57:38 +0300 Subject: [PATCH 0677/1271] fixtures: fix catastrophic performance problem in `reorder_items` Fix #12355. In the issue, it was reported that the `reorder_items` has quadratic (or worse...) behavior with certain simple parametrizations. After some debugging I found that the problem happens because the "Fix items_by_argkey order" loop keeps adding the same item to the deque, and it reaches epic sizes which causes the slowdown. I don't claim to understand how the `reorder_items` algorithm works, but if as far as I understand, if an item already exists in the deque, the correct thing to do is to move it to the front. Since a deque doesn't have such an (efficient) operation, this switches to `OrderedDict` which can efficiently append from both sides, deduplicate and move to front. --- changelog/12355.bugfix.rst | 1 + src/_pytest/fixtures.py | 20 +++++++++++++------- testing/python/fixtures.py | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 changelog/12355.bugfix.rst diff --git a/changelog/12355.bugfix.rst b/changelog/12355.bugfix.rst new file mode 100644 index 00000000000..1ce43e60ebd --- /dev/null +++ b/changelog/12355.bugfix.rst @@ -0,0 +1 @@ +Fix possible catastrophic performance slowdown on a certain parametrization pattern involving many higher-scoped parameters. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 37fc44ff9c9..353082c17e1 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -25,6 +25,7 @@ from typing import MutableMapping from typing import NoReturn from typing import Optional +from typing import OrderedDict from typing import overload from typing import Sequence from typing import Set @@ -77,8 +78,6 @@ if TYPE_CHECKING: - from typing import Deque - from _pytest.main import Session from _pytest.python import CallSpec2 from _pytest.python import Function @@ -215,16 +214,18 @@ def get_parametrized_fixture_argkeys( def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]: argkeys_by_item: Dict[Scope, Dict[nodes.Item, OrderedSet[FixtureArgKey]]] = {} - items_by_argkey: Dict[Scope, Dict[FixtureArgKey, Deque[nodes.Item]]] = {} + items_by_argkey: Dict[ + Scope, Dict[FixtureArgKey, OrderedDict[nodes.Item, None]] + ] = {} for scope in HIGH_SCOPES: scoped_argkeys_by_item = argkeys_by_item[scope] = {} - scoped_items_by_argkey = items_by_argkey[scope] = defaultdict(deque) + scoped_items_by_argkey = items_by_argkey[scope] = defaultdict(OrderedDict) for item in items: argkeys = dict.fromkeys(get_parametrized_fixture_argkeys(item, scope)) if argkeys: scoped_argkeys_by_item[item] = argkeys for argkey in argkeys: - scoped_items_by_argkey[argkey].append(item) + scoped_items_by_argkey[argkey][item] = None items_set = dict.fromkeys(items) return list( @@ -237,7 +238,9 @@ def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]: def reorder_items_atscope( items: OrderedSet[nodes.Item], argkeys_by_item: Mapping[Scope, Mapping[nodes.Item, OrderedSet[FixtureArgKey]]], - items_by_argkey: Mapping[Scope, Mapping[FixtureArgKey, "Deque[nodes.Item]"]], + items_by_argkey: Mapping[ + Scope, Mapping[FixtureArgKey, OrderedDict[nodes.Item, None]] + ], scope: Scope, ) -> OrderedSet[nodes.Item]: if scope is Scope.Function or len(items) < 3: @@ -274,7 +277,10 @@ def reorder_items_atscope( for other_scope in HIGH_SCOPES: other_scoped_items_by_argkey = items_by_argkey[other_scope] for argkey in argkeys_by_item[other_scope].get(i, ()): - other_scoped_items_by_argkey[argkey].appendleft(i) + other_scoped_items_by_argkey[argkey][i] = None + other_scoped_items_by_argkey[argkey].move_to_end( + i, last=False + ) break if no_argkey_items: reordered_no_argkey_items = reorder_items_atscope( diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index d54bcc4d4eb..d3cff38f977 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2219,6 +2219,25 @@ def test_check(): reprec = pytester.inline_run("-s") reprec.assertoutcome(passed=2) + def test_reordering_catastrophic_performance(self, pytester: Pytester) -> None: + """Check that a certain high-scope parametrization pattern doesn't cause + a catasrophic slowdown. + + Regression test for #12355. + """ + pytester.makepyfile(""" + import pytest + + params = tuple("abcdefghijklmnopqrstuvwxyz") + @pytest.mark.parametrize(params, [range(len(params))] * 3, scope="module") + def test_parametrize(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z): + pass + """) + + result = pytester.runpytest() + + result.assert_outcomes(passed=3) + class TestFixtureMarker: def test_parametrize(self, pytester: Pytester) -> None: From 4cd80e19c51c9cc57470b51d0c1c05d355f79556 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 4 Jun 2024 16:51:13 +0300 Subject: [PATCH 0678/1271] Merge pull request #12415 from pytest-dev/release-8.2.2 Prepare release 8.2.2 (cherry picked from commit f3a494cca3bf0491f7277abff229a1331382ae26) --- changelog/12290.doc.rst | 1 - changelog/12355.bugfix.rst | 1 - changelog/12356.doc.rst | 2 -- changelog/12363.doc.rst | 1 - changelog/12367.bugfix.rst | 1 - changelog/12381.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.2.2.rst | 19 +++++++++++++++++++ doc/en/builtin.rst | 4 ++-- doc/en/changelog.rst | 29 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 14 files changed, 58 insertions(+), 16 deletions(-) delete mode 100644 changelog/12290.doc.rst delete mode 100644 changelog/12355.bugfix.rst delete mode 100644 changelog/12356.doc.rst delete mode 100644 changelog/12363.doc.rst delete mode 100644 changelog/12367.bugfix.rst delete mode 100644 changelog/12381.bugfix.rst create mode 100644 doc/en/announce/release-8.2.2.rst diff --git a/changelog/12290.doc.rst b/changelog/12290.doc.rst deleted file mode 100644 index 07fe3babc66..00000000000 --- a/changelog/12290.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Updated Sphinx theme to use Furo instead of Flask, enabling Dark mode theme. diff --git a/changelog/12355.bugfix.rst b/changelog/12355.bugfix.rst deleted file mode 100644 index 1ce43e60ebd..00000000000 --- a/changelog/12355.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix possible catastrophic performance slowdown on a certain parametrization pattern involving many higher-scoped parameters. diff --git a/changelog/12356.doc.rst b/changelog/12356.doc.rst deleted file mode 100644 index 312c26d3298..00000000000 --- a/changelog/12356.doc.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added a subsection to the documentation for debugging flaky tests to mention -lack of thread safety in pytest as a possible source of flakyness. diff --git a/changelog/12363.doc.rst b/changelog/12363.doc.rst deleted file mode 100644 index c657281babf..00000000000 --- a/changelog/12363.doc.rst +++ /dev/null @@ -1 +0,0 @@ -The documentation webpages now links to a canonical version to reduce outdated documentation in search engine results. diff --git a/changelog/12367.bugfix.rst b/changelog/12367.bugfix.rst deleted file mode 100644 index e8bf2e4f155..00000000000 --- a/changelog/12367.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.2.0 where unittest class instances (a fresh one is created for each test) were not released promptly on test teardown but only on session teardown. diff --git a/changelog/12381.bugfix.rst b/changelog/12381.bugfix.rst deleted file mode 100644 index 02233cd4a84..00000000000 --- a/changelog/12381.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix possible "Directory not empty" crashes arising from concurent cache dir (``.pytest_cache``) creation. Regressed in pytest 8.2.0. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 8a33f7fb57d..c65eb5f3613 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.2.2 release-8.2.1 release-8.2.0 release-8.1.2 diff --git a/doc/en/announce/release-8.2.2.rst b/doc/en/announce/release-8.2.2.rst new file mode 100644 index 00000000000..3b1d93bd08b --- /dev/null +++ b/doc/en/announce/release-8.2.2.rst @@ -0,0 +1,19 @@ +pytest-8.2.2 +======================================= + +pytest 8.2.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 458253fabbb..8dfffb0828a 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:549 + cache -- .../_pytest/cacheprovider.py:560 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -115,7 +115,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1335 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1338 Session-scoped fixture that returns the session's :class:`pytest.Config` object. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index ca7f5b999bd..3ab2307ee5d 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -28,6 +28,35 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.2.2 (2024-06-04) +========================= + +Bug Fixes +--------- + +- `#12355 `_: Fix possible catastrophic performance slowdown on a certain parametrization pattern involving many higher-scoped parameters. + + +- `#12367 `_: Fix a regression in pytest 8.2.0 where unittest class instances (a fresh one is created for each test) were not released promptly on test teardown but only on session teardown. + + +- `#12381 `_: Fix possible "Directory not empty" crashes arising from concurent cache dir (``.pytest_cache``) creation. Regressed in pytest 8.2.0. + + + +Improved Documentation +---------------------- + +- `#12290 `_: Updated Sphinx theme to use Furo instead of Flask, enabling Dark mode theme. + + +- `#12356 `_: Added a subsection to the documentation for debugging flaky tests to mention + lack of thread safety in pytest as a possible source of flakyness. + + +- `#12363 `_: The documentation webpages now links to a canonical version to reduce outdated documentation in search engine results. + + pytest 8.2.1 (2024-05-19) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 03f6852e5c0..d540bf08337 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index aa9d05d7227..39b799ed934 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 94e0d80e656..85bee729ba1 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.2.1 + pytest 8.2.2 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 6cc20c8c3e4..35c3238dea7 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From c9d8765381d71197fc981a9636828aea5063dc7f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 3 Jun 2024 19:16:56 +0300 Subject: [PATCH 0679/1271] fixtures: change `register_fixture` to not accept `scope=None` There is no reason to allow this. --- src/_pytest/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 353082c17e1..c078898dd66 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1636,7 +1636,7 @@ def _register_fixture( func: "_FixtureFunc[object]", nodeid: Optional[str], scope: Union[ - Scope, _ScopeName, Callable[[str, Config], _ScopeName], None + Scope, _ScopeName, Callable[[str, Config], _ScopeName] ] = "function", params: Optional[Sequence[object]] = None, ids: Optional[ From 043ff9abc657124db3504d3604e16ddebfe6e28f Mon Sep 17 00:00:00 2001 From: holger krekel Date: Thu, 6 Jun 2024 12:24:31 +0200 Subject: [PATCH 0680/1271] Remove hp42 contact details from the documentation (#12427) --- doc/en/contact.rst | 7 ------- 1 file changed, 7 deletions(-) diff --git a/doc/en/contact.rst b/doc/en/contact.rst index beed10d7f27..68efef522ff 100644 --- a/doc/en/contact.rst +++ b/doc/en/contact.rst @@ -26,19 +26,12 @@ Contact channels `_, or `via Matrix `_). -- private mail to Holger.Krekel at gmail com if you want to communicate sensitive issues - - -- `merlinux.eu`_ offers pytest and tox-related professional teaching and - consulting. .. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues .. _`old issue tracker`: https://bitbucket.org/hpk42/py-trunk/issues/ .. _`pytest discussions`: https://github.com/pytest-dev/pytest/discussions -.. _`merlinux.eu`: https://merlinux.eu/ - .. _`get an account`: .. _tetamap: https://tetamap.wordpress.com/ From 6b2daaa2e9c8c325bdcb0886fc90d2df198af405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20K=C5=82oczko?= <31284574+kloczek@users.noreply.github.com> Date: Thu, 6 Jun 2024 22:52:29 +0100 Subject: [PATCH 0681/1271] [pre-commit] Add pyupgrade back as a manual stage (#12418) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Launchable with ``pre-commit run --hook-stage manual pyupgrade -a`` --------- Signed-off-by: Tomasz Kłoczko Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 5 +++++ testing/test_unittest.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6a9fde6a511..fb583b11126 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,6 +43,11 @@ repos: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version additional_dependencies: ["tox>=4.9"] +- repo: https://github.com/asottile/pyupgrade + rev: v3.15.2 + hooks: + - id: pyupgrade + stages: [manual] - repo: local hooks: - id: pylint diff --git a/testing/test_unittest.py b/testing/test_unittest.py index c359715dc2e..9561cad5eb5 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -384,7 +384,7 @@ def test_hello(self): @pytest.mark.parametrize("type", ["Error", "Failure"]) def test_testcase_custom_exception_info(pytester: Pytester, type: str) -> None: pytester.makepyfile( - """ + f""" from typing import Generic, TypeVar from unittest import TestCase import pytest, _pytest._code @@ -413,7 +413,7 @@ def from_exc_info(cls, *args, **kwargs): def test_hello(self): pass - """.format(**locals()) + """ ) result = pytester.runpytest() result.stdout.fnmatch_lines( From f94109937123ff5a9c780a74ed043e9467c4f1f2 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 7 Jun 2024 02:32:33 -0400 Subject: [PATCH 0682/1271] Cleanup MockAwareDocTestFinder. (#12431) * Only rely on _find_lineno on Python 3.10 and earlier. * Update docstring to reflect current expectation. * Only rely on _find on Python 3.9 and earlier. * Mark line as uncovered. * Remove empty else block (implicit is better than explicit). Closes #12430 Closes #12432 --- src/_pytest/doctest.py | 72 +++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 2d7453b4ee0..23ad7a7a979 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -505,43 +505,46 @@ def collect(self) -> Iterable[DoctestItem]: import doctest class MockAwareDocTestFinder(doctest.DocTestFinder): - """A hackish doctest finder that overrides stdlib internals to fix a stdlib bug. - - https://github.com/pytest-dev/pytest/issues/3456 - https://bugs.python.org/issue25532 - """ - - def _find_lineno(self, obj, source_lines): - """Doctest code does not take into account `@property`, this - is a hackish way to fix it. https://bugs.python.org/issue17446 - - Wrapped Doctests will need to be unwrapped so the correct - line number is returned. This will be reported upstream. #8796 - """ - if isinstance(obj, property): - obj = getattr(obj, "fget", obj) - - if hasattr(obj, "__wrapped__"): - # Get the main obj in case of it being wrapped - obj = inspect.unwrap(obj) - - # Type ignored because this is a private function. - return super()._find_lineno( # type:ignore[misc] - obj, - source_lines, - ) + if sys.version_info < (3, 11): + + def _find_lineno(self, obj, source_lines): + """On older Pythons, doctest code does not take into account + `@property`. https://github.com/python/cpython/issues/61648 + + Moreover, wrapped Doctests need to be unwrapped so the correct + line number is returned. #8796 + """ + if isinstance(obj, property): + obj = getattr(obj, "fget", obj) + + if hasattr(obj, "__wrapped__"): + # Get the main obj in case of it being wrapped + obj = inspect.unwrap(obj) - def _find( - self, tests, obj, name, module, source_lines, globs, seen - ) -> None: - if _is_mocked(obj): - return - with _patch_unwrap_mock_aware(): # Type ignored because this is a private function. - super()._find( # type:ignore[misc] - tests, obj, name, module, source_lines, globs, seen + return super()._find_lineno( # type:ignore[misc] + obj, + source_lines, ) + if sys.version_info < (3, 10): + + def _find( + self, tests, obj, name, module, source_lines, globs, seen + ) -> None: + """Override _find to work around issue in stdlib. + + https://github.com/pytest-dev/pytest/issues/3456 + https://github.com/python/cpython/issues/69718 + """ + if _is_mocked(obj): + return # pragma: no cover + with _patch_unwrap_mock_aware(): + # Type ignored because this is a private function. + super()._find( # type:ignore[misc] + tests, obj, name, module, source_lines, globs, seen + ) + if sys.version_info < (3, 13): def _from_module(self, module, object): @@ -556,9 +559,6 @@ def _from_module(self, module, object): # Type ignored because this is a private function. return super()._from_module(module, object) # type: ignore[misc] - else: # pragma: no cover - pass - try: module = self.obj except Collector.CollectError: From c07bbdfa5bc39b20ddc529fed83f3a405354ca75 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 4 Jun 2024 23:29:14 +0300 Subject: [PATCH 0683/1271] Avoid some TYPE_CHECKING It's better not to use it when possible. --- src/_pytest/_code/code.py | 12 ++++++------ src/_pytest/config/__init__.py | 17 ++++++++--------- src/_pytest/debugging.py | 14 +++++--------- src/_pytest/fixtures.py | 2 +- src/_pytest/main.py | 5 +++-- src/_pytest/mark/structures.py | 2 +- src/_pytest/nodes.py | 6 +++--- src/_pytest/stepwise.py | 7 +------ src/_pytest/unittest.py | 17 +++++++++-------- testing/code/test_excinfo.py | 6 +++--- 10 files changed, 40 insertions(+), 48 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index b1ef9fe227c..b6e06340dbe 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -55,7 +55,7 @@ if sys.version_info < (3, 11): from exceptiongroup import BaseExceptionGroup -_TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] +TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] class Code: @@ -628,7 +628,7 @@ def _getreprcrash(self) -> Optional["ReprFileLocation"]: def getrepr( self, showlocals: bool = False, - style: _TracebackStyle = "long", + style: TracebackStyle = "long", abspath: bool = False, tbfilter: Union[ bool, Callable[["ExceptionInfo[BaseException]"], Traceback] @@ -809,7 +809,7 @@ class FormattedExcinfo: fail_marker: ClassVar = "E" showlocals: bool = False - style: _TracebackStyle = "long" + style: TracebackStyle = "long" abspath: bool = True tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True funcargs: bool = False @@ -1174,7 +1174,7 @@ def toterminal(self, tw: TerminalWriter) -> None: class ReprTraceback(TerminalRepr): reprentries: Sequence[Union["ReprEntry", "ReprEntryNative"]] extraline: Optional[str] - style: _TracebackStyle + style: TracebackStyle entrysep: ClassVar = "_ " @@ -1208,7 +1208,7 @@ def __init__(self, tblines: Sequence[str]) -> None: class ReprEntryNative(TerminalRepr): lines: Sequence[str] - style: ClassVar[_TracebackStyle] = "native" + style: ClassVar[TracebackStyle] = "native" def toterminal(self, tw: TerminalWriter) -> None: tw.write("".join(self.lines)) @@ -1220,7 +1220,7 @@ class ReprEntry(TerminalRepr): reprfuncargs: Optional["ReprFuncArgs"] reprlocals: Optional["ReprLocals"] reprfileloc: Optional["ReprFileLocation"] - style: _TracebackStyle + style: TracebackStyle def _write_entry_lines(self, tw: TerminalWriter) -> None: """Write the source code portions of a list of traceback entries with syntax highlighting. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index f3d3b3062b5..287fac463cb 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -54,7 +54,10 @@ import _pytest._code from _pytest._code import ExceptionInfo from _pytest._code import filter_traceback +from _pytest._code.code import TracebackStyle from _pytest._io import TerminalWriter +from _pytest.config.argparsing import Argument +from _pytest.config.argparsing import Parser import _pytest.deprecated import _pytest.hookspec from _pytest.outcomes import fail @@ -71,9 +74,7 @@ if TYPE_CHECKING: - from .argparsing import Argument - from .argparsing import Parser - from _pytest._code.code import _TracebackStyle + from _pytest.cacheprovider import Cache from _pytest.terminal import TerminalReporter @@ -1030,6 +1031,9 @@ class ArgsSource(enum.Enum): #: 'testpaths' configuration value. TESTPATHS = enum.auto() + # Set by cacheprovider plugin. + cache: Optional["Cache"] + def __init__( self, pluginmanager: PytestPluginManager, @@ -1091,11 +1095,6 @@ def __init__( self.args_source = Config.ArgsSource.ARGS self.args: List[str] = [] - if TYPE_CHECKING: - from _pytest.cacheprovider import Cache - - self.cache: Optional[Cache] = None - @property def rootpath(self) -> Path: """The path to the :ref:`rootdir `. @@ -1175,7 +1174,7 @@ def notify_exception( option: Optional[argparse.Namespace] = None, ) -> None: if option and getattr(option, "fulltrace", False): - style: _TracebackStyle = "long" + style: TracebackStyle = "long" else: style = "native" excrepr = excinfo.getrepr( diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 1338ef9f22c..eacb2836d6c 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -13,12 +13,12 @@ from typing import Optional from typing import Tuple from typing import Type -from typing import TYPE_CHECKING from typing import Union import unittest from _pytest import outcomes from _pytest._code import ExceptionInfo +from _pytest.capture import CaptureManager from _pytest.config import Config from _pytest.config import ConftestImportFailure from _pytest.config import hookimpl @@ -27,11 +27,7 @@ from _pytest.config.exceptions import UsageError from _pytest.nodes import Node from _pytest.reports import BaseReport - - -if TYPE_CHECKING: - from _pytest.capture import CaptureManager - from _pytest.runner import CallInfo +from _pytest.runner import CallInfo def _validate_usepdb_cls(value: str) -> Tuple[str, str]: @@ -310,7 +306,7 @@ def pytest_pyfunc_call(self, pyfuncitem) -> Generator[None, object, object]: return (yield) -def wrap_pytest_function_for_tracing(pyfuncitem): +def wrap_pytest_function_for_tracing(pyfuncitem) -> None: """Change the Python function object of the given Function item by a wrapper which actually enters pdb before calling the python function itself, effectively leaving the user in the pdb prompt in the first @@ -322,14 +318,14 @@ def wrap_pytest_function_for_tracing(pyfuncitem): # python < 3.7.4) runcall's first param is `func`, which means we'd get # an exception if one of the kwargs to testfunction was called `func`. @functools.wraps(testfunction) - def wrapper(*args, **kwargs): + def wrapper(*args, **kwargs) -> None: func = functools.partial(testfunction, *args, **kwargs) _pdb.runcall(func) pyfuncitem.obj = wrapper -def maybe_wrap_pytest_function_for_tracing(pyfuncitem): +def maybe_wrap_pytest_function_for_tracing(pyfuncitem) -> None: """Wrap the given pytestfunct item for tracing support if --trace was given in the command line.""" if pyfuncitem.config.getvalue("trace"): diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 353082c17e1..93c8bc6697c 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -60,6 +60,7 @@ from _pytest.deprecated import check_ispytest from _pytest.deprecated import MARKED_FIXTURE from _pytest.deprecated import YIELD_FIXTURE +from _pytest.main import Session from _pytest.mark import Mark from _pytest.mark import ParameterSet from _pytest.mark.structures import MarkDecorator @@ -78,7 +79,6 @@ if TYPE_CHECKING: - from _pytest.main import Session from _pytest.python import CallSpec2 from _pytest.python import Function from _pytest.python import Metafunc diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 716d5cf783b..d200a6877ff 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -38,7 +38,6 @@ from _pytest.config import UsageError from _pytest.config.argparsing import Parser from _pytest.config.compat import PathAwareHookProxy -from _pytest.fixtures import FixtureManager from _pytest.outcomes import exit from _pytest.pathlib import absolutepath from _pytest.pathlib import bestrelpath @@ -55,6 +54,8 @@ if TYPE_CHECKING: from typing import Self + from _pytest.fixtures import FixtureManager + def pytest_addoption(parser: Parser) -> None: parser.addini( @@ -551,7 +552,7 @@ class Session(nodes.Collector): # Set on the session by runner.pytest_sessionstart. _setupstate: SetupState # Set on the session by fixtures.pytest_sessionstart. - _fixturemanager: FixtureManager + _fixturemanager: "FixtureManager" exitstatus: Union[int, ExitCode] def __init__(self, config: Config) -> None: diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 3567142a6d9..456808063ad 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -31,6 +31,7 @@ from _pytest.deprecated import check_ispytest from _pytest.deprecated import MARKED_FIXTURE from _pytest.outcomes import fail +from _pytest.scope import _ScopeName from _pytest.warning_types import PytestUnknownMarkWarning @@ -430,7 +431,6 @@ def store_mark(obj, mark: Mark, *, stacklevel: int = 2) -> None: # Typing for builtin pytest marks. This is cheating; it gives builtin marks # special privilege, and breaks modularity. But practicality beats purity... if TYPE_CHECKING: - from _pytest.scope import _ScopeName class _SkipMarkDecorator(MarkDecorator): @overload # type: ignore[override,no-overload-impl] diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index e731019715c..aad54f8b325 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -30,6 +30,7 @@ from _pytest._code.code import ExceptionInfo from _pytest._code.code import TerminalRepr from _pytest._code.code import Traceback +from _pytest._code.code import TracebackStyle from _pytest.compat import LEGACY_PATH from _pytest.config import Config from _pytest.config import ConftestImportFailure @@ -49,7 +50,6 @@ from typing import Self # Imported here due to circular import. - from _pytest._code.code import _TracebackStyle from _pytest.main import Session @@ -416,7 +416,7 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: def _repr_failure_py( self, excinfo: ExceptionInfo[BaseException], - style: "Optional[_TracebackStyle]" = None, + style: "Optional[TracebackStyle]" = None, ) -> TerminalRepr: from _pytest.fixtures import FixtureLookupError @@ -474,7 +474,7 @@ def _repr_failure_py( def repr_failure( self, excinfo: ExceptionInfo[BaseException], - style: "Optional[_TracebackStyle]" = None, + style: "Optional[TracebackStyle]" = None, ) -> Union[str, TerminalRepr]: """Return a representation of a collection or test failure. diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index 92d3a297e0d..1e3a09d9678 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -1,18 +1,14 @@ from typing import List from typing import Optional -from typing import TYPE_CHECKING from _pytest import nodes +from _pytest.cacheprovider import Cache from _pytest.config import Config from _pytest.config.argparsing import Parser from _pytest.main import Session from _pytest.reports import TestReport -import pytest -if TYPE_CHECKING: - from _pytest.cacheprovider import Cache - STEPWISE_CACHE_DIR = "cache/stepwise" @@ -37,7 +33,6 @@ def pytest_addoption(parser: Parser) -> None: ) -@pytest.hookimpl def pytest_configure(config: Config) -> None: if config.option.stepwise_skip: # allow --stepwise-skip to work on its own merits. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 643443f08c6..56a9c5d0976 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -41,10 +41,11 @@ import twisted.trial.unittest - _SysExcInfoType = Union[ - Tuple[Type[BaseException], BaseException, types.TracebackType], - Tuple[None, None, None], - ] + +_SysExcInfoType = Union[ + Tuple[Type[BaseException], BaseException, types.TracebackType], + Tuple[None, None, None], +] def pytest_pycollect_makeitem( @@ -228,7 +229,7 @@ def teardown(self) -> None: def startTest(self, testcase: "unittest.TestCase") -> None: pass - def _addexcinfo(self, rawexcinfo: "_SysExcInfoType") -> None: + def _addexcinfo(self, rawexcinfo: _SysExcInfoType) -> None: # Unwrap potential exception info (see twisted trial support below). rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo) try: @@ -264,7 +265,7 @@ def _addexcinfo(self, rawexcinfo: "_SysExcInfoType") -> None: self.__dict__.setdefault("_excinfo", []).append(excinfo) def addError( - self, testcase: "unittest.TestCase", rawexcinfo: "_SysExcInfoType" + self, testcase: "unittest.TestCase", rawexcinfo: _SysExcInfoType ) -> None: try: if isinstance(rawexcinfo[1], exit.Exception): @@ -274,7 +275,7 @@ def addError( self._addexcinfo(rawexcinfo) def addFailure( - self, testcase: "unittest.TestCase", rawexcinfo: "_SysExcInfoType" + self, testcase: "unittest.TestCase", rawexcinfo: _SysExcInfoType ) -> None: self._addexcinfo(rawexcinfo) @@ -287,7 +288,7 @@ def addSkip(self, testcase: "unittest.TestCase", reason: str) -> None: def addExpectedFailure( self, testcase: "unittest.TestCase", - rawexcinfo: "_SysExcInfoType", + rawexcinfo: _SysExcInfoType, reason: str = "", ) -> None: try: diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index f7f780e98f8..fc60ae9ac99 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -28,7 +28,7 @@ if TYPE_CHECKING: - from _pytest._code.code import _TracebackStyle + from _pytest._code.code import TracebackStyle if sys.version_info < (3, 11): from exceptiongroup import ExceptionGroup @@ -925,7 +925,7 @@ def entry(): ) excinfo = pytest.raises(ValueError, mod.entry) - styles: tuple[_TracebackStyle, ...] = ("long", "short") + styles: tuple[TracebackStyle, ...] = ("long", "short") for style in styles: p = FormattedExcinfo(style=style) reprtb = p.repr_traceback(excinfo) @@ -1052,7 +1052,7 @@ def entry(): ) excinfo = pytest.raises(ValueError, mod.entry) - styles: tuple[_TracebackStyle, ...] = ("short", "long", "no") + styles: tuple[TracebackStyle, ...] = ("short", "long", "no") for style in styles: for showlocals in (True, False): repr = excinfo.getrepr(style=style, showlocals=showlocals) From 13f97632c64a733bb8b11c96b423b8480e99246c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Jun 2024 07:03:09 +0000 Subject: [PATCH 0684/1271] build(deps): Bump pytest-trio in /testing/plugins_integration Bumps [pytest-trio](https://github.com/python-trio/pytest-trio) from 0.7.0 to 0.8.0. - [Release notes](https://github.com/python-trio/pytest-trio/releases) - [Commits](https://github.com/python-trio/pytest-trio/compare/v0.7.0...v0.8.0) --- updated-dependencies: - dependency-name: pytest-trio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index cf6e4763dc5..f44a02915f2 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -9,7 +9,7 @@ pytest-html==4.1.1 pytest-mock==3.14.0 pytest-rerunfailures==14.0 pytest-sugar==1.0.0 -pytest-trio==0.7.0 +pytest-trio==0.8.0 pytest-twisted==1.14.1 twisted==24.3.0 pytest-xvfb==3.0.0 From de47b73520fd9b7e41272701d7fd4663357af046 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Fri, 7 Jun 2024 09:49:29 +0300 Subject: [PATCH 0685/1271] unittest: fix assertion errors on unittest reruns This fixes unittest test reruns when using plugins like pytest-rerunfailures. The `instance` property uses AttributeError to check if the instance needs to be initialized, so `del` is the correct way to clear it, not setting to `None`. Regressed in 8.2.2. --- changelog/12424.bugfix.rst | 1 + src/_pytest/unittest.py | 2 +- .../pytest_rerunfailures_integration.py | 11 +++++++++++ tox.ini | 2 +- 4 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 changelog/12424.bugfix.rst create mode 100644 testing/plugins_integration/pytest_rerunfailures_integration.py diff --git a/changelog/12424.bugfix.rst b/changelog/12424.bugfix.rst new file mode 100644 index 00000000000..7ad1126858b --- /dev/null +++ b/changelog/12424.bugfix.rst @@ -0,0 +1 @@ +Fix crash with `assert testcase is not None` assertion failure when re-running unittest tests using plugins like pytest-rerunfailures. Regressed in 8.2.2. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 643443f08c6..ca82ac5c14a 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -222,7 +222,7 @@ def teardown(self) -> None: self._explicit_tearDown() self._explicit_tearDown = None self._obj = None - self._instance = None + del self._instance super().teardown() def startTest(self, testcase: "unittest.TestCase") -> None: diff --git a/testing/plugins_integration/pytest_rerunfailures_integration.py b/testing/plugins_integration/pytest_rerunfailures_integration.py new file mode 100644 index 00000000000..9a13a3279a9 --- /dev/null +++ b/testing/plugins_integration/pytest_rerunfailures_integration.py @@ -0,0 +1,11 @@ +import unittest + + +class MyTestCase(unittest.TestCase): + first_time = True + + def test_fail_the_first_time(self) -> None: + """Regression test for issue #12424.""" + if self.first_time: + type(self).first_time = False + self.fail() diff --git a/tox.ini b/tox.ini index 0a3f0acf5b8..35b335a015d 100644 --- a/tox.ini +++ b/tox.ini @@ -141,7 +141,7 @@ commands = pytest --cov=. simple_integration.py pytest --ds=django_settings simple_integration.py pytest --html=simple.html simple_integration.py - pytest --reruns 5 simple_integration.py + pytest --reruns 5 simple_integration.py pytest_rerunfailures_integration.py pytest pytest_anyio_integration.py pytest pytest_asyncio_integration.py pytest pytest_mock_integration.py From 9bfcca6f4838c854e526afb784820ec2af4f8ca1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 9 Jun 2024 22:49:33 -0300 Subject: [PATCH 0686/1271] [automated] Update plugin list (#12441) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 158 +++++++++++++++++++------------ 1 file changed, 99 insertions(+), 59 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 0f116277997..ab7d28edf0f 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =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-attributes` A plugin that allows users to add attributes to their tests. These attributes can then be referenced by fixtures or the test itself. Jun 06, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A :pypi:`pytest-autocap` automatically capture test & fixture stdout/stderr to files May 15, 2022 N/A pytest (<7.2,>=7.1.2) :pypi:`pytest-autochecklog` automatically check condition and log all the checks Apr 25, 2015 4 - Beta N/A @@ -140,7 +141,7 @@ This list contains 1471 plugins. :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 - :pypi:`pytest-bdd` BDD for pytest Mar 17, 2024 6 - Mature pytest (>=6.2.0) + :pypi:`pytest-bdd` BDD for pytest Jun 04, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports May 20, 2024 N/A pytest >=7.1.3 @@ -149,7 +150,7 @@ This list contains 1471 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 31, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jun 07, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -172,7 +173,7 @@ This list contains 1471 plugins. :pypi:`pytest-board` Local continuous test runner with pytest and watchdog. Jan 20, 2019 N/A N/A :pypi:`pytest-boost-xml` Plugin for pytest to generate boost xml reports Nov 30, 2022 4 - Beta N/A :pypi:`pytest-bootstrap` Mar 04, 2022 N/A N/A - :pypi:`pytest-boto-mock` Thin-wrapper around the mock package for easier use with pytest May 27, 2024 5 - Production/Stable pytest>=8.2.0 + :pypi:`pytest-boto-mock` Thin-wrapper around the mock package for easier use with pytest Jun 05, 2024 5 - Production/Stable pytest>=8.2.0 :pypi:`pytest-bpdb` A py.test plug-in to enable drop to bpdb debugger on test failure. Jan 19, 2015 2 - Pre-Alpha N/A :pypi:`pytest-bq` BigQuery fixtures and fixture factories for Pytest. May 08, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-bravado` Pytest-bravado automatically generates from OpenAPI specification client fixtures. Feb 15, 2022 N/A N/A @@ -185,7 +186,7 @@ This list contains 1471 plugins. :pypi:`pytest_browserstack` Py.test plugin for BrowserStack Jan 27, 2016 4 - Beta N/A :pypi:`pytest-browserstack-local` \`\`py.test\`\` plugin to run \`\`BrowserStackLocal\`\` in background. Feb 09, 2018 N/A N/A :pypi:`pytest-budosystems` Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. May 07, 2023 3 - Alpha pytest - :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Sep 23, 2023 5 - Production/Stable pytest >=7.1.0 + :pypi:`pytest-bug` Pytest plugin for marking tests as a bug Jun 05, 2024 5 - Production/Stable pytest>=8.0.0 :pypi:`pytest-bugtong-tag` pytest-bugtong-tag is a plugin for pytest Jan 16, 2022 N/A N/A :pypi:`pytest-bugzilla` py.test bugzilla integration plugin May 05, 2010 4 - Beta N/A :pypi:`pytest-bugzilla-notifier` A plugin that allows you to execute create, update, and read information from BugZilla bugs Jun 15, 2018 4 - Beta pytest (>=2.9.2) @@ -265,7 +266,7 @@ This list contains 1471 plugins. :pypi:`pytest-collect-pytest-interinfo` A simple plugin to use with pytest Sep 26, 2023 4 - Beta N/A :pypi:`pytest-colordots` Colorizes the progress indicators Oct 06, 2017 5 - Production/Stable N/A :pypi:`pytest-commander` An interactive GUI test runner for PyTest Aug 17, 2021 N/A pytest (<7.0.0,>=6.2.4) - :pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method May 15, 2022 N/A pytest (>=3.6,<8) + :pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method Jun 03, 2024 N/A pytest<9,>=3.6 :pypi:`pytest-compare` pytest plugin for comparing call arguments. Jun 22, 2023 5 - Production/Stable N/A :pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1) :pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A @@ -285,7 +286,7 @@ This list contains 1471 plugins. :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Apr 15, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Jun 04, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 @@ -335,7 +336,7 @@ This list contains 1471 plugins. :pypi:`pytest-dbt` Unit test dbt models with standard python tooling Jun 08, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-dbt-core` Pytest extension for dbt. Aug 25, 2023 N/A pytest >=6.2.5 ; extra == 'test' + :pypi:`pytest-dbt-core` Pytest extension for dbt. Jun 04, 2024 N/A pytest>=6.2.5; extra == "test" :pypi:`pytest-dbt-postgres` Pytest tooling to unittest DBT & Postgres models Jan 02, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) @@ -442,6 +443,7 @@ This list contains 1471 plugins. :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 + :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Jun 07, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 15, 2024 5 - Production/Stable pytest >=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) @@ -484,7 +486,7 @@ This list contains 1471 plugins. :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 :pypi:`pytest-exasol-itde` Feb 15, 2024 N/A pytest (>=7,<9) - :pypi:`pytest-exasol-saas` May 27, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-saas` Jun 07, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -515,7 +517,7 @@ This list contains 1471 plugins. :pypi:`pytest-failed-screen-record` Create a video of the screen when pytest fails Jan 05, 2023 4 - Beta pytest (>=7.1.2d,<8.0.0) :pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A :pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0) - :pypi:`pytest-fail-slow` Fail tests that take too long to run Feb 11, 2024 N/A pytest>=7.0 + :pypi:`pytest-fail-slow` Fail tests that take too long to run Jun 01, 2024 N/A pytest>=7.0 :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A :pypi:`pytest-falcon-client` A package to prevent Dependency Confusion attacks against Yandex. Feb 21, 2024 N/A N/A @@ -561,7 +563,7 @@ This list contains 1471 plugins. :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest - :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd May 15, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jun 05, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-fly` pytest observer Apr 14, 2024 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest @@ -628,13 +630,13 @@ This list contains 1471 plugins. :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-henry` Aug 29, 2023 N/A N/A :pypi:`pytest-hidecaptured` Hide captured output May 04, 2018 4 - Beta pytest (>=2.8.5) - :pypi:`pytest-himark` This plugin aims to create markers automatically based on a json configuration. May 15, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-himark` This plugin aims to create markers automatically based on a json configuration. Jun 05, 2024 4 - Beta pytest>=6.2.0 :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 Jan 14, 2024 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 May 31, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 08, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -703,7 +705,7 @@ This list contains 1471 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Apr 08, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Jun 06, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -715,7 +717,7 @@ This list contains 1471 plugins. :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 30, 2024 3 - Alpha N/A - :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked May 16, 2024 N/A pytest>=7.2.0 + :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 06, 2024 N/A pytest>=7.2.0 :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Mar 27, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest @@ -728,7 +730,7 @@ This list contains 1471 plugins. :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-jtl-collector` A simple plugin to use with pytest May 20, 2024 4 - Beta pytest>=7.2.1 - :pypi:`pytest-jtr` pytest plugin supporting json test report output Apr 15, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-jtr` pytest plugin supporting json test report output Jun 04, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest @@ -798,6 +800,7 @@ This list contains 1471 plugins. :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A + :pypi:`pytest-mark-manage` 用例标签化管理 Jun 07, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Mar 15, 2024 5 - Production/Stable pytest @@ -913,7 +916,7 @@ This list contains 1471 plugins. :pypi:`pytest-only` Use @pytest.mark.only to run a single test May 27, 2024 5 - Production/Stable pytest<9,>=3.6.0 :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 11, 2023 4 - Beta N/A :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A - :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Apr 16, 2020 3 - Alpha pytest (>=4.6) + :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Jun 05, 2024 3 - Alpha pytest>=4.6 :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Oct 01, 2023 N/A pytest :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Jun 02, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest @@ -1022,7 +1025,7 @@ This list contains 1471 plugins. :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-pt` pytest plugin to use \*.pt files as tests May 15, 2024 4 - Beta pytest :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) - :pypi:`pytest-publish` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-publish` Jun 04, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-pudb` Pytest PuDB debugger integration Oct 25, 2018 3 - Alpha pytest (>=2.0) :pypi:`pytest-pumpkin-spice` A pytest plugin that makes your test reporting pumpkin-spiced Sep 18, 2022 4 - Beta N/A :pypi:`pytest-purkinje` py.test plugin for purkinje test runner Oct 28, 2017 2 - Pre-Alpha N/A @@ -1077,13 +1080,13 @@ This list contains 1471 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection May 12, 2024 4 - Beta pytest>=7.4.3 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jun 07, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Mar 14, 2024 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 Dec 06, 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) + :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Jun 05, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) @@ -1151,7 +1154,7 @@ This list contains 1471 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them May 29, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Jun 07, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1176,7 +1179,7 @@ This list contains 1471 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 07, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1186,7 +1189,7 @@ This list contains 1471 plugins. :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 Feb 01, 2024 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. May 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 07, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1263,8 +1266,8 @@ This list contains 1471 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 May 27, 2024 N/A pytest<8,>5.4.0 - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX May 10, 2024 N/A N/A + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jun 03, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jun 05, 2024 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 @@ -1286,7 +1289,7 @@ This list contains 1471 plugins. :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-structlog` Structured logging assertions May 30, 2024 N/A pytest + :pypi:`pytest-structlog` Structured logging assertions Jun 08, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) @@ -1386,8 +1389,9 @@ This list contains 1471 plugins. :pypi:`pytest-tomato` Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-toolbelt` This is just a collection of utilities for pytest, but don't really belong in pytest proper. Aug 12, 2019 3 - Alpha N/A :pypi:`pytest-toolbox` Numerous useful plugins for pytest. Apr 07, 2018 N/A pytest (>=3.5.0) - :pypi:`pytest-toolkit` Useful utils for testing Apr 13, 2024 N/A N/A + :pypi:`pytest-toolkit` Useful utils for testing Jun 07, 2024 N/A N/A :pypi:`pytest-tools` Pytest tools Oct 21, 2022 4 - Beta N/A + :pypi:`pytest-topo` Topological sorting for pytest Jun 05, 2024 N/A pytest>=7.0.0 :pypi:`pytest-tornado` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Jun 17, 2020 5 - Production/Stable pytest (>=3.6) :pypi:`pytest-tornado5` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Nov 16, 2018 5 - Production/Stable pytest (>=3.6) :pypi:`pytest-tornado-yen3` A py.test plugin providing fixtures and markers to simplify testing of asynchronous tornado applications. Oct 15, 2018 5 - Production/Stable N/A @@ -1498,6 +1502,7 @@ This list contains 1471 plugins. :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A + :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jan 08, 2024 5 - Production/Stable pytest (>=4.5.0) :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A @@ -2091,6 +2096,13 @@ This list contains 1471 plugins. pytest plugin to select tests based on attributes similar to the nose-attrib plugin + :pypi:`pytest-attributes` + *last release*: Jun 06, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A plugin that allows users to add attributes to their tests. These attributes can then be referenced by fixtures or the test itself. + :pypi:`pytest-austin` *last release*: Oct 11, 2020, *status*: 4 - Beta, @@ -2253,9 +2265,9 @@ This list contains 1471 plugins. A pytest plugin to repeat the entire test suite in batches. :pypi:`pytest-bdd` - *last release*: Mar 17, 2024, + *last release*: Jun 04, 2024, *status*: 6 - Mature, - *requires*: pytest (>=6.2.0) + *requires*: pytest>=6.2.0 BDD for pytest @@ -2316,7 +2328,7 @@ This list contains 1471 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: May 31, 2024, + *last release*: Jun 07, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2477,7 +2489,7 @@ This list contains 1471 plugins. :pypi:`pytest-boto-mock` - *last release*: May 27, 2024, + *last release*: Jun 05, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=8.2.0 @@ -2568,9 +2580,9 @@ This list contains 1471 plugins. Budo Systems is a martial arts school management system. This module is the Budo Systems Pytest Plugin. :pypi:`pytest-bug` - *last release*: Sep 23, 2023, + *last release*: Jun 05, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.1.0 + *requires*: pytest>=8.0.0 Pytest plugin for marking tests as a bug @@ -3128,9 +3140,9 @@ This list contains 1471 plugins. An interactive GUI test runner for PyTest :pypi:`pytest-common-subject` - *last release*: May 15, 2022, + *last release*: Jun 03, 2024, *status*: N/A, - *requires*: pytest (>=3.6,<8) + *requires*: pytest<9,>=3.6 pytest framework for testing different aspects of a common method @@ -3268,7 +3280,7 @@ This list contains 1471 plugins. Coverage dynamic context support for PyTest, including sub-processes :pypi:`pytest-coveragemarkers` - *last release*: Apr 15, 2024, + *last release*: Jun 04, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -3618,9 +3630,9 @@ This list contains 1471 plugins. A pytest plugin for linting a dbt project's conventions :pypi:`pytest-dbt-core` - *last release*: Aug 25, 2023, + *last release*: Jun 04, 2024, *status*: N/A, - *requires*: pytest >=6.2.5 ; extra == 'test' + *requires*: pytest>=6.2.5; extra == "test" Pytest extension for dbt. @@ -4366,6 +4378,13 @@ This list contains 1471 plugins. pytest plugin with mechanisms for echoing environment variables, package version and generic attributes + :pypi:`pytest-edit` + *last release*: Jun 07, 2024, + *status*: N/A, + *requires*: pytest + + Edit the source code of a failed test with \`pytest --edit\`. + :pypi:`pytest-ekstazi` *last release*: Sep 10, 2022, *status*: N/A, @@ -4661,7 +4680,7 @@ This list contains 1471 plugins. :pypi:`pytest-exasol-saas` - *last release*: May 27, 2024, + *last release*: Jun 07, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -4878,7 +4897,7 @@ This list contains 1471 plugins. A pytest plugin that helps better distinguishing real test failures from setup flakiness. :pypi:`pytest-fail-slow` - *last release*: Feb 11, 2024, + *last release*: Jun 01, 2024, *status*: N/A, *requires*: pytest>=7.0 @@ -5200,7 +5219,7 @@ This list contains 1471 plugins. :pypi:`pytest-fluent` - *last release*: May 15, 2024, + *last release*: Jun 05, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -5669,7 +5688,7 @@ This list contains 1471 plugins. Hide captured output :pypi:`pytest-himark` - *last release*: May 15, 2024, + *last release*: Jun 05, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -5711,7 +5730,7 @@ This list contains 1471 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 31, 2024, + *last release*: Jun 08, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 @@ -6194,7 +6213,7 @@ This list contains 1471 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Apr 08, 2024, + *last release*: Jun 06, 2024, *status*: N/A, *requires*: pytest @@ -6278,7 +6297,7 @@ This list contains 1471 plugins. py.test JIRA integration plugin, using markers :pypi:`pytest-jira-xfail` - *last release*: May 16, 2024, + *last release*: Jun 06, 2024, *status*: N/A, *requires*: pytest>=7.2.0 @@ -6369,7 +6388,7 @@ This list contains 1471 plugins. A simple plugin to use with pytest :pypi:`pytest-jtr` - *last release*: Apr 15, 2024, + *last release*: Jun 04, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -6858,6 +6877,13 @@ This list contains 1471 plugins. UNKNOWN + :pypi:`pytest-mark-manage` + *last release*: Jun 07, 2024, + *status*: N/A, + *requires*: pytest + + 用例标签化管理 + :pypi:`pytest-mark-no-py3` *last release*: May 17, 2019, *status*: N/A, @@ -7664,9 +7690,9 @@ This list contains 1471 plugins. Run object-oriented tests in a simple format :pypi:`pytest-openfiles` - *last release*: Apr 16, 2020, + *last release*: Jun 05, 2024, *status*: 3 - Alpha, - *requires*: pytest (>=4.6) + *requires*: pytest>=4.6 Pytest plugin for detecting inadvertent open file handles @@ -8427,7 +8453,7 @@ This list contains 1471 plugins. Use ptera probes in tests :pypi:`pytest-publish` - *last release*: Jun 01, 2024, + *last release*: Jun 04, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -8812,7 +8838,7 @@ This list contains 1471 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-ranking` - *last release*: May 12, 2024, + *last release*: Jun 07, 2024, *status*: 4 - Beta, *requires*: pytest>=7.4.3 @@ -8854,9 +8880,9 @@ This list contains 1471 plugins. Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal :pypi:`pytest-redis` - *last release*: Apr 19, 2023, + *last release*: Jun 05, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=6.2) + *requires*: pytest>=6.2 Redis fixtures and fixture factories for Pytest. @@ -9330,7 +9356,7 @@ This list contains 1471 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: May 29, 2024, + *last release*: Jun 07, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9505,7 +9531,7 @@ This list contains 1471 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: May 16, 2024, + *last release*: Jun 07, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9575,7 +9601,7 @@ This list contains 1471 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: May 16, 2024, + *last release*: Jun 07, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10114,14 +10140,14 @@ This list contains 1471 plugins. :pypi:`pytest-splunk-addon` - *last release*: May 27, 2024, + *last release*: Jun 03, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: May 10, 2024, + *last release*: Jun 05, 2024, *status*: N/A, *requires*: N/A @@ -10275,7 +10301,7 @@ This list contains 1471 plugins. A Pytest plugin that allows you to loop tests for a user defined amount of time. :pypi:`pytest-structlog` - *last release*: May 30, 2024, + *last release*: Jun 08, 2024, *status*: N/A, *requires*: pytest @@ -10975,7 +11001,7 @@ This list contains 1471 plugins. Numerous useful plugins for pytest. :pypi:`pytest-toolkit` - *last release*: Apr 13, 2024, + *last release*: Jun 07, 2024, *status*: N/A, *requires*: N/A @@ -10988,6 +11014,13 @@ This list contains 1471 plugins. Pytest tools + :pypi:`pytest-topo` + *last release*: Jun 05, 2024, + *status*: N/A, + *requires*: pytest>=7.0.0 + + Topological sorting for pytest + :pypi:`pytest-tornado` *last release*: Jun 17, 2020, *status*: 5 - Production/Stable, @@ -11758,6 +11791,13 @@ This list contains 1471 plugins. OWASP ZAP plugin for py.test. + :pypi:`pytest-zcc` + *last release*: Jun 02, 2024, + *status*: N/A, + *requires*: N/A + + eee + :pypi:`pytest-zebrunner` *last release*: Jan 08, 2024, *status*: 5 - Production/Stable, From 3d91e422293c9fa811348a9f4602632a66d758eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 08:28:57 +0200 Subject: [PATCH 0687/1271] build(deps): Bump pytest-bdd in /testing/plugins_integration (#12442) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 7.1.2 to 7.2.0. - [Release notes](https://github.com/pytest-dev/pytest-bdd/releases) - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/7.1.2...7.2.0) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index f44a02915f2..b3ced6e5c9d 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,7 +1,7 @@ anyio[curio,trio]==4.4.0 django==5.0.6 pytest-asyncio==0.23.7 -pytest-bdd==7.1.2 +pytest-bdd==7.2.0 pytest-cov==5.0.0 pytest-django==4.8.0 pytest-flakes==4.0.5 From 67a570aea9e16ecf2694cea86bec326ce9056f9f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Jun 2024 11:38:33 +0300 Subject: [PATCH 0688/1271] terminalwriter: factor out pygments lexer & formatter selection to own functions We intend to add some more logic here. --- src/_pytest/_io/terminalwriter.py | 116 ++++++++++++++++++------------ 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 5bcd0592778..26344fd315a 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -8,11 +8,17 @@ from typing import Optional from typing import Sequence from typing import TextIO +from typing import TYPE_CHECKING from ..compat import assert_never from .wcwidth import wcswidth +if TYPE_CHECKING: + from pygments.formatter import Formatter + from pygments.lexer import Lexer + + # This code was initially copied from py 1.8.1, file _io/terminalwriter.py. @@ -194,58 +200,76 @@ def _write_source(self, lines: Sequence[str], indents: Sequence[str] = ()) -> No for indent, new_line in zip(indents, new_lines): self.line(indent + new_line) + def _get_pygments_lexer( + self, lexer: Literal["python", "diff"] + ) -> Optional["Lexer"]: + try: + if lexer == "python": + from pygments.lexers.python import PythonLexer + + return PythonLexer() + elif lexer == "diff": + from pygments.lexers.diff import DiffLexer + + return DiffLexer() + else: + assert_never(lexer) + except ModuleNotFoundError: + return None + + def _get_pygments_formatter(self) -> Optional["Formatter"]: + try: + import pygments.util + except ModuleNotFoundError: + return None + + from _pytest.config.exceptions import UsageError + + theme = os.getenv("PYTEST_THEME") + theme_mode = os.getenv("PYTEST_THEME_MODE", "dark") + + try: + from pygments.formatters.terminal import TerminalFormatter + + return TerminalFormatter(bg=theme_mode, style=theme) + + except pygments.util.ClassNotFound as e: + raise UsageError( + f"PYTEST_THEME environment variable had an invalid value: '{theme}'. " + "Only valid pygment styles are allowed." + ) from e + except pygments.util.OptionError as e: + raise UsageError( + f"PYTEST_THEME_MODE environment variable had an invalid value: '{theme_mode}'. " + "The only allowed values are 'dark' and 'light'." + ) from e + def _highlight( self, source: str, lexer: Literal["diff", "python"] = "python" ) -> str: """Highlight the given source if we have markup support.""" - from _pytest.config.exceptions import UsageError - if not source or not self.hasmarkup or not self.code_highlight: return source - try: - from pygments.formatters.terminal import TerminalFormatter + pygments_lexer = self._get_pygments_lexer(lexer) + if pygments_lexer is None: + return source - if lexer == "python": - from pygments.lexers.python import PythonLexer as Lexer - elif lexer == "diff": - from pygments.lexers.diff import DiffLexer as Lexer - else: - assert_never(lexer) - from pygments import highlight - import pygments.util - except ImportError: + pygments_formatter = self._get_pygments_formatter() + if pygments_formatter is None: return source - else: - try: - highlighted: str = highlight( - source, - Lexer(), - TerminalFormatter( - bg=os.getenv("PYTEST_THEME_MODE", "dark"), - style=os.getenv("PYTEST_THEME"), - ), - ) - # pygments terminal formatter may add a newline when there wasn't one. - # We don't want this, remove. - if highlighted[-1] == "\n" and source[-1] != "\n": - highlighted = highlighted[:-1] - - # Some lexers will not set the initial color explicitly - # which may lead to the previous color being propagated to the - # start of the expression, so reset first. - return "\x1b[0m" + highlighted - except pygments.util.ClassNotFound as e: - raise UsageError( - "PYTEST_THEME environment variable had an invalid value: '{}'. " - "Only valid pygment styles are allowed.".format( - os.getenv("PYTEST_THEME") - ) - ) from e - except pygments.util.OptionError as e: - raise UsageError( - "PYTEST_THEME_MODE environment variable had an invalid value: '{}'. " - "The only allowed values are 'dark' and 'light'.".format( - os.getenv("PYTEST_THEME_MODE") - ) - ) from e + + from pygments import highlight + + highlighted: str = highlight(source, pygments_lexer, pygments_formatter) + # pygments terminal formatter may add a newline when there wasn't one. + # We don't want this, remove. + if highlighted[-1] == "\n" and source[-1] != "\n": + highlighted = highlighted[:-1] + + # Some lexers will not set the initial color explicitly + # which may lead to the previous color being propagated to the + # start of the expression, so reset first. + highlighted = "\x1b[0m" + highlighted + + return highlighted From 7ef9da1f02f517d5db758117439edf289087cd7f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 10 Jun 2024 11:41:10 +0300 Subject: [PATCH 0689/1271] terminalwriter: improve `PYTEST_THEME`, `PYTEST_THEME_MODE` usage errors --- src/_pytest/_io/terminalwriter.py | 8 ++++---- testing/test_terminal.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 26344fd315a..083c18232ff 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -235,13 +235,13 @@ def _get_pygments_formatter(self) -> Optional["Formatter"]: except pygments.util.ClassNotFound as e: raise UsageError( - f"PYTEST_THEME environment variable had an invalid value: '{theme}'. " - "Only valid pygment styles are allowed." + f"PYTEST_THEME environment variable has an invalid value: '{theme}'. " + "Hint: See available pygments styles with `pygmentize -L styles`." ) from e except pygments.util.OptionError as e: raise UsageError( - f"PYTEST_THEME_MODE environment variable had an invalid value: '{theme_mode}'. " - "The only allowed values are 'dark' and 'light'." + f"PYTEST_THEME_MODE environment variable has an invalid value: '{theme_mode}'. " + "The allowed values are 'dark' (default) and 'light'." ) from e def _highlight( diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 6cd4a1827d2..ce9fdc50c8a 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2609,8 +2609,8 @@ def test_foo(): monkeypatch.setenv("PYTEST_THEME", "invalid") result = pytester.runpytest_subprocess("--color=yes") result.stderr.fnmatch_lines( - "ERROR: PYTEST_THEME environment variable had an invalid value: 'invalid'. " - "Only valid pygment styles are allowed." + "ERROR: PYTEST_THEME environment variable has an invalid value: 'invalid'. " + "Hint: See available pygments styles with `pygmentize -L styles`." ) def test_code_highlight_invalid_theme_mode( @@ -2625,8 +2625,8 @@ def test_foo(): monkeypatch.setenv("PYTEST_THEME_MODE", "invalid") result = pytester.runpytest_subprocess("--color=yes") result.stderr.fnmatch_lines( - "ERROR: PYTEST_THEME_MODE environment variable had an invalid value: 'invalid'. " - "The only allowed values are 'dark' and 'light'." + "ERROR: PYTEST_THEME_MODE environment variable has an invalid value: 'invalid'. " + "The allowed values are 'dark' (default) and 'light'." ) From 23ca9798f7a119615017c177fc884e2f77c23abc Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 11 Jun 2024 18:36:20 +0300 Subject: [PATCH 0690/1271] doc: fix broken code blocks (#12449) Caused by 4588653b2497ed25976b7aaff225b889fb476756. The issue was fixed in https://github.com/astral-sh/ruff/issues/11577, so won't trigger again. Fix #12437. --- src/_pytest/capture.py | 4 ++++ src/_pytest/config/__init__.py | 1 + src/_pytest/monkeypatch.py | 1 + src/_pytest/pytester.py | 3 +++ 4 files changed, 9 insertions(+) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 198d4195020..89a938d5416 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -983,6 +983,7 @@ def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]: Returns an instance of :class:`CaptureFixture[str] `. Example: + .. code-block:: python def test_output(capsys): @@ -1010,6 +1011,7 @@ def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, Returns an instance of :class:`CaptureFixture[bytes] `. Example: + .. code-block:: python def test_output(capsysbinary): @@ -1037,6 +1039,7 @@ def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]: Returns an instance of :class:`CaptureFixture[str] `. Example: + .. code-block:: python def test_system_echo(capfd): @@ -1064,6 +1067,7 @@ def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, N Returns an instance of :class:`CaptureFixture[bytes] `. Example: + .. code-block:: python def test_system_echo(capfdbinary): diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 287fac463cb..058aaa1ff30 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1735,6 +1735,7 @@ def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: can be used to explicitly use the global verbosity level. Example: + .. code-block:: ini # content of pytest.ini diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index 3f398df76b1..f498d60df14 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -142,6 +142,7 @@ def context(cls) -> Generator["MonkeyPatch", None, None]: which undoes any patching done inside the ``with`` block upon exit. Example: + .. code-block:: python import functools diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index f9ab007a4d1..42f50900ada 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -805,6 +805,7 @@ def makefile(self, ext: str, *args: str, **kwargs: str) -> Path: The first created file. Examples: + .. code-block:: python pytester.makefile(".txt", "line1", "line2") @@ -858,6 +859,7 @@ def makepyfile(self, *args, **kwargs) -> Path: existing files. Examples: + .. code-block:: python def test_something(pytester): @@ -877,6 +879,7 @@ def maketxtfile(self, *args, **kwargs) -> Path: existing files. Examples: + .. code-block:: python def test_something(pytester): From ff7598013581b5820dd83253df7d0cc46f785020 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Jun 2024 12:36:39 -0300 Subject: [PATCH 0691/1271] [pre-commit.ci] pre-commit autoupdate (#12447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.7 → v0.4.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.7...v0.4.8) - [github.com/asottile/pyupgrade: v3.15.2 → v3.16.0](https://github.com/asottile/pyupgrade/compare/v3.15.2...v3.16.0) * Apply pyupgrade automatically --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 4 ++-- src/_pytest/cacheprovider.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fb583b11126..42fbc31ea12 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.7" + rev: "v0.4.8" hooks: - id: ruff args: ["--fix"] @@ -44,7 +44,7 @@ repos: # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version additional_dependencies: ["tox>=4.9"] - repo: https://github.com/asottile/pyupgrade - rev: v3.15.2 + rev: v3.16.0 hooks: - id: pyupgrade stages: [manual] diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 7e00135a4c1..8ad36f9b91c 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -221,9 +221,9 @@ def _ensure_cache_dir_and_supporting_files(self) -> None: os.umask(umask) path.chmod(0o777 - umask) - with open(path.joinpath("README.md"), "xt", encoding="UTF-8") as f: + with open(path.joinpath("README.md"), "x", encoding="UTF-8") as f: f.write(README_CONTENT) - with open(path.joinpath(".gitignore"), "xt", encoding="UTF-8") as f: + with open(path.joinpath(".gitignore"), "x", encoding="UTF-8") as f: f.write("# Created by pytest automatically.\n*\n") with open(path.joinpath("CACHEDIR.TAG"), "xb") as f: f.write(CACHEDIR_TAG_CONTENT) From 037aaa7d45e0ec8385676f8a48563e4d620691c2 Mon Sep 17 00:00:00 2001 From: Stavros Ntentos <133706+stdedos@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:18:40 +0300 Subject: [PATCH 0692/1271] Update `contact.rst`: Update Matrix link --- doc/en/contact.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/contact.rst b/doc/en/contact.rst index 68efef522ff..44957a0d4a8 100644 --- a/doc/en/contact.rst +++ b/doc/en/contact.rst @@ -22,9 +22,9 @@ Contact channels requests to GitHub. - ``#pytest`` `on irc.libera.chat `_ IRC - channel for random questions (using an IRC client, `via webchat - `_, or `via Matrix - `_). + channel for random questions (using an IRC client, or `via webchat + `) +- ``#pytest`` `on Matrix https://matrix.to/#/#pytest:matrix.org>`. .. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues From 2effd8cb2c91abf4782201c431f19d0b22517920 Mon Sep 17 00:00:00 2001 From: neutraljump <162650677+neutraljump@users.noreply.github.com> Date: Thu, 13 Jun 2024 21:39:02 +0930 Subject: [PATCH 0693/1271] Docs: clean up various documentation pages (#12451) * Change Contribution doc title to match sidebar * Rearrange sentence for clarity * Update backwards-compatibility.rst some minor grammar changes * Update pythonpath.rst fixed some gramatical errors * Update AUTHORS * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update doc/en/explanation/pythonpath.rst From a quick overview it looks like lowercase is more consistent, although some pages do use `pytest` in code blocks Co-authored-by: Bruno Oliveira --------- Co-authored-by: Mackerello <82668740+Mackerello@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bruno Oliveira --- AUTHORS | 2 ++ CONTRIBUTING.rst | 4 ++-- doc/en/backwards-compatibility.rst | 28 ++++++++++++---------------- doc/en/explanation/pythonpath.rst | 16 ++++++++-------- 4 files changed, 24 insertions(+), 26 deletions(-) diff --git a/AUTHORS b/AUTHORS index 0560caf721b..80b6d5157cd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -259,6 +259,7 @@ Marc Bresson Marco Gorelli Mark Abramowitz Mark Dickinson +Mark Vong Marko Pacak Markus Unterwaditzer Martijn Faassen @@ -301,6 +302,7 @@ Nicholas Devenish Nicholas Murphy Niclas Olofsson Nicolas Delaby +Nico Vidal Nikolay Kondratyev Nipunn Koorapati Oleg Pidsadnyi diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 0bf440da261..12e2b18bb52 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,5 +1,5 @@ ============================ -Contribution getting started +Contributing ============================ Contributions are highly welcomed and appreciated. Every little bit of help counts, @@ -124,7 +124,7 @@ For example: Submitting Plugins to pytest-dev -------------------------------- -Pytest development of the core, some plugins and support code happens +Development of the pytest core, support code, and some plugins happens in repositories living under the ``pytest-dev`` organisations: - `pytest-dev on GitHub `_ diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index e04e64a76f9..c0feb833ce1 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -5,30 +5,26 @@ Backwards Compatibility Policy .. versionadded: 6.0 -pytest is actively evolving and is a project that has been decades in the making, -we keep learning about new and better structures to express different details about testing. +Pytest is an actively evolving project that has been decades in the making. +We keep learning about new and better structures to express different details about testing. -While we implement those modifications we try to ensure an easy transition and don't want to impose unnecessary churn on our users and community/plugin authors. +While we implement those modifications, we try to ensure an easy transition and don't want to impose unnecessary churn on our users and community/plugin authors. As of now, pytest considers multiple types of backward compatibility transitions: -a) trivial: APIs which trivially translate to the new mechanism, - and do not cause problematic changes. +a) trivial: APIs that trivially translate to the new mechanism and do not cause problematic changes. - We try to support those indefinitely while encouraging users to switch to newer/better mechanisms through documentation. + We try to support those indefinitely while encouraging users to switch to newer or better mechanisms through documentation. -b) transitional: the old and new API don't conflict - and we can help users transition by using warnings, while supporting both for a prolonged time. +b) transitional: the old and new APIs don't conflict, and we can help users transition by using warnings while supporting both for a prolonged period of time. - We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0). + We will only start the removal of deprecated functionality in major releases (e.g., if we deprecate something in 3.0, we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g., if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0). A deprecated feature scheduled to be removed in major version X will use the warning class `PytestRemovedInXWarning` (a subclass of :class:`~pytest.PytestDeprecationWarning`). - When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn `PytestRemovedInXWarning` (e.g. `PytestRemovedIn4Warning`) into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed. + When the deprecation expires (e.g., 4.0 is released), we won't remove the deprecated functionality immediately but will use the standard warning filters to turn `PytestRemovedInXWarning` (e.g., `PytestRemovedIn4Warning`) into **errors** by default. This approach makes it explicit that removal is imminent and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g., 4.1), the feature will be effectively removed. - -c) true breakage: should only be considered when normal transition is unreasonably unsustainable and would offset important development/features by years. - In addition, they should be limited to APIs where the number of actual users is very small (for example only impacting some plugins), and can be coordinated with the community in advance. +c) True breakage should only be considered when a normal transition is unreasonably unsustainable and would offset important developments or features by years. In addition, they should be limited to APIs where the number of actual users is very small (for example, only impacting some plugins) and can be coordinated with the community in advance. Examples for such upcoming changes: @@ -62,11 +58,11 @@ Focus primary on smooth transition - stance (pre 6.0) Keeping backwards compatibility has a very high priority in the pytest project. Although we have deprecated functionality over the years, most of it is still supported. All deprecations in pytest were done because simpler or more efficient ways of accomplishing the same tasks have emerged, making the old way of doing things unnecessary. -With the pytest 3.0 release we introduced a clear communication scheme for when we will actually remove the old busted joint and politely ask you to use the new hotness instead, while giving you enough time to adjust your tests or raise concerns if there are valid reasons to keep deprecated functionality around. +With the pytest 3.0 release, we introduced a clear communication scheme for when we will actually remove the old busted joint and politely ask you to use the new hotness instead, while giving you enough time to adjust your tests or raise concerns if there are valid reasons to keep deprecated functionality around. -To communicate changes we issue deprecation warnings using a custom warning hierarchy (see :ref:`internal-warnings`). These warnings may be suppressed using the standard means: ``-W`` command-line flag or ``filterwarnings`` ini options (see :ref:`warnings`), but we suggest to use these sparingly and temporarily, and heed the warnings when possible. +To communicate changes, we issue deprecation warnings using a custom warning hierarchy (see :ref:`internal-warnings`). These warnings may be suppressed using the standard means: ``-W`` command-line flag or ``filterwarnings`` ini options (see :ref:`warnings`), but we suggest to use these sparingly and temporarily, and heed the warnings when possible. -We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0 we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0). +We will only start the removal of deprecated functionality in major releases (e.g. if we deprecate something in 3.0, we will start to remove it in 4.0), and keep it around for at least two minor releases (e.g. if we deprecate something in 3.9 and 4.0 is the next release, we start to remove it in 5.0, not in 4.0). When the deprecation expires (e.g. 4.0 is released), we won't remove the deprecated functionality immediately, but will use the standard warning filters to turn them into **errors** by default. This approach makes it explicit that removal is imminent, and still gives you time to turn the deprecated feature into a warning instead of an error so it can be dealt with in your own time. In the next minor release (e.g. 4.1), the feature will be effectively removed. diff --git a/doc/en/explanation/pythonpath.rst b/doc/en/explanation/pythonpath.rst index 33eba86b57a..d0314a6dbcd 100644 --- a/doc/en/explanation/pythonpath.rst +++ b/doc/en/explanation/pythonpath.rst @@ -8,15 +8,15 @@ pytest import mechanisms and ``sys.path``/``PYTHONPATH`` Import modes ------------ -pytest as a testing framework needs to import test modules and ``conftest.py`` files for execution. +pytest as a testing framework that needs to import test modules and ``conftest.py`` files for execution. -Importing files in Python is a non-trivial processes, so aspects of the +Importing files in Python is a non-trivial process, so aspects of the import process can be controlled through the ``--import-mode`` command-line flag, which can assume these values: .. _`import-mode-prepend`: -* ``prepend`` (default): the directory path containing each module will be inserted into the *beginning* +* ``prepend`` (default): The directory path containing each module will be inserted into the *beginning* of :py:data:`sys.path` if not already there, and then imported with the :func:`importlib.import_module ` function. @@ -34,7 +34,7 @@ these values: * ``append``: the directory containing each module is appended to the end of :py:data:`sys.path` if not already there, and imported with :func:`importlib.import_module `. - This better allows to run test modules against installed versions of a package even if the + This better allows users to run test modules against installed versions of a package even if the package under test has the same import root. For example: :: @@ -45,7 +45,7 @@ these values: the tests will run against the installed version of ``pkg_under_test`` when ``--import-mode=append`` is used whereas - with ``prepend`` they would pick up the local version. This kind of confusion is why + with ``prepend``, they would pick up the local version. This kind of confusion is why we advocate for using :ref:`src-layouts `. Same as ``prepend``, requires test module names to be unique when the test directory tree is @@ -67,7 +67,7 @@ these values: are not importable. The recommendation in this case it to place testing utility modules together with the application/library code, for example ``app.testing.helpers``. - Important: by "test utility modules" we mean functions/classes which are imported by + Important: by "test utility modules", we mean functions/classes which are imported by other tests directly; this does not include fixtures, which should be placed in ``conftest.py`` files, along with the test modules, and are discovered automatically by pytest. @@ -76,8 +76,8 @@ these values: 1. Given a certain module path, for example ``tests/core/test_models.py``, derives a canonical name like ``tests.core.test_models`` and tries to import it. - For non-test modules this will work if they are accessible via :py:data:`sys.path`, so - for example ``.env/lib/site-packages/app/core.py`` will be importable as ``app.core``. + For non-test modules, this will work if they are accessible via :py:data:`sys.path`. So + for example, ``.env/lib/site-packages/app/core.py`` will be importable as ``app.core``. This is happens when plugins import non-test modules (for example doctesting). If this step succeeds, the module is returned. From 5037f8d1145b87b0008902487ace44653692374b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 16 Jun 2024 05:24:06 +0000 Subject: [PATCH 0694/1271] [automated] Update plugin list (#12462) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 126 ++++++++++++++++--------------- 1 file changed, 67 insertions(+), 59 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index ab7d28edf0f..83d074e7f03 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -150,7 +150,7 @@ This list contains 1476 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jun 07, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jun 12, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -160,7 +160,7 @@ This list contains 1476 plugins. :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) - :pypi:`pytest-bisect-tests` Find tests leaking state and affecting other Mar 25, 2024 N/A N/A + :pypi:`pytest-bisect-tests` Find tests leaking state and affecting other Jun 09, 2024 N/A N/A :pypi:`pytest-black` A pytest plugin to enable format checking with black Oct 05, 2020 4 - Beta N/A :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) @@ -222,7 +222,7 @@ This list contains 1476 plugins. :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<9,>=7.0 - :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Mar 12, 2024 N/A N/A + :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Jun 10, 2024 N/A N/A :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 20, 2024 N/A N/A :pypi:`pytest-ch-framework` My pytest framework Apr 17, 2024 N/A pytest==8.0.1 @@ -261,12 +261,11 @@ This list contains 1476 plugins. :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-interface-info-plugin` Get executed interface information in pytest interface automation framework Sep 25, 2023 4 - Beta N/A - :pypi:`pytest-collect-jmeter-report-tests` A simple plugin to use with pytest May 20, 2024 4 - Beta pytest>=7.2.1 :pypi:`pytest-collector` Python package for collecting pytest. Aug 02, 2022 N/A pytest (>=7.0,<8.0) :pypi:`pytest-collect-pytest-interinfo` A simple plugin to use with pytest Sep 26, 2023 4 - Beta N/A :pypi:`pytest-colordots` Colorizes the progress indicators Oct 06, 2017 5 - Production/Stable N/A :pypi:`pytest-commander` An interactive GUI test runner for PyTest Aug 17, 2021 N/A pytest (<7.0.0,>=6.2.4) - :pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method Jun 03, 2024 N/A pytest<9,>=3.6 + :pypi:`pytest-common-subject` pytest framework for testing different aspects of a common method Jun 12, 2024 N/A pytest<9,>=3.6 :pypi:`pytest-compare` pytest plugin for comparing call arguments. Jun 22, 2023 5 - Production/Stable N/A :pypi:`pytest-concurrent` Concurrently execute test cases with multithread, multiprocess and gevent Jan 12, 2019 4 - Beta pytest (>=3.1.1) :pypi:`pytest-config` Base configurations and utilities for developing your Python project test suite with pytest. Nov 07, 2014 5 - Production/Stable N/A @@ -314,7 +313,7 @@ This list contains 1476 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. May 25, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Jun 11, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -366,15 +365,16 @@ This list contains 1476 plugins. :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. May 11, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 :pypi:`pytest-discover` Pytest plugin to record discovered tests in a file Mar 26, 2024 N/A pytest - :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. May 29, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. Jun 09, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-ditto-pandas` pytest-ditto plugin for pandas snapshots. May 29, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-ditto-pyarrow` pytest-ditto plugin for pyarrow tables. Jun 09, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-django` A Django plugin for pytest. Jan 30, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A :pypi:`pytest-django-casperjs` Integrate CasperJS with your django tests as a pytest fixture. Mar 15, 2015 2 - Pre-Alpha N/A :pypi:`pytest-django-class` A pytest plugin for running django in class-scoped fixtures Aug 08, 2023 4 - Beta N/A - :pypi:`pytest-django-docker-pg` May 21, 2024 5 - Production/Stable pytest<9.0.0,>=7.0.0 + :pypi:`pytest-django-docker-pg` Jun 13, 2024 5 - Production/Stable pytest<9.0.0,>=7.0.0 :pypi:`pytest-django-dotenv` Pytest plugin used to setup environment variables with django-dotenv Nov 26, 2019 4 - Beta pytest (>=2.6.0) :pypi:`pytest-django-factories` Factories for your Django models that can be used as Pytest fixtures. Nov 12, 2020 4 - Beta N/A :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 @@ -443,7 +443,7 @@ This list contains 1476 plugins. :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 - :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Jun 07, 2024 N/A pytest + :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Jun 09, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 15, 2024 5 - Production/Stable pytest >=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) @@ -636,7 +636,7 @@ This list contains 1476 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jun 08, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 12, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -678,6 +678,7 @@ This list contains 1476 plugins. :pypi:`pytest-image-diff` Mar 09, 2023 3 - Alpha pytest :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-infinity` Jun 09, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-influxdb` Plugin for influxdb and pytest integration. Apr 20, 2021 N/A N/A :pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A @@ -729,7 +730,6 @@ This list contains 1476 plugins. :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-jtl-collector` A simple plugin to use with pytest May 20, 2024 4 - Beta pytest>=7.2.1 :pypi:`pytest-jtr` pytest plugin supporting json test report output Jun 04, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest @@ -824,7 +824,7 @@ This list contains 1476 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 Feb 12, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest - :pypi:`pytest-mh` Pytest multihost plugin May 28, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Jun 13, 2024 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) @@ -877,7 +877,7 @@ This list contains 1476 plugins. :pypi:`pytest-ndb` pytest notebook debugger Apr 28, 2024 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-neos` Pytest plugin for neos May 01, 2024 1 - Planning N/A + :pypi:`pytest-neos` Pytest plugin for neos Jun 11, 2024 1 - Planning N/A :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Mar 07, 2024 N/A pytest <7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest @@ -886,7 +886,7 @@ This list contains 1476 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies May 20, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jun 11, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Apr 11, 2024 N/A N/A @@ -950,7 +950,7 @@ This list contains 1476 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-patterns` pytest plugin to make testing complicated long string output easy to write and easy to debug Jun 14, 2024 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 @@ -1037,7 +1037,7 @@ This list contains 1476 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 Apr 30, 2024 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Jun 12, 2024 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) @@ -1059,7 +1059,7 @@ This list contains 1476 plugins. :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 30, 2024 4 - Beta pytest<9.0.0,>=7.2.2 :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 Nov 29, 2023 5 - Production/Stable pytest >=6.0 + :pypi:`pytest-qgis` A pytest plugin for testing QGIS python plugins Jun 14, 2024 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 Feb 07, 2024 5 - Production/Stable pytest @@ -1086,7 +1086,7 @@ This list contains 1476 plugins. :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 Dec 06, 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. Jun 05, 2024 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Jun 10, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) @@ -1267,7 +1267,7 @@ This list contains 1476 plugins. :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 Jun 03, 2024 N/A pytest<8,>5.4.0 - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jun 05, 2024 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jun 14, 2024 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 @@ -1289,7 +1289,7 @@ This list contains 1476 plugins. :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-structlog` Structured logging assertions Jun 08, 2024 N/A pytest + :pypi:`pytest-structlog` Structured logging assertions Jun 09, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) @@ -1461,7 +1461,7 @@ This list contains 1476 plugins. :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Nov 13, 2023 N/A pytest >= 7.0.0 + :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Jun 08, 2024 N/A pytest>=7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 28, 2024 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A @@ -1499,6 +1499,7 @@ This list contains 1476 plugins. :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Mar 30, 2024 N/A pytest<8.0.0,>=7.2.2 + :pypi:`pytest-youqu-playwright` pytest-youqu-playwright Jun 12, 2024 N/A pytest :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A @@ -2153,7 +2154,7 @@ This list contains 1476 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: May 31, 2024, + *last release*: Jun 10, 2024, *status*: N/A, *requires*: N/A @@ -2328,7 +2329,7 @@ This list contains 1476 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jun 07, 2024, + *last release*: Jun 12, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2398,7 +2399,7 @@ This list contains 1476 plugins. Provides a mock fixture for python bigquery client :pypi:`pytest-bisect-tests` - *last release*: Mar 25, 2024, + *last release*: Jun 09, 2024, *status*: N/A, *requires*: N/A @@ -2832,7 +2833,7 @@ This list contains 1476 plugins. Check links in files :pypi:`pytest-checklist` - *last release*: Mar 12, 2024, + *last release*: Jun 10, 2024, *status*: N/A, *requires*: N/A @@ -3104,13 +3105,6 @@ This list contains 1476 plugins. Get executed interface information in pytest interface automation framework - :pypi:`pytest-collect-jmeter-report-tests` - *last release*: May 20, 2024, - *status*: 4 - Beta, - *requires*: pytest>=7.2.1 - - A simple plugin to use with pytest - :pypi:`pytest-collector` *last release*: Aug 02, 2022, *status*: N/A, @@ -3140,7 +3134,7 @@ This list contains 1476 plugins. An interactive GUI test runner for PyTest :pypi:`pytest-common-subject` - *last release*: Jun 03, 2024, + *last release*: Jun 12, 2024, *status*: N/A, *requires*: pytest<9,>=3.6 @@ -3476,7 +3470,7 @@ This list contains 1476 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: May 25, 2024, + *last release*: Jun 11, 2024, *status*: 4 - Beta, *requires*: pytest @@ -3840,7 +3834,7 @@ This list contains 1476 plugins. Pytest plugin to record discovered tests in a file :pypi:`pytest-ditto` - *last release*: May 29, 2024, + *last release*: Jun 09, 2024, *status*: 4 - Beta, *requires*: pytest>=3.5.0 @@ -3853,6 +3847,13 @@ This list contains 1476 plugins. pytest-ditto plugin for pandas snapshots. + :pypi:`pytest-ditto-pyarrow` + *last release*: Jun 09, 2024, + *status*: 4 - Beta, + *requires*: pytest>=3.5.0 + + pytest-ditto plugin for pyarrow tables. + :pypi:`pytest-django` *last release*: Jan 30, 2024, *status*: 5 - Production/Stable, @@ -3896,7 +3897,7 @@ This list contains 1476 plugins. A pytest plugin for running django in class-scoped fixtures :pypi:`pytest-django-docker-pg` - *last release*: May 21, 2024, + *last release*: Jun 13, 2024, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=7.0.0 @@ -4379,7 +4380,7 @@ This list contains 1476 plugins. pytest plugin with mechanisms for echoing environment variables, package version and generic attributes :pypi:`pytest-edit` - *last release*: Jun 07, 2024, + *last release*: Jun 09, 2024, *status*: N/A, *requires*: pytest @@ -5730,7 +5731,7 @@ This list contains 1476 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 08, 2024, + *last release*: Jun 12, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 @@ -6023,6 +6024,13 @@ This list contains 1476 plugins. an incremental test runner (pytest plugin) + :pypi:`pytest-infinity` + *last release*: Jun 09, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.0.0 + + + :pypi:`pytest-influxdb` *last release*: Apr 20, 2021, *status*: N/A, @@ -6380,13 +6388,6 @@ This list contains 1476 plugins. A pytest plugin to perform JSONSchema validations - :pypi:`pytest-jtl-collector` - *last release*: May 20, 2024, - *status*: 4 - Beta, - *requires*: pytest>=7.2.1 - - A simple plugin to use with pytest - :pypi:`pytest-jtr` *last release*: Jun 04, 2024, *status*: N/A, @@ -7046,7 +7047,7 @@ This list contains 1476 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: May 28, 2024, + *last release*: Jun 13, 2024, *status*: N/A, *requires*: pytest @@ -7417,7 +7418,7 @@ This list contains 1476 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-neos` - *last release*: May 01, 2024, + *last release*: Jun 11, 2024, *status*: 1 - Planning, *requires*: N/A @@ -7480,7 +7481,7 @@ This list contains 1476 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: May 20, 2024, + *last release*: Jun 11, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -7928,7 +7929,7 @@ This list contains 1476 plugins. A contextmanager pytest fixture for handling multiple mock patches :pypi:`pytest-patterns` - *last release*: Nov 17, 2023, + *last release*: Jun 14, 2024, *status*: 4 - Beta, *requires*: N/A @@ -8537,7 +8538,7 @@ This list contains 1476 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Apr 30, 2024, + *last release*: Jun 12, 2024, *status*: N/A, *requires*: pytest @@ -8691,9 +8692,9 @@ This list contains 1476 plugins. Pytest plugin for uploading test results to your QA Touch Testrun. :pypi:`pytest-qgis` - *last release*: Nov 29, 2023, + *last release*: Jun 14, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6.0 + *requires*: pytest>=6.0 A pytest plugin for testing QGIS python plugins @@ -8880,7 +8881,7 @@ This list contains 1476 plugins. Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal :pypi:`pytest-redis` - *last release*: Jun 05, 2024, + *last release*: Jun 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.2 @@ -10147,7 +10148,7 @@ This list contains 1476 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Jun 05, 2024, + *last release*: Jun 14, 2024, *status*: N/A, *requires*: N/A @@ -10301,7 +10302,7 @@ This list contains 1476 plugins. A Pytest plugin that allows you to loop tests for a user defined amount of time. :pypi:`pytest-structlog` - *last release*: Jun 08, 2024, + *last release*: Jun 09, 2024, *status*: N/A, *requires*: pytest @@ -11505,9 +11506,9 @@ This list contains 1476 plugins. Selenium webdriver fixture for py.test :pypi:`pytest-webtest-extras` - *last release*: Nov 13, 2023, + *last release*: Jun 08, 2024, *status*: N/A, - *requires*: pytest >= 7.0.0 + *requires*: pytest>=7.0.0 Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. @@ -11770,6 +11771,13 @@ This list contains 1476 plugins. Pytest plugin to test the YLS as a whole. + :pypi:`pytest-youqu-playwright` + *last release*: Jun 12, 2024, + *status*: N/A, + *requires*: pytest + + pytest-youqu-playwright + :pypi:`pytest-yuk` *last release*: Mar 26, 2021, *status*: N/A, From 80b7657b2a1255d29978b7ead4006821ce8e3b65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:58:23 +0200 Subject: [PATCH 0695/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.8.14 to 1.9.0 (#12464) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.8.14 to 1.9.0. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.8.14...v1.9.0) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 640a0f1c281..f5ea4d39764 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.8.14 + uses: pypa/gh-action-pypi-publish@v1.9.0 - name: Push tag run: | From fe4961afae91f3c259b30690eb39cefe867acea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Mon, 17 Jun 2024 17:44:14 +0200 Subject: [PATCH 0696/1271] Modernize the skipped `test_issue_9765` regression test (#12468) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🚑 Explicitly set encoding @ `subprocess.run()` This invocation is present in the `test_issue_9765` regression test that is always skipped unconditionally, resulting in the `EncodingWarning` never manifesting itself in CI or development environments of the contributors. * Change `setup.py` call w/ `pip install` @ tests Using this CLI interface has been deprecated in `setuptools` [[1]]. [1]: https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html --- testing/acceptance_test.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index ac7fab3d27a..0f3b35036d7 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1464,14 +1464,21 @@ def my_fixture(self, request): } ) - subprocess.run([sys.executable, "setup.py", "develop"], check=True) + subprocess.run( + [sys.executable, "-Im", "pip", "install", "-e", "."], + check=True, + ) try: # We are using subprocess.run rather than pytester.run on purpose. # pytester.run is adding the current directory to PYTHONPATH which avoids # the bug. We also use pytest rather than python -m pytest for the same # PYTHONPATH reason. subprocess.run( - ["pytest", "my_package"], capture_output=True, check=True, text=True + ["pytest", "my_package"], + capture_output=True, + check=True, + encoding="utf-8", + text=True, ) except subprocess.CalledProcessError as exc: raise AssertionError( From 49374ec7a0a0cc945e0d6b34e34ad493b837125b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Tue, 18 Jun 2024 11:21:25 +0200 Subject: [PATCH 0697/1271] =?UTF-8?q?=F0=9F=9A=91=20Clarify=20patch=20cond?= =?UTF-8?q?ition=20for=20doctest=20finder=20hack=20(#12471)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was a regression caused by #12431 that excluded the patch on broken CPython patch version ranges 3.11.0–3.11.8 and 3.12.0–3.12.2. This change fixes that by adjusting the patching conditional clause to include said versions. Closes #12430. Co-authored-by: Florian Bruhin --- src/_pytest/doctest.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 23ad7a7a979..e61694d553f 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -505,7 +505,13 @@ def collect(self) -> Iterable[DoctestItem]: import doctest class MockAwareDocTestFinder(doctest.DocTestFinder): - if sys.version_info < (3, 11): + py_ver_info_minor = sys.version_info[:2] + is_find_lineno_broken = ( + py_ver_info_minor < (3, 11) + or (py_ver_info_minor == (3, 11) and sys.version_info.micro < 9) + or (py_ver_info_minor == (3, 12) and sys.version_info.micro < 3) + ) + if is_find_lineno_broken: def _find_lineno(self, obj, source_lines): """On older Pythons, doctest code does not take into account From 807d16abfdc62443201c23318ee196377e249fc5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 08:29:53 -0300 Subject: [PATCH 0698/1271] [pre-commit.ci] pre-commit autoupdate (#12470) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.8 → v0.4.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.8...v0.4.9) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 42fbc31ea12..5a3d75ff874 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.8" + rev: "v0.4.9" hooks: - id: ruff args: ["--fix"] From 76f3f3da00b67ff5fc8b84f111eae7bfa4436dc1 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 15 Jan 2024 12:20:23 +0100 Subject: [PATCH 0699/1271] fix #11797: be more lenient on SequenceLike approx this needs a validation as it allows partially implemented sequences --- changelog/11797.bugfix.rst | 1 + src/_pytest/python_api.py | 16 ++++++++++----- testing/python/approx.py | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 changelog/11797.bugfix.rst diff --git a/changelog/11797.bugfix.rst b/changelog/11797.bugfix.rst new file mode 100644 index 00000000000..94b72da00fd --- /dev/null +++ b/changelog/11797.bugfix.rst @@ -0,0 +1 @@ +:func:`pytest.approx` now correctly handles :class:`Sequence `-like objects. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 9b17e5cb786..bfc8dc33445 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -129,6 +129,8 @@ def _recursive_sequence_map(f, x): if isinstance(x, (list, tuple)): seq_type = type(x) return seq_type(_recursive_sequence_map(f, xi) for xi in x) + elif _is_sequence_like(x): + return [_recursive_sequence_map(f, xi) for xi in x] else: return f(x) @@ -721,11 +723,7 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: elif _is_numpy_array(expected): expected = _as_numpy_array(expected) cls = ApproxNumpy - elif ( - hasattr(expected, "__getitem__") - and isinstance(expected, Sized) - and not isinstance(expected, (str, bytes)) - ): + elif _is_sequence_like(expected): cls = ApproxSequenceLike elif isinstance(expected, Collection) and not isinstance(expected, (str, bytes)): msg = f"pytest.approx() only supports ordered sequences, but got: {expected!r}" @@ -736,6 +734,14 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: return cls(expected, rel, abs, nan_ok) +def _is_sequence_like(expected: object) -> bool: + return ( + hasattr(expected, "__getitem__") + and isinstance(expected, Sized) + and not isinstance(expected, (str, bytes)) + ) + + def _is_numpy_array(obj: object) -> bool: """ Return true if the given object is implicitly convertible to ndarray, diff --git a/testing/python/approx.py b/testing/python/approx.py index 968e8828512..31e64c4df3d 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -954,6 +954,43 @@ def test_allow_ordered_sequences_only(self) -> None: with pytest.raises(TypeError, match="only supports ordered sequences"): assert {1, 2, 3} == approx({1, 2, 3}) + def test_strange_sequence(self): + """https://github.com/pytest-dev/pytest/issues/11797""" + a = MyVec3(1, 2, 3) + b = MyVec3(0, 1, 2) + + # this would trigger the error inside the test + pytest.approx(a, abs=0.5)._repr_compare(b) + + assert b == pytest.approx(a, abs=2) + assert b != pytest.approx(a, abs=0.5) + + +class MyVec3: # incomplete + """sequence like""" + + _x: int + _y: int + _z: int + + def __init__(self, x: int, y: int, z: int): + self._x, self._y, self._z = x, y, z + + def __repr__(self) -> str: + return f"" + + def __len__(self) -> int: + return 3 + + def __getitem__(self, key: int) -> int: + if key == 0: + return self._x + if key == 1: + return self._y + if key == 2: + return self._z + raise IndexError(key) + class TestRecursiveSequenceMap: def test_map_over_scalar(self): @@ -981,3 +1018,6 @@ def test_map_over_mixed_sequence(self): (5, 8), [(7)], ] + + def test_map_over_sequence_like(self): + assert _recursive_sequence_map(int, MyVec3(1, 2, 3)) == [1, 2, 3] From 9e98b6db5b2a39c94b31ce9567ea647196c0ecce Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 18 Jun 2024 18:05:45 +0200 Subject: [PATCH 0700/1271] =?UTF-8?q?=F0=9F=A7=AA=20Bump=20RTD=20env=20to?= =?UTF-8?q?=20the=20latest=20LTS=20Ubuntu=20&=20Python?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .readthedocs.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index 266d4e07aea..04716fd2a6f 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -14,9 +14,10 @@ sphinx: fail_on_warning: true build: - os: ubuntu-20.04 + os: ubuntu-24.04 tools: - python: "3.9" + python: >- + 3.12 apt_packages: - inkscape From f479afc5c0a3d4a6dd062f30738458637c873df8 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 18 Jun 2024 23:32:18 +0200 Subject: [PATCH 0701/1271] =?UTF-8?q?=F0=9F=92=85=20Add=20a=20config=20for?= =?UTF-8?q?=20the=20Chronographer=20GitHub=20App?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This app allows requiring changelog fragments to be included with each pull request. --- .github/chronographer.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/chronographer.yml diff --git a/.github/chronographer.yml b/.github/chronographer.yml new file mode 100644 index 00000000000..803db1e3417 --- /dev/null +++ b/.github/chronographer.yml @@ -0,0 +1,20 @@ +--- + +branch-protection-check-name: Changelog entry +action-hints: + check-title-prefix: "Chronographer: " + external-docs-url: >- + https://docs.pytest.org/en/latest/contributing.html#preparing-pull-requests + inline-markdown: >- + See + https://docs.pytest.org/en/latest/contributing.html#preparing-pull-requests + for details. +enforce-name: + suffix: .rst +exclude: + humans: + - pyup-bot +labels: + skip-changelog: skip news + +... From d7b401063874141fcbcda78eaec3c28148e7dcd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Wed, 19 Jun 2024 02:41:33 +0200 Subject: [PATCH 0702/1271] =?UTF-8?q?=F0=9F=92=85=20Add=20a=20config=20for?= =?UTF-8?q?=20the=20Patchback=20GitHub=20App=20(#12475)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch prepares the project's backporting process to start being handled by the Patchback GitHub App [[1]]. Ref #9384 Resolves #9385 Resolves #9553 Resolves #9554 Resolves #9555 [1]: https://github.com/apps/patchback --- .github/patchback.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/patchback.yml diff --git a/.github/patchback.yml b/.github/patchback.yml new file mode 100644 index 00000000000..5d62fca12fe --- /dev/null +++ b/.github/patchback.yml @@ -0,0 +1,7 @@ +--- + +backport_branch_prefix: patchback/backports/ +backport_label_prefix: 'backport ' # IMPORTANT: the labels are space-delimited +# target_branch_prefix: '' # The project's backport branches are non-prefixed + +... From 19715bf313680509c2ef5bcc7af7b304a000a199 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Wed, 19 Jun 2024 11:22:55 +0200 Subject: [PATCH 0703/1271] =?UTF-8?q?=F0=9F=94=A5=20Exterminate=20legacy?= =?UTF-8?q?=20`backport`=20GHA=20workflow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, this workflow was being used to cherry-pick PRs made against `main` into older stable branches. Now that #12475 integrated the Patchback GitHub App, it's no longer needed as it's making duplicate pull requests which don't even trigger CI runs automatically due to #10354. So this patch removes said workflow to address the problem. --- .github/workflows/backport.yml | 51 ---------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml deleted file mode 100644 index 38ce7260278..00000000000 --- a/.github/workflows/backport.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: backport - -on: - # Note that `pull_request_target` has security implications: - # https://securitylab.github.com/research/github-actions-preventing-pwn-requests/ - # In particular: - # - Only allow triggers that can be used only be trusted users - # - Don't execute any code from the target branch - # - Don't use cache - pull_request_target: - types: [labeled] - -# Set permissions at the job level. -permissions: {} - -jobs: - backport: - if: startsWith(github.event.label.name, 'backport ') && github.event.pull_request.merged - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - persist-credentials: true - - - name: Create backport PR - run: | - set -eux - - git config --global user.name "pytest bot" - git config --global user.email "pytestbot@gmail.com" - - label='${{ github.event.label.name }}' - target_branch="${label#backport }" - backport_branch=backport-${{ github.event.number }}-to-"${target_branch}" - subject="[$target_branch] $(gh pr view --json title -q .title ${{ github.event.number }})" - - git checkout origin/"${target_branch}" -b "${backport_branch}" - git cherry-pick -x --mainline 1 ${{ github.event.pull_request.merge_commit_sha }} - git commit --amend --message "$subject" - git push --set-upstream origin --force-with-lease "${backport_branch}" - gh pr create \ - --base "${target_branch}" \ - --title "${subject}" \ - --body "Backport of PR #${{ github.event.number }} to $target_branch branch. PR created by backport workflow." - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From bab3c2c291464f38ddd12d15818e41d2a9bb5e25 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Wed, 19 Jun 2024 11:31:55 +0200 Subject: [PATCH 0704/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20myself=20to=20th?= =?UTF-8?q?e=20authors=20file?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 80b6d5157cd..347efad57b3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -392,6 +392,7 @@ Stefano Taschini Steffen Allner Stephan Obermann Sven-Hendrik Haase +Sviatoslav Sydorenko Sylvain Marié Tadek Teleżyński Takafumi Arakaki From 6a95bcaa587a8903d190d9c6fe0bb8b76c9482c1 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Wed, 19 Jun 2024 12:10:20 +0200 Subject: [PATCH 0705/1271] =?UTF-8?q?=F0=9F=A7=AA=20Make=20required=20CI?= =?UTF-8?q?=20jobs=20match=20branch=20protection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 89af24b3936..d16ce0edf93 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -182,6 +182,26 @@ jobs: tox_env: "doctesting" use_coverage: true + continue-on-error: >- + ${{ + contains( + fromJSON( + '[ + "windows-py38-pluggy", + "windows-py313", + "ubuntu-py38-pluggy", + "ubuntu-py38-freeze", + "ubuntu-py313", + "macos-py38", + "macos-py313" + ]' + ), + matrix.name + ) + && true + || false + }} + steps: - uses: actions/checkout@v4 with: From 0470c387a99eab366415e8e920d30242d136647c Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 10:22:17 +0200 Subject: [PATCH 0706/1271] =?UTF-8?q?=F0=9F=93=9D=20Rename=20the=20RTD=20c?= =?UTF-8?q?onfig=20to=20canonical=20filename?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, it was possible to use several different config file name variants. However, there is one canonical name now and the others are being deprecated [[1]]. [1]: https://docs.rtfd.io/en/stable/config-file/index.html --- .readthedocs.yml => .readthedocs.yaml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .readthedocs.yml => .readthedocs.yaml (100%) diff --git a/.readthedocs.yml b/.readthedocs.yaml similarity index 100% rename from .readthedocs.yml rename to .readthedocs.yaml From e702079fd5338c636a216aaa71525c2b2705872b Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Wed, 19 Jun 2024 22:44:28 +0200 Subject: [PATCH 0707/1271] =?UTF-8?q?=F0=9F=93=9D=F0=9F=92=85=20Always=20r?= =?UTF-8?q?ender=20changelog=20draft=20@=20Sphinx=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The earlier implementation was generating a temporary file, when the docs site was being built with `tox`. However, this was not enabled in RTD and is hackish. This patch integrates the `sphinxcontrib-towncrier` extension to make it work in any environment where Sphinx docs are being built. --- .gitignore | 1 - .readthedocs.yaml | 4 +++ doc/en/changelog.rst | 11 ++++--- doc/en/conf.py | 46 +++++++++++++----------------- doc/en/requirements.txt | 1 + scripts/towncrier-draft-to-file.py | 18 ------------ tox.ini | 10 +++---- 7 files changed, 37 insertions(+), 54 deletions(-) delete mode 100644 scripts/towncrier-draft-to-file.py diff --git a/.gitignore b/.gitignore index 9fccf93f7c3..c4557b33a1c 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,6 @@ src/_pytest/_version.py doc/*/_build doc/*/.doctrees -doc/*/_changelog_towncrier_draft.rst build/ dist/ *.egg-info diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 04716fd2a6f..f7370f1bb98 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -20,6 +20,10 @@ build: 3.12 apt_packages: - inkscape + jobs: + post_checkout: + - git fetch --unshallow || true + - git fetch --tags || true formats: - epub diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 3ab2307ee5d..7e32b943446 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -19,12 +19,15 @@ with advance notice in the **Deprecations** section of releases. we named the news folder changelog -.. only:: changelog_towncrier_draft +.. only:: not is_release - .. The 'changelog_towncrier_draft' tag is included by our 'tox -e docs', - but not on readthedocs. + To be included in v\ |release| (if present) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - .. include:: _changelog_towncrier_draft.rst + .. towncrier-draft-entries:: |release| [UNRELEASED DRAFT] + + Released versions + ^^^^^^^^^^^^^^^^^ .. towncrier release notes start diff --git a/doc/en/conf.py b/doc/en/conf.py index 738d07dc2f1..3e87003c510 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -15,6 +15,8 @@ # # The full version, including alpha/beta/rc tags. # The short X.Y version. +import os +from pathlib import Path import shutil from textwrap import dedent from typing import TYPE_CHECKING @@ -26,6 +28,16 @@ import sphinx.application +PROJECT_ROOT_DIR = Path(__file__).parents[2].resolve() +IS_RELEASE_ON_RTD = ( + os.getenv("READTHEDOCS", "False") == "True" + and os.environ["READTHEDOCS_VERSION_TYPE"] == "tag" +) +if IS_RELEASE_ON_RTD: + tags: set[str] + # pylint: disable-next=used-before-assignment + tags.add("is_release") # noqa: F821 + release = ".".join(version.split(".")[:2]) # If extensions (or modules to document with autodoc) are in another directory, @@ -72,6 +84,7 @@ "sphinx.ext.viewcode", "sphinx_removed_in", "sphinxcontrib_trio", + "sphinxcontrib.towncrier.ext", # provides `towncrier-draft-entries` directive ] # Building PDF docs on readthedocs requires inkscape for svg to pdf @@ -422,6 +435,13 @@ ) ] +# -- Options for towncrier_draft extension ----------------------------------- + +towncrier_draft_autoversion_mode = "draft" # or: 'sphinx-version', 'sphinx-release' +towncrier_draft_include_empty = True +towncrier_draft_working_directory = PROJECT_ROOT_DIR +towncrier_draft_config_path = "pyproject.toml" # relative to cwd + intersphinx_mapping = { "pluggy": ("https://pluggy.readthedocs.io/en/stable", None), @@ -435,30 +455,6 @@ } -def configure_logging(app: "sphinx.application.Sphinx") -> None: - """Configure Sphinx's WarningHandler to handle (expected) missing include.""" - import logging - - import sphinx.util.logging - - class WarnLogFilter(logging.Filter): - def filter(self, record: logging.LogRecord) -> bool: - """Ignore warnings about missing include with "only" directive. - - Ref: https://github.com/sphinx-doc/sphinx/issues/2150.""" - if ( - record.msg.startswith('Problems with "include" directive path:') - and "_changelog_towncrier_draft.rst" in record.msg - ): - return False - return True - - logger = logging.getLogger(sphinx.util.logging.NAMESPACE) - warn_handler = [x for x in logger.handlers if x.level == logging.WARNING] - assert len(warn_handler) == 1, warn_handler - warn_handler[0].filters.insert(0, WarnLogFilter()) - - def setup(app: "sphinx.application.Sphinx") -> None: app.add_crossref_type( "fixture", @@ -488,8 +484,6 @@ def setup(app: "sphinx.application.Sphinx") -> None: indextemplate="pair: %s; hook", ) - configure_logging(app) - # legacypath.py monkey-patches pytest.Testdir in. Import the file so # that autodoc can discover references to it. import _pytest.legacypath # noqa: F401 diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 6e7221d645a..e40a15f1f15 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -9,3 +9,4 @@ sphinxcontrib-svg2pdfconverter # See https://github.com/pytest-dev/pytest/pull/10578#issuecomment-1348249045. packaging furo +sphinxcontrib-towncrier diff --git a/scripts/towncrier-draft-to-file.py b/scripts/towncrier-draft-to-file.py deleted file mode 100644 index f771295a01f..00000000000 --- a/scripts/towncrier-draft-to-file.py +++ /dev/null @@ -1,18 +0,0 @@ -# mypy: disallow-untyped-defs -from subprocess import call -import sys - - -def main() -> int: - """ - Platform-agnostic wrapper script for towncrier. - Fixes the issue (#7251) where Windows users are unable to natively run tox -e docs to build pytest docs. - """ - with open( - "doc/en/_changelog_towncrier_draft.rst", "w", encoding="utf-8" - ) as draft_file: - return call(("towncrier", "--draft"), stdout=draft_file) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/tox.ini b/tox.ini index 35b335a015d..dae89975467 100644 --- a/tox.ini +++ b/tox.ini @@ -88,11 +88,11 @@ deps = # https://github.com/twisted/towncrier/issues/340 towncrier<21.3.0 commands = - python scripts/towncrier-draft-to-file.py - # the '-t changelog_towncrier_draft' tags makes sphinx include the draft - # changelog in the docs; this does not happen on ReadTheDocs because it uses - # the standard sphinx command so the 'changelog_towncrier_draft' is never set there - sphinx-build -W --keep-going -b html doc/en doc/en/_build/html -t changelog_towncrier_draft {posargs:} + # Retrieve possibly missing commits: + -git fetch --unshallow + -git fetch --tags + + sphinx-build -W --keep-going -b html doc/en doc/en/_build/html {posargs:} setenv = # Sphinx is not clean of this warning. PYTHONWARNDEFAULTENCODING= From 39b548e6ea0aa467969623b108d809604c0e12c0 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Mon, 17 Jun 2024 17:51:30 +0200 Subject: [PATCH 0708/1271] =?UTF-8?q?=F0=9F=93=9D=20Make=20"setuptools=20e?= =?UTF-8?q?ntrypoint"=20term=20generic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This feature grew out of `setuptools` but the modern interface for extracting this information from the distribution package metadata is `importlib.metadata`. So the patch attempts to reflect this in the documentation messaging. Refs: * https://docs.python.org/3/library/importlib.metadata.html#entry-points * https://packaging.python.org/en/latest/guides/creating-and-discovering-plugins/#using-package-metadata * https://packaging.python.org/en/latest/specifications/entry-points/#entry-points --- doc/en/example/simple.rst | 6 +++--- doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/usage.rst | 2 +- doc/en/how-to/writing_plugins.rst | 15 +++++++++------ doc/en/reference/customize.rst | 2 +- doc/en/reference/reference.rst | 7 ++++--- src/_pytest/config/__init__.py | 7 ++++--- src/_pytest/helpconfig.py | 2 +- testing/test_assertion.py | 2 +- testing/test_helpconfig.py | 2 +- 10 files changed, 26 insertions(+), 21 deletions(-) diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index dec1bed5f80..d4ace3f0413 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -212,7 +212,7 @@ the command line arguments before they get processed: .. code-block:: python - # setuptools plugin + # installable external plugin import sys @@ -1073,8 +1073,8 @@ Instead of freezing the pytest runner as a separate executable, you can make your frozen program work as the pytest runner by some clever argument handling during program startup. This allows you to have a single executable, which is usually more convenient. -Please note that the mechanism for plugin discovery used by pytest -(setuptools entry points) doesn't work with frozen executables so pytest +Please note that the mechanism for plugin discovery used by pytest (:ref:`entry +points `) doesn't work with frozen executables so pytest can't find any third party plugins automatically. To include third party plugins like ``pytest-timeout`` they must be imported explicitly and passed on to pytest.main. diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 35c3238dea7..ecd297867c5 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1931,7 +1931,7 @@ The same applies for the test folder level obviously. Using fixtures from other projects ---------------------------------- -Usually projects that provide pytest support will use :ref:`entry points `, +Usually projects that provide pytest support will use :ref:`entry points `, so just installing those projects into an environment will make those fixtures available for use. In case you want to use fixtures from a project that does not use entry points, you can diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index fe46fad2db5..705fa009ed5 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -154,7 +154,7 @@ You can early-load plugins (internal and external) explicitly in the command-lin The option receives a ``name`` parameter, which can be: * A full module dotted name, for example ``myproject.plugins``. This dotted name must be importable. -* The entry-point name of a plugin. This is the name passed to ``setuptools`` when the plugin is +* The entry-point name of a plugin. This is the name passed to ``importlib`` when the plugin is registered. For example to early-load the :pypi:`pytest-cov` plugin you can use:: pytest -p pytest_cov diff --git a/doc/en/how-to/writing_plugins.rst b/doc/en/how-to/writing_plugins.rst index 4bb6d183333..14e5194ce63 100644 --- a/doc/en/how-to/writing_plugins.rst +++ b/doc/en/how-to/writing_plugins.rst @@ -16,8 +16,8 @@ reporting by calling :ref:`well specified hooks ` of the followi * builtin plugins: loaded from pytest's internal ``_pytest`` directory. -* :ref:`external plugins `: modules discovered through - `setuptools entry points`_ +* :ref:`external plugins `: installed third-party modules discovered + through :ref:`entry points ` in their packaging metadata * `conftest.py plugins`_: modules auto-discovered in test directories @@ -42,7 +42,8 @@ Plugin discovery order at tool startup 3. by scanning the command line for the ``-p name`` option and loading the specified plugin. This happens before normal command-line parsing. -4. by loading all plugins registered through `setuptools entry points`_. +4. by loading all plugins registered through installed third-party package + :ref:`entry points `. 5. by loading all plugins specified through the :envvar:`PYTEST_PLUGINS` environment variable. @@ -142,7 +143,8 @@ Making your plugin installable by others If you want to make your plugin externally available, you may define a so-called entry point for your distribution so that ``pytest`` finds your plugin module. Entry points are -a feature that is provided by :std:doc:`setuptools `. +a feature that is provided by :std:doc:`packaging tools +`. pytest looks up the ``pytest11`` entrypoint to discover its plugins, thus you can make your plugin available by defining @@ -265,8 +267,9 @@ of the variable will also be loaded as plugins, and so on. tests root directory is deprecated, and will raise a warning. This mechanism makes it easy to share fixtures within applications or even -external applications without the need to create external plugins using -the ``setuptools``'s entry point technique. +external applications without the need to create external plugins using the +:std:doc:`entry point packaging metadata +` technique. Plugins imported by :globalvar:`pytest_plugins` will also automatically be marked for assertion rewriting (see :func:`pytest.register_assert_rewrite`). diff --git a/doc/en/reference/customize.rst b/doc/en/reference/customize.rst index cab1117266f..373223ec913 100644 --- a/doc/en/reference/customize.rst +++ b/doc/en/reference/customize.rst @@ -90,7 +90,7 @@ and can also be used to hold pytest configuration if they have a ``[pytest]`` se setup.cfg ~~~~~~~~~ -``setup.cfg`` files are general purpose configuration files, used originally by ``distutils`` (now deprecated) and `setuptools `__, and can also be used to hold pytest configuration +``setup.cfg`` files are general purpose configuration files, used originally by ``distutils`` (now deprecated) and :std:doc:`setuptools `, and can also be used to hold pytest configuration if they have a ``[tool:pytest]`` section. .. code-block:: ini diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 3675c7cb2ee..7c7b99d81c0 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -650,7 +650,7 @@ Reference to all hooks which can be implemented by :ref:`conftest.py files `. Only explicitly +specified plugins will be loaded. .. envvar:: PYTEST_PLUGINS diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 058aaa1ff30..39d79e475bf 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1290,7 +1290,8 @@ def _mark_plugins_for_rewrite(self, hook) -> None: self.pluginmanager.rewrite_hook = hook if os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD"): - # We don't autoload from setuptools entry points, no need to continue. + # We don't autoload from distribution package entry points, + # no need to continue. return package_files = ( @@ -1381,8 +1382,8 @@ def _preparse(self, args: List[str], addopts: bool = True) -> None: self._consider_importhook(args) self.pluginmanager.consider_preparse(args, exclude_only=False) if not os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD"): - # Don't autoload from setuptools entry point. Only explicitly specified - # plugins are going to be loaded. + # Don't autoload from distribution package entry point. Only + # explicitly specified plugins are going to be loaded. self.pluginmanager.load_setuptools_entrypoints("pytest11") self.pluginmanager.consider_env() diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 68e0bd881a7..af6d3063974 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -243,7 +243,7 @@ def getpluginversioninfo(config: Config) -> List[str]: lines = [] plugininfo = config.pluginmanager.list_plugin_distinfo() if plugininfo: - lines.append("setuptools registered plugins:") + lines.append("registered third-party plugins:") for plugin, dist in plugininfo: loc = getattr(plugin, "__file__", repr(plugin)) content = f"{dist.project_name}-{dist.version} at {loc}" diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 726235999b4..317dfa27d70 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -223,7 +223,7 @@ def test_installed_plugin_rewrite( ) -> None: monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False) # Make sure the hook is installed early enough so that plugins - # installed via setuptools are rewritten. + # installed via distribution package are rewritten. pytester.mkdir("hampkg") contents = { "hampkg/__init__.py": """\ diff --git a/testing/test_helpconfig.py b/testing/test_helpconfig.py index 4906ef5c8f0..967e01e9694 100644 --- a/testing/test_helpconfig.py +++ b/testing/test_helpconfig.py @@ -10,7 +10,7 @@ def test_version_verbose(pytester: Pytester, pytestconfig, monkeypatch) -> None: assert result.ret == 0 result.stdout.fnmatch_lines([f"*pytest*{pytest.__version__}*imported from*"]) if pytestconfig.pluginmanager.list_plugin_distinfo(): - result.stdout.fnmatch_lines(["*setuptools registered plugins:", "*at*"]) + result.stdout.fnmatch_lines(["*registered third-party plugins:", "*at*"]) def test_version_less_verbose(pytester: Pytester, pytestconfig, monkeypatch) -> None: From cb179472bb4d6fe3a164fcca7d6f4a9631e2a27e Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 10:18:11 +0200 Subject: [PATCH 0709/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20change=20notes?= =?UTF-8?q?=20for=20PR=20#12469?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12469.doc.rst | 6 ++++++ changelog/12469.improvement.rst | 4 ++++ 2 files changed, 10 insertions(+) create mode 100644 changelog/12469.doc.rst create mode 100644 changelog/12469.improvement.rst diff --git a/changelog/12469.doc.rst b/changelog/12469.doc.rst new file mode 100644 index 00000000000..2340315353c --- /dev/null +++ b/changelog/12469.doc.rst @@ -0,0 +1,6 @@ +The external plugin mentions in the documentation now avoid mentioning +:std:doc:`setuptools entry-points ` as the concept is +much more generic nowadays. Instead, the terminology of "external", +"installed", or "third-party" plugins (or packages) replaces that. + +-- by :user:`webknjaz` diff --git a/changelog/12469.improvement.rst b/changelog/12469.improvement.rst new file mode 100644 index 00000000000..a90fb1e6610 --- /dev/null +++ b/changelog/12469.improvement.rst @@ -0,0 +1,4 @@ +The console output now uses the "third-party plugins" terminology, +replacing the previously established but confusing and outdated +reference to :std:doc:`setuptools ` +-- by :user:`webknjaz`. From 9295f9ffffc11595cc4d7241008f60783f1f46c2 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 17 Jun 2024 17:01:28 +0200 Subject: [PATCH 0710/1271] RFC: from __future__ import annotations + migrate --- bench/bench.py | 2 + bench/bench_argcomplete.py | 2 + bench/empty.py | 3 + bench/manyparam.py | 2 + bench/skip.py | 2 + bench/unit_test.py | 2 + bench/xunit.py | 3 + doc/en/conf.py | 4 +- doc/en/conftest.py | 3 + doc/en/example/assertion/failure_demo.py | 2 + .../global_testmodule_config/conftest.py | 2 + .../test_hello_world.py | 3 + doc/en/example/assertion/test_failures.py | 2 + .../assertion/test_setup_flow_example.py | 3 + doc/en/example/conftest.py | 3 + doc/en/example/customdirectory/conftest.py | 2 + .../customdirectory/tests/test_first.py | 3 + .../customdirectory/tests/test_second.py | 3 + .../customdirectory/tests/test_third.py | 3 + .../fixtures/test_fixtures_order_autouse.py | 2 + ..._fixtures_order_autouse_multiple_scopes.py | 2 + ...est_fixtures_order_autouse_temp_effects.py | 2 + .../test_fixtures_order_dependencies.py | 2 + .../fixtures/test_fixtures_order_scope.py | 2 + .../test_fixtures_request_different_scope.py | 2 + doc/en/example/multipython.py | 2 + doc/en/example/nonpython/conftest.py | 2 + doc/en/example/pythoncollection.py | 1 + doc/en/example/xfail_demo.py | 2 + extra/get_issues.py | 2 + pyproject.toml | 9 + scripts/generate-gh-release-notes.py | 2 + scripts/prepare-release-pr.py | 2 + scripts/release.py | 2 + scripts/update-plugin-list.py | 2 + src/_pytest/__init__.py | 3 + src/_pytest/_argcomplete.py | 8 +- src/_pytest/_code/__init__.py | 2 + src/_pytest/_code/code.py | 225 ++++++++---------- src/_pytest/_code/source.py | 36 ++- src/_pytest/_io/__init__.py | 2 + src/_pytest/_io/pprint.py | 69 +++--- src/_pytest/_io/saferepr.py | 7 +- src/_pytest/_io/terminalwriter.py | 17 +- src/_pytest/_io/wcwidth.py | 2 + src/_pytest/assertion/__init__.py | 14 +- src/_pytest/assertion/rewrite.py | 114 +++++---- src/_pytest/assertion/truncate.py | 17 +- src/_pytest/assertion/util.py | 48 ++-- src/_pytest/cacheprovider.py | 41 ++-- src/_pytest/capture.py | 59 ++--- src/_pytest/config/__init__.py | 150 ++++++------ src/_pytest/config/argparsing.py | 87 ++++--- src/_pytest/config/exceptions.py | 2 + src/_pytest/config/findpaths.py | 27 +-- src/_pytest/debugging.py | 29 +-- src/_pytest/deprecated.py | 2 + src/_pytest/doctest.py | 82 +++---- src/_pytest/faulthandler.py | 2 + src/_pytest/fixtures.py | 222 ++++++++--------- src/_pytest/freeze_support.py | 8 +- src/_pytest/helpconfig.py | 13 +- src/_pytest/hookspec.py | 173 +++++++------- src/_pytest/junitxml.py | 49 ++-- src/_pytest/legacypath.py | 29 +-- src/_pytest/logging.py | 60 +++-- src/_pytest/main.py | 115 +++++---- src/_pytest/mark/__init__.py | 24 +- src/_pytest/mark/expression.py | 7 +- src/_pytest/mark/structures.py | 108 ++++----- src/_pytest/monkeypatch.py | 32 ++- src/_pytest/nodes.py | 120 +++++----- src/_pytest/outcomes.py | 21 +- src/_pytest/pastebin.py | 5 +- src/_pytest/pathlib.py | 69 +++--- src/_pytest/pytester.py | 184 +++++++------- src/_pytest/pytester_assertions.py | 18 +- src/_pytest/python.py | 147 ++++++------ src/_pytest/python_api.py | 57 +++-- src/_pytest/python_path.py | 2 + src/_pytest/recwarn.py | 69 +++--- src/_pytest/reports.py | 118 +++++---- src/_pytest/runner.py | 67 +++--- src/_pytest/scope.py | 13 +- src/_pytest/setuponly.py | 6 +- src/_pytest/setupplan.py | 7 +- src/_pytest/skipping.py | 14 +- src/_pytest/stash.py | 8 +- src/_pytest/stepwise.py | 11 +- src/_pytest/terminal.py | 132 +++++----- src/_pytest/threadexception.py | 23 +- src/_pytest/timing.py | 2 + src/_pytest/tmpdir.py | 20 +- src/_pytest/unittest.py | 34 +-- src/_pytest/unraisableexception.py | 23 +- src/_pytest/warning_types.py | 7 +- src/_pytest/warnings.py | 7 +- src/py.py | 2 + src/pytest/__init__.py | 2 + src/pytest/__main__.py | 2 + testing/_py/test_local.py | 2 + testing/acceptance_test.py | 2 + testing/code/test_code.py | 2 + testing/conftest.py | 11 +- testing/deprecated_test.py | 2 + .../acceptance/fixture_mock_integration.py | 2 + .../collect_init_tests/tests/__init__.py | 3 + .../collect_init_tests/tests/test_foo.py | 3 + .../package_infinite_recursion/conftest.py | 3 + .../tests/test_basic.py | 3 + .../package_init_given_as_arg/pkg/__init__.py | 3 + .../package_init_given_as_arg/pkg/test_foo.py | 3 + .../config/collect_pytest_prefix/conftest.py | 3 + .../config/collect_pytest_prefix/test_foo.py | 3 + .../conftest_usageerror/conftest.py | 3 + .../customdirectory/conftest.py | 2 + .../customdirectory/tests/test_first.py | 3 + .../customdirectory/tests/test_second.py | 3 + .../customdirectory/tests/test_third.py | 3 + .../dataclasses/test_compare_dataclasses.py | 2 + ...ompare_dataclasses_field_comparison_off.py | 2 + .../test_compare_dataclasses_verbose.py | 2 + ...test_compare_dataclasses_with_custom_eq.py | 2 + .../dataclasses/test_compare_initvar.py | 2 + .../test_compare_recursive_dataclasses.py | 2 + .../test_compare_two_different_dataclasses.py | 2 + .../doctest/main_py/__main__.py | 3 + .../doctest/main_py/test_normal_module.py | 3 + .../fixtures/custom_item/conftest.py | 2 + .../fixtures/custom_item/foo/test_foo.py | 3 + .../sub1/conftest.py | 2 + .../sub1/test_in_sub1.py | 3 + .../sub2/conftest.py | 2 + .../sub2/test_in_sub2.py | 3 + .../test_detect_recursive_dependency_error.py | 2 + .../conftest.py | 2 + .../pkg/conftest.py | 2 + .../pkg/test_spam.py | 3 + .../conftest.py | 2 + .../test_extend_fixture_conftest_module.py | 2 + .../test_extend_fixture_module_class.py | 2 + .../fill_fixtures/test_funcarg_basic.py | 2 + .../test_funcarg_lookup_classlevel.py | 2 + .../test_funcarg_lookup_modulelevel.py | 2 + .../fill_fixtures/test_funcarg_lookupfails.py | 2 + .../fixtures/test_fixture_named_request.py | 2 + .../fixtures/test_getfixturevalue_dynamic.py | 2 + .../conftest.py | 2 + .../test_hello.py | 3 + testing/example_scripts/issue_519.py | 6 +- .../test_marks_as_keywords.py | 2 + .../collect_stats/generate_folders.py | 2 + .../collect_stats/template_test.py | 3 + .../tmpdir/tmp_path_fixture.py | 2 + ...test_parametrized_fixture_error_message.py | 2 + .../unittest/test_setup_skip.py | 2 + .../unittest/test_setup_skip_class.py | 2 + .../unittest/test_setup_skip_module.py | 2 + .../unittest/test_unittest_asyncio.py | 5 +- .../unittest/test_unittest_asynctest.py | 5 +- .../unittest/test_unittest_plain_async.py | 2 + .../test_group_warnings_by_message.py | 2 + .../test_1.py | 2 + .../test_2.py | 2 + testing/examples/test_issue519.py | 2 + testing/freeze/create_executable.py | 3 + testing/freeze/runtests_script.py | 3 + testing/freeze/tests/test_trivial.py | 3 + testing/freeze/tox_run.py | 3 + testing/io/test_pprint.py | 2 + testing/io/test_saferepr.py | 2 + testing/io/test_terminalwriter.py | 5 +- testing/io/test_wcwidth.py | 2 + testing/logging/test_fixture.py | 2 + testing/logging/test_formatter.py | 2 + testing/logging/test_reporting.py | 2 + testing/plugins_integration/bdd_wallet.py | 2 + .../plugins_integration/django_settings.py | 3 + .../pytest_anyio_integration.py | 2 + .../pytest_asyncio_integration.py | 2 + .../pytest_mock_integration.py | 3 + .../pytest_rerunfailures_integration.py | 2 + .../pytest_trio_integration.py | 2 + .../pytest_twisted_integration.py | 2 + .../plugins_integration/simple_integration.py | 2 + testing/python/approx.py | 7 +- testing/python/collect.py | 5 +- testing/python/fixtures.py | 4 +- testing/python/integration.py | 2 + testing/python/metafunc.py | 22 +- testing/python/raises.py | 2 + testing/python/show_fixtures_per_test.py | 2 + testing/test_argcomplete.py | 2 + testing/test_assertion.py | 14 +- testing/test_assertrewrite.py | 18 +- testing/test_cacheprovider.py | 8 +- testing/test_capture.py | 2 + testing/test_collection.py | 8 +- testing/test_compat.py | 5 +- testing/test_config.py | 17 +- testing/test_conftest.py | 11 +- testing/test_debugging.py | 9 +- testing/test_doctest.py | 5 +- testing/test_entry_points.py | 2 + testing/test_error_diffs.py | 2 + testing/test_faulthandler.py | 2 + testing/test_findpaths.py | 2 + testing/test_helpconfig.py | 2 + testing/test_junitxml.py | 18 +- testing/test_legacypath.py | 2 + testing/test_link_resolve.py | 2 + testing/test_main.py | 5 +- testing/test_mark.py | 16 +- testing/test_mark_expression.py | 2 + testing/test_meta.py | 5 +- testing/test_monkeypatch.py | 10 +- testing/test_nodes.py | 5 +- testing/test_parseopt.py | 2 + testing/test_pastebin.py | 8 +- testing/test_pathlib.py | 12 +- testing/test_pluginmanager.py | 5 +- testing/test_pytester.py | 7 +- testing/test_python_path.py | 8 +- testing/test_recwarn.py | 12 +- testing/test_reports.py | 7 +- testing/test_runner.py | 14 +- testing/test_runner_xunit.py | 4 +- testing/test_scope.py | 2 + testing/test_session.py | 2 + testing/test_setuponly.py | 2 + testing/test_setupplan.py | 2 + testing/test_skipping.py | 2 + testing/test_stash.py | 2 + testing/test_stepwise.py | 2 + testing/test_terminal.py | 9 +- testing/test_threadexception.py | 2 + testing/test_tmpdir.py | 8 +- testing/test_unittest.py | 9 +- testing/test_unraisableexception.py | 2 + testing/test_warning_types.py | 2 + testing/test_warnings.py | 13 +- testing/typing_checks.py | 2 + 242 files changed, 1961 insertions(+), 1777 deletions(-) diff --git a/bench/bench.py b/bench/bench.py index 0bb13c75a15..139c292ecd8 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys diff --git a/bench/bench_argcomplete.py b/bench/bench_argcomplete.py index 459a12f9314..468c59217df 100644 --- a/bench/bench_argcomplete.py +++ b/bench/bench_argcomplete.py @@ -2,6 +2,8 @@ # 2.7.5 3.3.2 # FilesCompleter 75.1109 69.2116 # FastFilesCompleter 0.7383 1.0760 +from __future__ import annotations + import timeit diff --git a/bench/empty.py b/bench/empty.py index 4e7371b6f80..35abeef4140 100644 --- a/bench/empty.py +++ b/bench/empty.py @@ -1,2 +1,5 @@ +from __future__ import annotations + + for i in range(1000): exec("def test_func_%d(): pass" % i) diff --git a/bench/manyparam.py b/bench/manyparam.py index 1226c73bd9c..579f7b2488d 100644 --- a/bench/manyparam.py +++ b/bench/manyparam.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/bench/skip.py b/bench/skip.py index fd5c292d92c..9145cc0ceed 100644 --- a/bench/skip.py +++ b/bench/skip.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/bench/unit_test.py b/bench/unit_test.py index d3db111e1ae..0f106e16b6c 100644 --- a/bench/unit_test.py +++ b/bench/unit_test.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from unittest import TestCase # noqa: F401 diff --git a/bench/xunit.py b/bench/xunit.py index 3a77dcdce42..31ab432441c 100644 --- a/bench/xunit.py +++ b/bench/xunit.py @@ -1,3 +1,6 @@ +from __future__ import annotations + + for i in range(5000): exec( f""" diff --git a/doc/en/conf.py b/doc/en/conf.py index 3e87003c510..670d6adf74b 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -15,6 +15,8 @@ # # The full version, including alpha/beta/rc tags. # The short X.Y version. +from __future__ import annotations + import os from pathlib import Path import shutil @@ -455,7 +457,7 @@ } -def setup(app: "sphinx.application.Sphinx") -> None: +def setup(app: sphinx.application.Sphinx) -> None: app.add_crossref_type( "fixture", "fixture", diff --git a/doc/en/conftest.py b/doc/en/conftest.py index 1a62e1b5df5..50e43a0b544 100644 --- a/doc/en/conftest.py +++ b/doc/en/conftest.py @@ -1 +1,4 @@ +from __future__ import annotations + + collect_ignore = ["conf.py"] diff --git a/doc/en/example/assertion/failure_demo.py b/doc/en/example/assertion/failure_demo.py index f7a9c279426..dd1485b0b21 100644 --- a/doc/en/example/assertion/failure_demo.py +++ b/doc/en/example/assertion/failure_demo.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest from pytest import raises diff --git a/doc/en/example/assertion/global_testmodule_config/conftest.py b/doc/en/example/assertion/global_testmodule_config/conftest.py index 4aa7ec23bd1..835726473ba 100644 --- a/doc/en/example/assertion/global_testmodule_config/conftest.py +++ b/doc/en/example/assertion/global_testmodule_config/conftest.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os.path import pytest diff --git a/doc/en/example/assertion/global_testmodule_config/test_hello_world.py b/doc/en/example/assertion/global_testmodule_config/test_hello_world.py index a31a601a1ce..e3c927316f9 100644 --- a/doc/en/example/assertion/global_testmodule_config/test_hello_world.py +++ b/doc/en/example/assertion/global_testmodule_config/test_hello_world.py @@ -1,3 +1,6 @@ +from __future__ import annotations + + hello = "world" diff --git a/doc/en/example/assertion/test_failures.py b/doc/en/example/assertion/test_failures.py index 19d862f60b7..17373f62213 100644 --- a/doc/en/example/assertion/test_failures.py +++ b/doc/en/example/assertion/test_failures.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os.path import shutil diff --git a/doc/en/example/assertion/test_setup_flow_example.py b/doc/en/example/assertion/test_setup_flow_example.py index 0e7eded06b6..fe11c2bf3f2 100644 --- a/doc/en/example/assertion/test_setup_flow_example.py +++ b/doc/en/example/assertion/test_setup_flow_example.py @@ -1,3 +1,6 @@ +from __future__ import annotations + + def setup_module(module): module.TestStateFullThing.classcount = 0 diff --git a/doc/en/example/conftest.py b/doc/en/example/conftest.py index 66e70f14dd7..21c9a489961 100644 --- a/doc/en/example/conftest.py +++ b/doc/en/example/conftest.py @@ -1 +1,4 @@ +from __future__ import annotations + + collect_ignore = ["nonpython", "customdirectory"] diff --git a/doc/en/example/customdirectory/conftest.py b/doc/en/example/customdirectory/conftest.py index b2f68dba41a..ea922e04723 100644 --- a/doc/en/example/customdirectory/conftest.py +++ b/doc/en/example/customdirectory/conftest.py @@ -1,4 +1,6 @@ # content of conftest.py +from __future__ import annotations + import json import pytest diff --git a/doc/en/example/customdirectory/tests/test_first.py b/doc/en/example/customdirectory/tests/test_first.py index 0a78de59945..9953dd37785 100644 --- a/doc/en/example/customdirectory/tests/test_first.py +++ b/doc/en/example/customdirectory/tests/test_first.py @@ -1,3 +1,6 @@ # content of test_first.py +from __future__ import annotations + + def test_1(): pass diff --git a/doc/en/example/customdirectory/tests/test_second.py b/doc/en/example/customdirectory/tests/test_second.py index eed724a7d96..df264f48b3b 100644 --- a/doc/en/example/customdirectory/tests/test_second.py +++ b/doc/en/example/customdirectory/tests/test_second.py @@ -1,3 +1,6 @@ # content of test_second.py +from __future__ import annotations + + def test_2(): pass diff --git a/doc/en/example/customdirectory/tests/test_third.py b/doc/en/example/customdirectory/tests/test_third.py index 61cf59dc16c..b8b072dd770 100644 --- a/doc/en/example/customdirectory/tests/test_third.py +++ b/doc/en/example/customdirectory/tests/test_third.py @@ -1,3 +1,6 @@ # content of test_third.py +from __future__ import annotations + + def test_3(): pass diff --git a/doc/en/example/fixtures/test_fixtures_order_autouse.py b/doc/en/example/fixtures/test_fixtures_order_autouse.py index ec282ab4b2b..04cbc268b7f 100644 --- a/doc/en/example/fixtures/test_fixtures_order_autouse.py +++ b/doc/en/example/fixtures/test_fixtures_order_autouse.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/doc/en/example/fixtures/test_fixtures_order_autouse_multiple_scopes.py b/doc/en/example/fixtures/test_fixtures_order_autouse_multiple_scopes.py index de0c2642793..828fa4cf6d6 100644 --- a/doc/en/example/fixtures/test_fixtures_order_autouse_multiple_scopes.py +++ b/doc/en/example/fixtures/test_fixtures_order_autouse_multiple_scopes.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/doc/en/example/fixtures/test_fixtures_order_autouse_temp_effects.py b/doc/en/example/fixtures/test_fixtures_order_autouse_temp_effects.py index ba01ad32f57..ebd5d10f5bb 100644 --- a/doc/en/example/fixtures/test_fixtures_order_autouse_temp_effects.py +++ b/doc/en/example/fixtures/test_fixtures_order_autouse_temp_effects.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/doc/en/example/fixtures/test_fixtures_order_dependencies.py b/doc/en/example/fixtures/test_fixtures_order_dependencies.py index e76e3f93c62..1c59f010341 100644 --- a/doc/en/example/fixtures/test_fixtures_order_dependencies.py +++ b/doc/en/example/fixtures/test_fixtures_order_dependencies.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/doc/en/example/fixtures/test_fixtures_order_scope.py b/doc/en/example/fixtures/test_fixtures_order_scope.py index 5d9487cab34..4b4260fbdcd 100644 --- a/doc/en/example/fixtures/test_fixtures_order_scope.py +++ b/doc/en/example/fixtures/test_fixtures_order_scope.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/doc/en/example/fixtures/test_fixtures_request_different_scope.py b/doc/en/example/fixtures/test_fixtures_request_different_scope.py index 00e2e46d845..dee61f8c4d7 100644 --- a/doc/en/example/fixtures/test_fixtures_request_different_scope.py +++ b/doc/en/example/fixtures/test_fixtures_request_different_scope.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/doc/en/example/multipython.py b/doc/en/example/multipython.py index 861ae9e528d..f54524213bc 100644 --- a/doc/en/example/multipython.py +++ b/doc/en/example/multipython.py @@ -1,6 +1,8 @@ """Module containing a parametrized tests testing cross-python serialization via the pickle module.""" +from __future__ import annotations + import shutil import subprocess import textwrap diff --git a/doc/en/example/nonpython/conftest.py b/doc/en/example/nonpython/conftest.py index e969e3e2518..b7bdc77a004 100644 --- a/doc/en/example/nonpython/conftest.py +++ b/doc/en/example/nonpython/conftest.py @@ -1,4 +1,6 @@ # content of conftest.py +from __future__ import annotations + import pytest diff --git a/doc/en/example/pythoncollection.py b/doc/en/example/pythoncollection.py index 8742526a191..7595ee02ca4 100644 --- a/doc/en/example/pythoncollection.py +++ b/doc/en/example/pythoncollection.py @@ -1,5 +1,6 @@ # run this with $ pytest --collect-only test_collectonly.py # +from __future__ import annotations def test_function(): diff --git a/doc/en/example/xfail_demo.py b/doc/en/example/xfail_demo.py index 1040c89298d..4999e15f238 100644 --- a/doc/en/example/xfail_demo.py +++ b/doc/en/example/xfail_demo.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import pytest diff --git a/extra/get_issues.py b/extra/get_issues.py index 64e859e0c12..851d2f6d7f3 100644 --- a/extra/get_issues.py +++ b/extra/get_issues.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json from pathlib import Path import sys diff --git a/pyproject.toml b/pyproject.toml index 0627c94c732..734c508ca70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -98,6 +98,7 @@ lint.select = [ "D", # pydocstyle "E", # pycodestyle "F", # pyflakes + "FA100", # add future annotations "I", # isort "PGH004", # pygrep-hooks - Use specific rule codes when using noqa "PIE", # flake8-pie @@ -155,6 +156,10 @@ lint.per-file-ignores."src/_pytest/_version.py" = [ lint.per-file-ignores."testing/python/approx.py" = [ "B015", ] +lint.extend-safe-fixes = [ + "UP006", + "UP007", +] lint.isort.combine-as-imports = true lint.isort.force-single-line = true lint.isort.force-sort-within-sections = true @@ -164,9 +169,13 @@ lint.isort.known-local-folder = [ ] lint.isort.lines-after-imports = 2 lint.isort.order-by-type = false +lint.isort.required-imports = [ + "from __future__ import annotations", +] # In order to be able to format for 88 char in ruff format lint.pycodestyle.max-line-length = 120 lint.pydocstyle.convention = "pep257" +lint.pyupgrade.keep-runtime-typing = false [tool.pylint.main] # Maximum number of characters on a single line. diff --git a/scripts/generate-gh-release-notes.py b/scripts/generate-gh-release-notes.py index 4222702d5d4..7f195ba1e0a 100644 --- a/scripts/generate-gh-release-notes.py +++ b/scripts/generate-gh-release-notes.py @@ -9,6 +9,8 @@ Requires Python3.6+. """ +from __future__ import annotations + from pathlib import Path import re import sys diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index 7dabbd3b328..49cb2110639 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -14,6 +14,8 @@ `pytest bot ` commit author. """ +from __future__ import annotations + import argparse from pathlib import Path import re diff --git a/scripts/release.py b/scripts/release.py index bcbc4262d08..545919cd60b 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -1,6 +1,8 @@ # mypy: disallow-untyped-defs """Invoke development tasks.""" +from __future__ import annotations + import argparse import os from pathlib import Path diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 6831fc984dd..75df0ddba40 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -1,4 +1,6 @@ # mypy: disallow-untyped-defs +from __future__ import annotations + import datetime import pathlib import re diff --git a/src/_pytest/__init__.py b/src/_pytest/__init__.py index b694a5f244a..8eb8ec9605c 100644 --- a/src/_pytest/__init__.py +++ b/src/_pytest/__init__.py @@ -1,3 +1,6 @@ +from __future__ import annotations + + __all__ = ["__version__", "version_tuple"] try: diff --git a/src/_pytest/_argcomplete.py b/src/_pytest/_argcomplete.py index c24f925202a..59426ef949e 100644 --- a/src/_pytest/_argcomplete.py +++ b/src/_pytest/_argcomplete.py @@ -62,13 +62,13 @@ global argcomplete script). """ +from __future__ import annotations + import argparse from glob import glob import os import sys from typing import Any -from typing import List -from typing import Optional class FastFilesCompleter: @@ -77,7 +77,7 @@ class FastFilesCompleter: def __init__(self, directories: bool = True) -> None: self.directories = directories - def __call__(self, prefix: str, **kwargs: Any) -> List[str]: + def __call__(self, prefix: str, **kwargs: Any) -> list[str]: # Only called on non option completions. if os.sep in prefix[1:]: prefix_dir = len(os.path.dirname(prefix) + os.sep) @@ -104,7 +104,7 @@ def __call__(self, prefix: str, **kwargs: Any) -> List[str]: import argcomplete.completers except ImportError: sys.exit(-1) - filescompleter: Optional[FastFilesCompleter] = FastFilesCompleter() + filescompleter: FastFilesCompleter | None = FastFilesCompleter() def try_argcomplete(parser: argparse.ArgumentParser) -> None: argcomplete.autocomplete(parser, always_complete_options=False) diff --git a/src/_pytest/_code/__init__.py b/src/_pytest/_code/__init__.py index b0a418e9555..0bfde42604d 100644 --- a/src/_pytest/_code/__init__.py +++ b/src/_pytest/_code/__init__.py @@ -1,5 +1,7 @@ """Python inspection/code generation API.""" +from __future__ import annotations + from .code import Code from .code import ExceptionInfo from .code import filter_traceback diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index b6e06340dbe..750195b94e9 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import ast import dataclasses import inspect @@ -17,7 +19,6 @@ from typing import Any from typing import Callable from typing import ClassVar -from typing import Dict from typing import Final from typing import final from typing import Generic @@ -25,16 +26,11 @@ from typing import List from typing import Literal from typing import Mapping -from typing import Optional from typing import overload from typing import Pattern from typing import Sequence -from typing import Set from typing import SupportsIndex -from typing import Tuple -from typing import Type from typing import TypeVar -from typing import Union import pluggy @@ -57,6 +53,10 @@ TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] +EXCEPTION_OR_MORE = type[Exception] | tuple[type[Exception], ...] + +type_alias = type # to sidestep shadowing + class Code: """Wrapper around Python code objects.""" @@ -67,7 +67,7 @@ def __init__(self, obj: CodeType) -> None: self.raw = obj @classmethod - def from_function(cls, obj: object) -> "Code": + def from_function(cls, obj: object) -> Code: return cls(getrawcode(obj)) def __eq__(self, other): @@ -85,7 +85,7 @@ def name(self) -> str: return self.raw.co_name @property - def path(self) -> Union[Path, str]: + def path(self) -> Path | str: """Return a path object pointing to source code, or an ``str`` in case of ``OSError`` / non-existing file.""" if not self.raw.co_filename: @@ -102,17 +102,17 @@ def path(self) -> Union[Path, str]: return self.raw.co_filename @property - def fullsource(self) -> Optional["Source"]: + def fullsource(self) -> Source | None: """Return a _pytest._code.Source object for the full source file of the code.""" full, _ = findsource(self.raw) return full - def source(self) -> "Source": + def source(self) -> Source: """Return a _pytest._code.Source object for the code object's source only.""" # return source only for that part of code return Source(self.raw) - def getargs(self, var: bool = False) -> Tuple[str, ...]: + def getargs(self, var: bool = False) -> tuple[str, ...]: """Return a tuple with the argument names for the code object. If 'var' is set True also return the names of the variable and @@ -141,11 +141,11 @@ def lineno(self) -> int: return self.raw.f_lineno - 1 @property - def f_globals(self) -> Dict[str, Any]: + def f_globals(self) -> dict[str, Any]: return self.raw.f_globals @property - def f_locals(self) -> Dict[str, Any]: + def f_locals(self) -> dict[str, Any]: return self.raw.f_locals @property @@ -153,7 +153,7 @@ def code(self) -> Code: return Code(self.raw.f_code) @property - def statement(self) -> "Source": + def statement(self) -> Source: """Statement this frame is at.""" if self.code.fullsource is None: return Source("") @@ -197,14 +197,14 @@ class TracebackEntry: def __init__( self, rawentry: TracebackType, - repr_style: Optional['Literal["short", "long"]'] = None, + repr_style: Literal["short", "long"] | None = None, ) -> None: self._rawentry: Final = rawentry self._repr_style: Final = repr_style def with_repr_style( - self, repr_style: Optional['Literal["short", "long"]'] - ) -> "TracebackEntry": + self, repr_style: Literal["short", "long"] | None + ) -> TracebackEntry: return TracebackEntry(self._rawentry, repr_style) @property @@ -223,19 +223,19 @@ def __repr__(self) -> str: return "" % (self.frame.code.path, self.lineno + 1) @property - def statement(self) -> "Source": + def statement(self) -> Source: """_pytest._code.Source object for the current statement.""" source = self.frame.code.fullsource assert source is not None return source.getstatement(self.lineno) @property - def path(self) -> Union[Path, str]: + def path(self) -> Path | str: """Path to the source code.""" return self.frame.code.path @property - def locals(self) -> Dict[str, Any]: + def locals(self) -> dict[str, Any]: """Locals of underlying frame.""" return self.frame.f_locals @@ -243,8 +243,8 @@ def getfirstlinesource(self) -> int: return self.frame.code.firstlineno def getsource( - self, astcache: Optional[Dict[Union[str, Path], ast.AST]] = None - ) -> Optional["Source"]: + self, astcache: dict[str | Path, ast.AST] | None = None + ) -> Source | None: """Return failing source code.""" # we use the passed in astcache to not reparse asttrees # within exception info printing @@ -270,7 +270,7 @@ def getsource( source = property(getsource) - def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool: + def ishidden(self, excinfo: ExceptionInfo[BaseException] | None) -> bool: """Return True if the current frame has a var __tracebackhide__ resolving to True. @@ -279,9 +279,7 @@ def ishidden(self, excinfo: Optional["ExceptionInfo[BaseException]"]) -> bool: Mostly for internal use. """ - tbh: Union[bool, Callable[[Optional[ExceptionInfo[BaseException]]], bool]] = ( - False - ) + tbh: bool | Callable[[ExceptionInfo[BaseException] | None], bool] = False for maybe_ns_dct in (self.frame.f_locals, self.frame.f_globals): # in normal cases, f_locals and f_globals are dictionaries # however via `exec(...)` / `eval(...)` they can be other types @@ -326,13 +324,13 @@ class Traceback(List[TracebackEntry]): def __init__( self, - tb: Union[TracebackType, Iterable[TracebackEntry]], + tb: TracebackType | Iterable[TracebackEntry], ) -> None: """Initialize from given python traceback object and ExceptionInfo.""" if isinstance(tb, TracebackType): def f(cur: TracebackType) -> Iterable[TracebackEntry]: - cur_: Optional[TracebackType] = cur + cur_: TracebackType | None = cur while cur_ is not None: yield TracebackEntry(cur_) cur_ = cur_.tb_next @@ -343,11 +341,11 @@ def f(cur: TracebackType) -> Iterable[TracebackEntry]: def cut( self, - path: Optional[Union["os.PathLike[str]", str]] = None, - lineno: Optional[int] = None, - firstlineno: Optional[int] = None, - excludepath: Optional["os.PathLike[str]"] = None, - ) -> "Traceback": + path: os.PathLike[str] | str | None = None, + lineno: int | None = None, + firstlineno: int | None = None, + excludepath: os.PathLike[str] | None = None, + ) -> Traceback: """Return a Traceback instance wrapping part of this Traceback. By providing any combination of path, lineno and firstlineno, the @@ -378,14 +376,12 @@ def cut( return self @overload - def __getitem__(self, key: "SupportsIndex") -> TracebackEntry: ... + def __getitem__(self, key: SupportsIndex) -> TracebackEntry: ... @overload - def __getitem__(self, key: slice) -> "Traceback": ... + def __getitem__(self, key: slice) -> Traceback: ... - def __getitem__( - self, key: Union["SupportsIndex", slice] - ) -> Union[TracebackEntry, "Traceback"]: + def __getitem__(self, key: SupportsIndex | slice) -> TracebackEntry | Traceback: if isinstance(key, slice): return self.__class__(super().__getitem__(key)) else: @@ -393,12 +389,9 @@ def __getitem__( def filter( self, - excinfo_or_fn: Union[ - "ExceptionInfo[BaseException]", - Callable[[TracebackEntry], bool], - ], + excinfo_or_fn: ExceptionInfo[BaseException] | Callable[[TracebackEntry], bool], /, - ) -> "Traceback": + ) -> Traceback: """Return a Traceback instance with certain items removed. If the filter is an `ExceptionInfo`, removes all the ``TracebackEntry``s @@ -414,10 +407,10 @@ def filter( fn = excinfo_or_fn return Traceback(filter(fn, self)) - def recursionindex(self) -> Optional[int]: + def recursionindex(self) -> int | None: """Return the index of the frame/TracebackEntry where recursion originates if appropriate, None if no recursion occurred.""" - cache: Dict[Tuple[Any, int, int], List[Dict[str, Any]]] = {} + cache: dict[tuple[Any, int, int], list[dict[str, Any]]] = {} for i, entry in enumerate(self): # id for the code.raw is needed to work around # the strange metaprogramming in the decorator lib from pypi @@ -445,15 +438,15 @@ class ExceptionInfo(Generic[E]): _assert_start_repr: ClassVar = "AssertionError('assert " - _excinfo: Optional[Tuple[Type["E"], "E", TracebackType]] + _excinfo: tuple[type[E], E, TracebackType] | None _striptext: str - _traceback: Optional[Traceback] + _traceback: Traceback | None def __init__( self, - excinfo: Optional[Tuple[Type["E"], "E", TracebackType]], + excinfo: tuple[type[E], E, TracebackType] | None, striptext: str = "", - traceback: Optional[Traceback] = None, + traceback: Traceback | None = None, *, _ispytest: bool = False, ) -> None: @@ -469,8 +462,8 @@ def from_exception( # This is OK to ignore because this class is (conceptually) readonly. # See https://github.com/python/mypy/issues/7049. exception: E, # type: ignore[misc] - exprinfo: Optional[str] = None, - ) -> "ExceptionInfo[E]": + exprinfo: str | None = None, + ) -> ExceptionInfo[E]: """Return an ExceptionInfo for an existing exception. The exception must have a non-``None`` ``__traceback__`` attribute, @@ -495,9 +488,9 @@ def from_exception( @classmethod def from_exc_info( cls, - exc_info: Tuple[Type[E], E, TracebackType], - exprinfo: Optional[str] = None, - ) -> "ExceptionInfo[E]": + exc_info: tuple[type[E], E, TracebackType], + exprinfo: str | None = None, + ) -> ExceptionInfo[E]: """Like :func:`from_exception`, but using old-style exc_info tuple.""" _striptext = "" if exprinfo is None and isinstance(exc_info[1], AssertionError): @@ -510,9 +503,7 @@ def from_exc_info( return cls(exc_info, _striptext, _ispytest=True) @classmethod - def from_current( - cls, exprinfo: Optional[str] = None - ) -> "ExceptionInfo[BaseException]": + def from_current(cls, exprinfo: str | None = None) -> ExceptionInfo[BaseException]: """Return an ExceptionInfo matching the current traceback. .. warning:: @@ -532,17 +523,17 @@ def from_current( return ExceptionInfo.from_exc_info(exc_info, exprinfo) @classmethod - def for_later(cls) -> "ExceptionInfo[E]": + def for_later(cls) -> ExceptionInfo[E]: """Return an unfilled ExceptionInfo.""" return cls(None, _ispytest=True) - def fill_unfilled(self, exc_info: Tuple[Type[E], E, TracebackType]) -> None: + def fill_unfilled(self, exc_info: tuple[type[E], E, TracebackType]) -> None: """Fill an unfilled ExceptionInfo created with ``for_later()``.""" assert self._excinfo is None, "ExceptionInfo was already filled" self._excinfo = exc_info @property - def type(self) -> Type[E]: + def type(self) -> type[E]: """The exception class.""" assert ( self._excinfo is not None @@ -605,16 +596,14 @@ def exconly(self, tryshort: bool = False) -> str: text = text[len(self._striptext) :] return text - def errisinstance( - self, exc: Union[Type[BaseException], Tuple[Type[BaseException], ...]] - ) -> bool: + def errisinstance(self, exc: EXCEPTION_OR_MORE) -> bool: """Return True if the exception is an instance of exc. Consider using ``isinstance(excinfo.value, exc)`` instead. """ return isinstance(self.value, exc) - def _getreprcrash(self) -> Optional["ReprFileLocation"]: + def _getreprcrash(self) -> ReprFileLocation | None: # Find last non-hidden traceback entry that led to the exception of the # traceback, or None if all hidden. for i in range(-1, -len(self.traceback) - 1, -1): @@ -630,14 +619,12 @@ def getrepr( showlocals: bool = False, style: TracebackStyle = "long", abspath: bool = False, - tbfilter: Union[ - bool, Callable[["ExceptionInfo[BaseException]"], Traceback] - ] = True, + tbfilter: bool | Callable[[ExceptionInfo[BaseException]], Traceback] = True, funcargs: bool = False, truncate_locals: bool = True, truncate_args: bool = True, chain: bool = True, - ) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]: + ) -> ReprExceptionInfo | ExceptionChainRepr: """Return str()able representation of this exception info. :param bool showlocals: @@ -719,7 +706,7 @@ def _stringify_exception(self, exc: BaseException) -> str: ] ) - def match(self, regexp: Union[str, Pattern[str]]) -> "Literal[True]": + def match(self, regexp: str | Pattern[str]) -> Literal[True]: """Check whether the regular expression `regexp` matches the string representation of the exception using :func:`python:re.search`. @@ -737,9 +724,9 @@ def match(self, regexp: Union[str, Pattern[str]]) -> "Literal[True]": def _group_contains( self, exc_group: BaseExceptionGroup[BaseException], - expected_exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], - match: Union[str, Pattern[str], None], - target_depth: Optional[int] = None, + expected_exception: EXCEPTION_OR_MORE, + match: str | Pattern[str] | None, + target_depth: int | None = None, current_depth: int = 1, ) -> bool: """Return `True` if a `BaseExceptionGroup` contains a matching exception.""" @@ -766,10 +753,10 @@ def _group_contains( def group_contains( self, - expected_exception: Union[Type[BaseException], Tuple[Type[BaseException], ...]], + expected_exception: EXCEPTION_OR_MORE, *, - match: Union[str, Pattern[str], None] = None, - depth: Optional[int] = None, + match: str | Pattern[str] | None = None, + depth: int | None = None, ) -> bool: """Check whether a captured exception group contains a matching exception. @@ -811,16 +798,16 @@ class FormattedExcinfo: showlocals: bool = False style: TracebackStyle = "long" abspath: bool = True - tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True + tbfilter: bool | Callable[[ExceptionInfo[BaseException]], Traceback] = True funcargs: bool = False truncate_locals: bool = True truncate_args: bool = True chain: bool = True - astcache: Dict[Union[str, Path], ast.AST] = dataclasses.field( + astcache: dict[str | Path, ast.AST] = dataclasses.field( default_factory=dict, init=False, repr=False ) - def _getindent(self, source: "Source") -> int: + def _getindent(self, source: Source) -> int: # Figure out indent for the given source. try: s = str(source.getstatement(len(source) - 1)) @@ -835,13 +822,13 @@ def _getindent(self, source: "Source") -> int: return 0 return 4 + (len(s) - len(s.lstrip())) - def _getentrysource(self, entry: TracebackEntry) -> Optional["Source"]: + def _getentrysource(self, entry: TracebackEntry) -> Source | None: source = entry.getsource(self.astcache) if source is not None: source = source.deindent() return source - def repr_args(self, entry: TracebackEntry) -> Optional["ReprFuncArgs"]: + def repr_args(self, entry: TracebackEntry) -> ReprFuncArgs | None: if self.funcargs: args = [] for argname, argvalue in entry.frame.getargs(var=True): @@ -855,11 +842,11 @@ def repr_args(self, entry: TracebackEntry) -> Optional["ReprFuncArgs"]: def get_source( self, - source: Optional["Source"], + source: Source | None, line_index: int = -1, - excinfo: Optional[ExceptionInfo[BaseException]] = None, + excinfo: ExceptionInfo[BaseException] | None = None, short: bool = False, - ) -> List[str]: + ) -> list[str]: """Return formatted and marked up source lines.""" lines = [] if source is not None and line_index < 0: @@ -888,7 +875,7 @@ def get_exconly( excinfo: ExceptionInfo[BaseException], indent: int = 4, markall: bool = False, - ) -> List[str]: + ) -> list[str]: lines = [] indentstr = " " * indent # Get the real exception information out. @@ -900,7 +887,7 @@ def get_exconly( failindent = indentstr return lines - def repr_locals(self, locals: Mapping[str, object]) -> Optional["ReprLocals"]: + def repr_locals(self, locals: Mapping[str, object]) -> ReprLocals | None: if self.showlocals: lines = [] keys = [loc for loc in locals if loc[0] != "@"] @@ -928,10 +915,10 @@ def repr_locals(self, locals: Mapping[str, object]) -> Optional["ReprLocals"]: def repr_traceback_entry( self, - entry: Optional[TracebackEntry], - excinfo: Optional[ExceptionInfo[BaseException]] = None, - ) -> "ReprEntry": - lines: List[str] = [] + entry: TracebackEntry | None, + excinfo: ExceptionInfo[BaseException] | None = None, + ) -> ReprEntry: + lines: list[str] = [] style = ( entry._repr_style if entry is not None and entry._repr_style is not None @@ -966,7 +953,7 @@ def repr_traceback_entry( lines.extend(self.get_exconly(excinfo, indent=4)) return ReprEntry(lines, None, None, None, style) - def _makepath(self, path: Union[Path, str]) -> str: + def _makepath(self, path: Path | str) -> str: if not self.abspath and isinstance(path, Path): try: np = bestrelpath(Path.cwd(), path) @@ -976,7 +963,7 @@ def _makepath(self, path: Union[Path, str]) -> str: return np return str(path) - def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> "ReprTraceback": + def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> ReprTraceback: traceback = excinfo.traceback if callable(self.tbfilter): traceback = self.tbfilter(excinfo) @@ -1007,7 +994,7 @@ def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> "ReprTracebac def _truncate_recursive_traceback( self, traceback: Traceback - ) -> Tuple[Traceback, Optional[str]]: + ) -> tuple[Traceback, str | None]: """Truncate the given recursive traceback trying to find the starting point of the recursion. @@ -1024,7 +1011,7 @@ def _truncate_recursive_traceback( recursionindex = traceback.recursionindex() except Exception as e: max_frames = 10 - extraline: Optional[str] = ( + extraline: str | None = ( "!!! Recursion error detected, but an error occurred locating the origin of recursion.\n" " The following exception happened when comparing locals in the stack frame:\n" f" {type(e).__name__}: {e!s}\n" @@ -1042,16 +1029,12 @@ def _truncate_recursive_traceback( return traceback, extraline - def repr_excinfo( - self, excinfo: ExceptionInfo[BaseException] - ) -> "ExceptionChainRepr": - repr_chain: List[ - Tuple[ReprTraceback, Optional[ReprFileLocation], Optional[str]] - ] = [] - e: Optional[BaseException] = excinfo.value - excinfo_: Optional[ExceptionInfo[BaseException]] = excinfo + def repr_excinfo(self, excinfo: ExceptionInfo[BaseException]) -> ExceptionChainRepr: + repr_chain: list[tuple[ReprTraceback, ReprFileLocation | None, str | None]] = [] + e: BaseException | None = excinfo.value + excinfo_: ExceptionInfo[BaseException] | None = excinfo descr = None - seen: Set[int] = set() + seen: set[int] = set() while e is not None and id(e) not in seen: seen.add(id(e)) @@ -1060,7 +1043,7 @@ def repr_excinfo( # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 if isinstance(e, BaseExceptionGroup): - reprtraceback: Union[ReprTracebackNative, ReprTraceback] = ( + reprtraceback: ReprTracebackNative | ReprTraceback = ( ReprTracebackNative( traceback.format_exception( type(excinfo_.value), @@ -1118,9 +1101,9 @@ def toterminal(self, tw: TerminalWriter) -> None: @dataclasses.dataclass(eq=False) class ExceptionRepr(TerminalRepr): # Provided by subclasses. - reprtraceback: "ReprTraceback" - reprcrash: Optional["ReprFileLocation"] - sections: List[Tuple[str, str, str]] = dataclasses.field( + reprtraceback: ReprTraceback + reprcrash: ReprFileLocation | None + sections: list[tuple[str, str, str]] = dataclasses.field( init=False, default_factory=list ) @@ -1135,13 +1118,11 @@ def toterminal(self, tw: TerminalWriter) -> None: @dataclasses.dataclass(eq=False) class ExceptionChainRepr(ExceptionRepr): - chain: Sequence[Tuple["ReprTraceback", Optional["ReprFileLocation"], Optional[str]]] + chain: Sequence[tuple[ReprTraceback, ReprFileLocation | None, str | None]] def __init__( self, - chain: Sequence[ - Tuple["ReprTraceback", Optional["ReprFileLocation"], Optional[str]] - ], + chain: Sequence[tuple[ReprTraceback, ReprFileLocation | None, str | None]], ) -> None: # reprcrash and reprtraceback of the outermost (the newest) exception # in the chain. @@ -1162,8 +1143,8 @@ def toterminal(self, tw: TerminalWriter) -> None: @dataclasses.dataclass(eq=False) class ReprExceptionInfo(ExceptionRepr): - reprtraceback: "ReprTraceback" - reprcrash: Optional["ReprFileLocation"] + reprtraceback: ReprTraceback + reprcrash: ReprFileLocation | None def toterminal(self, tw: TerminalWriter) -> None: self.reprtraceback.toterminal(tw) @@ -1172,8 +1153,8 @@ def toterminal(self, tw: TerminalWriter) -> None: @dataclasses.dataclass(eq=False) class ReprTraceback(TerminalRepr): - reprentries: Sequence[Union["ReprEntry", "ReprEntryNative"]] - extraline: Optional[str] + reprentries: Sequence[ReprEntry | ReprEntryNative] + extraline: str | None style: TracebackStyle entrysep: ClassVar = "_ " @@ -1217,9 +1198,9 @@ def toterminal(self, tw: TerminalWriter) -> None: @dataclasses.dataclass(eq=False) class ReprEntry(TerminalRepr): lines: Sequence[str] - reprfuncargs: Optional["ReprFuncArgs"] - reprlocals: Optional["ReprLocals"] - reprfileloc: Optional["ReprFileLocation"] + reprfuncargs: ReprFuncArgs | None + reprlocals: ReprLocals | None + reprfileloc: ReprFileLocation | None style: TracebackStyle def _write_entry_lines(self, tw: TerminalWriter) -> None: @@ -1243,9 +1224,9 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: # such as "> assert 0" fail_marker = f"{FormattedExcinfo.fail_marker} " indent_size = len(fail_marker) - indents: List[str] = [] - source_lines: List[str] = [] - failure_lines: List[str] = [] + indents: list[str] = [] + source_lines: list[str] = [] + failure_lines: list[str] = [] for index, line in enumerate(self.lines): is_failure_line = line.startswith(fail_marker) if is_failure_line: @@ -1324,7 +1305,7 @@ def toterminal(self, tw: TerminalWriter, indent="") -> None: @dataclasses.dataclass(eq=False) class ReprFuncArgs(TerminalRepr): - args: Sequence[Tuple[str, object]] + args: Sequence[tuple[str, object]] def toterminal(self, tw: TerminalWriter) -> None: if self.args: @@ -1345,7 +1326,7 @@ def toterminal(self, tw: TerminalWriter) -> None: tw.line("") -def getfslineno(obj: object) -> Tuple[Union[str, Path], int]: +def getfslineno(obj: object) -> tuple[str | Path, int]: """Return source location (path, lineno) for the given object. If the source cannot be determined return ("", -1). diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index 7fa577e03b3..604aff8ba19 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import ast from bisect import bisect_right import inspect @@ -7,11 +9,7 @@ import types from typing import Iterable from typing import Iterator -from typing import List -from typing import Optional from typing import overload -from typing import Tuple -from typing import Union import warnings @@ -23,7 +21,7 @@ class Source: def __init__(self, obj: object = None) -> None: if not obj: - self.lines: List[str] = [] + self.lines: list[str] = [] elif isinstance(obj, Source): self.lines = obj.lines elif isinstance(obj, (tuple, list)): @@ -50,9 +48,9 @@ def __eq__(self, other: object) -> bool: def __getitem__(self, key: int) -> str: ... @overload - def __getitem__(self, key: slice) -> "Source": ... + def __getitem__(self, key: slice) -> Source: ... - def __getitem__(self, key: Union[int, slice]) -> Union[str, "Source"]: + def __getitem__(self, key: int | slice) -> str | Source: if isinstance(key, int): return self.lines[key] else: @@ -68,7 +66,7 @@ def __iter__(self) -> Iterator[str]: def __len__(self) -> int: return len(self.lines) - def strip(self) -> "Source": + def strip(self) -> Source: """Return new Source object with trailing and leading blank lines removed.""" start, end = 0, len(self) while start < end and not self.lines[start].strip(): @@ -79,20 +77,20 @@ def strip(self) -> "Source": source.lines[:] = self.lines[start:end] return source - def indent(self, indent: str = " " * 4) -> "Source": + def indent(self, indent: str = " " * 4) -> Source: """Return a copy of the source object with all lines indented by the given indent-string.""" newsource = Source() newsource.lines = [(indent + line) for line in self.lines] return newsource - def getstatement(self, lineno: int) -> "Source": + def getstatement(self, lineno: int) -> Source: """Return Source statement which contains the given linenumber (counted from 0).""" start, end = self.getstatementrange(lineno) return self[start:end] - def getstatementrange(self, lineno: int) -> Tuple[int, int]: + def getstatementrange(self, lineno: int) -> tuple[int, int]: """Return (start, end) tuple which spans the minimal statement region which containing the given lineno.""" if not (0 <= lineno < len(self)): @@ -100,7 +98,7 @@ def getstatementrange(self, lineno: int) -> Tuple[int, int]: ast, start, end = getstatementrange_ast(lineno, self) return start, end - def deindent(self) -> "Source": + def deindent(self) -> Source: """Return a new Source object deindented.""" newsource = Source() newsource.lines[:] = deindent(self.lines) @@ -115,7 +113,7 @@ def __str__(self) -> str: # -def findsource(obj) -> Tuple[Optional[Source], int]: +def findsource(obj) -> tuple[Source | None, int]: try: sourcelines, lineno = inspect.findsource(obj) except Exception: @@ -138,14 +136,14 @@ def getrawcode(obj: object, trycall: bool = True) -> types.CodeType: raise TypeError(f"could not get code object for {obj!r}") -def deindent(lines: Iterable[str]) -> List[str]: +def deindent(lines: Iterable[str]) -> list[str]: return textwrap.dedent("\n".join(lines)).splitlines() -def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[int]]: +def get_statement_startend2(lineno: int, node: ast.AST) -> tuple[int, int | None]: # Flatten all statements and except handlers into one lineno-list. # AST's line numbers start indexing at 1. - values: List[int] = [] + values: list[int] = [] for x in ast.walk(node): if isinstance(x, (ast.stmt, ast.ExceptHandler)): # The lineno points to the class/def, so need to include the decorators. @@ -154,7 +152,7 @@ def get_statement_startend2(lineno: int, node: ast.AST) -> Tuple[int, Optional[i values.append(d.lineno - 1) values.append(x.lineno - 1) for name in ("finalbody", "orelse"): - val: Optional[List[ast.stmt]] = getattr(x, name, None) + val: list[ast.stmt] | None = getattr(x, name, None) if val: # Treat the finally/orelse part as its own statement. values.append(val[0].lineno - 1 - 1) @@ -172,8 +170,8 @@ def getstatementrange_ast( lineno: int, source: Source, assertion: bool = False, - astnode: Optional[ast.AST] = None, -) -> Tuple[ast.AST, int, int]: + astnode: ast.AST | None = None, +) -> tuple[ast.AST, int, int]: if astnode is None: content = str(source) # See #4260: diff --git a/src/_pytest/_io/__init__.py b/src/_pytest/_io/__init__.py index db001e918cb..b0155b18b60 100644 --- a/src/_pytest/_io/__init__.py +++ b/src/_pytest/_io/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from .terminalwriter import get_terminal_width from .terminalwriter import TerminalWriter diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index e637eec59e1..7213be7ba9b 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -13,6 +13,8 @@ # tuples with fairly non-descriptive content. This is modeled very much # after Lisp/Scheme - style pretty-printing of lists. If you find it # useful, thank small children who sleep at night. +from __future__ import annotations + import collections as _collections import dataclasses as _dataclasses from io import StringIO as _StringIO @@ -20,13 +22,8 @@ import types as _types 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: @@ -64,7 +61,7 @@ def __init__( self, indent: int = 4, width: int = 80, - depth: Optional[int] = None, + depth: int | None = None, ) -> None: """Handle pretty printing operations onto a stream using a set of configured parameters. @@ -100,7 +97,7 @@ def _format( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: objid = id(object) @@ -136,7 +133,7 @@ def _pprint_dataclass( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: cls_name = object.__class__.__name__ @@ -149,9 +146,9 @@ def _pprint_dataclass( self._format_namespace_items(items, stream, indent, allowance, context, level) stream.write(")") - _dispatch: Dict[ + _dispatch: dict[ Callable[..., str], - Callable[["PrettyPrinter", Any, IO[str], int, int, Set[int], int], None], + Callable[[PrettyPrinter, Any, IO[str], int, int, set[int], int], None], ] = {} def _pprint_dict( @@ -160,7 +157,7 @@ def _pprint_dict( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: write = stream.write @@ -177,7 +174,7 @@ def _pprint_ordered_dict( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: if not len(object): @@ -196,7 +193,7 @@ def _pprint_list( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: stream.write("[") @@ -211,7 +208,7 @@ def _pprint_tuple( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: stream.write("(") @@ -226,7 +223,7 @@ def _pprint_set( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: if not len(object): @@ -252,7 +249,7 @@ def _pprint_str( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: write = stream.write @@ -311,7 +308,7 @@ def _pprint_bytes( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: write = stream.write @@ -340,7 +337,7 @@ def _pprint_bytearray( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: write = stream.write @@ -358,7 +355,7 @@ def _pprint_mappingproxy( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: stream.write("mappingproxy(") @@ -373,7 +370,7 @@ def _pprint_simplenamespace( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: if type(object) is _types.SimpleNamespace: @@ -391,11 +388,11 @@ def _pprint_simplenamespace( def _format_dict_items( self, - items: List[Tuple[Any, Any]], + items: list[tuple[Any, Any]], stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: if not items: @@ -415,11 +412,11 @@ def _format_dict_items( def _format_namespace_items( self, - items: List[Tuple[Any, Any]], + items: list[tuple[Any, Any]], stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: if not items: @@ -452,11 +449,11 @@ def _format_namespace_items( def _format_items( self, - items: List[Any], + items: list[Any], stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: if not items: @@ -473,7 +470,7 @@ def _format_items( write("\n" + " " * indent) - def _repr(self, object: Any, context: Set[int], level: int) -> str: + def _repr(self, object: Any, context: set[int], level: int) -> str: return self._safe_repr(object, context.copy(), self._depth, level) def _pprint_default_dict( @@ -482,7 +479,7 @@ def _pprint_default_dict( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: rdf = self._repr(object.default_factory, context, level) @@ -498,7 +495,7 @@ def _pprint_counter( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: stream.write(object.__class__.__name__ + "(") @@ -519,7 +516,7 @@ def _pprint_chain_map( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: if not len(object.maps) or (len(object.maps) == 1 and not len(object.maps[0])): @@ -538,7 +535,7 @@ def _pprint_deque( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: stream.write(object.__class__.__name__ + "(") @@ -557,7 +554,7 @@ def _pprint_user_dict( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) @@ -570,7 +567,7 @@ def _pprint_user_list( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) @@ -583,7 +580,7 @@ def _pprint_user_string( stream: IO[str], indent: int, allowance: int, - context: Set[int], + context: set[int], level: int, ) -> None: self._format(object.data, stream, indent, allowance, context, level - 1) @@ -591,7 +588,7 @@ def _pprint_user_string( _dispatch[_collections.UserString.__repr__] = _pprint_user_string def _safe_repr( - self, object: Any, context: Set[int], maxlevels: Optional[int], level: int + self, object: Any, context: set[int], maxlevels: int | None, level: int ) -> str: typ = type(object) if typ in _builtin_scalars: @@ -608,7 +605,7 @@ def _safe_repr( if objid in context: return _recursion(object) context.add(objid) - components: List[str] = [] + components: list[str] = [] append = components.append level += 1 for k, v in sorted(object.items(), key=_safe_tuple): diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index 9f33fced676..5ace418227d 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -1,6 +1,7 @@ +from __future__ import annotations + import pprint import reprlib -from typing import Optional def _try_repr_or_str(obj: object) -> str: @@ -38,7 +39,7 @@ class SafeRepr(reprlib.Repr): information on exceptions raised during the call. """ - def __init__(self, maxsize: Optional[int], use_ascii: bool = False) -> None: + def __init__(self, maxsize: int | None, use_ascii: bool = False) -> None: """ :param maxsize: If not None, will truncate the resulting repr to that specific size, using ellipsis @@ -97,7 +98,7 @@ def safeformat(obj: object) -> str: def saferepr( - obj: object, maxsize: Optional[int] = DEFAULT_REPR_MAX_SIZE, use_ascii: bool = False + obj: object, maxsize: int | None = DEFAULT_REPR_MAX_SIZE, use_ascii: bool = False ) -> str: """Return a size-limited safe repr-string for the given object. diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 083c18232ff..70ebd3d061b 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -1,11 +1,12 @@ """Helper functions for writing to terminals and files.""" +from __future__ import annotations + import os import shutil import sys from typing import final from typing import Literal -from typing import Optional from typing import Sequence from typing import TextIO from typing import TYPE_CHECKING @@ -71,7 +72,7 @@ class TerminalWriter: invert=7, ) - def __init__(self, file: Optional[TextIO] = None) -> None: + def __init__(self, file: TextIO | None = None) -> None: if file is None: file = sys.stdout if hasattr(file, "isatty") and file.isatty() and sys.platform == "win32": @@ -85,7 +86,7 @@ def __init__(self, file: Optional[TextIO] = None) -> None: self._file = file self.hasmarkup = should_do_markup(file) self._current_line = "" - self._terminal_width: Optional[int] = None + self._terminal_width: int | None = None self.code_highlight = True @property @@ -116,8 +117,8 @@ def markup(self, text: str, **markup: bool) -> str: def sep( self, sepchar: str, - title: Optional[str] = None, - fullwidth: Optional[int] = None, + title: str | None = None, + fullwidth: int | None = None, **markup: bool, ) -> None: if fullwidth is None: @@ -200,9 +201,7 @@ def _write_source(self, lines: Sequence[str], indents: Sequence[str] = ()) -> No for indent, new_line in zip(indents, new_lines): self.line(indent + new_line) - def _get_pygments_lexer( - self, lexer: Literal["python", "diff"] - ) -> Optional["Lexer"]: + def _get_pygments_lexer(self, lexer: Literal["python", "diff"]) -> Lexer | None: try: if lexer == "python": from pygments.lexers.python import PythonLexer @@ -217,7 +216,7 @@ def _get_pygments_lexer( except ModuleNotFoundError: return None - def _get_pygments_formatter(self) -> Optional["Formatter"]: + def _get_pygments_formatter(self) -> Formatter | None: try: import pygments.util except ModuleNotFoundError: diff --git a/src/_pytest/_io/wcwidth.py b/src/_pytest/_io/wcwidth.py index 53803133519..23886ff1581 100644 --- a/src/_pytest/_io/wcwidth.py +++ b/src/_pytest/_io/wcwidth.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from functools import lru_cache import unicodedata diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index 21dd4a4a4bb..f2f1d029b4c 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -1,11 +1,11 @@ # mypy: allow-untyped-defs """Support for presenting detailed information in failing assertions.""" +from __future__ import annotations + import sys from typing import Any from typing import Generator -from typing import List -from typing import Optional from typing import TYPE_CHECKING from _pytest.assertion import rewrite @@ -94,7 +94,7 @@ class AssertionState: def __init__(self, config: Config, mode) -> None: self.mode = mode self.trace = config.trace.root.get("assertion") - self.hook: Optional[rewrite.AssertionRewritingHook] = None + self.hook: rewrite.AssertionRewritingHook | None = None def install_importhook(config: Config) -> rewrite.AssertionRewritingHook: @@ -113,7 +113,7 @@ def undo() -> None: return hook -def pytest_collection(session: "Session") -> None: +def pytest_collection(session: Session) -> None: # This hook is only called when test modules are collected # so for example not in the managing process of pytest-xdist # (which does not collect test modules). @@ -133,7 +133,7 @@ def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: """ ihook = item.ihook - def callbinrepr(op, left: object, right: object) -> Optional[str]: + def callbinrepr(op, left: object, right: object) -> str | None: """Call the pytest_assertrepr_compare hook and prepare the result. This uses the first result from the hook and then ensures the @@ -179,7 +179,7 @@ def call_assertion_pass_hook(lineno: int, orig: str, expl: str) -> None: util._config = None -def pytest_sessionfinish(session: "Session") -> None: +def pytest_sessionfinish(session: Session) -> None: assertstate = session.config.stash.get(assertstate_key, None) if assertstate: if assertstate.hook is not None: @@ -188,5 +188,5 @@ def pytest_sessionfinish(session: "Session") -> None: def pytest_assertrepr_compare( config: Config, op: str, left: Any, right: Any -) -> Optional[List[str]]: +) -> list[str] | None: return util.assertrepr_compare(config=config, op=op, left=left, right=right) diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index b29a254f5f7..442fc5d9f30 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -1,5 +1,7 @@ """Rewrite assertion AST to produce nice error messages.""" +from __future__ import annotations + import ast from collections import defaultdict import errno @@ -18,17 +20,11 @@ import tokenize import types from typing import Callable -from typing import Dict from typing import IO from typing import Iterable from typing import Iterator -from typing import List -from typing import Optional from typing import Sequence -from typing import Set -from typing import Tuple from typing import TYPE_CHECKING -from typing import Union from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import saferepr @@ -73,17 +69,17 @@ def __init__(self, config: Config) -> None: self.fnpats = config.getini("python_files") except ValueError: self.fnpats = ["test_*.py", "*_test.py"] - self.session: Optional[Session] = None - self._rewritten_names: Dict[str, Path] = {} - self._must_rewrite: Set[str] = set() + self.session: Session | None = None + self._rewritten_names: dict[str, Path] = {} + self._must_rewrite: set[str] = set() # flag to guard against trying to rewrite a pyc file while we are already writing another pyc file, # which might result in infinite recursion (#3506) self._writing_pyc = False self._basenames_to_check_rewrite = {"conftest"} - self._marked_for_rewrite_cache: Dict[str, bool] = {} + self._marked_for_rewrite_cache: dict[str, bool] = {} self._session_paths_checked = False - def set_session(self, session: Optional[Session]) -> None: + def set_session(self, session: Session | None) -> None: self.session = session self._session_paths_checked = False @@ -93,9 +89,9 @@ def set_session(self, session: Optional[Session]) -> None: def find_spec( self, name: str, - path: Optional[Sequence[Union[str, bytes]]] = None, - target: Optional[types.ModuleType] = None, - ) -> Optional[importlib.machinery.ModuleSpec]: + path: Sequence[str | bytes] | None = None, + target: types.ModuleType | None = None, + ) -> importlib.machinery.ModuleSpec | None: if self._writing_pyc: return None state = self.config.stash[assertstate_key] @@ -132,7 +128,7 @@ def find_spec( def create_module( self, spec: importlib.machinery.ModuleSpec - ) -> Optional[types.ModuleType]: + ) -> types.ModuleType | None: return None # default behaviour is fine def exec_module(self, module: types.ModuleType) -> None: @@ -177,7 +173,7 @@ def exec_module(self, module: types.ModuleType) -> None: state.trace(f"found cached rewritten pyc for {fn}") exec(co, module.__dict__) - def _early_rewrite_bailout(self, name: str, state: "AssertionState") -> bool: + def _early_rewrite_bailout(self, name: str, state: AssertionState) -> bool: """A fast way to get out of rewriting modules. Profiling has shown that the call to PathFinder.find_spec (inside of @@ -216,7 +212,7 @@ def _early_rewrite_bailout(self, name: str, state: "AssertionState") -> bool: state.trace(f"early skip of rewriting module: {name}") return True - def _should_rewrite(self, name: str, fn: str, state: "AssertionState") -> bool: + def _should_rewrite(self, name: str, fn: str, state: AssertionState) -> bool: # always rewrite conftest files if os.path.basename(fn) == "conftest.py": state.trace(f"rewriting conftest file: {fn!r}") @@ -237,7 +233,7 @@ def _should_rewrite(self, name: str, fn: str, state: "AssertionState") -> bool: return self._is_marked_for_rewrite(name, state) - def _is_marked_for_rewrite(self, name: str, state: "AssertionState") -> bool: + def _is_marked_for_rewrite(self, name: str, state: AssertionState) -> bool: try: return self._marked_for_rewrite_cache[name] except KeyError: @@ -278,7 +274,7 @@ def _warn_already_imported(self, name: str) -> None: stacklevel=5, ) - def get_data(self, pathname: Union[str, bytes]) -> bytes: + def get_data(self, pathname: str | bytes) -> bytes: """Optional PEP302 get_data API.""" with open(pathname, "rb") as f: return f.read() @@ -317,7 +313,7 @@ def _write_pyc_fp( def _write_pyc( - state: "AssertionState", + state: AssertionState, co: types.CodeType, source_stat: os.stat_result, pyc: Path, @@ -341,7 +337,7 @@ def _write_pyc( return True -def _rewrite_test(fn: Path, config: Config) -> Tuple[os.stat_result, types.CodeType]: +def _rewrite_test(fn: Path, config: Config) -> tuple[os.stat_result, types.CodeType]: """Read and rewrite *fn* and return the code object.""" stat = os.stat(fn) source = fn.read_bytes() @@ -354,7 +350,7 @@ def _rewrite_test(fn: Path, config: Config) -> Tuple[os.stat_result, types.CodeT def _read_pyc( source: Path, pyc: Path, trace: Callable[[str], None] = lambda x: None -) -> Optional[types.CodeType]: +) -> types.CodeType | None: """Possibly read a pytest pyc containing rewritten code. Return rewritten code if successful or None if not. @@ -404,8 +400,8 @@ def _read_pyc( def rewrite_asserts( mod: ast.Module, source: bytes, - module_path: Optional[str] = None, - config: Optional[Config] = None, + module_path: str | None = None, + config: Config | None = None, ) -> None: """Rewrite the assert statements in mod.""" AssertionRewriter(module_path, config, source).run(mod) @@ -425,7 +421,7 @@ def _saferepr(obj: object) -> str: return saferepr(obj, maxsize=maxsize).replace("\n", "\\n") -def _get_maxsize_for_saferepr(config: Optional[Config]) -> Optional[int]: +def _get_maxsize_for_saferepr(config: Config | None) -> int | None: """Get `maxsize` configuration for saferepr based on the given config object.""" if config is None: verbosity = 0 @@ -543,14 +539,14 @@ def traverse_node(node: ast.AST) -> Iterator[ast.AST]: @functools.lru_cache(maxsize=1) -def _get_assertion_exprs(src: bytes) -> Dict[int, str]: +def _get_assertion_exprs(src: bytes) -> dict[int, str]: """Return a mapping from {lineno: "assertion test expression"}.""" - ret: Dict[int, str] = {} + ret: dict[int, str] = {} depth = 0 - lines: List[str] = [] - assert_lineno: Optional[int] = None - seen_lines: Set[int] = set() + lines: list[str] = [] + assert_lineno: int | None = None + seen_lines: set[int] = set() def _write_and_reset() -> None: nonlocal depth, lines, assert_lineno, seen_lines @@ -657,7 +653,7 @@ class AssertionRewriter(ast.NodeVisitor): """ def __init__( - self, module_path: Optional[str], config: Optional[Config], source: bytes + self, module_path: str | None, config: Config | None, source: bytes ) -> None: super().__init__() self.module_path = module_path @@ -670,7 +666,7 @@ def __init__( self.enable_assertion_pass_hook = False self.source = source self.scope: tuple[ast.AST, ...] = () - self.variables_overwrite: defaultdict[tuple[ast.AST, ...], Dict[str, str]] = ( + self.variables_overwrite: defaultdict[tuple[ast.AST, ...], dict[str, str]] = ( defaultdict(dict) ) @@ -737,7 +733,7 @@ def run(self, mod: ast.Module) -> None: # Collect asserts. self.scope = (mod,) - nodes: List[Union[ast.AST, Sentinel]] = [mod] + nodes: list[ast.AST | Sentinel] = [mod] while nodes: node = nodes.pop() if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)): @@ -749,7 +745,7 @@ def run(self, mod: ast.Module) -> None: assert isinstance(node, ast.AST) for name, field in ast.iter_fields(node): if isinstance(field, list): - new: List[ast.AST] = [] + new: list[ast.AST] = [] for i, child in enumerate(field): if isinstance(child, ast.Assert): # Transform assert. @@ -821,7 +817,7 @@ def push_format_context(self) -> None: to format a string of %-formatted values as added by .explanation_param(). """ - self.explanation_specifiers: Dict[str, ast.expr] = {} + self.explanation_specifiers: dict[str, ast.expr] = {} self.stack.append(self.explanation_specifiers) def pop_format_context(self, expl_expr: ast.expr) -> ast.Name: @@ -835,7 +831,7 @@ def pop_format_context(self, expl_expr: ast.expr) -> ast.Name: current = self.stack.pop() if self.stack: self.explanation_specifiers = self.stack[-1] - keys: List[Optional[ast.expr]] = [ast.Constant(key) for key in current.keys()] + keys: list[ast.expr | None] = [ast.Constant(key) for key in current.keys()] format_dict = ast.Dict(keys, list(current.values())) form = ast.BinOp(expl_expr, ast.Mod(), format_dict) name = "@py_format" + str(next(self.variable_counter)) @@ -844,13 +840,13 @@ def pop_format_context(self, expl_expr: ast.expr) -> ast.Name: self.expl_stmts.append(ast.Assign([ast.Name(name, ast.Store())], form)) return ast.Name(name, ast.Load()) - def generic_visit(self, node: ast.AST) -> Tuple[ast.Name, str]: + def generic_visit(self, node: ast.AST) -> tuple[ast.Name, str]: """Handle expressions we don't have custom code for.""" assert isinstance(node, ast.expr) res = self.assign(node) return res, self.explanation_param(self.display(res)) - def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: + def visit_Assert(self, assert_: ast.Assert) -> list[ast.stmt]: """Return the AST statements to replace the ast.Assert instance. This rewrites the test of an assertion to provide @@ -874,15 +870,15 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: lineno=assert_.lineno, ) - self.statements: List[ast.stmt] = [] - self.variables: List[str] = [] + self.statements: list[ast.stmt] = [] + self.variables: list[str] = [] self.variable_counter = itertools.count() if self.enable_assertion_pass_hook: - self.format_variables: List[str] = [] + self.format_variables: list[str] = [] - self.stack: List[Dict[str, ast.expr]] = [] - self.expl_stmts: List[ast.stmt] = [] + self.stack: list[dict[str, ast.expr]] = [] + self.expl_stmts: list[ast.stmt] = [] self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) @@ -926,13 +922,13 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: [*self.expl_stmts, hook_call_pass], [], ) - statements_pass: List[ast.stmt] = [hook_impl_test] + statements_pass: list[ast.stmt] = [hook_impl_test] # Test for assertion condition main_test = ast.If(negation, statements_fail, statements_pass) self.statements.append(main_test) if self.format_variables: - variables: List[ast.expr] = [ + variables: list[ast.expr] = [ ast.Name(name, ast.Store()) for name in self.format_variables ] clear_format = ast.Assign(variables, ast.Constant(None)) @@ -968,7 +964,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]: ast.copy_location(node, assert_) return self.statements - def visit_NamedExpr(self, name: ast.NamedExpr) -> Tuple[ast.NamedExpr, str]: + def visit_NamedExpr(self, name: ast.NamedExpr) -> tuple[ast.NamedExpr, str]: # This method handles the 'walrus operator' repr of the target # name if it's a local variable or _should_repr_global_name() # thinks it's acceptable. @@ -980,7 +976,7 @@ def visit_NamedExpr(self, name: ast.NamedExpr) -> Tuple[ast.NamedExpr, str]: expr = ast.IfExp(test, self.display(name), ast.Constant(target_id)) return name, self.explanation_param(expr) - def visit_Name(self, name: ast.Name) -> Tuple[ast.Name, str]: + def visit_Name(self, name: ast.Name) -> tuple[ast.Name, str]: # Display the repr of the name if it's a local variable or # _should_repr_global_name() thinks it's acceptable. locs = ast.Call(self.builtin("locals"), [], []) @@ -990,7 +986,7 @@ def visit_Name(self, name: ast.Name) -> Tuple[ast.Name, str]: expr = ast.IfExp(test, self.display(name), ast.Constant(name.id)) return name, self.explanation_param(expr) - def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: + def visit_BoolOp(self, boolop: ast.BoolOp) -> tuple[ast.Name, str]: res_var = self.variable() expl_list = self.assign(ast.List([], ast.Load())) app = ast.Attribute(expl_list, "append", ast.Load()) @@ -1002,7 +998,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: # Process each operand, short-circuiting if needed. for i, v in enumerate(boolop.values): if i: - fail_inner: List[ast.stmt] = [] + fail_inner: list[ast.stmt] = [] # cond is set in a prior loop iteration below self.expl_stmts.append(ast.If(cond, fail_inner, [])) # noqa: F821 self.expl_stmts = fail_inner @@ -1030,7 +1026,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: cond: ast.expr = res if is_or: cond = ast.UnaryOp(ast.Not(), cond) - inner: List[ast.stmt] = [] + inner: list[ast.stmt] = [] self.statements.append(ast.If(cond, inner, [])) self.statements = body = inner self.statements = save @@ -1039,13 +1035,13 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> Tuple[ast.Name, str]: expl = self.pop_format_context(expl_template) return ast.Name(res_var, ast.Load()), self.explanation_param(expl) - def visit_UnaryOp(self, unary: ast.UnaryOp) -> Tuple[ast.Name, str]: + def visit_UnaryOp(self, unary: ast.UnaryOp) -> tuple[ast.Name, str]: pattern = UNARY_MAP[unary.op.__class__] operand_res, operand_expl = self.visit(unary.operand) res = self.assign(ast.UnaryOp(unary.op, operand_res)) return res, pattern % (operand_expl,) - def visit_BinOp(self, binop: ast.BinOp) -> Tuple[ast.Name, str]: + def visit_BinOp(self, binop: ast.BinOp) -> tuple[ast.Name, str]: symbol = BINOP_MAP[binop.op.__class__] left_expr, left_expl = self.visit(binop.left) right_expr, right_expl = self.visit(binop.right) @@ -1053,7 +1049,7 @@ def visit_BinOp(self, binop: ast.BinOp) -> Tuple[ast.Name, str]: res = self.assign(ast.BinOp(left_expr, binop.op, right_expr)) return res, explanation - def visit_Call(self, call: ast.Call) -> Tuple[ast.Name, str]: + def visit_Call(self, call: ast.Call) -> tuple[ast.Name, str]: new_func, func_expl = self.visit(call.func) arg_expls = [] new_args = [] @@ -1085,13 +1081,13 @@ def visit_Call(self, call: ast.Call) -> Tuple[ast.Name, str]: outer_expl = f"{res_expl}\n{{{res_expl} = {expl}\n}}" return res, outer_expl - def visit_Starred(self, starred: ast.Starred) -> Tuple[ast.Starred, str]: + def visit_Starred(self, starred: ast.Starred) -> tuple[ast.Starred, str]: # A Starred node can appear in a function call. res, expl = self.visit(starred.value) new_starred = ast.Starred(res, starred.ctx) return new_starred, "*" + expl - def visit_Attribute(self, attr: ast.Attribute) -> Tuple[ast.Name, str]: + def visit_Attribute(self, attr: ast.Attribute) -> tuple[ast.Name, str]: if not isinstance(attr.ctx, ast.Load): return self.generic_visit(attr) value, value_expl = self.visit(attr.value) @@ -1101,7 +1097,7 @@ def visit_Attribute(self, attr: ast.Attribute) -> Tuple[ast.Name, str]: expl = pat % (res_expl, res_expl, value_expl, attr.attr) return res, expl - def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: + def visit_Compare(self, comp: ast.Compare) -> tuple[ast.expr, str]: self.push_format_context() # We first check if we have overwritten a variable in the previous assert if isinstance( @@ -1114,11 +1110,11 @@ def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]: if isinstance(comp.left, (ast.Compare, ast.BoolOp)): left_expl = f"({left_expl})" res_variables = [self.variable() for i in range(len(comp.ops))] - load_names: List[ast.expr] = [ast.Name(v, ast.Load()) for v in res_variables] + load_names: list[ast.expr] = [ast.Name(v, ast.Load()) for v in res_variables] store_names = [ast.Name(v, ast.Store()) for v in res_variables] it = zip(range(len(comp.ops)), comp.ops, comp.comparators) - expls: List[ast.expr] = [] - syms: List[ast.expr] = [] + expls: list[ast.expr] = [] + syms: list[ast.expr] = [] results = [left_res] for i, op, next_operand in it: if ( diff --git a/src/_pytest/assertion/truncate.py b/src/_pytest/assertion/truncate.py index 4fdfd86a519..b67f02ccaf8 100644 --- a/src/_pytest/assertion/truncate.py +++ b/src/_pytest/assertion/truncate.py @@ -4,8 +4,7 @@ terminal lines, unless running with an assertions verbosity level of at least 2 or running on CI. """ -from typing import List -from typing import Optional +from __future__ import annotations from _pytest.assertion import util from _pytest.config import Config @@ -18,8 +17,8 @@ def truncate_if_required( - explanation: List[str], item: Item, max_length: Optional[int] = None -) -> List[str]: + explanation: list[str], item: Item, max_length: int | None = None +) -> list[str]: """Truncate this assertion explanation if the given test item is eligible.""" if _should_truncate_item(item): return _truncate_explanation(explanation) @@ -33,10 +32,10 @@ def _should_truncate_item(item: Item) -> bool: def _truncate_explanation( - input_lines: List[str], - max_lines: Optional[int] = None, - max_chars: Optional[int] = None, -) -> List[str]: + input_lines: list[str], + max_lines: int | None = None, + max_chars: int | None = None, +) -> list[str]: """Truncate given list of strings that makes up the assertion explanation. Truncates to either 8 lines, or 640 characters - whichever the input reaches @@ -100,7 +99,7 @@ def _truncate_explanation( ] -def _truncate_by_char_count(input_lines: List[str], max_chars: int) -> List[str]: +def _truncate_by_char_count(input_lines: list[str], max_chars: int) -> list[str]: # Find point at which input length exceeds total allowed length iterated_char_count = 0 for iterated_index, input_line in enumerate(input_lines): diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index a118befcc16..4dc1af4af03 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Utilities for assertion debugging.""" +from __future__ import annotations + import collections.abc import os import pprint @@ -8,10 +10,8 @@ from typing import Any from typing import Callable from typing import Iterable -from typing import List from typing import Literal from typing import Mapping -from typing import Optional from typing import Protocol from typing import Sequence from unicodedata import normalize @@ -28,14 +28,14 @@ # interpretation code and assertion rewriter to detect this plugin was # loaded and in turn call the hooks defined here as part of the # DebugInterpreter. -_reprcompare: Optional[Callable[[str, object, object], Optional[str]]] = None +_reprcompare: Callable[[str, object, object], str | None] | None = None # Works similarly as _reprcompare attribute. Is populated with the hook call # when pytest_runtest_setup is called. -_assertion_pass: Optional[Callable[[int, str, str], None]] = None +_assertion_pass: Callable[[int, str, str], None] | None = None # Config object which is assigned during pytest_runtest_protocol. -_config: Optional[Config] = None +_config: Config | None = None class _HighlightFunc(Protocol): @@ -58,7 +58,7 @@ def format_explanation(explanation: str) -> str: return "\n".join(result) -def _split_explanation(explanation: str) -> List[str]: +def _split_explanation(explanation: str) -> list[str]: r"""Return a list of individual lines in the explanation. This will return a list of lines split on '\n{', '\n}' and '\n~'. @@ -75,7 +75,7 @@ def _split_explanation(explanation: str) -> List[str]: return lines -def _format_lines(lines: Sequence[str]) -> List[str]: +def _format_lines(lines: Sequence[str]) -> list[str]: """Format the individual lines. This will replace the '{', '}' and '~' characters of our mini formatting @@ -169,7 +169,7 @@ def has_default_eq( def assertrepr_compare( config, op: str, left: Any, right: Any, use_ascii: bool = False -) -> Optional[List[str]]: +) -> list[str] | None: """Return specialised explanations for some operators/operands.""" verbose = config.get_verbosity(Config.VERBOSITY_ASSERTIONS) @@ -239,7 +239,7 @@ def assertrepr_compare( def _compare_eq_any( left: Any, right: Any, highlighter: _HighlightFunc, verbose: int = 0 -) -> List[str]: +) -> list[str]: explanation = [] if istext(left) and istext(right): explanation = _diff_text(left, right, verbose) @@ -274,7 +274,7 @@ def _compare_eq_any( return explanation -def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]: +def _diff_text(left: str, right: str, verbose: int = 0) -> list[str]: """Return the explanation for the diff between text. Unless --verbose is used this will skip leading and trailing @@ -282,7 +282,7 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> List[str]: """ from difflib import ndiff - explanation: List[str] = [] + explanation: list[str] = [] if verbose < 1: i = 0 # just in case left or right has zero length @@ -327,7 +327,7 @@ def _compare_eq_iterable( right: Iterable[Any], highlighter: _HighlightFunc, verbose: int = 0, -) -> List[str]: +) -> list[str]: if verbose <= 0 and not running_on_ci(): return ["Use -v to get more diff"] # dynamic import to speedup pytest @@ -356,9 +356,9 @@ def _compare_eq_sequence( right: Sequence[Any], highlighter: _HighlightFunc, verbose: int = 0, -) -> List[str]: +) -> list[str]: comparing_bytes = isinstance(left, bytes) and isinstance(right, bytes) - explanation: List[str] = [] + explanation: list[str] = [] len_left = len(left) len_right = len(right) for i in range(min(len_left, len_right)): @@ -417,7 +417,7 @@ def _compare_eq_set( right: AbstractSet[Any], highlighter: _HighlightFunc, verbose: int = 0, -) -> List[str]: +) -> list[str]: explanation = [] explanation.extend(_set_one_sided_diff("left", left, right, highlighter)) explanation.extend(_set_one_sided_diff("right", right, left, highlighter)) @@ -429,7 +429,7 @@ def _compare_gt_set( right: AbstractSet[Any], highlighter: _HighlightFunc, verbose: int = 0, -) -> List[str]: +) -> list[str]: explanation = _compare_gte_set(left, right, highlighter) if not explanation: return ["Both sets are equal"] @@ -441,7 +441,7 @@ def _compare_lt_set( right: AbstractSet[Any], highlighter: _HighlightFunc, verbose: int = 0, -) -> List[str]: +) -> list[str]: explanation = _compare_lte_set(left, right, highlighter) if not explanation: return ["Both sets are equal"] @@ -453,7 +453,7 @@ def _compare_gte_set( right: AbstractSet[Any], highlighter: _HighlightFunc, verbose: int = 0, -) -> List[str]: +) -> list[str]: return _set_one_sided_diff("right", right, left, highlighter) @@ -462,7 +462,7 @@ def _compare_lte_set( right: AbstractSet[Any], highlighter: _HighlightFunc, verbose: int = 0, -) -> List[str]: +) -> list[str]: return _set_one_sided_diff("left", left, right, highlighter) @@ -471,7 +471,7 @@ def _set_one_sided_diff( set1: AbstractSet[Any], set2: AbstractSet[Any], highlighter: _HighlightFunc, -) -> List[str]: +) -> list[str]: explanation = [] diff = set1 - set2 if diff: @@ -486,8 +486,8 @@ def _compare_eq_dict( right: Mapping[Any, Any], highlighter: _HighlightFunc, verbose: int = 0, -) -> List[str]: - explanation: List[str] = [] +) -> list[str]: + explanation: list[str] = [] set_left = set(left) set_right = set(right) common = set_left.intersection(set_right) @@ -531,7 +531,7 @@ def _compare_eq_dict( def _compare_eq_cls( left: Any, right: Any, highlighter: _HighlightFunc, verbose: int -) -> List[str]: +) -> list[str]: if not has_default_eq(left): return [] if isdatacls(left): @@ -584,7 +584,7 @@ def _compare_eq_cls( return explanation -def _notin_text(term: str, text: str, verbose: int = 0) -> List[str]: +def _notin_text(term: str, text: str, verbose: int = 0) -> list[str]: index = text.find(term) head = text[:index] tail = text[index + len(term) :] diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 8ad36f9b91c..51778c456c4 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -3,20 +3,17 @@ # This plugin was not named "cache" to avoid conflicts with the external # pytest-cache version. +from __future__ import annotations + import dataclasses import errno import json import os from pathlib import Path import tempfile -from typing import Dict from typing import final from typing import Generator from typing import Iterable -from typing import List -from typing import Optional -from typing import Set -from typing import Union from .pathlib import resolve_from_str from .pathlib import rm_rf @@ -77,7 +74,7 @@ def __init__( self._config = config @classmethod - def for_config(cls, config: Config, *, _ispytest: bool = False) -> "Cache": + def for_config(cls, config: Config, *, _ispytest: bool = False) -> Cache: """Create the Cache instance for a Config. :meta private: @@ -249,7 +246,7 @@ def _ensure_cache_dir_and_supporting_files(self) -> None: class LFPluginCollWrapper: - def __init__(self, lfplugin: "LFPlugin") -> None: + def __init__(self, lfplugin: LFPlugin) -> None: self.lfplugin = lfplugin self._collected_at_least_one_failure = False @@ -263,7 +260,7 @@ def pytest_make_collect_report( lf_paths = self.lfplugin._last_failed_paths # Use stable sort to prioritize last failed. - def sort_key(node: Union[nodes.Item, nodes.Collector]) -> bool: + def sort_key(node: nodes.Item | nodes.Collector) -> bool: return node.path in lf_paths res.result = sorted( @@ -301,13 +298,13 @@ def sort_key(node: Union[nodes.Item, nodes.Collector]) -> bool: class LFPluginCollSkipfiles: - def __init__(self, lfplugin: "LFPlugin") -> None: + def __init__(self, lfplugin: LFPlugin) -> None: self.lfplugin = lfplugin @hookimpl def pytest_make_collect_report( self, collector: nodes.Collector - ) -> Optional[CollectReport]: + ) -> CollectReport | None: if isinstance(collector, File): if collector.path not in self.lfplugin._last_failed_paths: self.lfplugin._skipped_files += 1 @@ -326,9 +323,9 @@ def __init__(self, config: Config) -> None: active_keys = "lf", "failedfirst" self.active = any(config.getoption(key) for key in active_keys) assert config.cache - self.lastfailed: Dict[str, bool] = config.cache.get("cache/lastfailed", {}) - self._previously_failed_count: Optional[int] = None - self._report_status: Optional[str] = None + self.lastfailed: dict[str, bool] = config.cache.get("cache/lastfailed", {}) + self._previously_failed_count: int | None = None + self._report_status: str | None = None self._skipped_files = 0 # count skipped files during collection due to --lf if config.getoption("lf"): @@ -337,7 +334,7 @@ def __init__(self, config: Config) -> None: LFPluginCollWrapper(self), "lfplugin-collwrapper" ) - def get_last_failed_paths(self) -> Set[Path]: + def get_last_failed_paths(self) -> set[Path]: """Return a set with all Paths of the previously failed nodeids and their parents.""" rootpath = self.config.rootpath @@ -348,7 +345,7 @@ def get_last_failed_paths(self) -> Set[Path]: result.update(path.parents) return {x for x in result if x.exists()} - def pytest_report_collectionfinish(self) -> Optional[str]: + def pytest_report_collectionfinish(self) -> str | None: if self.active and self.config.getoption("verbose") >= 0: return f"run-last-failure: {self._report_status}" return None @@ -370,7 +367,7 @@ def pytest_collectreport(self, report: CollectReport) -> None: @hookimpl(wrapper=True, tryfirst=True) def pytest_collection_modifyitems( - self, config: Config, items: List[nodes.Item] + self, config: Config, items: list[nodes.Item] ) -> Generator[None, None, None]: res = yield @@ -442,13 +439,13 @@ def __init__(self, config: Config) -> None: @hookimpl(wrapper=True, tryfirst=True) def pytest_collection_modifyitems( - self, items: List[nodes.Item] + self, items: list[nodes.Item] ) -> Generator[None, None, None]: res = yield if self.active: - new_items: Dict[str, nodes.Item] = {} - other_items: Dict[str, nodes.Item] = {} + new_items: dict[str, nodes.Item] = {} + other_items: dict[str, nodes.Item] = {} for item in items: if item.nodeid not in self.cached_nodeids: new_items[item.nodeid] = item @@ -464,7 +461,7 @@ def pytest_collection_modifyitems( return res - def _get_increasing_order(self, items: Iterable[nodes.Item]) -> List[nodes.Item]: + def _get_increasing_order(self, items: Iterable[nodes.Item]) -> list[nodes.Item]: return sorted(items, key=lambda item: item.path.stat().st_mtime, reverse=True) def pytest_sessionfinish(self) -> None: @@ -541,7 +538,7 @@ def pytest_addoption(parser: Parser) -> None: ) -def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: +def pytest_cmdline_main(config: Config) -> int | ExitCode | None: if config.option.cacheshow and not config.option.help: from _pytest.main import wrap_session @@ -572,7 +569,7 @@ def cache(request: FixtureRequest) -> Cache: return request.config.cache -def pytest_report_header(config: Config) -> Optional[str]: +def pytest_report_header(config: Config) -> str | None: """Display cachedir with --cache-show and if non-default.""" if config.option.verbose > 0 or config.getini("cache_dir") != ".pytest_cache": assert config.cache is not None diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 89a938d5416..c4dfcc27552 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Per-test stdout/stderr capturing mechanism.""" +from __future__ import annotations + import abc import collections import contextlib @@ -19,15 +21,14 @@ from typing import Generic from typing import Iterable from typing import Iterator -from typing import List from typing import Literal from typing import NamedTuple -from typing import Optional from typing import TextIO -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING -from typing import Union + + +if TYPE_CHECKING: + from typing_extensions import Self from _pytest.config import Config from _pytest.config import hookimpl @@ -213,7 +214,7 @@ def read(self, size: int = -1) -> str: def __next__(self) -> str: return self.readline() - def readlines(self, hint: Optional[int] = -1) -> List[str]: + def readlines(self, hint: int | None = -1) -> list[str]: raise OSError( "pytest: reading from stdin while output is captured! Consider using `-s`." ) @@ -245,7 +246,7 @@ def seekable(self) -> bool: def tell(self) -> int: raise UnsupportedOperation("redirected stdin is pseudofile, has no tell()") - def truncate(self, size: Optional[int] = None) -> int: + def truncate(self, size: int | None = None) -> int: raise UnsupportedOperation("cannot truncate stdin") def write(self, data: str) -> int: @@ -257,14 +258,14 @@ def writelines(self, lines: Iterable[str]) -> None: def writable(self) -> bool: return False - def __enter__(self) -> "DontReadFromInput": + def __enter__(self) -> Self: return self def __exit__( self, - type: Optional[Type[BaseException]], - value: Optional[BaseException], - traceback: Optional[TracebackType], + type: type[BaseException] | None, + value: BaseException | None, + traceback: TracebackType | None, ) -> None: pass @@ -339,7 +340,7 @@ def writeorg(self, data: str) -> None: class SysCaptureBase(CaptureBase[AnyStr]): def __init__( - self, fd: int, tmpfile: Optional[TextIO] = None, *, tee: bool = False + self, fd: int, tmpfile: TextIO | None = None, *, tee: bool = False ) -> None: name = patchsysdict[fd] self._old: TextIO = getattr(sys, name) @@ -370,7 +371,7 @@ def __repr__(self) -> str: self.tmpfile, ) - def _assert_state(self, op: str, states: Tuple[str, ...]) -> None: + def _assert_state(self, op: str, states: tuple[str, ...]) -> None: assert ( self._state in states ), "cannot {} in state {!r}: expected one of {}".format( @@ -457,7 +458,7 @@ def __init__(self, targetfd: int) -> None: # Further complications are the need to support suspend() and the # possibility of FD reuse (e.g. the tmpfile getting the very same # target FD). The following approach is robust, I believe. - self.targetfd_invalid: Optional[int] = os.open(os.devnull, os.O_RDWR) + self.targetfd_invalid: int | None = os.open(os.devnull, os.O_RDWR) os.dup2(self.targetfd_invalid, targetfd) else: self.targetfd_invalid = None @@ -487,7 +488,7 @@ def __repr__(self) -> str: f"_state={self._state!r} tmpfile={self.tmpfile!r}>" ) - def _assert_state(self, op: str, states: Tuple[str, ...]) -> None: + def _assert_state(self, op: str, states: tuple[str, ...]) -> None: assert ( self._state in states ), "cannot {} in state {!r}: expected one of {}".format( @@ -609,13 +610,13 @@ class MultiCapture(Generic[AnyStr]): def __init__( self, - in_: Optional[CaptureBase[AnyStr]], - out: Optional[CaptureBase[AnyStr]], - err: Optional[CaptureBase[AnyStr]], + in_: CaptureBase[AnyStr] | None, + out: CaptureBase[AnyStr] | None, + err: CaptureBase[AnyStr] | None, ) -> None: - self.in_: Optional[CaptureBase[AnyStr]] = in_ - self.out: Optional[CaptureBase[AnyStr]] = out - self.err: Optional[CaptureBase[AnyStr]] = err + self.in_: CaptureBase[AnyStr] | None = in_ + self.out: CaptureBase[AnyStr] | None = out + self.err: CaptureBase[AnyStr] | None = err def __repr__(self) -> str: return ( @@ -632,7 +633,7 @@ def start_capturing(self) -> None: if self.err: self.err.start() - def pop_outerr_to_orig(self) -> Tuple[AnyStr, AnyStr]: + def pop_outerr_to_orig(self) -> tuple[AnyStr, AnyStr]: """Pop current snapshot out/err capture and flush to orig streams.""" out, err = self.readouterr() if out: @@ -725,8 +726,8 @@ class CaptureManager: def __init__(self, method: _CaptureMethod) -> None: self._method: Final = method - self._global_capturing: Optional[MultiCapture[str]] = None - self._capture_fixture: Optional[CaptureFixture[Any]] = None + self._global_capturing: MultiCapture[str] | None = None + self._capture_fixture: CaptureFixture[Any] | None = None def __repr__(self) -> str: return ( @@ -734,7 +735,7 @@ def __repr__(self) -> str: f"_capture_fixture={self._capture_fixture!r}>" ) - def is_capturing(self) -> Union[str, bool]: + def is_capturing(self) -> str | bool: if self.is_globally_capturing(): return "global" if self._capture_fixture: @@ -782,7 +783,7 @@ def read_global_capture(self) -> CaptureResult[str]: # Fixture Control - def set_fixture(self, capture_fixture: "CaptureFixture[Any]") -> None: + def set_fixture(self, capture_fixture: CaptureFixture[Any]) -> None: if self._capture_fixture: current_fixture = self._capture_fixture.request.fixturename requested_fixture = capture_fixture.request.fixturename @@ -897,15 +898,15 @@ class CaptureFixture(Generic[AnyStr]): def __init__( self, - captureclass: Type[CaptureBase[AnyStr]], + captureclass: type[CaptureBase[AnyStr]], request: SubRequest, *, _ispytest: bool = False, ) -> None: check_ispytest(_ispytest) - self.captureclass: Type[CaptureBase[AnyStr]] = captureclass + self.captureclass: type[CaptureBase[AnyStr]] = captureclass self.request = request - self._capture: Optional[MultiCapture[AnyStr]] = None + self._capture: MultiCapture[AnyStr] | None = None self._captured_out: AnyStr = self.captureclass.EMPTY_BUFFER self._captured_err: AnyStr = self.captureclass.EMPTY_BUFFER diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 058aaa1ff30..47e3f5b5a50 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Command line options, ini-file and conftest.py processing.""" +from __future__ import annotations + import argparse import collections.abc import copy @@ -21,22 +23,16 @@ from typing import Any from typing import Callable from typing import cast -from typing import Dict from typing import Final from typing import final from typing import Generator from typing import IO from typing import Iterable from typing import Iterator -from typing import List -from typing import Optional from typing import Sequence -from typing import Set from typing import TextIO -from typing import Tuple from typing import Type from typing import TYPE_CHECKING -from typing import Union import warnings import pluggy @@ -141,9 +137,9 @@ def filter_traceback_for_conftest_import_failure( def main( - args: Optional[Union[List[str], "os.PathLike[str]"]] = None, - plugins: Optional[Sequence[Union[str, _PluggyPlugin]]] = None, -) -> Union[int, ExitCode]: + args: list[str] | os.PathLike[str] | None = None, + plugins: Sequence[str | _PluggyPlugin] | None = None, +) -> int | ExitCode: """Perform an in-process test run. :param args: @@ -176,9 +172,7 @@ def main( return ExitCode.USAGE_ERROR else: try: - ret: Union[ExitCode, int] = config.hook.pytest_cmdline_main( - config=config - ) + ret: ExitCode | int = config.hook.pytest_cmdline_main(config=config) try: return ExitCode(ret) except ValueError: @@ -286,9 +280,9 @@ def directory_arg(path: str, optname: str) -> str: def get_config( - args: Optional[List[str]] = None, - plugins: Optional[Sequence[Union[str, _PluggyPlugin]]] = None, -) -> "Config": + args: list[str] | None = None, + plugins: Sequence[str | _PluggyPlugin] | None = None, +) -> Config: # subsequent calls to main will create a fresh instance pluginmanager = PytestPluginManager() config = Config( @@ -310,7 +304,7 @@ def get_config( return config -def get_plugin_manager() -> "PytestPluginManager": +def get_plugin_manager() -> PytestPluginManager: """Obtain a new instance of the :py:class:`pytest.PytestPluginManager`, with default plugins already loaded. @@ -322,9 +316,9 @@ def get_plugin_manager() -> "PytestPluginManager": def _prepareconfig( - args: Optional[Union[List[str], "os.PathLike[str]"]] = None, - plugins: Optional[Sequence[Union[str, _PluggyPlugin]]] = None, -) -> "Config": + args: list[str] | os.PathLike[str] | None = None, + plugins: Sequence[str | _PluggyPlugin] | None = None, +) -> Config: if args is None: args = sys.argv[1:] elif isinstance(args, os.PathLike): @@ -364,14 +358,14 @@ def _get_directory(path: Path) -> Path: def _get_legacy_hook_marks( method: Any, hook_type: str, - opt_names: Tuple[str, ...], -) -> Dict[str, bool]: + opt_names: tuple[str, ...], +) -> dict[str, bool]: if TYPE_CHECKING: # abuse typeguard from importlib to avoid massive method type union thats lacking a alias assert inspect.isroutine(method) - known_marks: Set[str] = {m.name for m in getattr(method, "pytestmark", [])} - must_warn: List[str] = [] - opts: Dict[str, bool] = {} + known_marks: set[str] = {m.name for m in getattr(method, "pytestmark", [])} + must_warn: list[str] = [] + opts: dict[str, bool] = {} for opt_name in opt_names: opt_attr = getattr(method, opt_name, AttributeError) if opt_attr is not AttributeError: @@ -410,13 +404,13 @@ def __init__(self) -> None: # -- State related to local conftest plugins. # All loaded conftest modules. - self._conftest_plugins: Set[types.ModuleType] = set() + self._conftest_plugins: set[types.ModuleType] = set() # All conftest modules applicable for a directory. # This includes the directory's own conftest modules as well # as those of its parent directories. - self._dirpath2confmods: Dict[Path, List[types.ModuleType]] = {} + self._dirpath2confmods: dict[Path, list[types.ModuleType]] = {} # Cutoff directory above which conftests are no longer discovered. - self._confcutdir: Optional[Path] = None + self._confcutdir: Path | None = None # If set, conftest loading is skipped. self._noconftest = False @@ -430,7 +424,7 @@ def __init__(self) -> None: # previously we would issue a warning when a plugin was skipped, but # since we refactored warnings as first citizens of Config, they are # just stored here to be used later. - self.skipped_plugins: List[Tuple[str, str]] = [] + self.skipped_plugins: list[tuple[str, str]] = [] self.add_hookspecs(_pytest.hookspec) self.register(self) @@ -456,7 +450,7 @@ def __init__(self) -> None: def parse_hookimpl_opts( self, plugin: _PluggyPlugin, name: str - ) -> Optional[HookimplOpts]: + ) -> HookimplOpts | None: """:meta private:""" # pytest hooks are always prefixed with "pytest_", # so we avoid accessing possibly non-readable attributes @@ -480,7 +474,7 @@ def parse_hookimpl_opts( method, "impl", ("tryfirst", "trylast", "optionalhook", "hookwrapper") ) - def parse_hookspec_opts(self, module_or_class, name: str) -> Optional[HookspecOpts]: + def parse_hookspec_opts(self, module_or_class, name: str) -> HookspecOpts | None: """:meta private:""" opts = super().parse_hookspec_opts(module_or_class, name) if opts is None: @@ -493,9 +487,7 @@ def parse_hookspec_opts(self, module_or_class, name: str) -> Optional[HookspecOp ) return opts - def register( - self, plugin: _PluggyPlugin, name: Optional[str] = None - ) -> Optional[str]: + def register(self, plugin: _PluggyPlugin, name: str | None = None) -> str | None: if name in _pytest.deprecated.DEPRECATED_EXTERNAL_PLUGINS: warnings.warn( PytestConfigWarning( @@ -522,14 +514,14 @@ def register( def getplugin(self, name: str): # Support deprecated naming because plugins (xdist e.g.) use it. - plugin: Optional[_PluggyPlugin] = self.get_plugin(name) + plugin: _PluggyPlugin | None = self.get_plugin(name) return plugin def hasplugin(self, name: str) -> bool: """Return whether a plugin with the given name is registered.""" return bool(self.get_plugin(name)) - def pytest_configure(self, config: "Config") -> None: + def pytest_configure(self, config: Config) -> None: """:meta private:""" # XXX now that the pluginmanager exposes hookimpl(tryfirst...) # we should remove tryfirst/trylast as markers. @@ -552,13 +544,13 @@ def pytest_configure(self, config: "Config") -> None: # def _set_initial_conftests( self, - args: Sequence[Union[str, Path]], + args: Sequence[str | Path], pyargs: bool, noconftest: bool, rootpath: Path, - confcutdir: Optional[Path], + confcutdir: Path | None, invocation_dir: Path, - importmode: Union[ImportMode, str], + importmode: ImportMode | str, *, consider_namespace_packages: bool, ) -> None: @@ -619,7 +611,7 @@ def _is_in_confcutdir(self, path: Path) -> bool: def _try_load_conftest( self, anchor: Path, - importmode: Union[str, ImportMode], + importmode: str | ImportMode, rootpath: Path, *, consider_namespace_packages: bool, @@ -644,7 +636,7 @@ def _try_load_conftest( def _loadconftestmodules( self, path: Path, - importmode: Union[str, ImportMode], + importmode: str | ImportMode, rootpath: Path, *, consider_namespace_packages: bool, @@ -681,7 +673,7 @@ def _rget_with_confmod( self, name: str, path: Path, - ) -> Tuple[types.ModuleType, Any]: + ) -> tuple[types.ModuleType, Any]: modules = self._getconftestmodules(path) for mod in reversed(modules): try: @@ -693,7 +685,7 @@ def _rget_with_confmod( def _importconftest( self, conftestpath: Path, - importmode: Union[str, ImportMode], + importmode: str | ImportMode, rootpath: Path, *, consider_namespace_packages: bool, @@ -832,7 +824,7 @@ def consider_module(self, mod: types.ModuleType) -> None: self._import_plugin_specs(getattr(mod, "pytest_plugins", [])) def _import_plugin_specs( - self, spec: Union[None, types.ModuleType, str, Sequence[str]] + self, spec: None | types.ModuleType | str | Sequence[str] ) -> None: plugins = _get_plugin_specs_as_list(spec) for import_spec in plugins: @@ -877,8 +869,8 @@ def import_plugin(self, modname: str, consider_entry_points: bool = False) -> No def _get_plugin_specs_as_list( - specs: Union[None, types.ModuleType, str, Sequence[str]], -) -> List[str]: + specs: None | types.ModuleType | str | Sequence[str], +) -> list[str]: """Parse a plugins specification into a list of plugin names.""" # None means empty. if specs is None: @@ -999,9 +991,9 @@ class InvocationParams: Plugins accessing ``InvocationParams`` must be aware of that. """ - args: Tuple[str, ...] + args: tuple[str, ...] """The command-line arguments as passed to :func:`pytest.main`.""" - plugins: Optional[Sequence[Union[str, _PluggyPlugin]]] + plugins: Sequence[str | _PluggyPlugin] | None """Extra plugins, might be `None`.""" dir: Path """The directory from which :func:`pytest.main` was invoked.""" @@ -1010,7 +1002,7 @@ def __init__( self, *, args: Iterable[str], - plugins: Optional[Sequence[Union[str, _PluggyPlugin]]], + plugins: Sequence[str | _PluggyPlugin] | None, dir: Path, ) -> None: object.__setattr__(self, "args", tuple(args)) @@ -1032,13 +1024,13 @@ class ArgsSource(enum.Enum): TESTPATHS = enum.auto() # Set by cacheprovider plugin. - cache: Optional["Cache"] + cache: Cache | None def __init__( self, pluginmanager: PytestPluginManager, *, - invocation_params: Optional[InvocationParams] = None, + invocation_params: InvocationParams | None = None, ) -> None: from .argparsing import FILE_OR_DIR from .argparsing import Parser @@ -1083,17 +1075,17 @@ def __init__( self.trace = self.pluginmanager.trace.root.get("config") self.hook: pluggy.HookRelay = PathAwareHookProxy(self.pluginmanager.hook) # type: ignore[assignment] - self._inicache: Dict[str, Any] = {} + self._inicache: dict[str, Any] = {} self._override_ini: Sequence[str] = () - self._opt2dest: Dict[str, str] = {} - self._cleanup: List[Callable[[], None]] = [] + self._opt2dest: dict[str, str] = {} + self._cleanup: list[Callable[[], None]] = [] self.pluginmanager.register(self, "pytestconfig") self._configured = False self.hook.pytest_addoption.call_historic( kwargs=dict(parser=self._parser, pluginmanager=self.pluginmanager) ) self.args_source = Config.ArgsSource.ARGS - self.args: List[str] = [] + self.args: list[str] = [] @property def rootpath(self) -> Path: @@ -1106,7 +1098,7 @@ def rootpath(self) -> Path: return self._rootpath @property - def inipath(self) -> Optional[Path]: + def inipath(self) -> Path | None: """The path to the :ref:`configfile `. :type: Optional[pathlib.Path] @@ -1137,15 +1129,15 @@ def _ensure_unconfigure(self) -> None: fin() def get_terminal_writer(self) -> TerminalWriter: - terminalreporter: Optional[TerminalReporter] = self.pluginmanager.get_plugin( + terminalreporter: TerminalReporter | None = self.pluginmanager.get_plugin( "terminalreporter" ) assert terminalreporter is not None return terminalreporter._tw def pytest_cmdline_parse( - self, pluginmanager: PytestPluginManager, args: List[str] - ) -> "Config": + self, pluginmanager: PytestPluginManager, args: list[str] + ) -> Config: try: self.parse(args) except UsageError: @@ -1171,7 +1163,7 @@ def pytest_cmdline_parse( def notify_exception( self, excinfo: ExceptionInfo[BaseException], - option: Optional[argparse.Namespace] = None, + option: argparse.Namespace | None = None, ) -> None: if option and getattr(option, "fulltrace", False): style: TracebackStyle = "long" @@ -1194,7 +1186,7 @@ def cwd_relative_nodeid(self, nodeid: str) -> str: return nodeid @classmethod - def fromdictargs(cls, option_dict, args) -> "Config": + def fromdictargs(cls, option_dict, args) -> Config: """Constructor usable for subprocesses.""" config = get_config(args) config.option.__dict__.update(option_dict) @@ -1203,7 +1195,7 @@ def fromdictargs(cls, option_dict, args) -> "Config": config.pluginmanager.consider_pluginarg(x) return config - def _processopt(self, opt: "Argument") -> None: + def _processopt(self, opt: Argument) -> None: for name in opt._short_opts + opt._long_opts: self._opt2dest[name] = opt.dest @@ -1212,7 +1204,7 @@ def _processopt(self, opt: "Argument") -> None: setattr(self.option, opt.dest, opt.default) @hookimpl(trylast=True) - def pytest_load_initial_conftests(self, early_config: "Config") -> None: + def pytest_load_initial_conftests(self, early_config: Config) -> None: # We haven't fully parsed the command line arguments yet, so # early_config.args it not set yet. But we need it for # discovering the initial conftests. So "pre-run" the logic here. @@ -1303,7 +1295,7 @@ def _mark_plugins_for_rewrite(self, hook) -> None: for name in _iter_rewritable_modules(package_files): hook.mark_rewrite(name) - def _validate_args(self, args: List[str], via: str) -> List[str]: + def _validate_args(self, args: list[str], via: str) -> list[str]: """Validate known args.""" self._parser._config_source_hint = via # type: ignore try: @@ -1318,13 +1310,13 @@ def _validate_args(self, args: List[str], via: str) -> List[str]: def _decide_args( self, *, - args: List[str], + args: list[str], pyargs: bool, - testpaths: List[str], + testpaths: list[str], invocation_dir: Path, rootpath: Path, warn: bool, - ) -> Tuple[List[str], ArgsSource]: + ) -> tuple[list[str], ArgsSource]: """Decide the args (initial paths/nodeids) to use given the relevant inputs. :param warn: Whether can issue warnings. @@ -1360,7 +1352,7 @@ def _decide_args( result = [str(invocation_dir)] return result, source - def _preparse(self, args: List[str], addopts: bool = True) -> None: + def _preparse(self, args: list[str], addopts: bool = True) -> None: if addopts: env_addopts = os.environ.get("PYTEST_ADDOPTS", "") if len(env_addopts): @@ -1484,11 +1476,11 @@ def _warn_or_fail_if_strict(self, message: str) -> None: self.issue_config_time_warning(PytestConfigWarning(message), stacklevel=3) - def _get_unknown_ini_keys(self) -> List[str]: + def _get_unknown_ini_keys(self) -> list[str]: parser_inicfg = self._parser._inidict return [name for name in self.inicfg if name not in parser_inicfg] - def parse(self, args: List[str], addopts: bool = True) -> None: + def parse(self, args: list[str], addopts: bool = True) -> None: # Parse given cmdline arguments into this config object. assert ( self.args == [] @@ -1592,7 +1584,7 @@ def getini(self, name: str): # Meant for easy monkeypatching by legacypath plugin. # Can be inlined back (with no cover removed) once legacypath is gone. - def _getini_unknown_type(self, name: str, type: str, value: Union[str, List[str]]): + def _getini_unknown_type(self, name: str, type: str, value: str | list[str]): msg = f"unknown configuration type: {type}" raise ValueError(msg, value) # pragma: no cover @@ -1648,14 +1640,14 @@ def _getini(self, name: str): else: return self._getini_unknown_type(name, type, value) - def _getconftest_pathlist(self, name: str, path: Path) -> Optional[List[Path]]: + def _getconftest_pathlist(self, name: str, path: Path) -> list[Path] | None: try: mod, relroots = self.pluginmanager._rget_with_confmod(name, path) except KeyError: return None assert mod.__file__ is not None modpath = Path(mod.__file__).parent - values: List[Path] = [] + values: list[Path] = [] for relroot in relroots: if isinstance(relroot, os.PathLike): relroot = Path(relroot) @@ -1665,7 +1657,7 @@ def _getconftest_pathlist(self, name: str, path: Path) -> Optional[List[Path]]: values.append(relroot) return values - def _get_override_ini_value(self, name: str) -> Optional[str]: + def _get_override_ini_value(self, name: str) -> str | None: value = None # override_ini is a list of "ini=value" options. # Always use the last item if multiple values are set for same ini-name, @@ -1720,7 +1712,7 @@ def getvalueorskip(self, name: str, path=None): VERBOSITY_TEST_CASES: Final = "test_cases" _VERBOSITY_INI_DEFAULT: Final = "auto" - def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: + def get_verbosity(self, verbosity_type: str | None = None) -> int: r"""Retrieve the verbosity level for a fine-grained verbosity type. :param verbosity_type: Verbosity type to get level for. If a level is @@ -1771,7 +1763,7 @@ def _verbosity_ini_name(verbosity_type: str) -> str: return f"verbosity_{verbosity_type}" @staticmethod - def _add_verbosity_ini(parser: "Parser", verbosity_type: str, help: str) -> None: + def _add_verbosity_ini(parser: Parser, verbosity_type: str, help: str) -> None: """Add a output verbosity configuration option for the given output type. :param parser: Parser for command line arguments and ini-file values. @@ -1827,7 +1819,7 @@ def _assertion_supported() -> bool: def create_terminal_writer( - config: Config, file: Optional[TextIO] = None + config: Config, file: TextIO | None = None ) -> TerminalWriter: """Create a TerminalWriter instance configured according to the options in the config object. @@ -1871,7 +1863,7 @@ def _strtobool(val: str) -> bool: @lru_cache(maxsize=50) def parse_warning_filter( arg: str, *, escape: bool -) -> Tuple["warnings._ActionKind", str, Type[Warning], str, int]: +) -> tuple[warnings._ActionKind, str, type[Warning], str, int]: """Parse a warnings filter string. This is copied from warnings._setoption with the following changes: @@ -1917,7 +1909,7 @@ def parse_warning_filter( except warnings._OptionError as e: raise UsageError(error_template.format(error=str(e))) from None try: - category: Type[Warning] = _resolve_warning_category(category_) + category: type[Warning] = _resolve_warning_category(category_) except Exception: exc_info = ExceptionInfo.from_current() exception_text = exc_info.getrepr(style="native") @@ -1940,7 +1932,7 @@ def parse_warning_filter( return action, message, category, module, lineno -def _resolve_warning_category(category: str) -> Type[Warning]: +def _resolve_warning_category(category: str) -> type[Warning]: """ Copied from warnings._getcategory, but changed so it lets exceptions (specially ImportErrors) propagate so we can get access to their tracebacks (#9218). diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index f270b864c6a..85aa4632702 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import argparse from gettext import gettext import os @@ -6,16 +8,12 @@ from typing import Any from typing import Callable from typing import cast -from typing import Dict from typing import final from typing import List from typing import Literal from typing import Mapping from typing import NoReturn -from typing import Optional from typing import Sequence -from typing import Tuple -from typing import Union import _pytest._io from _pytest.config.exceptions import UsageError @@ -41,32 +39,32 @@ class Parser: there's an error processing the command line arguments. """ - prog: Optional[str] = None + prog: str | None = None def __init__( self, - usage: Optional[str] = None, - processopt: Optional[Callable[["Argument"], None]] = None, + usage: str | None = None, + processopt: Callable[[Argument], None] | None = None, *, _ispytest: bool = False, ) -> None: check_ispytest(_ispytest) self._anonymous = OptionGroup("Custom options", parser=self, _ispytest=True) - self._groups: List[OptionGroup] = [] + self._groups: list[OptionGroup] = [] self._processopt = processopt self._usage = usage - self._inidict: Dict[str, Tuple[str, Optional[str], Any]] = {} - self._ininames: List[str] = [] - self.extra_info: Dict[str, Any] = {} + self._inidict: dict[str, tuple[str, str | None, Any]] = {} + self._ininames: list[str] = [] + self.extra_info: dict[str, Any] = {} - def processoption(self, option: "Argument") -> None: + def processoption(self, option: Argument) -> None: if self._processopt: if option.dest: self._processopt(option) def getgroup( - self, name: str, description: str = "", after: Optional[str] = None - ) -> "OptionGroup": + self, name: str, description: str = "", after: str | None = None + ) -> OptionGroup: """Get (or create) a named option Group. :param name: Name of the option group. @@ -108,8 +106,8 @@ def addoption(self, *opts: str, **attrs: Any) -> None: def parse( self, - args: Sequence[Union[str, "os.PathLike[str]"]], - namespace: Optional[argparse.Namespace] = None, + args: Sequence[str | os.PathLike[str]], + namespace: argparse.Namespace | None = None, ) -> argparse.Namespace: from _pytest._argcomplete import try_argcomplete @@ -118,7 +116,7 @@ def parse( strargs = [os.fspath(x) for x in args] return self.optparser.parse_args(strargs, namespace=namespace) - def _getparser(self) -> "MyOptionParser": + def _getparser(self) -> MyOptionParser: from _pytest._argcomplete import filescompleter optparser = MyOptionParser(self, self.extra_info, prog=self.prog) @@ -139,10 +137,10 @@ def _getparser(self) -> "MyOptionParser": def parse_setoption( self, - args: Sequence[Union[str, "os.PathLike[str]"]], + args: Sequence[str | os.PathLike[str]], option: argparse.Namespace, - namespace: Optional[argparse.Namespace] = None, - ) -> List[str]: + namespace: argparse.Namespace | None = None, + ) -> list[str]: parsedoption = self.parse(args, namespace=namespace) for name, value in parsedoption.__dict__.items(): setattr(option, name, value) @@ -150,8 +148,8 @@ def parse_setoption( def parse_known_args( self, - args: Sequence[Union[str, "os.PathLike[str]"]], - namespace: Optional[argparse.Namespace] = None, + args: Sequence[str | os.PathLike[str]], + namespace: argparse.Namespace | None = None, ) -> argparse.Namespace: """Parse the known arguments at this point. @@ -161,9 +159,9 @@ def parse_known_args( def parse_known_and_unknown_args( self, - args: Sequence[Union[str, "os.PathLike[str]"]], - namespace: Optional[argparse.Namespace] = None, - ) -> Tuple[argparse.Namespace, List[str]]: + args: Sequence[str | os.PathLike[str]], + namespace: argparse.Namespace | None = None, + ) -> tuple[argparse.Namespace, list[str]]: """Parse the known arguments at this point, and also return the remaining unknown arguments. @@ -179,9 +177,8 @@ def addini( self, name: str, help: str, - type: Optional[ - Literal["string", "paths", "pathlist", "args", "linelist", "bool"] - ] = None, + type: Literal["string", "paths", "pathlist", "args", "linelist", "bool"] + | None = None, default: Any = NOT_SET, ) -> None: """Register an ini-file option. @@ -224,7 +221,7 @@ def addini( def get_ini_default_for_type( - type: Optional[Literal["string", "paths", "pathlist", "args", "linelist", "bool"]], + type: Literal["string", "paths", "pathlist", "args", "linelist", "bool"] | None, ) -> Any: """ Used by addini to get the default value for a given ini-option type, when @@ -244,7 +241,7 @@ class ArgumentError(Exception): """Raised if an Argument instance is created with invalid or inconsistent arguments.""" - def __init__(self, msg: str, option: Union["Argument", str]) -> None: + def __init__(self, msg: str, option: Argument | str) -> None: self.msg = msg self.option_id = str(option) @@ -267,8 +264,8 @@ class Argument: def __init__(self, *names: str, **attrs: Any) -> None: """Store params in private vars for use in add_argument.""" self._attrs = attrs - self._short_opts: List[str] = [] - self._long_opts: List[str] = [] + self._short_opts: list[str] = [] + self._long_opts: list[str] = [] try: self.type = attrs["type"] except KeyError: @@ -279,7 +276,7 @@ def __init__(self, *names: str, **attrs: Any) -> None: except KeyError: pass self._set_opt_strings(names) - dest: Optional[str] = attrs.get("dest") + dest: str | None = attrs.get("dest") if dest: self.dest = dest elif self._long_opts: @@ -291,7 +288,7 @@ def __init__(self, *names: str, **attrs: Any) -> None: self.dest = "???" # Needed for the error repr. raise ArgumentError("need a long or short option", self) from e - def names(self) -> List[str]: + def names(self) -> list[str]: return self._short_opts + self._long_opts def attrs(self) -> Mapping[str, Any]: @@ -335,7 +332,7 @@ def _set_opt_strings(self, opts: Sequence[str]) -> None: self._long_opts.append(opt) def __repr__(self) -> str: - args: List[str] = [] + args: list[str] = [] if self._short_opts: args += ["_short_opts: " + repr(self._short_opts)] if self._long_opts: @@ -355,14 +352,14 @@ def __init__( self, name: str, description: str = "", - parser: Optional[Parser] = None, + parser: Parser | None = None, *, _ispytest: bool = False, ) -> None: check_ispytest(_ispytest) self.name = name self.description = description - self.options: List[Argument] = [] + self.options: list[Argument] = [] self.parser = parser def addoption(self, *opts: str, **attrs: Any) -> None: @@ -391,7 +388,7 @@ def _addoption(self, *opts: str, **attrs: Any) -> None: option = Argument(*opts, **attrs) self._addoption_instance(option, shortupper=True) - def _addoption_instance(self, option: "Argument", shortupper: bool = False) -> None: + def _addoption_instance(self, option: Argument, shortupper: bool = False) -> None: if not shortupper: for opt in option._short_opts: if opt[0] == "-" and opt[1].islower(): @@ -405,8 +402,8 @@ class MyOptionParser(argparse.ArgumentParser): def __init__( self, parser: Parser, - extra_info: Optional[Dict[str, Any]] = None, - prog: Optional[str] = None, + extra_info: dict[str, Any] | None = None, + prog: str | None = None, ) -> None: self._parser = parser super().__init__( @@ -433,8 +430,8 @@ def error(self, message: str) -> NoReturn: # Type ignored because typeshed has a very complex type in the superclass. def parse_args( # type: ignore self, - args: Optional[Sequence[str]] = None, - namespace: Optional[argparse.Namespace] = None, + args: Sequence[str] | None = None, + namespace: argparse.Namespace | None = None, ) -> argparse.Namespace: """Allow splitting of positional arguments.""" parsed, unrecognized = self.parse_known_args(args, namespace) @@ -455,7 +452,7 @@ def parse_args( # type: ignore # disable long --argument abbreviations without breaking short flags. def _parse_optional( self, arg_string: str - ) -> Optional[Tuple[Optional[argparse.Action], str, Optional[str]]]: + ) -> tuple[argparse.Action | None, str, str | None] | None: if not arg_string: return None if arg_string[0] not in self.prefix_chars: @@ -507,7 +504,7 @@ def _format_action_invocation(self, action: argparse.Action) -> str: orgstr = super()._format_action_invocation(action) if orgstr and orgstr[0] != "-": # only optional arguments return orgstr - res: Optional[str] = getattr(action, "_formatted_action_invocation", None) + res: str | None = getattr(action, "_formatted_action_invocation", None) if res: return res options = orgstr.split(", ") @@ -516,7 +513,7 @@ def _format_action_invocation(self, action: argparse.Action) -> str: action._formatted_action_invocation = orgstr # type: ignore return orgstr return_list = [] - short_long: Dict[str, str] = {} + short_long: dict[str, str] = {} for option in options: if len(option) == 2 or option[2] == " ": continue diff --git a/src/_pytest/config/exceptions.py b/src/_pytest/config/exceptions.py index 4031ea732f3..90108eca904 100644 --- a/src/_pytest/config/exceptions.py +++ b/src/_pytest/config/exceptions.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import final diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 9909376de0f..ce4c990b810 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -1,13 +1,10 @@ +from __future__ import annotations + import os from pathlib import Path import sys -from typing import Dict from typing import Iterable -from typing import List -from typing import Optional from typing import Sequence -from typing import Tuple -from typing import Union import iniconfig @@ -32,7 +29,7 @@ def _parse_ini_config(path: Path) -> iniconfig.IniConfig: def load_config_dict_from_file( filepath: Path, -) -> Optional[Dict[str, Union[str, List[str]]]]: +) -> dict[str, str | list[str]] | None: """Load pytest configuration from the given file path, if supported. Return None if the file does not contain valid pytest configuration. @@ -77,7 +74,7 @@ def load_config_dict_from_file( # TOML supports richer data types than ini files (strings, arrays, floats, ints, etc), # however we need to convert all scalar values to str for compatibility with the rest # of the configuration system, which expects strings only. - def make_scalar(v: object) -> Union[str, List[str]]: + def make_scalar(v: object) -> str | list[str]: return v if isinstance(v, list) else str(v) return {k: make_scalar(v) for k, v in result.items()} @@ -88,7 +85,7 @@ def make_scalar(v: object) -> Union[str, List[str]]: def locate_config( invocation_dir: Path, args: Iterable[Path], -) -> Tuple[Optional[Path], Optional[Path], Dict[str, Union[str, List[str]]]]: +) -> tuple[Path | None, Path | None, dict[str, str | list[str]]]: """Search in the list of arguments for a valid ini-file for pytest, and return a tuple of (rootdir, inifile, cfg-dict).""" config_names = [ @@ -101,7 +98,7 @@ def locate_config( args = [x for x in args if not str(x).startswith("-")] if not args: args = [invocation_dir] - found_pyproject_toml: Optional[Path] = None + found_pyproject_toml: Path | None = None for arg in args: argpath = absolutepath(arg) for base in (argpath, *argpath.parents): @@ -122,7 +119,7 @@ def get_common_ancestor( invocation_dir: Path, paths: Iterable[Path], ) -> Path: - common_ancestor: Optional[Path] = None + common_ancestor: Path | None = None for path in paths: if not path.exists(): continue @@ -144,7 +141,7 @@ def get_common_ancestor( return common_ancestor -def get_dirs_from_args(args: Iterable[str]) -> List[Path]: +def get_dirs_from_args(args: Iterable[str]) -> list[Path]: def is_option(x: str) -> bool: return x.startswith("-") @@ -171,11 +168,11 @@ def get_dir_from_path(path: Path) -> Path: def determine_setup( *, - inifile: Optional[str], + inifile: str | None, args: Sequence[str], - rootdir_cmd_arg: Optional[str], + rootdir_cmd_arg: str | None, invocation_dir: Path, -) -> Tuple[Path, Optional[Path], Dict[str, Union[str, List[str]]]]: +) -> tuple[Path, Path | None, dict[str, str | list[str]]]: """Determine the rootdir, inifile and ini configuration values from the command line arguments. @@ -192,7 +189,7 @@ def determine_setup( dirs = get_dirs_from_args(args) if inifile: inipath_ = absolutepath(inifile) - inipath: Optional[Path] = inipath_ + inipath: Path | None = inipath_ inicfg = load_config_dict_from_file(inipath_) or {} if rootdir_cmd_arg is None: rootdir = inipath_.parent diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index eacb2836d6c..3e1463fff26 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -2,6 +2,8 @@ # ruff: noqa: T100 """Interactive debugging with PDB, the Python Debugger.""" +from __future__ import annotations + import argparse import functools import sys @@ -9,11 +11,6 @@ from typing import Any from typing import Callable from typing import Generator -from typing import List -from typing import Optional -from typing import Tuple -from typing import Type -from typing import Union import unittest from _pytest import outcomes @@ -30,7 +27,7 @@ from _pytest.runner import CallInfo -def _validate_usepdb_cls(value: str) -> Tuple[str, str]: +def _validate_usepdb_cls(value: str) -> tuple[str, str]: """Validate syntax of --pdbcls option.""" try: modname, classname = value.split(":") @@ -95,22 +92,22 @@ def fin() -> None: class pytestPDB: """Pseudo PDB that defers to the real pdb.""" - _pluginmanager: Optional[PytestPluginManager] = None - _config: Optional[Config] = None - _saved: List[ - Tuple[Callable[..., None], Optional[PytestPluginManager], Optional[Config]] + _pluginmanager: PytestPluginManager | None = None + _config: Config | None = None + _saved: list[ + tuple[Callable[..., None], PytestPluginManager | None, Config | None] ] = [] _recursive_debug = 0 - _wrapped_pdb_cls: Optional[Tuple[Type[Any], Type[Any]]] = None + _wrapped_pdb_cls: tuple[type[Any], type[Any]] | None = None @classmethod - def _is_capturing(cls, capman: Optional["CaptureManager"]) -> Union[str, bool]: + def _is_capturing(cls, capman: CaptureManager | None) -> str | bool: if capman: return capman.is_capturing() return False @classmethod - def _import_pdb_cls(cls, capman: Optional["CaptureManager"]): + def _import_pdb_cls(cls, capman: CaptureManager | None): if not cls._config: import pdb @@ -149,7 +146,7 @@ def _import_pdb_cls(cls, capman: Optional["CaptureManager"]): return wrapped_cls @classmethod - def _get_pdb_wrapper_class(cls, pdb_cls, capman: Optional["CaptureManager"]): + def _get_pdb_wrapper_class(cls, pdb_cls, capman: CaptureManager | None): import _pytest.config class PytestPdbWrapper(pdb_cls): @@ -238,7 +235,7 @@ def _init_pdb(cls, method, *args, **kwargs): import _pytest.config if cls._pluginmanager is None: - capman: Optional[CaptureManager] = None + capman: CaptureManager | None = None else: capman = cls._pluginmanager.getplugin("capturemanager") if capman: @@ -281,7 +278,7 @@ def set_trace(cls, *args, **kwargs) -> None: class PdbInvoke: def pytest_exception_interact( - self, node: Node, call: "CallInfo[Any]", report: BaseReport + self, node: Node, call: CallInfo[Any], report: BaseReport ) -> None: capman = node.config.pluginmanager.getplugin("capturemanager") if capman: diff --git a/src/_pytest/deprecated.py b/src/_pytest/deprecated.py index 10811d158aa..a605c24e58f 100644 --- a/src/_pytest/deprecated.py +++ b/src/_pytest/deprecated.py @@ -9,6 +9,8 @@ in case of warnings which need to format their messages. """ +from __future__ import annotations + from warnings import warn from _pytest.warning_types import PytestDeprecationWarning diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index e61694d553f..cb46d9a3bb5 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Discover and run doctests in modules and test files.""" +from __future__ import annotations + import bdb from contextlib import contextmanager import functools @@ -13,17 +15,11 @@ import types from typing import Any from typing import Callable -from typing import Dict from typing import Generator from typing import Iterable -from typing import List -from typing import Optional from typing import Pattern from typing import Sequence -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING -from typing import Union import warnings from _pytest import outcomes @@ -67,7 +63,7 @@ # Lazy definition of runner class RUNNER_CLASS = None # Lazy definition of output checker class -CHECKER_CLASS: Optional[Type["doctest.OutputChecker"]] = None +CHECKER_CLASS: type[doctest.OutputChecker] | None = None def pytest_addoption(parser: Parser) -> None: @@ -129,7 +125,7 @@ def pytest_unconfigure() -> None: def pytest_collect_file( file_path: Path, parent: Collector, -) -> Optional[Union["DoctestModule", "DoctestTextfile"]]: +) -> DoctestModule | DoctestTextfile | None: config = parent.config if file_path.suffix == ".py": if config.option.doctestmodules and not any( @@ -161,7 +157,7 @@ def _is_main_py(path: Path) -> bool: class ReprFailDoctest(TerminalRepr): def __init__( - self, reprlocation_lines: Sequence[Tuple[ReprFileLocation, Sequence[str]]] + self, reprlocation_lines: Sequence[tuple[ReprFileLocation, Sequence[str]]] ) -> None: self.reprlocation_lines = reprlocation_lines @@ -173,12 +169,12 @@ def toterminal(self, tw: TerminalWriter) -> None: class MultipleDoctestFailures(Exception): - def __init__(self, failures: Sequence["doctest.DocTestFailure"]) -> None: + def __init__(self, failures: Sequence[doctest.DocTestFailure]) -> None: super().__init__() self.failures = failures -def _init_runner_class() -> Type["doctest.DocTestRunner"]: +def _init_runner_class() -> type[doctest.DocTestRunner]: import doctest class PytestDoctestRunner(doctest.DebugRunner): @@ -190,8 +186,8 @@ class PytestDoctestRunner(doctest.DebugRunner): def __init__( self, - checker: Optional["doctest.OutputChecker"] = None, - verbose: Optional[bool] = None, + checker: doctest.OutputChecker | None = None, + verbose: bool | None = None, optionflags: int = 0, continue_on_failure: bool = True, ) -> None: @@ -201,8 +197,8 @@ def __init__( def report_failure( self, out, - test: "doctest.DocTest", - example: "doctest.Example", + test: doctest.DocTest, + example: doctest.Example, got: str, ) -> None: failure = doctest.DocTestFailure(test, example, got) @@ -214,9 +210,9 @@ def report_failure( def report_unexpected_exception( self, out, - test: "doctest.DocTest", - example: "doctest.Example", - exc_info: Tuple[Type[BaseException], BaseException, types.TracebackType], + test: doctest.DocTest, + example: doctest.Example, + exc_info: tuple[type[BaseException], BaseException, types.TracebackType], ) -> None: if isinstance(exc_info[1], OutcomeException): raise exc_info[1] @@ -232,11 +228,11 @@ def report_unexpected_exception( def _get_runner( - checker: Optional["doctest.OutputChecker"] = None, - verbose: Optional[bool] = None, + checker: doctest.OutputChecker | None = None, + verbose: bool | None = None, optionflags: int = 0, continue_on_failure: bool = True, -) -> "doctest.DocTestRunner": +) -> doctest.DocTestRunner: # We need this in order to do a lazy import on doctest global RUNNER_CLASS if RUNNER_CLASS is None: @@ -255,9 +251,9 @@ class DoctestItem(Item): def __init__( self, name: str, - parent: "Union[DoctestTextfile, DoctestModule]", - runner: "doctest.DocTestRunner", - dtest: "doctest.DocTest", + parent: DoctestTextfile | DoctestModule, + runner: doctest.DocTestRunner, + dtest: doctest.DocTest, ) -> None: super().__init__(name, parent) self.runner = runner @@ -274,18 +270,18 @@ def __init__( @classmethod def from_parent( # type: ignore[override] cls, - parent: "Union[DoctestTextfile, DoctestModule]", + parent: DoctestTextfile | DoctestModule, *, name: str, - runner: "doctest.DocTestRunner", - dtest: "doctest.DocTest", - ) -> "Self": + runner: doctest.DocTestRunner, + dtest: doctest.DocTest, + ) -> Self: # incompatible signature due to imposed limits on subclass """The public named constructor.""" return super().from_parent(name=name, parent=parent, runner=runner, dtest=dtest) def _initrequest(self) -> None: - self.funcargs: Dict[str, object] = {} + self.funcargs: dict[str, object] = {} self._request = TopRequest(self, _ispytest=True) # type: ignore[arg-type] def setup(self) -> None: @@ -298,7 +294,7 @@ def setup(self) -> None: def runtest(self) -> None: _check_all_skipped(self.dtest) self._disable_output_capturing_for_darwin() - failures: List[doctest.DocTestFailure] = [] + failures: list[doctest.DocTestFailure] = [] # Type ignored because we change the type of `out` from what # doctest expects. self.runner.run(self.dtest, out=failures) # type: ignore[arg-type] @@ -320,12 +316,12 @@ def _disable_output_capturing_for_darwin(self) -> None: def repr_failure( # type: ignore[override] self, excinfo: ExceptionInfo[BaseException], - ) -> Union[str, TerminalRepr]: + ) -> str | TerminalRepr: import doctest - failures: Optional[ - Sequence[Union[doctest.DocTestFailure, doctest.UnexpectedException]] - ] = None + failures: ( + Sequence[doctest.DocTestFailure | doctest.UnexpectedException] | None + ) = None if isinstance( excinfo.value, (doctest.DocTestFailure, doctest.UnexpectedException) ): @@ -381,11 +377,11 @@ def repr_failure( # type: ignore[override] reprlocation_lines.append((reprlocation, lines)) return ReprFailDoctest(reprlocation_lines) - def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: + def reportinfo(self) -> tuple[os.PathLike[str] | str, int | None, str]: return self.path, self.dtest.lineno, f"[doctest] {self.name}" -def _get_flag_lookup() -> Dict[str, int]: +def _get_flag_lookup() -> dict[str, int]: import doctest return dict( @@ -451,7 +447,7 @@ def collect(self) -> Iterable[DoctestItem]: ) -def _check_all_skipped(test: "doctest.DocTest") -> None: +def _check_all_skipped(test: doctest.DocTest) -> None: """Raise pytest.skip() if all examples in the given DocTest have the SKIP option set.""" import doctest @@ -477,7 +473,7 @@ def _patch_unwrap_mock_aware() -> Generator[None, None, None]: real_unwrap = inspect.unwrap def _mock_aware_unwrap( - func: Callable[..., Any], *, stop: Optional[Callable[[Any], Any]] = None + func: Callable[..., Any], *, stop: Callable[[Any], Any] | None = None ) -> Any: try: if stop is None or stop is _is_mocked: @@ -594,7 +590,7 @@ def _from_module(self, module, object): ) -def _init_checker_class() -> Type["doctest.OutputChecker"]: +def _init_checker_class() -> type[doctest.OutputChecker]: import doctest import re @@ -662,8 +658,8 @@ def _remove_unwanted_precision(self, want: str, got: str) -> str: return got offset = 0 for w, g in zip(wants, gots): - fraction: Optional[str] = w.group("fraction") - exponent: Optional[str] = w.group("exponent1") + fraction: str | None = w.group("fraction") + exponent: str | None = w.group("exponent1") if exponent is None: exponent = w.group("exponent2") precision = 0 if fraction is None else len(fraction) @@ -682,7 +678,7 @@ def _remove_unwanted_precision(self, want: str, got: str) -> str: return LiteralsOutputChecker -def _get_checker() -> "doctest.OutputChecker": +def _get_checker() -> doctest.OutputChecker: """Return a doctest.OutputChecker subclass that supports some additional options: @@ -741,7 +737,7 @@ def _get_report_choice(key: str) -> int: @fixture(scope="session") -def doctest_namespace() -> Dict[str, Any]: +def doctest_namespace() -> dict[str, Any]: """Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index 083bcb83739..07e60f03fc9 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import sys from typing import Generator diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 383084e07f1..0151a4d9c86 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import abc from collections import defaultdict from collections import deque @@ -20,7 +22,6 @@ from typing import Generic from typing import Iterable from typing import Iterator -from typing import List from typing import Mapping from typing import MutableMapping from typing import NoReturn @@ -28,7 +29,6 @@ from typing import OrderedDict from typing import overload from typing import Sequence -from typing import Set from typing import Tuple from typing import TYPE_CHECKING from typing import TypeVar @@ -113,18 +113,18 @@ @dataclasses.dataclass(frozen=True) class PseudoFixtureDef(Generic[FixtureValue]): - cached_result: "_FixtureCachedResult[FixtureValue]" + cached_result: _FixtureCachedResult[FixtureValue] _scope: Scope -def pytest_sessionstart(session: "Session") -> None: +def pytest_sessionstart(session: Session) -> None: session._fixturemanager = FixtureManager(session) def get_scope_package( node: nodes.Item, - fixturedef: "FixtureDef[object]", -) -> Optional[nodes.Node]: + fixturedef: FixtureDef[object], +) -> nodes.Node | None: from _pytest.python import Package for parent in node.iter_parents(): @@ -133,7 +133,7 @@ def get_scope_package( return node.session -def get_scope_node(node: nodes.Node, scope: Scope) -> Optional[nodes.Node]: +def get_scope_node(node: nodes.Node, scope: Scope) -> nodes.Node | None: import _pytest.python if scope is Scope.Function: @@ -152,7 +152,7 @@ def get_scope_node(node: nodes.Node, scope: Scope) -> Optional[nodes.Node]: assert_never(scope) -def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]: +def getfixturemarker(obj: object) -> FixtureFunctionMarker | None: """Return fixturemarker or None if it doesn't exist or raised exceptions.""" return cast( @@ -171,8 +171,8 @@ def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]: class FixtureArgKey: argname: str param_index: int - scoped_item_path: Optional[Path] - item_cls: Optional[type] + scoped_item_path: Path | None + item_cls: type | None _V = TypeVar("_V") @@ -212,10 +212,10 @@ def get_parametrized_fixture_argkeys( yield FixtureArgKey(argname, param_index, scoped_item_path, item_cls) -def reorder_items(items: Sequence[nodes.Item]) -> List[nodes.Item]: - argkeys_by_item: Dict[Scope, Dict[nodes.Item, OrderedSet[FixtureArgKey]]] = {} - items_by_argkey: Dict[ - Scope, Dict[FixtureArgKey, OrderedDict[nodes.Item, None]] +def reorder_items(items: Sequence[nodes.Item]) -> list[nodes.Item]: + argkeys_by_item: dict[Scope, dict[nodes.Item, OrderedSet[FixtureArgKey]]] = {} + items_by_argkey: dict[ + Scope, dict[FixtureArgKey, OrderedDict[nodes.Item, None]] ] = {} for scope in HIGH_SCOPES: scoped_argkeys_by_item = argkeys_by_item[scope] = {} @@ -249,7 +249,7 @@ def reorder_items_atscope( scoped_items_by_argkey = items_by_argkey[scope] scoped_argkeys_by_item = argkeys_by_item[scope] - ignore: Set[FixtureArgKey] = set() + ignore: set[FixtureArgKey] = set() items_deque = deque(items) items_done: OrderedSet[nodes.Item] = {} while items_deque: @@ -309,19 +309,19 @@ class FuncFixtureInfo: __slots__ = ("argnames", "initialnames", "names_closure", "name2fixturedefs") # Fixture names that the item requests directly by function parameters. - argnames: Tuple[str, ...] + argnames: tuple[str, ...] # Fixture names that the item immediately requires. These include # argnames + fixture names specified via usefixtures and via autouse=True in # fixture definitions. - initialnames: Tuple[str, ...] + initialnames: tuple[str, ...] # The transitive closure of the fixture names that the item requires. # Note: can't include dynamic dependencies (`request.getfixturevalue` calls). - names_closure: List[str] + names_closure: list[str] # A map from a fixture name in the transitive closure to the FixtureDefs # matching the name which are applicable to this function. # There may be multiple overriding fixtures with the same name. The # sequence is ordered from furthest to closes to the function. - name2fixturedefs: Dict[str, Sequence["FixtureDef[Any]"]] + name2fixturedefs: dict[str, Sequence[FixtureDef[Any]]] def prune_dependency_tree(self) -> None: """Recompute names_closure from initialnames and name2fixturedefs. @@ -334,7 +334,7 @@ def prune_dependency_tree(self) -> None: tree. In this way the dependency tree can get pruned, and the closure of argnames may get reduced. """ - closure: Set[str] = set() + closure: set[str] = set() working_set = set(self.initialnames) while working_set: argname = working_set.pop() @@ -360,10 +360,10 @@ class FixtureRequest(abc.ABC): def __init__( self, - pyfuncitem: "Function", - fixturename: Optional[str], - arg2fixturedefs: Dict[str, Sequence["FixtureDef[Any]"]], - fixture_defs: Dict[str, "FixtureDef[Any]"], + pyfuncitem: Function, + fixturename: str | None, + arg2fixturedefs: dict[str, Sequence[FixtureDef[Any]]], + fixture_defs: dict[str, FixtureDef[Any]], *, _ispytest: bool = False, ) -> None: @@ -390,7 +390,7 @@ def __init__( self.param: Any @property - def _fixturemanager(self) -> "FixtureManager": + def _fixturemanager(self) -> FixtureManager: return self._pyfuncitem.session._fixturemanager @property @@ -406,13 +406,13 @@ def scope(self) -> _ScopeName: @abc.abstractmethod def _check_scope( self, - requested_fixturedef: Union["FixtureDef[object]", PseudoFixtureDef[object]], + requested_fixturedef: FixtureDef[object] | PseudoFixtureDef[object], requested_scope: Scope, ) -> None: raise NotImplementedError() @property - def fixturenames(self) -> List[str]: + def fixturenames(self) -> list[str]: """Names of all active fixtures in this request.""" result = list(self._pyfuncitem.fixturenames) result.extend(set(self._fixture_defs).difference(result)) @@ -477,7 +477,7 @@ def keywords(self) -> MutableMapping[str, Any]: return node.keywords @property - def session(self) -> "Session": + def session(self) -> Session: """Pytest session object.""" return self._pyfuncitem.session @@ -487,7 +487,7 @@ def addfinalizer(self, finalizer: Callable[[], object]) -> None: the last test within the requesting test context finished execution.""" raise NotImplementedError() - def applymarker(self, marker: Union[str, MarkDecorator]) -> None: + def applymarker(self, marker: str | MarkDecorator) -> None: """Apply a marker to a single test function invocation. This method is useful if you don't want to have a keyword/marker @@ -498,7 +498,7 @@ def applymarker(self, marker: Union[str, MarkDecorator]) -> None: """ self.node.add_marker(marker) - def raiseerror(self, msg: Optional[str]) -> NoReturn: + def raiseerror(self, msg: str | None) -> NoReturn: """Raise a FixtureLookupError exception. :param msg: @@ -535,7 +535,7 @@ def getfixturevalue(self, argname: str) -> Any: ) return fixturedef.cached_result[0] - def _iter_chain(self) -> Iterator["SubRequest"]: + def _iter_chain(self) -> Iterator[SubRequest]: """Yield all SubRequests in the chain, from self up. Note: does *not* yield the TopRequest. @@ -547,7 +547,7 @@ def _iter_chain(self) -> Iterator["SubRequest"]: def _get_active_fixturedef( self, argname: str - ) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]: + ) -> FixtureDef[object] | PseudoFixtureDef[object]: if argname == "request": cached_result = (self, [0], None) return PseudoFixtureDef(cached_result, Scope.Function) @@ -618,7 +618,7 @@ def _get_active_fixturedef( self._fixture_defs[argname] = fixturedef return fixturedef - def _check_fixturedef_without_param(self, fixturedef: "FixtureDef[object]") -> None: + def _check_fixturedef_without_param(self, fixturedef: FixtureDef[object]) -> None: """Check that this request is allowed to execute this fixturedef without a param.""" funcitem = self._pyfuncitem @@ -651,7 +651,7 @@ def _check_fixturedef_without_param(self, fixturedef: "FixtureDef[object]") -> N ) fail(msg, pytrace=False) - def _get_fixturestack(self) -> List["FixtureDef[Any]"]: + def _get_fixturestack(self) -> list[FixtureDef[Any]]: values = [request._fixturedef for request in self._iter_chain()] values.reverse() return values @@ -661,7 +661,7 @@ def _get_fixturestack(self) -> List["FixtureDef[Any]"]: class TopRequest(FixtureRequest): """The type of the ``request`` fixture in a test function.""" - def __init__(self, pyfuncitem: "Function", *, _ispytest: bool = False) -> None: + def __init__(self, pyfuncitem: Function, *, _ispytest: bool = False) -> None: super().__init__( fixturename=None, pyfuncitem=pyfuncitem, @@ -676,7 +676,7 @@ def _scope(self) -> Scope: def _check_scope( self, - requested_fixturedef: Union["FixtureDef[object]", PseudoFixtureDef[object]], + requested_fixturedef: FixtureDef[object] | PseudoFixtureDef[object], requested_scope: Scope, ) -> None: # TopRequest always has function scope so always valid. @@ -710,7 +710,7 @@ def __init__( scope: Scope, param: Any, param_index: int, - fixturedef: "FixtureDef[object]", + fixturedef: FixtureDef[object], *, _ispytest: bool = False, ) -> None: @@ -740,7 +740,7 @@ def node(self): scope = self._scope if scope is Scope.Function: # This might also be a non-function Item despite its attribute name. - node: Optional[nodes.Node] = self._pyfuncitem + node: nodes.Node | None = self._pyfuncitem elif scope is Scope.Package: node = get_scope_package(self._pyfuncitem, self._fixturedef) else: @@ -753,7 +753,7 @@ def node(self): def _check_scope( self, - requested_fixturedef: Union["FixtureDef[object]", PseudoFixtureDef[object]], + requested_fixturedef: FixtureDef[object] | PseudoFixtureDef[object], requested_scope: Scope, ) -> None: if isinstance(requested_fixturedef, PseudoFixtureDef): @@ -774,7 +774,7 @@ def _check_scope( pytrace=False, ) - def _format_fixturedef_line(self, fixturedef: "FixtureDef[object]") -> str: + def _format_fixturedef_line(self, fixturedef: FixtureDef[object]) -> str: factory = fixturedef.func path, lineno = getfslineno(factory) if isinstance(path, Path): @@ -791,15 +791,15 @@ class FixtureLookupError(LookupError): """Could not return a requested fixture (missing or invalid).""" def __init__( - self, argname: Optional[str], request: FixtureRequest, msg: Optional[str] = None + self, argname: str | None, request: FixtureRequest, msg: str | None = None ) -> None: self.argname = argname self.request = request self.fixturestack = request._get_fixturestack() self.msg = msg - def formatrepr(self) -> "FixtureLookupErrorRepr": - tblines: List[str] = [] + def formatrepr(self) -> FixtureLookupErrorRepr: + tblines: list[str] = [] addline = tblines.append stack = [self.request._pyfuncitem.obj] stack.extend(map(lambda x: x.func, self.fixturestack)) @@ -847,11 +847,11 @@ def formatrepr(self) -> "FixtureLookupErrorRepr": class FixtureLookupErrorRepr(TerminalRepr): def __init__( self, - filename: Union[str, "os.PathLike[str]"], + filename: str | os.PathLike[str], firstlineno: int, tblines: Sequence[str], errorstring: str, - argname: Optional[str], + argname: str | None, ) -> None: self.tblines = tblines self.errorstring = errorstring @@ -879,7 +879,7 @@ def toterminal(self, tw: TerminalWriter) -> None: def call_fixture_func( - fixturefunc: "_FixtureFunc[FixtureValue]", request: FixtureRequest, kwargs + fixturefunc: _FixtureFunc[FixtureValue], request: FixtureRequest, kwargs ) -> FixtureValue: if is_generator(fixturefunc): fixturefunc = cast( @@ -950,14 +950,12 @@ class FixtureDef(Generic[FixtureValue]): def __init__( self, config: Config, - baseid: Optional[str], + baseid: str | None, argname: str, - func: "_FixtureFunc[FixtureValue]", - scope: Union[Scope, _ScopeName, Callable[[str, Config], _ScopeName], None], - params: Optional[Sequence[object]], - ids: Optional[ - Union[Tuple[Optional[object], ...], Callable[[Any], Optional[object]]] - ] = None, + func: _FixtureFunc[FixtureValue], + scope: Scope | _ScopeName | Callable[[str, Config], _ScopeName] | None, + params: Sequence[object] | None, + ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None, *, _ispytest: bool = False, ) -> None: @@ -1003,8 +1001,8 @@ def __init__( self.argnames: Final = getfuncargnames(func, name=argname) # If the fixture was executed, the current value of the fixture. # Can change if the fixture is executed with different parameters. - self.cached_result: Optional[_FixtureCachedResult[FixtureValue]] = None - self._finalizers: Final[List[Callable[[], object]]] = [] + self.cached_result: _FixtureCachedResult[FixtureValue] | None = None + self._finalizers: Final[list[Callable[[], object]]] = [] @property def scope(self) -> _ScopeName: @@ -1015,7 +1013,7 @@ def addfinalizer(self, finalizer: Callable[[], object]) -> None: self._finalizers.append(finalizer) def finish(self, request: SubRequest) -> None: - exceptions: List[BaseException] = [] + exceptions: list[BaseException] = [] while self._finalizers: fin = self._finalizers.pop() try: @@ -1099,7 +1097,7 @@ def __repr__(self) -> str: def resolve_fixture_function( fixturedef: FixtureDef[FixtureValue], request: FixtureRequest -) -> "_FixtureFunc[FixtureValue]": +) -> _FixtureFunc[FixtureValue]: """Get the actual callable that can be called to obtain the fixture value.""" fixturefunc = fixturedef.func @@ -1147,7 +1145,7 @@ def pytest_fixture_setup( def wrap_function_to_error_out_if_called_directly( function: FixtureFunction, - fixture_marker: "FixtureFunctionMarker", + fixture_marker: FixtureFunctionMarker, ) -> FixtureFunction: """Wrap the given fixture function so we can raise an error about it being called directly, instead of used as an argument in a test function.""" @@ -1173,13 +1171,11 @@ def result(*args, **kwargs): @final @dataclasses.dataclass(frozen=True) class FixtureFunctionMarker: - scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" - params: Optional[Tuple[object, ...]] + scope: _ScopeName | Callable[[str, Config], _ScopeName] + params: tuple[object, ...] | None autouse: bool = False - ids: Optional[ - Union[Tuple[Optional[object], ...], Callable[[Any], Optional[object]]] - ] = None - name: Optional[str] = None + ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None + name: str | None = None _ispytest: dataclasses.InitVar[bool] = False @@ -1217,13 +1213,11 @@ def __call__(self, function: FixtureFunction) -> FixtureFunction: def fixture( fixture_function: FixtureFunction, *, - scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., - params: Optional[Iterable[object]] = ..., + scope: _ScopeName | Callable[[str, Config], _ScopeName] = ..., + params: Iterable[object] | None = ..., autouse: bool = ..., - ids: Optional[ - Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] - ] = ..., - name: Optional[str] = ..., + ids: Sequence[object | None] | Callable[[Any], object | None] | None = ..., + name: str | None = ..., ) -> FixtureFunction: ... @@ -1231,27 +1225,23 @@ def fixture( def fixture( fixture_function: None = ..., *, - scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., - params: Optional[Iterable[object]] = ..., + scope: _ScopeName | Callable[[str, Config], _ScopeName] = ..., + params: Iterable[object] | None = ..., autouse: bool = ..., - ids: Optional[ - Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] - ] = ..., - name: Optional[str] = None, + ids: Sequence[object | None] | Callable[[Any], object | None] | None = ..., + name: str | None = None, ) -> FixtureFunctionMarker: ... def fixture( - fixture_function: Optional[FixtureFunction] = None, + fixture_function: FixtureFunction | None = None, *, - scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = "function", - params: Optional[Iterable[object]] = None, + scope: _ScopeName | Callable[[str, Config], _ScopeName] = "function", + params: Iterable[object] | None = None, autouse: bool = False, - ids: Optional[ - Union[Sequence[Optional[object]], Callable[[Any], Optional[object]]] - ] = None, - name: Optional[str] = None, -) -> Union[FixtureFunctionMarker, FixtureFunction]: + ids: Sequence[object | None] | Callable[[Any], object | None] | None = None, + name: str | None = None, +) -> FixtureFunctionMarker | FixtureFunction: """Decorator to mark a fixture factory function. This decorator can be used, with or without parameters, to define a @@ -1385,7 +1375,7 @@ def pytest_addoption(parser: Parser) -> None: ) -def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: +def pytest_cmdline_main(config: Config) -> int | ExitCode | None: if config.option.showfixtures: showfixtures(config) return 0 @@ -1395,7 +1385,7 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: return None -def _get_direct_parametrize_args(node: nodes.Node) -> Set[str]: +def _get_direct_parametrize_args(node: nodes.Node) -> set[str]: """Return all direct parametrization arguments of a node, so we don't mistake them for fixtures. @@ -1404,7 +1394,7 @@ def _get_direct_parametrize_args(node: nodes.Node) -> Set[str]: These things are done later as well when dealing with parametrization so this could be improved. """ - parametrize_argnames: Set[str] = set() + parametrize_argnames: set[str] = set() for marker in node.iter_markers(name="parametrize"): if not marker.kwargs.get("indirect", False): p_argnames, _ = ParameterSet._parse_parametrize_args( @@ -1414,7 +1404,7 @@ def _get_direct_parametrize_args(node: nodes.Node) -> Set[str]: return parametrize_argnames -def deduplicate_names(*seqs: Iterable[str]) -> Tuple[str, ...]: +def deduplicate_names(*seqs: Iterable[str]) -> tuple[str, ...]: """De-duplicate the sequence of names while keeping the original order.""" # Ideally we would use a set, but it does not preserve insertion order. return tuple(dict.fromkeys(name for seq in seqs for name in seq)) @@ -1451,17 +1441,17 @@ class FixtureManager: by a lookup of their FuncFixtureInfo. """ - def __init__(self, session: "Session") -> None: + def __init__(self, session: Session) -> None: self.session = session self.config: Config = session.config # Maps a fixture name (argname) to all of the FixtureDefs in the test # suite/plugins defined with this name. Populated by parsefactories(). # TODO: The order of the FixtureDefs list of each arg is significant, # explain. - self._arg2fixturedefs: Final[Dict[str, List[FixtureDef[Any]]]] = {} - self._holderobjseen: Final[Set[object]] = set() + self._arg2fixturedefs: Final[dict[str, list[FixtureDef[Any]]]] = {} + self._holderobjseen: Final[set[object]] = set() # A mapping from a nodeid to a list of autouse fixtures it defines. - self._nodeid_autousenames: Final[Dict[str, List[str]]] = { + self._nodeid_autousenames: Final[dict[str, list[str]]] = { "": self.config.getini("usefixtures"), } session.config.pluginmanager.register(self, "funcmanage") @@ -1469,8 +1459,8 @@ def __init__(self, session: "Session") -> None: def getfixtureinfo( self, node: nodes.Item, - func: Optional[Callable[..., object]], - cls: Optional[type], + func: Callable[..., object] | None, + cls: type | None, ) -> FuncFixtureInfo: """Calculate the :class:`FuncFixtureInfo` for an item. @@ -1541,9 +1531,9 @@ def _getusefixturesnames(self, node: nodes.Item) -> Iterator[str]: def getfixtureclosure( self, parentnode: nodes.Node, - initialnames: Tuple[str, ...], + initialnames: tuple[str, ...], ignore_args: AbstractSet[str], - ) -> Tuple[List[str], Dict[str, Sequence[FixtureDef[Any]]]]: + ) -> tuple[list[str], dict[str, Sequence[FixtureDef[Any]]]]: # Collect the closure of all fixtures, starting with the given # fixturenames as the initial set. As we have to visit all # factory definitions anyway, we also return an arg2fixturedefs @@ -1553,7 +1543,7 @@ def getfixtureclosure( fixturenames_closure = list(initialnames) - arg2fixturedefs: Dict[str, Sequence[FixtureDef[Any]]] = {} + arg2fixturedefs: dict[str, Sequence[FixtureDef[Any]]] = {} lastlen = -1 while lastlen != len(fixturenames_closure): lastlen = len(fixturenames_closure) @@ -1580,7 +1570,7 @@ def sort_by_scope(arg_name: str) -> Scope: fixturenames_closure.sort(key=sort_by_scope, reverse=True) return fixturenames_closure, arg2fixturedefs - def pytest_generate_tests(self, metafunc: "Metafunc") -> None: + def pytest_generate_tests(self, metafunc: Metafunc) -> None: """Generate new tests based on parametrized fixtures used by the given metafunc""" def get_parametrize_mark_argnames(mark: Mark) -> Sequence[str]: @@ -1625,7 +1615,7 @@ def get_parametrize_mark_argnames(mark: Mark) -> Sequence[str]: # Try next super fixture, if any. - def pytest_collection_modifyitems(self, items: List[nodes.Item]) -> None: + def pytest_collection_modifyitems(self, items: list[nodes.Item]) -> None: # Separate parametrized setups. items[:] = reorder_items(items) @@ -1633,15 +1623,11 @@ def _register_fixture( self, *, name: str, - func: "_FixtureFunc[object]", - nodeid: Optional[str], - scope: Union[ - Scope, _ScopeName, Callable[[str, Config], _ScopeName] - ] = "function", - params: Optional[Sequence[object]] = None, - ids: Optional[ - Union[Tuple[Optional[object], ...], Callable[[Any], Optional[object]]] - ] = None, + func: _FixtureFunc[object], + nodeid: str | None, + scope: Scope | _ScopeName | Callable[[str, Config], _ScopeName] = "function", + params: Sequence[object] | None = None, + ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None, autouse: bool = False, ) -> None: """Register a fixture @@ -1699,14 +1685,14 @@ def parsefactories( def parsefactories( self, node_or_obj: object, - nodeid: Optional[str], + nodeid: str | None, ) -> None: raise NotImplementedError() def parsefactories( self, - node_or_obj: Union[nodes.Node, object], - nodeid: Union[str, NotSetType, None] = NOTSET, + node_or_obj: nodes.Node | object, + nodeid: str | NotSetType | None = NOTSET, ) -> None: """Collect fixtures from a collection node or object. @@ -1764,7 +1750,7 @@ def parsefactories( def getfixturedefs( self, argname: str, node: nodes.Node - ) -> Optional[Sequence[FixtureDef[Any]]]: + ) -> Sequence[FixtureDef[Any]] | None: """Get FixtureDefs for a fixture name which are applicable to a given node. @@ -1791,7 +1777,7 @@ def _matchfactories( yield fixturedef -def show_fixtures_per_test(config: Config) -> Union[int, ExitCode]: +def show_fixtures_per_test(config: Config) -> int | ExitCode: from _pytest.main import wrap_session return wrap_session(config, _show_fixtures_per_test) @@ -1809,7 +1795,7 @@ def _pretty_fixture_path(invocation_dir: Path, func) -> str: return bestrelpath(invocation_dir, loc) -def _show_fixtures_per_test(config: Config, session: "Session") -> None: +def _show_fixtures_per_test(config: Config, session: Session) -> None: import _pytest.config session.perform_collect() @@ -1842,7 +1828,7 @@ def write_fixture(fixture_def: FixtureDef[object]) -> None: def write_item(item: nodes.Item) -> None: # Not all items have _fixtureinfo attribute. - info: Optional[FuncFixtureInfo] = getattr(item, "_fixtureinfo", None) + info: FuncFixtureInfo | None = getattr(item, "_fixtureinfo", None) if info is None or not info.name2fixturedefs: # This test item does not use any fixtures. return @@ -1862,13 +1848,13 @@ def write_item(item: nodes.Item) -> None: write_item(session_item) -def showfixtures(config: Config) -> Union[int, ExitCode]: +def showfixtures(config: Config) -> int | ExitCode: from _pytest.main import wrap_session return wrap_session(config, _showfixtures_main) -def _showfixtures_main(config: Config, session: "Session") -> None: +def _showfixtures_main(config: Config, session: Session) -> None: import _pytest.config session.perform_collect() @@ -1879,7 +1865,7 @@ def _showfixtures_main(config: Config, session: "Session") -> None: fm = session._fixturemanager available = [] - seen: Set[Tuple[str, str]] = set() + seen: set[tuple[str, str]] = set() for argname, fixturedefs in fm._arg2fixturedefs.items(): assert fixturedefs is not None diff --git a/src/_pytest/freeze_support.py b/src/_pytest/freeze_support.py index e03a6d1753d..2ba6f9b8bcc 100644 --- a/src/_pytest/freeze_support.py +++ b/src/_pytest/freeze_support.py @@ -1,13 +1,13 @@ """Provides a function to report all internal modules for using freezing tools.""" +from __future__ import annotations + import types from typing import Iterator -from typing import List -from typing import Union -def freeze_includes() -> List[str]: +def freeze_includes() -> list[str]: """Return a list of module names used by pytest that should be included by cx_freeze.""" import _pytest @@ -17,7 +17,7 @@ def freeze_includes() -> List[str]: def _iter_all_modules( - package: Union[str, types.ModuleType], + package: str | types.ModuleType, prefix: str = "", ) -> Iterator[str]: """Iterate over the names of all modules that can be found in the given diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 68e0bd881a7..e7a1afab526 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -1,13 +1,12 @@ # mypy: allow-untyped-defs """Version info, help messages, tracing configuration.""" +from __future__ import annotations + from argparse import Action import os import sys from typing import Generator -from typing import List -from typing import Optional -from typing import Union from _pytest.config import Config from _pytest.config import ExitCode @@ -147,7 +146,7 @@ def showversion(config: Config) -> None: sys.stdout.write(f"pytest {pytest.__version__}\n") -def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: +def pytest_cmdline_main(config: Config) -> int | ExitCode | None: if config.option.version > 0: showversion(config) return 0 @@ -162,7 +161,7 @@ def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: def showhelp(config: Config) -> None: import textwrap - reporter: Optional[TerminalReporter] = config.pluginmanager.get_plugin( + reporter: TerminalReporter | None = config.pluginmanager.get_plugin( "terminalreporter" ) assert reporter is not None @@ -239,7 +238,7 @@ def showhelp(config: Config) -> None: conftest_options = [("pytest_plugins", "list of plugin names to load")] -def getpluginversioninfo(config: Config) -> List[str]: +def getpluginversioninfo(config: Config) -> list[str]: lines = [] plugininfo = config.pluginmanager.list_plugin_distinfo() if plugininfo: @@ -251,7 +250,7 @@ def getpluginversioninfo(config: Config) -> List[str]: return lines -def pytest_report_header(config: Config) -> List[str]: +def pytest_report_header(config: Config) -> list[str]: lines = [] if config.option.debug or config.option.traceconfig: lines.append(f"using: pytest-{pytest.__version__}") diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index c7f9d036c33..13f4fddbddb 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -3,16 +3,13 @@ """Hook specifications for pytest plugins which are invoked by pytest itself and by builtin plugins.""" +from __future__ import annotations + from pathlib import Path from typing import Any -from typing import Dict -from typing import List from typing import Mapping -from typing import Optional from typing import Sequence -from typing import Tuple from typing import TYPE_CHECKING -from typing import Union from pluggy import HookspecMarker @@ -57,7 +54,7 @@ @hookspec(historic=True) -def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: +def pytest_addhooks(pluginmanager: PytestPluginManager) -> None: """Called at plugin registration time to allow adding new hooks via a call to :func:`pluginmanager.add_hookspecs(module_or_class, prefix) `. @@ -76,9 +73,9 @@ def pytest_addhooks(pluginmanager: "PytestPluginManager") -> None: @hookspec(historic=True) def pytest_plugin_registered( - plugin: "_PluggyPlugin", + plugin: _PluggyPlugin, plugin_name: str, - manager: "PytestPluginManager", + manager: PytestPluginManager, ) -> None: """A new pytest plugin got registered. @@ -100,7 +97,7 @@ def pytest_plugin_registered( @hookspec(historic=True) -def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> None: +def pytest_addoption(parser: Parser, pluginmanager: PytestPluginManager) -> None: """Register argparse-style options and ini-style config values, called once at the beginning of a test run. @@ -141,7 +138,7 @@ def pytest_addoption(parser: "Parser", pluginmanager: "PytestPluginManager") -> @hookspec(historic=True) -def pytest_configure(config: "Config") -> None: +def pytest_configure(config: Config) -> None: """Allow plugins and conftest files to perform initial configuration. .. note:: @@ -166,8 +163,8 @@ def pytest_configure(config: "Config") -> None: @hookspec(firstresult=True) def pytest_cmdline_parse( - pluginmanager: "PytestPluginManager", args: List[str] -) -> Optional["Config"]: + pluginmanager: PytestPluginManager, args: list[str] +) -> Config | None: """Return an initialized :class:`~pytest.Config`, parsing the specified args. Stops at first non-None result, see :ref:`firstresult`. @@ -189,7 +186,7 @@ def pytest_cmdline_parse( def pytest_load_initial_conftests( - early_config: "Config", parser: "Parser", args: List[str] + early_config: Config, parser: Parser, args: list[str] ) -> None: """Called to implement the loading of :ref:`initial conftest files ` ahead of command line option parsing. @@ -206,7 +203,7 @@ def pytest_load_initial_conftests( @hookspec(firstresult=True) -def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]: +def pytest_cmdline_main(config: Config) -> ExitCode | int | None: """Called for performing the main command line action. The default implementation will invoke the configure hooks and @@ -230,7 +227,7 @@ def pytest_cmdline_main(config: "Config") -> Optional[Union["ExitCode", int]]: @hookspec(firstresult=True) -def pytest_collection(session: "Session") -> Optional[object]: +def pytest_collection(session: Session) -> object | None: """Perform the collection phase for the given session. Stops at first non-None result, see :ref:`firstresult`. @@ -272,7 +269,7 @@ def pytest_collection(session: "Session") -> Optional[object]: def pytest_collection_modifyitems( - session: "Session", config: "Config", items: List["Item"] + session: Session, config: Config, items: list[Item] ) -> None: """Called after collection has been performed. May filter or re-order the items in-place. @@ -288,7 +285,7 @@ def pytest_collection_modifyitems( """ -def pytest_collection_finish(session: "Session") -> None: +def pytest_collection_finish(session: Session) -> None: """Called after collection has been performed and modified. :param session: The pytest session object. @@ -309,8 +306,8 @@ def pytest_collection_finish(session: "Session") -> None: }, ) def pytest_ignore_collect( - collection_path: Path, path: "LEGACY_PATH", config: "Config" -) -> Optional[bool]: + collection_path: Path, path: LEGACY_PATH, config: Config +) -> bool | None: """Return ``True`` to ignore this path for collection. Return ``None`` to let other plugins ignore the path for collection. @@ -343,7 +340,7 @@ def pytest_ignore_collect( @hookspec(firstresult=True) -def pytest_collect_directory(path: Path, parent: "Collector") -> "Optional[Collector]": +def pytest_collect_directory(path: Path, parent: Collector) -> Collector | None: """Create a :class:`~pytest.Collector` for the given directory, or None if not relevant. @@ -379,8 +376,8 @@ def pytest_collect_directory(path: Path, parent: "Collector") -> "Optional[Colle }, ) def pytest_collect_file( - file_path: Path, path: "LEGACY_PATH", parent: "Collector" -) -> "Optional[Collector]": + file_path: Path, path: LEGACY_PATH, parent: Collector +) -> Collector | None: """Create a :class:`~pytest.Collector` for the given path, or None if not relevant. For best results, the returned collector should be a subclass of @@ -407,7 +404,7 @@ def pytest_collect_file( # logging hooks for collection -def pytest_collectstart(collector: "Collector") -> None: +def pytest_collectstart(collector: Collector) -> None: """Collector starts collecting. :param collector: @@ -422,7 +419,7 @@ def pytest_collectstart(collector: "Collector") -> None: """ -def pytest_itemcollected(item: "Item") -> None: +def pytest_itemcollected(item: Item) -> None: """We just collected a test item. :param item: @@ -436,7 +433,7 @@ def pytest_itemcollected(item: "Item") -> None: """ -def pytest_collectreport(report: "CollectReport") -> None: +def pytest_collectreport(report: CollectReport) -> None: """Collector finished collecting. :param report: @@ -451,7 +448,7 @@ def pytest_collectreport(report: "CollectReport") -> None: """ -def pytest_deselected(items: Sequence["Item"]) -> None: +def pytest_deselected(items: Sequence[Item]) -> None: """Called for deselected test items, e.g. by keyword. May be called multiple times. @@ -467,7 +464,7 @@ def pytest_deselected(items: Sequence["Item"]) -> None: @hookspec(firstresult=True) -def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectReport]": +def pytest_make_collect_report(collector: Collector) -> CollectReport | None: """Perform :func:`collector.collect() ` and return a :class:`~pytest.CollectReport`. @@ -499,8 +496,8 @@ def pytest_make_collect_report(collector: "Collector") -> "Optional[CollectRepor }, ) def pytest_pycollect_makemodule( - module_path: Path, path: "LEGACY_PATH", parent -) -> Optional["Module"]: + module_path: Path, path: LEGACY_PATH, parent +) -> Module | None: """Return a :class:`pytest.Module` collector or None for the given path. This hook will be called for each matching test module path. @@ -529,8 +526,8 @@ def pytest_pycollect_makemodule( @hookspec(firstresult=True) def pytest_pycollect_makeitem( - collector: Union["Module", "Class"], name: str, obj: object -) -> Union[None, "Item", "Collector", List[Union["Item", "Collector"]]]: + collector: Module | Class, name: str, obj: object +) -> None | Item | Collector | list[Item | Collector]: """Return a custom item/collector for a Python object in a module, or None. Stops at first non-None result, see :ref:`firstresult`. @@ -554,7 +551,7 @@ def pytest_pycollect_makeitem( @hookspec(firstresult=True) -def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]: +def pytest_pyfunc_call(pyfuncitem: Function) -> object | None: """Call underlying test function. Stops at first non-None result, see :ref:`firstresult`. @@ -571,7 +568,7 @@ def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]: """ -def pytest_generate_tests(metafunc: "Metafunc") -> None: +def pytest_generate_tests(metafunc: Metafunc) -> None: """Generate (multiple) parametrized calls to a test function. :param metafunc: @@ -587,9 +584,7 @@ def pytest_generate_tests(metafunc: "Metafunc") -> None: @hookspec(firstresult=True) -def pytest_make_parametrize_id( - config: "Config", val: object, argname: str -) -> Optional[str]: +def pytest_make_parametrize_id(config: Config, val: object, argname: str) -> str | None: """Return a user-friendly string representation of the given ``val`` that will be used by @pytest.mark.parametrize calls, or None if the hook doesn't know about ``val``. @@ -615,7 +610,7 @@ def pytest_make_parametrize_id( @hookspec(firstresult=True) -def pytest_runtestloop(session: "Session") -> Optional[object]: +def pytest_runtestloop(session: Session) -> object | None: """Perform the main runtest loop (after collection finished). The default hook implementation performs the runtest protocol for all items @@ -641,9 +636,7 @@ def pytest_runtestloop(session: "Session") -> Optional[object]: @hookspec(firstresult=True) -def pytest_runtest_protocol( - item: "Item", nextitem: "Optional[Item]" -) -> Optional[object]: +def pytest_runtest_protocol(item: Item, nextitem: Item | None) -> object | None: """Perform the runtest protocol for a single test item. The default runtest protocol is this (see individual hooks for full details): @@ -683,9 +676,7 @@ def pytest_runtest_protocol( """ -def pytest_runtest_logstart( - nodeid: str, location: Tuple[str, Optional[int], str] -) -> None: +def pytest_runtest_logstart(nodeid: str, location: tuple[str, int | None, str]) -> None: """Called at the start of running the runtest protocol for a single item. See :hook:`pytest_runtest_protocol` for a description of the runtest protocol. @@ -704,7 +695,7 @@ def pytest_runtest_logstart( def pytest_runtest_logfinish( - nodeid: str, location: Tuple[str, Optional[int], str] + nodeid: str, location: tuple[str, int | None, str] ) -> None: """Called at the end of running the runtest protocol for a single item. @@ -723,7 +714,7 @@ def pytest_runtest_logfinish( """ -def pytest_runtest_setup(item: "Item") -> None: +def pytest_runtest_setup(item: Item) -> None: """Called to perform the setup phase for a test item. The default implementation runs ``setup()`` on ``item`` and all of its @@ -742,7 +733,7 @@ def pytest_runtest_setup(item: "Item") -> None: """ -def pytest_runtest_call(item: "Item") -> None: +def pytest_runtest_call(item: Item) -> None: """Called to run the test for test item (the call phase). The default implementation calls ``item.runtest()``. @@ -758,7 +749,7 @@ def pytest_runtest_call(item: "Item") -> None: """ -def pytest_runtest_teardown(item: "Item", nextitem: Optional["Item"]) -> None: +def pytest_runtest_teardown(item: Item, nextitem: Item | None) -> None: """Called to perform the teardown phase for a test item. The default implementation runs the finalizers and calls ``teardown()`` @@ -783,9 +774,7 @@ def pytest_runtest_teardown(item: "Item", nextitem: Optional["Item"]) -> None: @hookspec(firstresult=True) -def pytest_runtest_makereport( - item: "Item", call: "CallInfo[None]" -) -> Optional["TestReport"]: +def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> TestReport | None: """Called to create a :class:`~pytest.TestReport` for each of the setup, call and teardown runtest phases of a test item. @@ -804,7 +793,7 @@ def pytest_runtest_makereport( """ -def pytest_runtest_logreport(report: "TestReport") -> None: +def pytest_runtest_logreport(report: TestReport) -> None: """Process the :class:`~pytest.TestReport` produced for each of the setup, call and teardown runtest phases of an item. @@ -820,9 +809,9 @@ def pytest_runtest_logreport(report: "TestReport") -> None: @hookspec(firstresult=True) def pytest_report_to_serializable( - config: "Config", - report: Union["CollectReport", "TestReport"], -) -> Optional[Dict[str, Any]]: + config: Config, + report: CollectReport | TestReport, +) -> dict[str, Any] | None: """Serialize the given report object into a data structure suitable for sending over the wire, e.g. converted to JSON. @@ -839,9 +828,9 @@ def pytest_report_to_serializable( @hookspec(firstresult=True) def pytest_report_from_serializable( - config: "Config", - data: Dict[str, Any], -) -> Optional[Union["CollectReport", "TestReport"]]: + config: Config, + data: dict[str, Any], +) -> CollectReport | TestReport | None: """Restore a report object previously serialized with :hook:`pytest_report_to_serializable`. @@ -862,8 +851,8 @@ def pytest_report_from_serializable( @hookspec(firstresult=True) def pytest_fixture_setup( - fixturedef: "FixtureDef[Any]", request: "SubRequest" -) -> Optional[object]: + fixturedef: FixtureDef[Any], request: SubRequest +) -> object | None: """Perform fixture setup execution. :param fixturedef: @@ -890,7 +879,7 @@ def pytest_fixture_setup( def pytest_fixture_post_finalizer( - fixturedef: "FixtureDef[Any]", request: "SubRequest" + fixturedef: FixtureDef[Any], request: SubRequest ) -> None: """Called after fixture teardown, but before the cache is cleared, so the fixture result ``fixturedef.cached_result`` is still available (not @@ -915,7 +904,7 @@ def pytest_fixture_post_finalizer( # ------------------------------------------------------------------------- -def pytest_sessionstart(session: "Session") -> None: +def pytest_sessionstart(session: Session) -> None: """Called after the ``Session`` object has been created and before performing collection and entering the run test loop. @@ -929,8 +918,8 @@ def pytest_sessionstart(session: "Session") -> None: def pytest_sessionfinish( - session: "Session", - exitstatus: Union[int, "ExitCode"], + session: Session, + exitstatus: int | ExitCode, ) -> None: """Called after whole test run finished, right before returning the exit status to the system. @@ -944,7 +933,7 @@ def pytest_sessionfinish( """ -def pytest_unconfigure(config: "Config") -> None: +def pytest_unconfigure(config: Config) -> None: """Called before test process is exited. :param config: The pytest config object. @@ -962,8 +951,8 @@ def pytest_unconfigure(config: "Config") -> None: def pytest_assertrepr_compare( - config: "Config", op: str, left: object, right: object -) -> Optional[List[str]]: + config: Config, op: str, left: object, right: object +) -> list[str] | None: """Return explanation for comparisons in failing assert expressions. Return None for no custom explanation, otherwise return a list @@ -984,7 +973,7 @@ def pytest_assertrepr_compare( """ -def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> None: +def pytest_assertion_pass(item: Item, lineno: int, orig: str, expl: str) -> None: """Called whenever an assertion passes. .. versionadded:: 5.0 @@ -1031,8 +1020,8 @@ def pytest_assertion_pass(item: "Item", lineno: int, orig: str, expl: str) -> No }, ) def pytest_report_header( # type:ignore[empty-body] - config: "Config", start_path: Path, startdir: "LEGACY_PATH" -) -> Union[str, List[str]]: + config: Config, start_path: Path, startdir: LEGACY_PATH +) -> str | list[str]: """Return a string or list of strings to be displayed as header info for terminal reporting. :param config: The pytest config object. @@ -1066,11 +1055,11 @@ def pytest_report_header( # type:ignore[empty-body] }, ) def pytest_report_collectionfinish( # type:ignore[empty-body] - config: "Config", + config: Config, start_path: Path, - startdir: "LEGACY_PATH", - items: Sequence["Item"], -) -> Union[str, List[str]]: + startdir: LEGACY_PATH, + items: Sequence[Item], +) -> str | list[str]: """Return a string or list of strings to be displayed after collection has finished successfully. @@ -1104,8 +1093,8 @@ def pytest_report_collectionfinish( # type:ignore[empty-body] @hookspec(firstresult=True) def pytest_report_teststatus( # type:ignore[empty-body] - report: Union["CollectReport", "TestReport"], config: "Config" -) -> "TestShortLogReport | Tuple[str, str, Union[str, Tuple[str, Mapping[str, bool]]]]": + report: CollectReport | TestReport, config: Config +) -> TestShortLogReport | tuple[str, str, str | tuple[str, Mapping[str, bool]]]: """Return result-category, shortletter and verbose word for status reporting. @@ -1136,9 +1125,9 @@ def pytest_report_teststatus( # type:ignore[empty-body] def pytest_terminal_summary( - terminalreporter: "TerminalReporter", - exitstatus: "ExitCode", - config: "Config", + terminalreporter: TerminalReporter, + exitstatus: ExitCode, + config: Config, ) -> None: """Add a section to terminal summary reporting. @@ -1158,10 +1147,10 @@ def pytest_terminal_summary( @hookspec(historic=True) def pytest_warning_recorded( - warning_message: "warnings.WarningMessage", - when: "Literal['config', 'collect', 'runtest']", + warning_message: warnings.WarningMessage, + when: Literal["config", "collect", "runtest"], nodeid: str, - location: Optional[Tuple[str, int, str]], + location: tuple[str, int, str] | None, ) -> None: """Process a warning captured by the internal pytest warnings plugin. @@ -1202,8 +1191,8 @@ def pytest_warning_recorded( def pytest_markeval_namespace( # type:ignore[empty-body] - config: "Config", -) -> Dict[str, Any]: + config: Config, +) -> dict[str, Any]: """Called when constructing the globals dictionary used for evaluating string conditions in xfail/skipif markers. @@ -1231,9 +1220,9 @@ def pytest_markeval_namespace( # type:ignore[empty-body] def pytest_internalerror( - excrepr: "ExceptionRepr", - excinfo: "ExceptionInfo[BaseException]", -) -> Optional[bool]: + excrepr: ExceptionRepr, + excinfo: ExceptionInfo[BaseException], +) -> bool | None: """Called for internal errors. Return True to suppress the fallback handling of printing an @@ -1250,7 +1239,7 @@ def pytest_internalerror( def pytest_keyboard_interrupt( - excinfo: "ExceptionInfo[Union[KeyboardInterrupt, Exit]]", + excinfo: ExceptionInfo[KeyboardInterrupt | Exit], ) -> None: """Called for keyboard interrupt. @@ -1264,9 +1253,9 @@ def pytest_keyboard_interrupt( def pytest_exception_interact( - node: Union["Item", "Collector"], - call: "CallInfo[Any]", - report: Union["CollectReport", "TestReport"], + node: Item | Collector, + call: CallInfo[Any], + report: CollectReport | TestReport, ) -> None: """Called when an exception was raised which can potentially be interactively handled. @@ -1295,7 +1284,7 @@ def pytest_exception_interact( """ -def pytest_enter_pdb(config: "Config", pdb: "pdb.Pdb") -> None: +def pytest_enter_pdb(config: Config, pdb: pdb.Pdb) -> None: """Called upon pdb.set_trace(). Can be used by plugins to take special action just before the python @@ -1311,7 +1300,7 @@ def pytest_enter_pdb(config: "Config", pdb: "pdb.Pdb") -> None: """ -def pytest_leave_pdb(config: "Config", pdb: "pdb.Pdb") -> None: +def pytest_leave_pdb(config: Config, pdb: pdb.Pdb) -> None: """Called when leaving pdb (e.g. with continue after pdb.set_trace()). Can be used by plugins to take special action just after the python diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 011af6100e9..a525f1d14de 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -8,18 +8,15 @@ https://github.com/jenkinsci/xunit-plugin/blob/master/src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd """ +from __future__ import annotations + from datetime import datetime import functools import os import platform import re from typing import Callable -from typing import Dict -from typing import List from typing import Match -from typing import Optional -from typing import Tuple -from typing import Union import xml.etree.ElementTree as ET from _pytest import nodes @@ -89,15 +86,15 @@ def merge_family(left, right) -> None: class _NodeReporter: - def __init__(self, nodeid: Union[str, TestReport], xml: "LogXML") -> None: + def __init__(self, nodeid: str | TestReport, xml: LogXML) -> None: self.id = nodeid self.xml = xml self.add_stats = self.xml.add_stats self.family = self.xml.family self.duration = 0.0 - self.properties: List[Tuple[str, str]] = [] - self.nodes: List[ET.Element] = [] - self.attrs: Dict[str, str] = {} + self.properties: list[tuple[str, str]] = [] + self.nodes: list[ET.Element] = [] + self.attrs: dict[str, str] = {} def append(self, node: ET.Element) -> None: self.xml.add_stats(node.tag) @@ -109,7 +106,7 @@ def add_property(self, name: str, value: object) -> None: def add_attribute(self, name: str, value: object) -> None: self.attrs[str(name)] = bin_xml_escape(value) - def make_properties_node(self) -> Optional[ET.Element]: + def make_properties_node(self) -> ET.Element | None: """Return a Junit node containing custom properties, if any.""" if self.properties: properties = ET.Element("properties") @@ -124,7 +121,7 @@ def record_testreport(self, testreport: TestReport) -> None: classnames = names[:-1] if self.xml.prefix: classnames.insert(0, self.xml.prefix) - attrs: Dict[str, str] = { + attrs: dict[str, str] = { "classname": ".".join(classnames), "name": bin_xml_escape(names[-1]), "file": testreport.location[0], @@ -156,7 +153,7 @@ def to_xml(self) -> ET.Element: testcase.extend(self.nodes) return testcase - def _add_simple(self, tag: str, message: str, data: Optional[str] = None) -> None: + def _add_simple(self, tag: str, message: str, data: str | None = None) -> None: node = ET.Element(tag, message=message) node.text = bin_xml_escape(data) self.append(node) @@ -201,7 +198,7 @@ def append_failure(self, report: TestReport) -> None: self._add_simple("skipped", "xfail-marked test passes unexpectedly") else: assert report.longrepr is not None - reprcrash: Optional[ReprFileLocation] = getattr( + reprcrash: ReprFileLocation | None = getattr( report.longrepr, "reprcrash", None ) if reprcrash is not None: @@ -221,9 +218,7 @@ def append_collect_skipped(self, report: TestReport) -> None: def append_error(self, report: TestReport) -> None: assert report.longrepr is not None - reprcrash: Optional[ReprFileLocation] = getattr( - report.longrepr, "reprcrash", None - ) + reprcrash: ReprFileLocation | None = getattr(report.longrepr, "reprcrash", None) if reprcrash is not None: reason = reprcrash.message else: @@ -451,7 +446,7 @@ def pytest_unconfigure(config: Config) -> None: config.pluginmanager.unregister(xml) -def mangle_test_address(address: str) -> List[str]: +def mangle_test_address(address: str) -> list[str]: path, possible_open_bracket, params = address.partition("[") names = path.split("::") # Convert file path to dotted path. @@ -466,7 +461,7 @@ class LogXML: def __init__( self, logfile, - prefix: Optional[str], + prefix: str | None, suite_name: str = "pytest", logging: str = "no", report_duration: str = "total", @@ -481,17 +476,15 @@ def __init__( self.log_passing_tests = log_passing_tests self.report_duration = report_duration self.family = family - self.stats: Dict[str, int] = dict.fromkeys( + self.stats: dict[str, int] = dict.fromkeys( ["error", "passed", "failure", "skipped"], 0 ) - self.node_reporters: Dict[ - Tuple[Union[str, TestReport], object], _NodeReporter - ] = {} - self.node_reporters_ordered: List[_NodeReporter] = [] - self.global_properties: List[Tuple[str, str]] = [] + self.node_reporters: dict[tuple[str | TestReport, object], _NodeReporter] = {} + self.node_reporters_ordered: list[_NodeReporter] = [] + self.global_properties: list[tuple[str, str]] = [] # List of reports that failed on call but teardown is pending. - self.open_reports: List[TestReport] = [] + self.open_reports: list[TestReport] = [] self.cnt_double_fail_tests = 0 # Replaces convenience family with real family. @@ -510,8 +503,8 @@ def finalize(self, report: TestReport) -> None: if reporter is not None: reporter.finalize() - def node_reporter(self, report: Union[TestReport, str]) -> _NodeReporter: - nodeid: Union[str, TestReport] = getattr(report, "nodeid", report) + def node_reporter(self, report: TestReport | str) -> _NodeReporter: + nodeid: str | TestReport = getattr(report, "nodeid", report) # Local hack to handle xdist report order. workernode = getattr(report, "node", None) @@ -691,7 +684,7 @@ def add_global_property(self, name: str, value: object) -> None: _check_record_param_type("name", name) self.global_properties.append((name, bin_xml_escape(value))) - def _get_global_properties_node(self) -> Optional[ET.Element]: + def _get_global_properties_node(self) -> ET.Element | None: """Return a Junit node containing custom properties, if any.""" if self.global_properties: properties = ET.Element("properties") diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index d9de65b1a53..61476d68932 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -1,16 +1,15 @@ # mypy: allow-untyped-defs """Add backward compatibility support for the legacy py path type.""" +from __future__ import annotations + import dataclasses from pathlib import Path import shlex import subprocess from typing import Final from typing import final -from typing import List -from typing import Optional from typing import TYPE_CHECKING -from typing import Union from iniconfig import SectionWrapper @@ -50,8 +49,8 @@ class Testdir: __test__ = False - CLOSE_STDIN: "Final" = Pytester.CLOSE_STDIN - TimeoutExpired: "Final" = Pytester.TimeoutExpired + CLOSE_STDIN: Final = Pytester.CLOSE_STDIN + TimeoutExpired: Final = Pytester.TimeoutExpired def __init__(self, pytester: Pytester, *, _ispytest: bool = False) -> None: check_ispytest(_ispytest) @@ -145,7 +144,7 @@ def copy_example(self, name=None) -> LEGACY_PATH: """See :meth:`Pytester.copy_example`.""" return legacy_path(self._pytester.copy_example(name)) - def getnode(self, config: Config, arg) -> Optional[Union[Item, Collector]]: + def getnode(self, config: Config, arg) -> Item | Collector | None: """See :meth:`Pytester.getnode`.""" return self._pytester.getnode(config, arg) @@ -153,7 +152,7 @@ def getpathnode(self, path): """See :meth:`Pytester.getpathnode`.""" return self._pytester.getpathnode(path) - def genitems(self, colitems: List[Union[Item, Collector]]) -> List[Item]: + def genitems(self, colitems: list[Item | Collector]) -> list[Item]: """See :meth:`Pytester.genitems`.""" return self._pytester.genitems(colitems) @@ -205,9 +204,7 @@ def getmodulecol(self, source, configargs=(), withinit=False): source, configargs=configargs, withinit=withinit ) - def collect_by_name( - self, modcol: Collector, name: str - ) -> Optional[Union[Item, Collector]]: + def collect_by_name(self, modcol: Collector, name: str) -> Item | Collector | None: """See :meth:`Pytester.collect_by_name`.""" return self._pytester.collect_by_name(modcol, name) @@ -238,13 +235,11 @@ def runpytest_subprocess(self, *args, timeout=None) -> RunResult: """See :meth:`Pytester.runpytest_subprocess`.""" return self._pytester.runpytest_subprocess(*args, timeout=timeout) - def spawn_pytest( - self, string: str, expect_timeout: float = 10.0 - ) -> "pexpect.spawn": + def spawn_pytest(self, string: str, expect_timeout: float = 10.0) -> pexpect.spawn: """See :meth:`Pytester.spawn_pytest`.""" return self._pytester.spawn_pytest(string, expect_timeout=expect_timeout) - def spawn(self, cmd: str, expect_timeout: float = 10.0) -> "pexpect.spawn": + def spawn(self, cmd: str, expect_timeout: float = 10.0) -> pexpect.spawn: """See :meth:`Pytester.spawn`.""" return self._pytester.spawn(cmd, expect_timeout=expect_timeout) @@ -374,7 +369,7 @@ def Config_rootdir(self: Config) -> LEGACY_PATH: return legacy_path(str(self.rootpath)) -def Config_inifile(self: Config) -> Optional[LEGACY_PATH]: +def Config_inifile(self: Config) -> LEGACY_PATH | None: """The path to the :ref:`configfile `. Prefer to use :attr:`inipath`, which is a :class:`pathlib.Path`. @@ -394,9 +389,7 @@ def Session_startdir(self: Session) -> LEGACY_PATH: return legacy_path(self.startpath) -def Config__getini_unknown_type( - self, name: str, type: str, value: Union[str, List[str]] -): +def Config__getini_unknown_type(self, name: str, type: str, value: str | list[str]): if type == "pathlist": # TODO: This assert is probably not valid in all cases. assert self.inipath is not None diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index c9139d369ef..fe3be060fdd 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Access and control log capturing.""" +from __future__ import annotations + from contextlib import contextmanager from contextlib import nullcontext from datetime import datetime @@ -22,12 +24,8 @@ from typing import List from typing import Literal from typing import Mapping -from typing import Optional -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING from typing import TypeVar -from typing import Union from _pytest import nodes from _pytest._io import TerminalWriter @@ -68,7 +66,7 @@ class DatetimeFormatter(logging.Formatter): :func:`time.strftime` in case of microseconds in format string. """ - def formatTime(self, record: LogRecord, datefmt: Optional[str] = None) -> str: + def formatTime(self, record: LogRecord, datefmt: str | None = None) -> str: if datefmt and "%f" in datefmt: ct = self.converter(record.created) tz = timezone(timedelta(seconds=ct.tm_gmtoff), ct.tm_zone) @@ -100,7 +98,7 @@ def __init__(self, terminalwriter: TerminalWriter, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self._terminalwriter = terminalwriter self._original_fmt = self._style._fmt - self._level_to_fmt_mapping: Dict[int, str] = {} + self._level_to_fmt_mapping: dict[int, str] = {} for level, color_opts in self.LOGLEVEL_COLOROPTS.items(): self.add_color_level(level, *color_opts) @@ -148,12 +146,12 @@ class PercentStyleMultiline(logging.PercentStyle): formats the message as if each line were logged separately. """ - def __init__(self, fmt: str, auto_indent: Union[int, str, bool, None]) -> None: + def __init__(self, fmt: str, auto_indent: int | str | bool | None) -> None: super().__init__(fmt) self._auto_indent = self._get_auto_indent(auto_indent) @staticmethod - def _get_auto_indent(auto_indent_option: Union[int, str, bool, None]) -> int: + def _get_auto_indent(auto_indent_option: int | str | bool | None) -> int: """Determine the current auto indentation setting. Specify auto indent behavior (on/off/fixed) by passing in @@ -348,7 +346,7 @@ class catching_logs(Generic[_HandlerType]): __slots__ = ("handler", "level", "orig_level") - def __init__(self, handler: _HandlerType, level: Optional[int] = None) -> None: + def __init__(self, handler: _HandlerType, level: int | None = None) -> None: self.handler = handler self.level = level @@ -364,9 +362,9 @@ def __enter__(self) -> _HandlerType: def __exit__( self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, ) -> None: root_logger = logging.getLogger() if self.level is not None: @@ -380,7 +378,7 @@ class LogCaptureHandler(logging_StreamHandler): def __init__(self) -> None: """Create a new log handler.""" super().__init__(StringIO()) - self.records: List[logging.LogRecord] = [] + self.records: list[logging.LogRecord] = [] def emit(self, record: logging.LogRecord) -> None: """Keep the log records in a list in addition to the log text.""" @@ -411,10 +409,10 @@ class LogCaptureFixture: def __init__(self, item: nodes.Node, *, _ispytest: bool = False) -> None: check_ispytest(_ispytest) self._item = item - self._initial_handler_level: Optional[int] = None + self._initial_handler_level: int | None = None # Dict of log name -> log level. - self._initial_logger_levels: Dict[Optional[str], int] = {} - self._initial_disabled_logging_level: Optional[int] = None + self._initial_logger_levels: dict[str | None, int] = {} + self._initial_disabled_logging_level: int | None = None def _finalize(self) -> None: """Finalize the fixture. @@ -439,7 +437,7 @@ def handler(self) -> LogCaptureHandler: def get_records( self, when: Literal["setup", "call", "teardown"] - ) -> List[logging.LogRecord]: + ) -> list[logging.LogRecord]: """Get the logging records for one of the possible test phases. :param when: @@ -458,12 +456,12 @@ def text(self) -> str: return _remove_ansi_escape_sequences(self.handler.stream.getvalue()) @property - def records(self) -> List[logging.LogRecord]: + def records(self) -> list[logging.LogRecord]: """The list of log records.""" return self.handler.records @property - def record_tuples(self) -> List[Tuple[str, int, str]]: + def record_tuples(self) -> list[tuple[str, int, str]]: """A list of a stripped down version of log records intended for use in assertion comparison. @@ -474,7 +472,7 @@ def record_tuples(self) -> List[Tuple[str, int, str]]: return [(r.name, r.levelno, r.getMessage()) for r in self.records] @property - def messages(self) -> List[str]: + def messages(self) -> list[str]: """A list of format-interpolated log messages. Unlike 'records', which contains the format string and parameters for @@ -497,7 +495,7 @@ def clear(self) -> None: self.handler.clear() def _force_enable_logging( - self, level: Union[int, str], logger_obj: logging.Logger + self, level: int | str, logger_obj: logging.Logger ) -> int: """Enable the desired logging level if the global level was disabled via ``logging.disabled``. @@ -530,7 +528,7 @@ def _force_enable_logging( return original_disable_level - def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> None: + def set_level(self, level: int | str, logger: str | None = None) -> None: """Set the threshold level of a logger for the duration of a test. Logging messages which are less severe than this level will not be captured. @@ -557,7 +555,7 @@ def set_level(self, level: Union[int, str], logger: Optional[str] = None) -> Non @contextmanager def at_level( - self, level: Union[int, str], logger: Optional[str] = None + self, level: int | str, logger: str | None = None ) -> Generator[None, None, None]: """Context manager that sets the level for capturing of logs. After the end of the 'with' statement the level is restored to its original @@ -615,7 +613,7 @@ def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]: result._finalize() -def get_log_level_for_setting(config: Config, *setting_names: str) -> Optional[int]: +def get_log_level_for_setting(config: Config, *setting_names: str) -> int | None: for setting_name in setting_names: log_level = config.getoption(setting_name) if log_level is None: @@ -701,9 +699,9 @@ def __init__(self, config: Config) -> None: assert terminal_reporter is not None capture_manager = config.pluginmanager.get_plugin("capturemanager") # if capturemanager plugin is disabled, live logging still works. - self.log_cli_handler: Union[ - _LiveLoggingStreamHandler, _LiveLoggingNullHandler - ] = _LiveLoggingStreamHandler(terminal_reporter, capture_manager) + self.log_cli_handler: ( + _LiveLoggingStreamHandler | _LiveLoggingNullHandler + ) = _LiveLoggingStreamHandler(terminal_reporter, capture_manager) else: self.log_cli_handler = _LiveLoggingNullHandler() log_cli_formatter = self._create_formatter( @@ -714,7 +712,7 @@ def __init__(self, config: Config) -> None: self.log_cli_handler.setFormatter(log_cli_formatter) self._disable_loggers(loggers_to_disable=config.option.logger_disable) - def _disable_loggers(self, loggers_to_disable: List[str]) -> None: + def _disable_loggers(self, loggers_to_disable: list[str]) -> None: if not loggers_to_disable: return @@ -839,7 +837,7 @@ def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None, None, Non def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]: self.log_cli_handler.set_when("setup") - empty: Dict[str, List[logging.LogRecord]] = {} + empty: dict[str, list[logging.LogRecord]] = {} item.stash[caplog_records_key] = empty yield from self._runtest_for(item, "setup") @@ -902,7 +900,7 @@ class _LiveLoggingStreamHandler(logging_StreamHandler): def __init__( self, terminal_reporter: TerminalReporter, - capture_manager: Optional[CaptureManager], + capture_manager: CaptureManager | None, ) -> None: super().__init__(stream=terminal_reporter) # type: ignore[arg-type] self.capture_manager = capture_manager @@ -914,7 +912,7 @@ def reset(self) -> None: """Reset the handler; should be called before the start of each test.""" self._first_record_emitted = False - def set_when(self, when: Optional[str]) -> None: + def set_when(self, when: str | None) -> None: """Prepare for the given test phase (setup/call/teardown).""" self._when = when self._section_name_shown = False diff --git a/src/_pytest/main.py b/src/_pytest/main.py index d200a6877ff..a19ddef58fb 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -1,5 +1,7 @@ """Core implementation of the testing process: init, session, runtest loop.""" +from __future__ import annotations + import argparse import dataclasses import fnmatch @@ -13,17 +15,12 @@ from typing import Callable from typing import Dict from typing import final -from typing import FrozenSet from typing import Iterable from typing import Iterator -from typing import List from typing import Literal -from typing import Optional from typing import overload from typing import Sequence -from typing import Tuple from typing import TYPE_CHECKING -from typing import Union import warnings import pluggy @@ -271,8 +268,8 @@ def is_ancestor(base: Path, query: Path) -> bool: def wrap_session( - config: Config, doit: Callable[[Config, "Session"], Optional[Union[int, ExitCode]]] -) -> Union[int, ExitCode]: + config: Config, doit: Callable[[Config, Session], int | ExitCode | None] +) -> int | ExitCode: """Skeleton command line program.""" session = Session.from_config(config) session.exitstatus = ExitCode.OK @@ -291,7 +288,7 @@ def wrap_session( session.exitstatus = ExitCode.TESTS_FAILED except (KeyboardInterrupt, exit.Exception): excinfo = _pytest._code.ExceptionInfo.from_current() - exitstatus: Union[int, ExitCode] = ExitCode.INTERRUPTED + exitstatus: int | ExitCode = ExitCode.INTERRUPTED if isinstance(excinfo.value, exit.Exception): if excinfo.value.returncode is not None: exitstatus = excinfo.value.returncode @@ -329,11 +326,11 @@ def wrap_session( return session.exitstatus -def pytest_cmdline_main(config: Config) -> Union[int, ExitCode]: +def pytest_cmdline_main(config: Config) -> int | ExitCode: return wrap_session(config, _main) -def _main(config: Config, session: "Session") -> Optional[Union[int, ExitCode]]: +def _main(config: Config, session: Session) -> int | ExitCode | None: """Default command line protocol for initialization, session, running tests and reporting.""" config.hook.pytest_collection(session=session) @@ -346,11 +343,11 @@ def _main(config: Config, session: "Session") -> Optional[Union[int, ExitCode]]: return None -def pytest_collection(session: "Session") -> None: +def pytest_collection(session: Session) -> None: session.perform_collect() -def pytest_runtestloop(session: "Session") -> bool: +def pytest_runtestloop(session: Session) -> bool: if session.testsfailed and not session.config.option.continue_on_collection_errors: raise session.Interrupted( "%d error%s during collection" @@ -390,7 +387,7 @@ def _in_venv(path: Path) -> bool: return any(fname.name in activates for fname in bindir.iterdir()) -def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[bool]: +def pytest_ignore_collect(collection_path: Path, config: Config) -> bool | None: if collection_path.name == "__pycache__": return True @@ -430,11 +427,11 @@ def pytest_ignore_collect(collection_path: Path, config: Config) -> Optional[boo def pytest_collect_directory( path: Path, parent: nodes.Collector -) -> Optional[nodes.Collector]: +) -> nodes.Collector | None: return Dir.from_parent(parent, path=path) -def pytest_collection_modifyitems(items: List[nodes.Item], config: Config) -> None: +def pytest_collection_modifyitems(items: list[nodes.Item], config: Config) -> None: deselect_prefixes = tuple(config.getoption("deselect") or []) if not deselect_prefixes: return @@ -508,7 +505,7 @@ def from_parent( # type: ignore[override] parent: nodes.Collector, *, path: Path, - ) -> "Self": + ) -> Self: """The public constructor. :param parent: The parent collector of this Dir. @@ -516,9 +513,9 @@ def from_parent( # type: ignore[override] """ return super().from_parent(parent=parent, path=path) - def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: + def collect(self) -> Iterable[nodes.Item | nodes.Collector]: config = self.config - col: Optional[nodes.Collector] + col: nodes.Collector | None cols: Sequence[nodes.Collector] ihook = self.ihook for direntry in scandir(self.path): @@ -552,8 +549,8 @@ class Session(nodes.Collector): # Set on the session by runner.pytest_sessionstart. _setupstate: SetupState # Set on the session by fixtures.pytest_sessionstart. - _fixturemanager: "FixtureManager" - exitstatus: Union[int, ExitCode] + _fixturemanager: FixtureManager + exitstatus: int | ExitCode def __init__(self, config: Config) -> None: super().__init__( @@ -567,22 +564,22 @@ def __init__(self, config: Config) -> None: ) self.testsfailed = 0 self.testscollected = 0 - self._shouldstop: Union[bool, str] = False - self._shouldfail: Union[bool, str] = False + self._shouldstop: bool | str = False + self._shouldfail: bool | str = False self.trace = config.trace.root.get("collection") - self._initialpaths: FrozenSet[Path] = frozenset() - self._initialpaths_with_parents: FrozenSet[Path] = frozenset() - self._notfound: List[Tuple[str, Sequence[nodes.Collector]]] = [] - self._initial_parts: List[CollectionArgument] = [] - self._collection_cache: Dict[nodes.Collector, CollectReport] = {} - self.items: List[nodes.Item] = [] + self._initialpaths: frozenset[Path] = frozenset() + self._initialpaths_with_parents: frozenset[Path] = frozenset() + self._notfound: list[tuple[str, Sequence[nodes.Collector]]] = [] + self._initial_parts: list[CollectionArgument] = [] + self._collection_cache: dict[nodes.Collector, CollectReport] = {} + self.items: list[nodes.Item] = [] - self._bestrelpathcache: Dict[Path, str] = _bestrelpath_cache(config.rootpath) + self._bestrelpathcache: dict[Path, str] = _bestrelpath_cache(config.rootpath) self.config.pluginmanager.register(self, name="session") @classmethod - def from_config(cls, config: Config) -> "Session": + def from_config(cls, config: Config) -> Session: session: Session = cls._create(config=config) return session @@ -596,11 +593,11 @@ def __repr__(self) -> str: ) @property - def shouldstop(self) -> Union[bool, str]: + def shouldstop(self) -> bool | str: return self._shouldstop @shouldstop.setter - def shouldstop(self, value: Union[bool, str]) -> None: + def shouldstop(self, value: bool | str) -> None: # The runner checks shouldfail and assumes that if it is set we are # definitely stopping, so prevent unsetting it. if value is False and self._shouldstop: @@ -614,11 +611,11 @@ def shouldstop(self, value: Union[bool, str]) -> None: self._shouldstop = value @property - def shouldfail(self) -> Union[bool, str]: + def shouldfail(self) -> bool | str: return self._shouldfail @shouldfail.setter - def shouldfail(self, value: Union[bool, str]) -> None: + def shouldfail(self, value: bool | str) -> None: # The runner checks shouldfail and assumes that if it is set we are # definitely stopping, so prevent unsetting it. if value is False and self._shouldfail: @@ -651,9 +648,7 @@ def pytest_collectstart(self) -> None: raise self.Interrupted(self.shouldstop) @hookimpl(tryfirst=True) - def pytest_runtest_logreport( - self, report: Union[TestReport, CollectReport] - ) -> None: + def pytest_runtest_logreport(self, report: TestReport | CollectReport) -> None: if report.failed and not hasattr(report, "wasxfail"): self.testsfailed += 1 maxfail = self.config.getvalue("maxfail") @@ -664,7 +659,7 @@ def pytest_runtest_logreport( def isinitpath( self, - path: Union[str, "os.PathLike[str]"], + path: str | os.PathLike[str], *, with_parents: bool = False, ) -> bool: @@ -686,7 +681,7 @@ def isinitpath( else: return path_ in self._initialpaths - def gethookproxy(self, fspath: "os.PathLike[str]") -> pluggy.HookRelay: + def gethookproxy(self, fspath: os.PathLike[str]) -> pluggy.HookRelay: # Optimization: Path(Path(...)) is much slower than isinstance. path = fspath if isinstance(fspath, Path) else Path(fspath) pm = self.config.pluginmanager @@ -706,7 +701,7 @@ def gethookproxy(self, fspath: "os.PathLike[str]") -> pluggy.HookRelay: def _collect_path( self, path: Path, - path_cache: Dict[Path, Sequence[nodes.Collector]], + path_cache: dict[Path, Sequence[nodes.Collector]], ) -> Sequence[nodes.Collector]: """Create a Collector for the given path. @@ -718,7 +713,7 @@ def _collect_path( if path.is_dir(): ihook = self.gethookproxy(path.parent) - col: Optional[nodes.Collector] = ihook.pytest_collect_directory( + col: nodes.Collector | None = ihook.pytest_collect_directory( path=path, parent=self ) cols: Sequence[nodes.Collector] = (col,) if col is not None else () @@ -736,17 +731,17 @@ def _collect_path( @overload def perform_collect( - self, args: Optional[Sequence[str]] = ..., genitems: "Literal[True]" = ... + self, args: Sequence[str] | None = ..., genitems: Literal[True] = ... ) -> Sequence[nodes.Item]: ... @overload def perform_collect( - self, args: Optional[Sequence[str]] = ..., genitems: bool = ... - ) -> Sequence[Union[nodes.Item, nodes.Collector]]: ... + self, args: Sequence[str] | None = ..., genitems: bool = ... + ) -> Sequence[nodes.Item | nodes.Collector]: ... def perform_collect( - self, args: Optional[Sequence[str]] = None, genitems: bool = True - ) -> Sequence[Union[nodes.Item, nodes.Collector]]: + self, args: Sequence[str] | None = None, genitems: bool = True + ) -> Sequence[nodes.Item | nodes.Collector]: """Perform the collection phase for this session. This is called by the default :hook:`pytest_collection` hook @@ -772,10 +767,10 @@ def perform_collect( self._initial_parts = [] self._collection_cache = {} self.items = [] - items: Sequence[Union[nodes.Item, nodes.Collector]] = self.items + items: Sequence[nodes.Item | nodes.Collector] = self.items try: - initialpaths: List[Path] = [] - initialpaths_with_parents: List[Path] = [] + initialpaths: list[Path] = [] + initialpaths_with_parents: list[Path] = [] for arg in args: collection_argument = resolve_collection_argument( self.config.invocation_params.dir, @@ -830,7 +825,7 @@ def _collect_one_node( self, node: nodes.Collector, handle_dupes: bool = True, - ) -> Tuple[CollectReport, bool]: + ) -> tuple[CollectReport, bool]: if node in self._collection_cache and handle_dupes: rep = self._collection_cache[node] return rep, True @@ -839,11 +834,11 @@ def _collect_one_node( self._collection_cache[node] = rep return rep, False - def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: + def collect(self) -> Iterator[nodes.Item | nodes.Collector]: # This is a cache for the root directories of the initial paths. # We can't use collection_cache for Session because of its special # role as the bootstrapping collector. - path_cache: Dict[Path, Sequence[nodes.Collector]] = {} + path_cache: dict[Path, Sequence[nodes.Collector]] = {} pm = self.config.pluginmanager @@ -881,9 +876,9 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: # and discarding all nodes which don't match the level's part. any_matched_in_initial_part = False notfound_collectors = [] - work: List[ - Tuple[Union[nodes.Collector, nodes.Item], List[Union[Path, str]]] - ] = [(self, [*paths, *names])] + work: list[tuple[nodes.Collector | nodes.Item, list[Path | str]]] = [ + (self, [*paths, *names]) + ] while work: matchnode, matchparts = work.pop() @@ -900,7 +895,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: # Collect this level of matching. # Collecting Session (self) is done directly to avoid endless # recursion to this function. - subnodes: Sequence[Union[nodes.Collector, nodes.Item]] + subnodes: Sequence[nodes.Collector | nodes.Item] if isinstance(matchnode, Session): assert isinstance(matchparts[0], Path) subnodes = matchnode._collect_path(matchparts[0], path_cache) @@ -960,9 +955,7 @@ def collect(self) -> Iterator[Union[nodes.Item, nodes.Collector]]: self.trace.root.indent -= 1 - def genitems( - self, node: Union[nodes.Item, nodes.Collector] - ) -> Iterator[nodes.Item]: + def genitems(self, node: nodes.Item | nodes.Collector) -> Iterator[nodes.Item]: self.trace("genitems", node) if isinstance(node, nodes.Item): node.ihook.pytest_itemcollected(item=node) @@ -982,7 +975,7 @@ def genitems( node.ihook.pytest_collectreport(report=rep) -def search_pypath(module_name: str) -> Optional[str]: +def search_pypath(module_name: str) -> str | None: """Search sys.path for the given a dotted module name, and return its file system path if found.""" try: @@ -1006,7 +999,7 @@ class CollectionArgument: path: Path parts: Sequence[str] - module_name: Optional[str] + module_name: str | None def resolve_collection_argument( diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index 950a6959ec9..b8a3092151f 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -1,12 +1,12 @@ """Generic mechanism for marking and selecting python functions.""" +from __future__ import annotations + import dataclasses from typing import AbstractSet from typing import Collection -from typing import List from typing import Optional from typing import TYPE_CHECKING -from typing import Union from .expression import Expression from .expression import ParseError @@ -44,8 +44,8 @@ def param( *values: object, - marks: Union[MarkDecorator, Collection[Union[MarkDecorator, Mark]]] = (), - id: Optional[str] = None, + marks: MarkDecorator | Collection[MarkDecorator | Mark] = (), + id: str | None = None, ) -> ParameterSet: """Specify a parameter in `pytest.mark.parametrize`_ calls or :ref:`parametrized fixtures `. @@ -112,7 +112,7 @@ def pytest_addoption(parser: Parser) -> None: @hookimpl(tryfirst=True) -def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: +def pytest_cmdline_main(config: Config) -> int | ExitCode | None: import _pytest.config if config.option.markers: @@ -151,7 +151,7 @@ class KeywordMatcher: _names: AbstractSet[str] @classmethod - def from_item(cls, item: "Item") -> "KeywordMatcher": + def from_item(cls, item: Item) -> KeywordMatcher: mapped_names = set() # Add the names of the current item and any parent items, @@ -191,7 +191,7 @@ def __call__(self, subname: str) -> bool: return False -def deselect_by_keyword(items: "List[Item]", config: Config) -> None: +def deselect_by_keyword(items: list[Item], config: Config) -> None: keywordexpr = config.option.keyword.lstrip() if not keywordexpr: return @@ -223,7 +223,7 @@ class MarkMatcher: own_mark_names: AbstractSet[str] @classmethod - def from_item(cls, item: "Item") -> "MarkMatcher": + def from_item(cls, item: Item) -> MarkMatcher: mark_names = {mark.name for mark in item.iter_markers()} return cls(mark_names) @@ -231,14 +231,14 @@ def __call__(self, name: str) -> bool: return name in self.own_mark_names -def deselect_by_mark(items: "List[Item]", config: Config) -> None: +def deselect_by_mark(items: list[Item], config: Config) -> None: matchexpr = config.option.markexpr if not matchexpr: return expr = _parse_expression(matchexpr, "Wrong expression passed to '-m'") - remaining: List[Item] = [] - deselected: List[Item] = [] + remaining: list[Item] = [] + deselected: list[Item] = [] for item in items: if expr.evaluate(MarkMatcher.from_item(item)): remaining.append(item) @@ -256,7 +256,7 @@ def _parse_expression(expr: str, exc_message: str) -> Expression: raise UsageError(f"{exc_message}: {expr}: {e}") from None -def pytest_collection_modifyitems(items: "List[Item]", config: Config) -> None: +def pytest_collection_modifyitems(items: list[Item], config: Config) -> None: deselect_by_keyword(items, config) deselect_by_mark(items, config) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 78b7fda696b..e65b028589b 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -15,6 +15,8 @@ - or/and/not evaluate according to the usual boolean semantics. """ +from __future__ import annotations + import ast import dataclasses import enum @@ -24,7 +26,6 @@ from typing import Iterator from typing import Mapping from typing import NoReturn -from typing import Optional from typing import Sequence @@ -105,7 +106,7 @@ def lex(self, input: str) -> Iterator[Token]: ) yield Token(TokenType.EOF, "", pos) - def accept(self, type: TokenType, *, reject: bool = False) -> Optional[Token]: + def accept(self, type: TokenType, *, reject: bool = False) -> Token | None: if self.current.type is type: token = self.current if token.type is not TokenType.EOF: @@ -197,7 +198,7 @@ def __init__(self, code: types.CodeType) -> None: self.code = code @classmethod - def compile(self, input: str) -> "Expression": + def compile(self, input: str) -> Expression: """Compile a match expression. :param input: The input expression - one line. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 456808063ad..92ade55f7c0 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import collections.abc import dataclasses import inspect @@ -8,16 +10,11 @@ from typing import final from typing import Iterable from typing import Iterator -from typing import List from typing import Mapping from typing import MutableMapping from typing import NamedTuple -from typing import Optional from typing import overload from typing import Sequence -from typing import Set -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING from typing import TypeVar from typing import Union @@ -48,7 +45,7 @@ def istestfunc(func) -> bool: def get_empty_parameterset_mark( config: Config, argnames: Sequence[str], func -) -> "MarkDecorator": +) -> MarkDecorator: from ..nodes import Collector fs, lineno = getfslineno(func) @@ -76,17 +73,17 @@ def get_empty_parameterset_mark( class ParameterSet(NamedTuple): - values: Sequence[Union[object, NotSetType]] - marks: Collection[Union["MarkDecorator", "Mark"]] - id: Optional[str] + values: Sequence[object | NotSetType] + marks: Collection[MarkDecorator | Mark] + id: str | None @classmethod def param( cls, *values: object, - marks: Union["MarkDecorator", Collection[Union["MarkDecorator", "Mark"]]] = (), - id: Optional[str] = None, - ) -> "ParameterSet": + marks: MarkDecorator | Collection[MarkDecorator | Mark] = (), + id: str | None = None, + ) -> ParameterSet: if isinstance(marks, MarkDecorator): marks = (marks,) else: @@ -101,9 +98,9 @@ def param( @classmethod def extract_from( cls, - parameterset: Union["ParameterSet", Sequence[object], object], + parameterset: ParameterSet | Sequence[object] | object, force_tuple: bool = False, - ) -> "ParameterSet": + ) -> ParameterSet: """Extract from an object or objects. :param parameterset: @@ -128,11 +125,11 @@ def extract_from( @staticmethod def _parse_parametrize_args( - argnames: Union[str, Sequence[str]], - argvalues: Iterable[Union["ParameterSet", Sequence[object], object]], + argnames: str | Sequence[str], + argvalues: Iterable[ParameterSet | Sequence[object] | object], *args, **kwargs, - ) -> Tuple[Sequence[str], bool]: + ) -> tuple[Sequence[str], bool]: if isinstance(argnames, str): argnames = [x.strip() for x in argnames.split(",") if x.strip()] force_tuple = len(argnames) == 1 @@ -142,9 +139,9 @@ def _parse_parametrize_args( @staticmethod def _parse_parametrize_parameters( - argvalues: Iterable[Union["ParameterSet", Sequence[object], object]], + argvalues: Iterable[ParameterSet | Sequence[object] | object], force_tuple: bool, - ) -> List["ParameterSet"]: + ) -> list[ParameterSet]: return [ ParameterSet.extract_from(x, force_tuple=force_tuple) for x in argvalues ] @@ -152,12 +149,12 @@ def _parse_parametrize_parameters( @classmethod def _for_parametrize( cls, - argnames: Union[str, Sequence[str]], - argvalues: Iterable[Union["ParameterSet", Sequence[object], object]], + argnames: str | Sequence[str], + argvalues: Iterable[ParameterSet | Sequence[object] | object], func, config: Config, nodeid: str, - ) -> Tuple[Sequence[str], List["ParameterSet"]]: + ) -> tuple[Sequence[str], list[ParameterSet]]: argnames, force_tuple = cls._parse_parametrize_args(argnames, argvalues) parameters = cls._parse_parametrize_parameters(argvalues, force_tuple) del argvalues @@ -200,24 +197,24 @@ class Mark: #: Name of the mark. name: str #: Positional arguments of the mark decorator. - args: Tuple[Any, ...] + args: tuple[Any, ...] #: Keyword arguments of the mark decorator. kwargs: Mapping[str, Any] #: Source Mark for ids with parametrize Marks. - _param_ids_from: Optional["Mark"] = dataclasses.field(default=None, repr=False) + _param_ids_from: Mark | None = dataclasses.field(default=None, repr=False) #: Resolved/generated ids with parametrize Marks. - _param_ids_generated: Optional[Sequence[str]] = dataclasses.field( + _param_ids_generated: Sequence[str] | None = dataclasses.field( default=None, repr=False ) def __init__( self, name: str, - args: Tuple[Any, ...], + args: tuple[Any, ...], kwargs: Mapping[str, Any], - param_ids_from: Optional["Mark"] = None, - param_ids_generated: Optional[Sequence[str]] = None, + param_ids_from: Mark | None = None, + param_ids_generated: Sequence[str] | None = None, *, _ispytest: bool = False, ) -> None: @@ -233,7 +230,7 @@ def __init__( def _has_param_ids(self) -> bool: return "ids" in self.kwargs or len(self.args) >= 4 - def combined_with(self, other: "Mark") -> "Mark": + def combined_with(self, other: Mark) -> Mark: """Return a new Mark which is a combination of this Mark and another Mark. @@ -245,7 +242,7 @@ def combined_with(self, other: "Mark") -> "Mark": assert self.name == other.name # Remember source of ids with parametrize Marks. - param_ids_from: Optional[Mark] = None + param_ids_from: Mark | None = None if self.name == "parametrize": if other._has_param_ids(): param_ids_from = other @@ -316,7 +313,7 @@ def name(self) -> str: return self.mark.name @property - def args(self) -> Tuple[Any, ...]: + def args(self) -> tuple[Any, ...]: """Alias for mark.args.""" return self.mark.args @@ -330,7 +327,7 @@ def markname(self) -> str: """:meta private:""" return self.name # for backward-compat (2.4.1 had this attr) - def with_args(self, *args: object, **kwargs: object) -> "MarkDecorator": + def with_args(self, *args: object, **kwargs: object) -> MarkDecorator: """Return a MarkDecorator with extra arguments added. Unlike calling the MarkDecorator, with_args() can be used even @@ -347,7 +344,7 @@ def __call__(self, arg: Markable) -> Markable: # type: ignore[overload-overlap] pass @overload - def __call__(self, *args: object, **kwargs: object) -> "MarkDecorator": + def __call__(self, *args: object, **kwargs: object) -> MarkDecorator: pass def __call__(self, *args: object, **kwargs: object): @@ -362,10 +359,10 @@ def __call__(self, *args: object, **kwargs: object): def get_unpacked_marks( - obj: Union[object, type], + obj: object | type, *, consider_mro: bool = True, -) -> List[Mark]: +) -> list[Mark]: """Obtain the unpacked marks that are stored on an object. If obj is a class and consider_mro is true, return marks applied to @@ -395,7 +392,7 @@ def get_unpacked_marks( def normalize_mark_list( - mark_list: Iterable[Union[Mark, MarkDecorator]], + mark_list: Iterable[Mark | MarkDecorator], ) -> Iterable[Mark]: """ Normalize an iterable of Mark or MarkDecorator objects into a list of marks @@ -437,13 +434,13 @@ class _SkipMarkDecorator(MarkDecorator): def __call__(self, arg: Markable) -> Markable: ... @overload - def __call__(self, reason: str = ...) -> "MarkDecorator": ... + def __call__(self, reason: str = ...) -> MarkDecorator: ... class _SkipifMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] self, - condition: Union[str, bool] = ..., - *conditions: Union[str, bool], + condition: str | bool = ..., + *conditions: str | bool, reason: str = ..., ) -> MarkDecorator: ... @@ -454,30 +451,25 @@ def __call__(self, arg: Markable) -> Markable: ... @overload def __call__( self, - condition: Union[str, bool] = False, - *conditions: Union[str, bool], + condition: str | bool = False, + *conditions: str | bool, reason: str = ..., run: bool = ..., - raises: Union[ - None, Type[BaseException], Tuple[Type[BaseException], ...] - ] = ..., + raises: None | type[BaseException] | tuple[type[BaseException], ...] = ..., strict: bool = ..., ) -> MarkDecorator: ... class _ParametrizeMarkDecorator(MarkDecorator): def __call__( # type: ignore[override] self, - argnames: Union[str, Sequence[str]], - argvalues: Iterable[Union[ParameterSet, Sequence[object], object]], + argnames: str | Sequence[str], + argvalues: Iterable[ParameterSet | Sequence[object] | object], *, - indirect: Union[bool, Sequence[str]] = ..., - ids: Optional[ - Union[ - Iterable[Union[None, str, float, int, bool]], - Callable[[Any], Optional[object]], - ] - ] = ..., - scope: Optional[_ScopeName] = ..., + indirect: bool | Sequence[str] = ..., + ids: Iterable[None | str | float | int | bool] + | Callable[[Any], object | None] + | None = ..., + scope: _ScopeName | None = ..., ) -> MarkDecorator: ... class _UsefixturesMarkDecorator(MarkDecorator): @@ -517,8 +509,8 @@ def test_function(): def __init__(self, *, _ispytest: bool = False) -> None: check_ispytest(_ispytest) - self._config: Optional[Config] = None - self._markers: Set[str] = set() + self._config: Config | None = None + self._markers: set[str] = set() def __getattr__(self, name: str) -> MarkDecorator: """Generate a new :class:`MarkDecorator` with the given name.""" @@ -569,7 +561,7 @@ def __getattr__(self, name: str) -> MarkDecorator: class NodeKeywords(MutableMapping[str, Any]): __slots__ = ("node", "parent", "_markers") - def __init__(self, node: "Node") -> None: + def __init__(self, node: Node) -> None: self.node = node self.parent = node.parent self._markers = {node.name: True} @@ -597,7 +589,7 @@ def __contains__(self, key: object) -> bool: def update( # type: ignore[override] self, - other: Union[Mapping[str, Any], Iterable[Tuple[str, Any]]] = (), + other: Mapping[str, Any] | Iterable[tuple[str, Any]] = (), **kwds: Any, ) -> None: self._markers.update(other) diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index f498d60df14..75b019a3be6 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Monkeypatching and mocking functionality.""" +from __future__ import annotations + from contextlib import contextmanager import os import re @@ -8,14 +10,10 @@ from typing import Any from typing import final from typing import Generator -from typing import List from typing import Mapping from typing import MutableMapping -from typing import Optional from typing import overload -from typing import Tuple from typing import TypeVar -from typing import Union import warnings from _pytest.fixtures import fixture @@ -30,7 +28,7 @@ @fixture -def monkeypatch() -> Generator["MonkeyPatch", None, None]: +def monkeypatch() -> Generator[MonkeyPatch, None, None]: """A convenient fixture for monkey-patching. The fixture provides these methods to modify objects, dictionaries, or @@ -97,7 +95,7 @@ def annotated_getattr(obj: object, name: str, ann: str) -> object: return obj -def derive_importpath(import_path: str, raising: bool) -> Tuple[str, object]: +def derive_importpath(import_path: str, raising: bool) -> tuple[str, object]: if not isinstance(import_path, str) or "." not in import_path: raise TypeError(f"must be absolute import path string, not {import_path!r}") module, attr = import_path.rsplit(".", 1) @@ -130,14 +128,14 @@ class MonkeyPatch: """ def __init__(self) -> None: - self._setattr: List[Tuple[object, str, object]] = [] - self._setitem: List[Tuple[Mapping[Any, Any], object, object]] = [] - self._cwd: Optional[str] = None - self._savesyspath: Optional[List[str]] = None + self._setattr: list[tuple[object, str, object]] = [] + self._setitem: list[tuple[Mapping[Any, Any], object, object]] = [] + self._cwd: str | None = None + self._savesyspath: list[str] | None = None @classmethod @contextmanager - def context(cls) -> Generator["MonkeyPatch", None, None]: + def context(cls) -> Generator[MonkeyPatch, None, None]: """Context manager that returns a new :class:`MonkeyPatch` object which undoes any patching done inside the ``with`` block upon exit. @@ -182,8 +180,8 @@ def setattr( def setattr( self, - target: Union[str, object], - name: Union[object, str], + target: str | object, + name: object | str, value: object = notset, raising: bool = True, ) -> None: @@ -254,8 +252,8 @@ def setattr( def delattr( self, - target: Union[object, str], - name: Union[str, Notset] = notset, + target: object | str, + name: str | Notset = notset, raising: bool = True, ) -> None: """Delete attribute ``name`` from ``target``. @@ -310,7 +308,7 @@ def delitem(self, dic: Mapping[K, V], name: K, raising: bool = True) -> None: # Not all Mapping types support indexing, but MutableMapping doesn't support TypedDict del dic[name] # type: ignore[attr-defined] - def setenv(self, name: str, value: str, prepend: Optional[str] = None) -> None: + def setenv(self, name: str, value: str, prepend: str | None = None) -> None: """Set environment variable ``name`` to ``value``. If ``prepend`` is a character, read the current environment variable @@ -363,7 +361,7 @@ def syspath_prepend(self, path) -> None: invalidate_caches() - def chdir(self, path: Union[str, "os.PathLike[str]"]) -> None: + def chdir(self, path: str | os.PathLike[str]) -> None: """Change the current working directory to the specified path. :param path: diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index aad54f8b325..bbde2664b90 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import abc from functools import cached_property from inspect import signature @@ -10,17 +12,11 @@ from typing import cast from typing import Iterable from typing import Iterator -from typing import List from typing import MutableMapping from typing import NoReturn -from typing import Optional from typing import overload -from typing import Set -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING from typing import TypeVar -from typing import Union import warnings import pluggy @@ -62,9 +58,9 @@ def _imply_path( - node_type: Type["Node"], - path: Optional[Path], - fspath: Optional[LEGACY_PATH], + node_type: type[Node], + path: Path | None, + fspath: LEGACY_PATH | None, ) -> Path: if fspath is not None: warnings.warn( @@ -109,7 +105,7 @@ def __call__(cls, *k, **kw) -> NoReturn: ).format(name=f"{cls.__module__}.{cls.__name__}") fail(msg, pytrace=False) - def _create(cls: Type[_T], *k, **kw) -> _T: + def _create(cls: type[_T], *k, **kw) -> _T: try: return super().__call__(*k, **kw) # type: ignore[no-any-return,misc] except TypeError: @@ -160,12 +156,12 @@ class Node(abc.ABC, metaclass=NodeMeta): def __init__( self, name: str, - parent: "Optional[Node]" = None, - config: Optional[Config] = None, - session: "Optional[Session]" = None, - fspath: Optional[LEGACY_PATH] = None, - path: Optional[Path] = None, - nodeid: Optional[str] = None, + parent: Node | None = None, + config: Config | None = None, + session: Session | None = None, + fspath: LEGACY_PATH | None = None, + path: Path | None = None, + nodeid: str | None = None, ) -> None: #: A unique name within the scope of the parent node. self.name: str = name @@ -199,10 +195,10 @@ def __init__( self.keywords: MutableMapping[str, Any] = NodeKeywords(self) #: The marker objects belonging to this node. - self.own_markers: List[Mark] = [] + self.own_markers: list[Mark] = [] #: Allow adding of extra keywords to use for matching. - self.extra_keyword_matches: Set[str] = set() + self.extra_keyword_matches: set[str] = set() if nodeid is not None: assert "::()" not in nodeid @@ -219,7 +215,7 @@ def __init__( self._store = self.stash @classmethod - def from_parent(cls, parent: "Node", **kw) -> "Self": + def from_parent(cls, parent: Node, **kw) -> Self: """Public constructor for Nodes. This indirection got introduced in order to enable removing @@ -295,31 +291,29 @@ def setup(self) -> None: def teardown(self) -> None: pass - def iter_parents(self) -> Iterator["Node"]: + def iter_parents(self) -> Iterator[Node]: """Iterate over all parent collectors starting from and including self up to the root of the collection tree. .. versionadded:: 8.1 """ - parent: Optional[Node] = self + parent: Node | None = self while parent is not None: yield parent parent = parent.parent - def listchain(self) -> List["Node"]: + def listchain(self) -> list[Node]: """Return a list of all parent collectors starting from the root of the collection tree down to and including self.""" chain = [] - item: Optional[Node] = self + item: Node | None = self while item is not None: chain.append(item) item = item.parent chain.reverse() return chain - def add_marker( - self, marker: Union[str, MarkDecorator], append: bool = True - ) -> None: + def add_marker(self, marker: str | MarkDecorator, append: bool = True) -> None: """Dynamically add a marker object to the node. :param marker: @@ -341,7 +335,7 @@ def add_marker( else: self.own_markers.insert(0, marker_.mark) - def iter_markers(self, name: Optional[str] = None) -> Iterator[Mark]: + def iter_markers(self, name: str | None = None) -> Iterator[Mark]: """Iterate over all markers of the node. :param name: If given, filter the results by the name attribute. @@ -350,8 +344,8 @@ def iter_markers(self, name: Optional[str] = None) -> Iterator[Mark]: return (x[1] for x in self.iter_markers_with_node(name=name)) def iter_markers_with_node( - self, name: Optional[str] = None - ) -> Iterator[Tuple["Node", Mark]]: + self, name: str | None = None + ) -> Iterator[tuple[Node, Mark]]: """Iterate over all markers of the node. :param name: If given, filter the results by the name attribute. @@ -363,14 +357,12 @@ def iter_markers_with_node( yield node, mark @overload - def get_closest_marker(self, name: str) -> Optional[Mark]: ... + def get_closest_marker(self, name: str) -> Mark | None: ... @overload def get_closest_marker(self, name: str, default: Mark) -> Mark: ... - def get_closest_marker( - self, name: str, default: Optional[Mark] = None - ) -> Optional[Mark]: + def get_closest_marker(self, name: str, default: Mark | None = None) -> Mark | None: """Return the first marker matching the name, from closest (for example function) to farther level (for example module level). @@ -379,14 +371,14 @@ def get_closest_marker( """ return next(self.iter_markers(name=name), default) - def listextrakeywords(self) -> Set[str]: + def listextrakeywords(self) -> set[str]: """Return a set of all extra keywords in self and any parents.""" - extra_keywords: Set[str] = set() + extra_keywords: set[str] = set() for item in self.listchain(): extra_keywords.update(item.extra_keyword_matches) return extra_keywords - def listnames(self) -> List[str]: + def listnames(self) -> list[str]: return [x.name for x in self.listchain()] def addfinalizer(self, fin: Callable[[], object]) -> None: @@ -398,7 +390,7 @@ def addfinalizer(self, fin: Callable[[], object]) -> None: """ self.session._setupstate.addfinalizer(fin, self) - def getparent(self, cls: Type[_NodeType]) -> Optional[_NodeType]: + def getparent(self, cls: type[_NodeType]) -> _NodeType | None: """Get the closest parent node (including self) which is an instance of the given class. @@ -416,7 +408,7 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: def _repr_failure_py( self, excinfo: ExceptionInfo[BaseException], - style: "Optional[TracebackStyle]" = None, + style: TracebackStyle | None = None, ) -> TerminalRepr: from _pytest.fixtures import FixtureLookupError @@ -428,7 +420,7 @@ def _repr_failure_py( if isinstance(excinfo.value, FixtureLookupError): return excinfo.value.formatrepr() - tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] + tbfilter: bool | Callable[[ExceptionInfo[BaseException]], Traceback] if self.config.getoption("fulltrace", False): style = "long" tbfilter = False @@ -474,8 +466,8 @@ def _repr_failure_py( def repr_failure( self, excinfo: ExceptionInfo[BaseException], - style: "Optional[TracebackStyle]" = None, - ) -> Union[str, TerminalRepr]: + style: TracebackStyle | None = None, + ) -> str | TerminalRepr: """Return a representation of a collection or test failure. .. seealso:: :ref:`non-python tests` @@ -485,7 +477,7 @@ def repr_failure( return self._repr_failure_py(excinfo, style) -def get_fslocation_from_item(node: "Node") -> Tuple[Union[str, Path], Optional[int]]: +def get_fslocation_from_item(node: Node) -> tuple[str | Path, int | None]: """Try to extract the actual location from a node, depending on available attributes: * "location": a pair (path, lineno) @@ -495,7 +487,7 @@ def get_fslocation_from_item(node: "Node") -> Tuple[Union[str, Path], Optional[i :rtype: A tuple of (str|Path, int) with filename and 0-based line number. """ # See Item.location. - location: Optional[Tuple[str, Optional[int], str]] = getattr(node, "location", None) + location: tuple[str, int | None, str] | None = getattr(node, "location", None) if location is not None: return location[:2] obj = getattr(node, "obj", None) @@ -515,14 +507,14 @@ class CollectError(Exception): """An error during collection, contains a custom message.""" @abc.abstractmethod - def collect(self) -> Iterable[Union["Item", "Collector"]]: + def collect(self) -> Iterable[Item | Collector]: """Collect children (items and collectors) for this collector.""" raise NotImplementedError("abstract") # TODO: This omits the style= parameter which breaks Liskov Substitution. def repr_failure( # type: ignore[override] self, excinfo: ExceptionInfo[BaseException] - ) -> Union[str, TerminalRepr]: + ) -> str | TerminalRepr: """Return a representation of a collection failure. :param excinfo: Exception information for the failure. @@ -551,7 +543,7 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: return excinfo.traceback -def _check_initialpaths_for_relpath(session: "Session", path: Path) -> Optional[str]: +def _check_initialpaths_for_relpath(session: Session, path: Path) -> str | None: for initial_path in session._initialpaths: if commonpath(path, initial_path) == initial_path: rel = str(path.relative_to(initial_path)) @@ -564,14 +556,14 @@ class FSCollector(Collector, abc.ABC): def __init__( self, - fspath: Optional[LEGACY_PATH] = None, - path_or_parent: Optional[Union[Path, Node]] = None, - path: Optional[Path] = None, - name: Optional[str] = None, - parent: Optional[Node] = None, - config: Optional[Config] = None, - session: Optional["Session"] = None, - nodeid: Optional[str] = None, + fspath: LEGACY_PATH | None = None, + path_or_parent: Path | Node | None = None, + path: Path | None = None, + name: str | None = None, + parent: Node | None = None, + config: Config | None = None, + session: Session | None = None, + nodeid: str | None = None, ) -> None: if path_or_parent: if isinstance(path_or_parent, Node): @@ -621,10 +613,10 @@ def from_parent( cls, parent, *, - fspath: Optional[LEGACY_PATH] = None, - path: Optional[Path] = None, + fspath: LEGACY_PATH | None = None, + path: Path | None = None, **kw, - ) -> "Self": + ) -> Self: """The public constructor.""" return super().from_parent(parent=parent, fspath=fspath, path=path, **kw) @@ -666,9 +658,9 @@ def __init__( self, name, parent=None, - config: Optional[Config] = None, - session: Optional["Session"] = None, - nodeid: Optional[str] = None, + config: Config | None = None, + session: Session | None = None, + nodeid: str | None = None, **kw, ) -> None: # The first two arguments are intentionally passed positionally, @@ -683,11 +675,11 @@ def __init__( nodeid=nodeid, **kw, ) - self._report_sections: List[Tuple[str, str, str]] = [] + self._report_sections: list[tuple[str, str, str]] = [] #: A list of tuples (name, value) that holds user defined properties #: for this test. - self.user_properties: List[Tuple[str, object]] = [] + self.user_properties: list[tuple[str, object]] = [] self._check_item_and_collector_diamond_inheritance() @@ -747,7 +739,7 @@ def add_report_section(self, when: str, key: str, content: str) -> None: if content: self._report_sections.append((when, key, content)) - def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: + def reportinfo(self) -> tuple[os.PathLike[str] | str, int | None, str]: """Get location information for this item for test reports. Returns a tuple with three elements: @@ -761,7 +753,7 @@ def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str return self.path, None, "" @cached_property - def location(self) -> Tuple[str, Optional[int], str]: + def location(self) -> tuple[str, int | None, str]: """ Returns a tuple of ``(relfspath, lineno, testname)`` for this item where ``relfspath`` is file path relative to ``config.rootpath`` diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index f953dabe03d..5b20803e586 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -1,12 +1,13 @@ """Exception classes and constants handling test outcomes as well as functions creating them.""" +from __future__ import annotations + import sys from typing import Any from typing import Callable from typing import cast from typing import NoReturn -from typing import Optional from typing import Protocol from typing import Type from typing import TypeVar @@ -18,7 +19,7 @@ class OutcomeException(BaseException): """OutcomeException and its subclass instances indicate and contain info about test and collection outcomes.""" - def __init__(self, msg: Optional[str] = None, pytrace: bool = True) -> None: + def __init__(self, msg: str | None = None, pytrace: bool = True) -> None: if msg is not None and not isinstance(msg, str): error_msg = ( # type: ignore[unreachable] "{} expected string as 'msg' parameter, got '{}' instead.\n" @@ -47,7 +48,7 @@ class Skipped(OutcomeException): def __init__( self, - msg: Optional[str] = None, + msg: str | None = None, pytrace: bool = True, allow_module_level: bool = False, *, @@ -70,7 +71,7 @@ class Exit(Exception): """Raised for immediate program exits (no tracebacks/summaries).""" def __init__( - self, msg: str = "unknown reason", returncode: Optional[int] = None + self, msg: str = "unknown reason", returncode: int | None = None ) -> None: self.msg = msg self.returncode = returncode @@ -104,7 +105,7 @@ def decorate(func: _F) -> _WithException[_F, _ET]: @_with_exception(Exit) def exit( reason: str = "", - returncode: Optional[int] = None, + returncode: int | None = None, ) -> NoReturn: """Exit testing process. @@ -207,10 +208,10 @@ def xfail(reason: str = "") -> NoReturn: def importorskip( modname: str, - minversion: Optional[str] = None, - reason: Optional[str] = None, + minversion: str | None = None, + reason: str | None = None, *, - exc_type: Optional[Type[ImportError]] = None, + exc_type: type[ImportError] | None = None, ) -> Any: """Import and return the requested module ``modname``, or skip the current test if the module cannot be imported. @@ -267,8 +268,8 @@ def importorskip( else: warn_on_import_error = False - skipped: Optional[Skipped] = None - warning: Optional[Warning] = None + skipped: Skipped | None = None + warning: Warning | None = None with warnings.catch_warnings(): # Make sure to ignore ImportWarnings that might happen because diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 20cb8ca83c3..69c011ed24a 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -1,10 +1,11 @@ # mypy: allow-untyped-defs """Submit failure or test session information to a pastebin service.""" +from __future__ import annotations + from io import StringIO import tempfile from typing import IO -from typing import Union from _pytest.config import Config from _pytest.config import create_terminal_writer @@ -68,7 +69,7 @@ def pytest_unconfigure(config: Config) -> None: tr.write_line(f"pastebin session-log: {pastebinurl}\n") -def create_new_paste(contents: Union[str, bytes]) -> str: +def create_new_paste(contents: str | bytes) -> str: """Create a new paste using the bpaste.net service. :contents: Paste contents string. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index b11eea4e7ef..e4dc4eddc9c 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import atexit import contextlib from enum import Enum @@ -24,16 +26,9 @@ from types import ModuleType from typing import Any from typing import Callable -from typing import Dict from typing import Iterable from typing import Iterator -from typing import List -from typing import Optional -from typing import Set -from typing import Tuple -from typing import Type from typing import TypeVar -from typing import Union import uuid import warnings @@ -71,12 +66,10 @@ def get_lock_path(path: _AnyPurePath) -> _AnyPurePath: def on_rm_rf_error( - func: Optional[Callable[..., Any]], + func: Callable[..., Any] | None, path: str, - excinfo: Union[ - BaseException, - Tuple[Type[BaseException], BaseException, Optional[types.TracebackType]], - ], + excinfo: BaseException + | tuple[type[BaseException], BaseException, types.TracebackType | None], *, start_path: Path, ) -> bool: @@ -172,7 +165,7 @@ def rm_rf(path: Path) -> None: shutil.rmtree(str(path), onerror=onerror) -def find_prefixed(root: Path, prefix: str) -> Iterator["os.DirEntry[str]"]: +def find_prefixed(root: Path, prefix: str) -> Iterator[os.DirEntry[str]]: """Find all elements in root that begin with the prefix, case-insensitive.""" l_prefix = prefix.lower() for x in os.scandir(root): @@ -180,7 +173,7 @@ def find_prefixed(root: Path, prefix: str) -> Iterator["os.DirEntry[str]"]: yield x -def extract_suffixes(iter: Iterable["os.DirEntry[str]"], prefix: str) -> Iterator[str]: +def extract_suffixes(iter: Iterable[os.DirEntry[str]], prefix: str) -> Iterator[str]: """Return the parts of the paths following the prefix. :param iter: Iterator over path names. @@ -204,9 +197,7 @@ def parse_num(maybe_num: str) -> int: return -1 -def _force_symlink( - root: Path, target: Union[str, PurePath], link_to: Union[str, Path] -) -> None: +def _force_symlink(root: Path, target: str | PurePath, link_to: str | Path) -> None: """Helper to create the current symlink. It's full of race conditions that are reasonably OK to ignore @@ -420,7 +411,7 @@ def resolve_from_str(input: str, rootpath: Path) -> Path: return rootpath.joinpath(input) -def fnmatch_ex(pattern: str, path: Union[str, "os.PathLike[str]"]) -> bool: +def fnmatch_ex(pattern: str, path: str | os.PathLike[str]) -> bool: """A port of FNMatcher from py.path.common which works with PurePath() instances. The difference between this algorithm and PurePath.match() is that the @@ -456,14 +447,14 @@ def fnmatch_ex(pattern: str, path: Union[str, "os.PathLike[str]"]) -> bool: return fnmatch.fnmatch(name, pattern) -def parts(s: str) -> Set[str]: +def parts(s: str) -> set[str]: parts = s.split(sep) return {sep.join(parts[: i + 1]) or sep for i in range(len(parts))} def symlink_or_skip( - src: Union["os.PathLike[str]", str], - dst: Union["os.PathLike[str]", str], + src: os.PathLike[str] | str, + dst: os.PathLike[str] | str, **kwargs: Any, ) -> None: """Make a symlink, or skip the test in case symlinks are not supported.""" @@ -491,9 +482,9 @@ class ImportPathMismatchError(ImportError): def import_path( - path: Union[str, "os.PathLike[str]"], + path: str | os.PathLike[str], *, - mode: Union[str, ImportMode] = ImportMode.prepend, + mode: str | ImportMode = ImportMode.prepend, root: Path, consider_namespace_packages: bool, ) -> ModuleType: @@ -618,7 +609,7 @@ def import_path( def _import_module_using_spec( module_name: str, module_path: Path, module_location: Path, *, insert_modules: bool -) -> Optional[ModuleType]: +) -> ModuleType | None: """ Tries to import a module by its canonical name, path to the .py file, and its parent location. @@ -641,7 +632,7 @@ def _import_module_using_spec( # Attempt to import the parent module, seems is our responsibility: # https://github.com/python/cpython/blob/73906d5c908c1e0b73c5436faeff7d93698fc074/Lib/importlib/_bootstrap.py#L1308-L1311 parent_module_name, _, name = module_name.rpartition(".") - parent_module: Optional[ModuleType] = None + parent_module: ModuleType | None = None if parent_module_name: parent_module = sys.modules.get(parent_module_name) if parent_module is None: @@ -680,9 +671,7 @@ def _import_module_using_spec( return None -def spec_matches_module_path( - module_spec: Optional[ModuleSpec], module_path: Path -) -> bool: +def spec_matches_module_path(module_spec: ModuleSpec | None, module_path: Path) -> bool: """Return true if the given ModuleSpec can be used to import the given module path.""" if module_spec is None or module_spec.origin is None: return False @@ -734,7 +723,7 @@ def module_name_from_path(path: Path, root: Path) -> str: return ".".join(path_parts) -def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) -> None: +def insert_missing_modules(modules: dict[str, ModuleType], module_name: str) -> None: """ Used by ``import_path`` to create intermediate modules when using mode=importlib. @@ -772,7 +761,7 @@ def insert_missing_modules(modules: Dict[str, ModuleType], module_name: str) -> module_name = ".".join(module_parts) -def resolve_package_path(path: Path) -> Optional[Path]: +def resolve_package_path(path: Path) -> Path | None: """Return the Python package path by looking for the last directory upwards which still contains an __init__.py. @@ -791,7 +780,7 @@ def resolve_package_path(path: Path) -> Optional[Path]: def resolve_pkg_root_and_module_name( path: Path, *, consider_namespace_packages: bool = False -) -> Tuple[Path, str]: +) -> tuple[Path, str]: """ Return the path to the directory of the root package that contains the given Python file, and its module name: @@ -812,7 +801,7 @@ def resolve_pkg_root_and_module_name( Raises CouldNotResolvePathError if the given path does not belong to a package (missing any __init__.py files). """ - pkg_root: Optional[Path] = None + pkg_root: Path | None = None pkg_path = resolve_package_path(path) if pkg_path is not None: pkg_root = pkg_path.parent @@ -859,7 +848,7 @@ def is_importable(module_name: str, module_path: Path) -> bool: return spec_matches_module_path(spec, module_path) -def compute_module_name(root: Path, module_path: Path) -> Optional[str]: +def compute_module_name(root: Path, module_path: Path) -> str | None: """Compute a module name based on a path and a root anchor.""" try: path_without_suffix = module_path.with_suffix("") @@ -884,9 +873,9 @@ class CouldNotResolvePathError(Exception): def scandir( - path: Union[str, "os.PathLike[str]"], - sort_key: Callable[["os.DirEntry[str]"], object] = lambda entry: entry.name, -) -> List["os.DirEntry[str]"]: + path: str | os.PathLike[str], + sort_key: Callable[[os.DirEntry[str]], object] = lambda entry: entry.name, +) -> list[os.DirEntry[str]]: """Scan a directory recursively, in breadth-first order. The returned entries are sorted according to the given key. @@ -909,8 +898,8 @@ def scandir( def visit( - path: Union[str, "os.PathLike[str]"], recurse: Callable[["os.DirEntry[str]"], bool] -) -> Iterator["os.DirEntry[str]"]: + path: str | os.PathLike[str], recurse: Callable[[os.DirEntry[str]], bool] +) -> Iterator[os.DirEntry[str]]: """Walk a directory recursively, in breadth-first order. The `recurse` predicate determines whether a directory is recursed. @@ -924,7 +913,7 @@ def visit( yield from visit(entry.path, recurse) -def absolutepath(path: "Union[str, os.PathLike[str]]") -> Path: +def absolutepath(path: str | os.PathLike[str]) -> Path: """Convert a path to an absolute path using os.path.abspath. Prefer this over Path.resolve() (see #6523). @@ -933,7 +922,7 @@ def absolutepath(path: "Union[str, os.PathLike[str]]") -> Path: return Path(os.path.abspath(path)) -def commonpath(path1: Path, path2: Path) -> Optional[Path]: +def commonpath(path1: Path, path2: Path) -> Path | None: """Return the common part shared with the other path, or None if there is no common part. diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 42f50900ada..e27648507e9 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -4,6 +4,8 @@ PYTEST_DONT_REWRITE """ +from __future__ import annotations + import collections.abc import contextlib from fnmatch import fnmatch @@ -21,22 +23,16 @@ import traceback from typing import Any from typing import Callable -from typing import Dict from typing import Final from typing import final from typing import Generator from typing import IO from typing import Iterable -from typing import List from typing import Literal -from typing import Optional from typing import overload from typing import Sequence from typing import TextIO -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING -from typing import Union from weakref import WeakKeyDictionary from iniconfig import IniConfig @@ -123,7 +119,7 @@ def pytest_configure(config: Config) -> None: class LsofFdLeakChecker: - def get_open_files(self) -> List[Tuple[str, str]]: + def get_open_files(self) -> list[tuple[str, str]]: if sys.version_info >= (3, 11): # New in Python 3.11, ignores utf-8 mode encoding = locale.getencoding() @@ -199,7 +195,7 @@ def pytest_runtest_protocol(self, item: Item) -> Generator[None, object, object] @fixture -def _pytest(request: FixtureRequest) -> "PytestArg": +def _pytest(request: FixtureRequest) -> PytestArg: """Return a helper which offers a gethookrecorder(hook) method which returns a HookRecorder instance which helps to make assertions about called hooks.""" @@ -210,13 +206,13 @@ class PytestArg: def __init__(self, request: FixtureRequest) -> None: self._request = request - def gethookrecorder(self, hook) -> "HookRecorder": + def gethookrecorder(self, hook) -> HookRecorder: hookrecorder = HookRecorder(hook._pm) self._request.addfinalizer(hookrecorder.finish_recording) return hookrecorder -def get_public_names(values: Iterable[str]) -> List[str]: +def get_public_names(values: Iterable[str]) -> list[str]: """Only return names from iterator values without a leading underscore.""" return [x for x in values if x[0] != "_"] @@ -265,8 +261,8 @@ def __init__( check_ispytest(_ispytest) self._pluginmanager = pluginmanager - self.calls: List[RecordedHookCall] = [] - self.ret: Optional[Union[int, ExitCode]] = None + self.calls: list[RecordedHookCall] = [] + self.ret: int | ExitCode | None = None def before(hook_name: str, hook_impls, kwargs) -> None: self.calls.append(RecordedHookCall(hook_name, kwargs)) @@ -279,13 +275,13 @@ def after(outcome, hook_name: str, hook_impls, kwargs) -> None: def finish_recording(self) -> None: self._undo_wrapping() - def getcalls(self, names: Union[str, Iterable[str]]) -> List[RecordedHookCall]: + def getcalls(self, names: str | Iterable[str]) -> list[RecordedHookCall]: """Get all recorded calls to hooks with the given names (or name).""" if isinstance(names, str): names = names.split() return [call for call in self.calls if call._name in names] - def assert_contains(self, entries: Sequence[Tuple[str, str]]) -> None: + def assert_contains(self, entries: Sequence[tuple[str, str]]) -> None: __tracebackhide__ = True i = 0 entries = list(entries) @@ -327,42 +323,42 @@ def getcall(self, name: str) -> RecordedHookCall: @overload def getreports( self, - names: "Literal['pytest_collectreport']", + names: Literal["pytest_collectreport"], ) -> Sequence[CollectReport]: ... @overload def getreports( self, - names: "Literal['pytest_runtest_logreport']", + names: Literal["pytest_runtest_logreport"], ) -> Sequence[TestReport]: ... @overload def getreports( self, - names: Union[str, Iterable[str]] = ( + names: str | Iterable[str] = ( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: ... + ) -> Sequence[CollectReport | TestReport]: ... def getreports( self, - names: Union[str, Iterable[str]] = ( + names: str | Iterable[str] = ( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: + ) -> Sequence[CollectReport | TestReport]: return [x.report for x in self.getcalls(names)] def matchreport( self, inamepart: str = "", - names: Union[str, Iterable[str]] = ( + names: str | Iterable[str] = ( "pytest_runtest_logreport", "pytest_collectreport", ), - when: Optional[str] = None, - ) -> Union[CollectReport, TestReport]: + when: str | None = None, + ) -> CollectReport | TestReport: """Return a testreport whose dotted import path matches.""" values = [] for rep in self.getreports(names=names): @@ -387,31 +383,31 @@ def matchreport( @overload def getfailures( self, - names: "Literal['pytest_collectreport']", + names: Literal["pytest_collectreport"], ) -> Sequence[CollectReport]: ... @overload def getfailures( self, - names: "Literal['pytest_runtest_logreport']", + names: Literal["pytest_runtest_logreport"], ) -> Sequence[TestReport]: ... @overload def getfailures( self, - names: Union[str, Iterable[str]] = ( + names: str | Iterable[str] = ( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: ... + ) -> Sequence[CollectReport | TestReport]: ... def getfailures( self, - names: Union[str, Iterable[str]] = ( + names: str | Iterable[str] = ( "pytest_collectreport", "pytest_runtest_logreport", ), - ) -> Sequence[Union[CollectReport, TestReport]]: + ) -> Sequence[CollectReport | TestReport]: return [rep for rep in self.getreports(names) if rep.failed] def getfailedcollections(self) -> Sequence[CollectReport]: @@ -419,10 +415,10 @@ def getfailedcollections(self) -> Sequence[CollectReport]: def listoutcomes( self, - ) -> Tuple[ + ) -> tuple[ Sequence[TestReport], - Sequence[Union[CollectReport, TestReport]], - Sequence[Union[CollectReport, TestReport]], + Sequence[CollectReport | TestReport], + Sequence[CollectReport | TestReport], ]: passed = [] skipped = [] @@ -441,7 +437,7 @@ def listoutcomes( failed.append(rep) return passed, skipped, failed - def countoutcomes(self) -> List[int]: + def countoutcomes(self) -> list[int]: return [len(x) for x in self.listoutcomes()] def assertoutcome(self, passed: int = 0, skipped: int = 0, failed: int = 0) -> None: @@ -461,14 +457,14 @@ def clear(self) -> None: @fixture -def linecomp() -> "LineComp": +def linecomp() -> LineComp: """A :class: `LineComp` instance for checking that an input linearly contains a sequence of strings.""" return LineComp() @fixture(name="LineMatcher") -def LineMatcher_fixture(request: FixtureRequest) -> Type["LineMatcher"]: +def LineMatcher_fixture(request: FixtureRequest) -> type[LineMatcher]: """A reference to the :class: `LineMatcher`. This is instantiable with a list of lines (without their trailing newlines). @@ -480,7 +476,7 @@ def LineMatcher_fixture(request: FixtureRequest) -> Type["LineMatcher"]: @fixture def pytester( request: FixtureRequest, tmp_path_factory: TempPathFactory, monkeypatch: MonkeyPatch -) -> "Pytester": +) -> Pytester: """ Facilities to write tests/configuration files, execute pytest in isolation, and match against expected output, perfect for black-box testing of pytest plugins. @@ -524,13 +520,13 @@ class RunResult: def __init__( self, - ret: Union[int, ExitCode], - outlines: List[str], - errlines: List[str], + ret: int | ExitCode, + outlines: list[str], + errlines: list[str], duration: float, ) -> None: try: - self.ret: Union[int, ExitCode] = ExitCode(ret) + self.ret: int | ExitCode = ExitCode(ret) """The return value.""" except ValueError: self.ret = ret @@ -555,7 +551,7 @@ def __repr__(self) -> str: % (self.ret, len(self.stdout.lines), len(self.stderr.lines), self.duration) ) - def parseoutcomes(self) -> Dict[str, int]: + def parseoutcomes(self) -> dict[str, int]: """Return a dictionary of outcome noun -> count from parsing the terminal output that the test process produced. @@ -568,7 +564,7 @@ def parseoutcomes(self) -> Dict[str, int]: return self.parse_summary_nouns(self.outlines) @classmethod - def parse_summary_nouns(cls, lines) -> Dict[str, int]: + def parse_summary_nouns(cls, lines) -> dict[str, int]: """Extract the nouns from a pytest terminal summary line. It always returns the plural noun for consistency:: @@ -599,8 +595,8 @@ def assert_outcomes( errors: int = 0, xpassed: int = 0, xfailed: int = 0, - warnings: Optional[int] = None, - deselected: Optional[int] = None, + warnings: int | None = None, + deselected: int | None = None, ) -> None: """ Assert that the specified outcomes appear with the respective @@ -626,7 +622,7 @@ def assert_outcomes( class SysModulesSnapshot: - def __init__(self, preserve: Optional[Callable[[str], bool]] = None) -> None: + def __init__(self, preserve: Callable[[str], bool] | None = None) -> None: self.__preserve = preserve self.__saved = dict(sys.modules) @@ -659,7 +655,7 @@ class Pytester: __test__ = False - CLOSE_STDIN: "Final" = NOTSET + CLOSE_STDIN: Final = NOTSET class TimeoutExpired(Exception): pass @@ -674,9 +670,9 @@ def __init__( ) -> None: check_ispytest(_ispytest) self._request = request - self._mod_collections: WeakKeyDictionary[ - Collector, List[Union[Item, Collector]] - ] = WeakKeyDictionary() + self._mod_collections: WeakKeyDictionary[Collector, list[Item | Collector]] = ( + WeakKeyDictionary() + ) if request.function: name: str = request.function.__name__ else: @@ -687,7 +683,7 @@ def __init__( #: :py:meth:`runpytest`. Initially this is an empty list but plugins can #: be added to the list. The type of items to add to the list depends on #: the method using them so refer to them for details. - self.plugins: List[Union[str, _PluggyPlugin]] = [] + self.plugins: list[str | _PluggyPlugin] = [] self._sys_path_snapshot = SysPathsSnapshot() self._sys_modules_snapshot = self.__take_sys_modules_snapshot() self._request.addfinalizer(self._finalize) @@ -755,8 +751,8 @@ def chdir(self) -> None: def _makefile( self, ext: str, - lines: Sequence[Union[Any, bytes]], - files: Dict[str, str], + lines: Sequence[Any | bytes], + files: dict[str, str], encoding: str = "utf-8", ) -> Path: items = list(files.items()) @@ -769,7 +765,7 @@ def _makefile( f"pytester.makefile expects a file extension, try .{ext} instead of {ext}" ) - def to_text(s: Union[Any, bytes]) -> str: + def to_text(s: Any | bytes) -> str: return s.decode(encoding) if isinstance(s, bytes) else str(s) if lines: @@ -892,9 +888,7 @@ def test_something(pytester): """ return self._makefile(".txt", args, kwargs) - def syspathinsert( - self, path: Optional[Union[str, "os.PathLike[str]"]] = None - ) -> None: + def syspathinsert(self, path: str | os.PathLike[str] | None = None) -> None: """Prepend a directory to sys.path, defaults to :attr:`path`. This is undone automatically when this object dies at the end of each @@ -908,7 +902,7 @@ def syspathinsert( self._monkeypatch.syspath_prepend(str(path)) - def mkdir(self, name: Union[str, "os.PathLike[str]"]) -> Path: + def mkdir(self, name: str | os.PathLike[str]) -> Path: """Create a new (sub)directory. :param name: @@ -920,7 +914,7 @@ def mkdir(self, name: Union[str, "os.PathLike[str]"]) -> Path: p.mkdir() return p - def mkpydir(self, name: Union[str, "os.PathLike[str]"]) -> Path: + def mkpydir(self, name: str | os.PathLike[str]) -> Path: """Create a new python package. This creates a (sub)directory with an empty ``__init__.py`` file so it @@ -931,7 +925,7 @@ def mkpydir(self, name: Union[str, "os.PathLike[str]"]) -> Path: p.joinpath("__init__.py").touch() return p - def copy_example(self, name: Optional[str] = None) -> Path: + def copy_example(self, name: str | None = None) -> Path: """Copy file from project's directory into the testdir. :param name: @@ -976,9 +970,7 @@ def copy_example(self, name: Optional[str] = None) -> Path: f'example "{example_path}" is not found as a file or directory' ) - def getnode( - self, config: Config, arg: Union[str, "os.PathLike[str]"] - ) -> Union[Collector, Item]: + def getnode(self, config: Config, arg: str | os.PathLike[str]) -> Collector | Item: """Get the collection node of a file. :param config: @@ -997,9 +989,7 @@ def getnode( config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK) return res - def getpathnode( - self, path: Union[str, "os.PathLike[str]"] - ) -> Union[Collector, Item]: + def getpathnode(self, path: str | os.PathLike[str]) -> Collector | Item: """Return the collection node of a file. This is like :py:meth:`getnode` but uses :py:meth:`parseconfigure` to @@ -1019,7 +1009,7 @@ def getpathnode( config.hook.pytest_sessionfinish(session=session, exitstatus=ExitCode.OK) return res - def genitems(self, colitems: Sequence[Union[Item, Collector]]) -> List[Item]: + def genitems(self, colitems: Sequence[Item | Collector]) -> list[Item]: """Generate all test items from a collection node. This recurses into the collection node and returns a list of all the @@ -1031,7 +1021,7 @@ def genitems(self, colitems: Sequence[Union[Item, Collector]]) -> List[Item]: The collected items. """ session = colitems[0].session - result: List[Item] = [] + result: list[Item] = [] for colitem in colitems: result.extend(session.genitems(colitem)) return result @@ -1065,7 +1055,7 @@ def inline_runsource(self, source: str, *cmdlineargs) -> HookRecorder: values = [*list(cmdlineargs), p] return self.inline_run(*values) - def inline_genitems(self, *args) -> Tuple[List[Item], HookRecorder]: + def inline_genitems(self, *args) -> tuple[list[Item], HookRecorder]: """Run ``pytest.main(['--collect-only'])`` in-process. Runs the :py:func:`pytest.main` function to run all of pytest inside @@ -1078,7 +1068,7 @@ def inline_genitems(self, *args) -> Tuple[List[Item], HookRecorder]: def inline_run( self, - *args: Union[str, "os.PathLike[str]"], + *args: str | os.PathLike[str], plugins=(), no_reraise_ctrlc: bool = False, ) -> HookRecorder: @@ -1148,7 +1138,7 @@ class reprec: # type: ignore finalizer() def runpytest_inprocess( - self, *args: Union[str, "os.PathLike[str]"], **kwargs: Any + self, *args: str | os.PathLike[str], **kwargs: Any ) -> RunResult: """Return result of running pytest in-process, providing a similar interface to what self.runpytest() provides.""" @@ -1191,9 +1181,7 @@ class reprec: # type: ignore res.reprec = reprec # type: ignore return res - def runpytest( - self, *args: Union[str, "os.PathLike[str]"], **kwargs: Any - ) -> RunResult: + def runpytest(self, *args: str | os.PathLike[str], **kwargs: Any) -> RunResult: """Run pytest inline or in a subprocess, depending on the command line option "--runpytest" and return a :py:class:`~pytest.RunResult`.""" new_args = self._ensure_basetemp(args) @@ -1204,8 +1192,8 @@ def runpytest( raise RuntimeError(f"Unrecognized runpytest option: {self._method}") def _ensure_basetemp( - self, args: Sequence[Union[str, "os.PathLike[str]"]] - ) -> List[Union[str, "os.PathLike[str]"]]: + self, args: Sequence[str | os.PathLike[str]] + ) -> list[str | os.PathLike[str]]: new_args = list(args) for x in new_args: if str(x).startswith("--basetemp"): @@ -1216,7 +1204,7 @@ def _ensure_basetemp( ) return new_args - def parseconfig(self, *args: Union[str, "os.PathLike[str]"]) -> Config: + def parseconfig(self, *args: str | os.PathLike[str]) -> Config: """Return a new pytest :class:`pytest.Config` instance from given commandline args. @@ -1240,7 +1228,7 @@ def parseconfig(self, *args: Union[str, "os.PathLike[str]"]) -> Config: self._request.addfinalizer(config._ensure_unconfigure) return config - def parseconfigure(self, *args: Union[str, "os.PathLike[str]"]) -> Config: + def parseconfigure(self, *args: str | os.PathLike[str]) -> Config: """Return a new pytest configured Config instance. Returns a new :py:class:`pytest.Config` instance like @@ -1252,7 +1240,7 @@ def parseconfigure(self, *args: Union[str, "os.PathLike[str]"]) -> Config: return config def getitem( - self, source: Union[str, "os.PathLike[str]"], funcname: str = "test_func" + self, source: str | os.PathLike[str], funcname: str = "test_func" ) -> Item: """Return the test item for a test function. @@ -1273,7 +1261,7 @@ def getitem( return item assert 0, f"{funcname!r} item not found in module:\n{source}\nitems: {items}" - def getitems(self, source: Union[str, "os.PathLike[str]"]) -> List[Item]: + def getitems(self, source: str | os.PathLike[str]) -> list[Item]: """Return all test items collected from the module. Writes the source to a Python file and runs pytest's collection on @@ -1284,7 +1272,7 @@ def getitems(self, source: Union[str, "os.PathLike[str]"]) -> List[Item]: def getmodulecol( self, - source: Union[str, "os.PathLike[str]"], + source: str | os.PathLike[str], configargs=(), *, withinit: bool = False, @@ -1316,9 +1304,7 @@ def getmodulecol( self.config = config = self.parseconfigure(path, *configargs) return self.getnode(config, path) - def collect_by_name( - self, modcol: Collector, name: str - ) -> Optional[Union[Item, Collector]]: + def collect_by_name(self, modcol: Collector, name: str) -> Item | Collector | None: """Return the collection node for name from the module collection. Searches a module collection node for a collection node matching the @@ -1336,10 +1322,10 @@ def collect_by_name( def popen( self, - cmdargs: Sequence[Union[str, "os.PathLike[str]"]], - stdout: Union[int, TextIO] = subprocess.PIPE, - stderr: Union[int, TextIO] = subprocess.PIPE, - stdin: Union[NotSetType, bytes, IO[Any], int] = CLOSE_STDIN, + cmdargs: Sequence[str | os.PathLike[str]], + stdout: int | TextIO = subprocess.PIPE, + stderr: int | TextIO = subprocess.PIPE, + stdin: NotSetType | bytes | IO[Any] | int = CLOSE_STDIN, **kw, ): """Invoke :py:class:`subprocess.Popen`. @@ -1374,9 +1360,9 @@ def popen( def run( self, - *cmdargs: Union[str, "os.PathLike[str]"], - timeout: Optional[float] = None, - stdin: Union[NotSetType, bytes, IO[Any], int] = CLOSE_STDIN, + *cmdargs: str | os.PathLike[str], + timeout: float | None = None, + stdin: NotSetType | bytes | IO[Any] | int = CLOSE_STDIN, ) -> RunResult: """Run a command with arguments. @@ -1462,10 +1448,10 @@ def _dump_lines(self, lines, fp): except UnicodeEncodeError: print(f"couldn't print to {fp} because of encoding") - def _getpytestargs(self) -> Tuple[str, ...]: + def _getpytestargs(self) -> tuple[str, ...]: return sys.executable, "-mpytest" - def runpython(self, script: "os.PathLike[str]") -> RunResult: + def runpython(self, script: os.PathLike[str]) -> RunResult: """Run a python script using sys.executable as interpreter.""" return self.run(sys.executable, script) @@ -1474,7 +1460,7 @@ def runpython_c(self, command: str) -> RunResult: return self.run(sys.executable, "-c", command) def runpytest_subprocess( - self, *args: Union[str, "os.PathLike[str]"], timeout: Optional[float] = None + self, *args: str | os.PathLike[str], timeout: float | None = None ) -> RunResult: """Run pytest as a subprocess with given arguments. @@ -1501,9 +1487,7 @@ def runpytest_subprocess( args = self._getpytestargs() + args return self.run(*args, timeout=timeout) - def spawn_pytest( - self, string: str, expect_timeout: float = 10.0 - ) -> "pexpect.spawn": + def spawn_pytest(self, string: str, expect_timeout: float = 10.0) -> pexpect.spawn: """Run pytest using pexpect. This makes sure to use the right pytest and sets up the temporary @@ -1517,7 +1501,7 @@ def spawn_pytest( cmd = f"{invoke} --basetemp={basetemp} {string}" return self.spawn(cmd, expect_timeout=expect_timeout) - def spawn(self, cmd: str, expect_timeout: float = 10.0) -> "pexpect.spawn": + def spawn(self, cmd: str, expect_timeout: float = 10.0) -> pexpect.spawn: """Run a command using pexpect. The pexpect child is returned. @@ -1562,9 +1546,9 @@ class LineMatcher: ``text.splitlines()``. """ - def __init__(self, lines: List[str]) -> None: + def __init__(self, lines: list[str]) -> None: self.lines = lines - self._log_output: List[str] = [] + self._log_output: list[str] = [] def __str__(self) -> str: """Return the entire original text. @@ -1574,7 +1558,7 @@ def __str__(self) -> str: """ return "\n".join(self.lines) - def _getlines(self, lines2: Union[str, Sequence[str], Source]) -> Sequence[str]: + def _getlines(self, lines2: str | Sequence[str] | Source) -> Sequence[str]: if isinstance(lines2, str): lines2 = Source(lines2) if isinstance(lines2, Source): diff --git a/src/_pytest/pytester_assertions.py b/src/_pytest/pytester_assertions.py index d20c2bb5999..d543798f75a 100644 --- a/src/_pytest/pytester_assertions.py +++ b/src/_pytest/pytester_assertions.py @@ -4,21 +4,19 @@ # contain them itself, since it is imported by the `pytest` module, # hence cannot be subject to assertion rewriting, which requires a # module to not be already imported. -from typing import Dict -from typing import Optional +from __future__ import annotations + from typing import Sequence -from typing import Tuple -from typing import Union from _pytest.reports import CollectReport from _pytest.reports import TestReport def assertoutcome( - outcomes: Tuple[ + outcomes: tuple[ Sequence[TestReport], - Sequence[Union[CollectReport, TestReport]], - Sequence[Union[CollectReport, TestReport]], + Sequence[CollectReport | TestReport], + Sequence[CollectReport | TestReport], ], passed: int = 0, skipped: int = 0, @@ -37,15 +35,15 @@ def assertoutcome( def assert_outcomes( - outcomes: Dict[str, int], + outcomes: dict[str, int], passed: int = 0, skipped: int = 0, failed: int = 0, errors: int = 0, xpassed: int = 0, xfailed: int = 0, - warnings: Optional[int] = None, - deselected: Optional[int] = None, + warnings: int | None = None, + deselected: int | None = None, ) -> None: """Assert that the specified outcomes appear with the respective numbers (0 means it didn't occur) in the text output from a test run.""" diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 4887614de3b..2904c3a1e0f 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Python test discovery, setup and run of test functions.""" +from __future__ import annotations + import abc from collections import Counter from collections import defaultdict @@ -20,16 +22,11 @@ from typing import Generator from typing import Iterable from typing import Iterator -from typing import List from typing import Literal from typing import Mapping -from typing import Optional from typing import Pattern from typing import Sequence -from typing import Set -from typing import Tuple from typing import TYPE_CHECKING -from typing import Union import warnings import _pytest @@ -113,7 +110,7 @@ def pytest_addoption(parser: Parser) -> None: ) -def pytest_generate_tests(metafunc: "Metafunc") -> None: +def pytest_generate_tests(metafunc: Metafunc) -> None: for marker in metafunc.definition.iter_markers(name="parametrize"): metafunc.parametrize(*marker.args, **marker.kwargs, _param_mark=marker) @@ -153,7 +150,7 @@ def async_warn_and_skip(nodeid: str) -> None: @hookimpl(trylast=True) -def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]: +def pytest_pyfunc_call(pyfuncitem: Function) -> object | None: testfunction = pyfuncitem.obj if is_async_function(testfunction): async_warn_and_skip(pyfuncitem.nodeid) @@ -174,7 +171,7 @@ def pytest_pyfunc_call(pyfuncitem: "Function") -> Optional[object]: def pytest_collect_directory( path: Path, parent: nodes.Collector -) -> Optional[nodes.Collector]: +) -> nodes.Collector | None: pkginit = path / "__init__.py" try: has_pkginit = pkginit.is_file() @@ -186,7 +183,7 @@ def pytest_collect_directory( return None -def pytest_collect_file(file_path: Path, parent: nodes.Collector) -> Optional["Module"]: +def pytest_collect_file(file_path: Path, parent: nodes.Collector) -> Module | None: if file_path.suffix == ".py": if not parent.session.isinitpath(file_path): if not path_matches_patterns( @@ -206,14 +203,14 @@ def path_matches_patterns(path: Path, patterns: Iterable[str]) -> bool: return any(fnmatch_ex(pattern, path) for pattern in patterns) -def pytest_pycollect_makemodule(module_path: Path, parent) -> "Module": +def pytest_pycollect_makemodule(module_path: Path, parent) -> Module: return Module.from_parent(parent, path=module_path) @hookimpl(trylast=True) def pytest_pycollect_makeitem( - collector: Union["Module", "Class"], name: str, obj: object -) -> Union[None, nodes.Item, nodes.Collector, List[Union[nodes.Item, nodes.Collector]]]: + collector: Module | Class, name: str, obj: object +) -> None | nodes.Item | nodes.Collector | list[nodes.Item | nodes.Collector]: assert isinstance(collector, (Class, Module)), type(collector) # Nothing was collected elsewhere, let's do it here. if safe_isclass(obj): @@ -320,7 +317,7 @@ def getmodpath(self, stopatmodule: bool = True, includemodule: bool = False) -> parts.reverse() return ".".join(parts) - def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str]: + def reportinfo(self) -> tuple[os.PathLike[str] | str, int | None, str]: # XXX caching? path, lineno = getfslineno(self.obj) modpath = self.getmodpath() @@ -394,7 +391,7 @@ def _matches_prefix_or_glob_option(self, option_name: str, name: str) -> bool: return True return False - def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: + def collect(self) -> Iterable[nodes.Item | nodes.Collector]: if not getattr(self.obj, "__test__", True): return [] @@ -406,11 +403,11 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: # In each class, nodes should be definition ordered. # __dict__ is definition ordered. - seen: Set[str] = set() - dict_values: List[List[Union[nodes.Item, nodes.Collector]]] = [] + seen: set[str] = set() + dict_values: list[list[nodes.Item | nodes.Collector]] = [] ihook = self.ihook for dic in dicts: - values: List[Union[nodes.Item, nodes.Collector]] = [] + values: list[nodes.Item | nodes.Collector] = [] # Note: seems like the dict can change during iteration - # be careful not to remove the list() without consideration. for name, obj in list(dic.items()): @@ -437,7 +434,7 @@ def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: result.extend(values) return result - def _genfunctions(self, name: str, funcobj) -> Iterator["Function"]: + def _genfunctions(self, name: str, funcobj) -> Iterator[Function]: modulecol = self.getparent(Module) assert modulecol is not None module = modulecol.obj @@ -548,7 +545,7 @@ class Module(nodes.File, PyCollector): def _getobj(self): return importtestmodule(self.path, self.config) - def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: + def collect(self) -> Iterable[nodes.Item | nodes.Collector]: self._register_setup_module_fixture() self._register_setup_function_fixture() self.session._fixturemanager.parsefactories(self) @@ -642,13 +639,13 @@ class Package(nodes.Directory): def __init__( self, - fspath: Optional[LEGACY_PATH], + fspath: LEGACY_PATH | None, parent: nodes.Collector, # NOTE: following args are unused: config=None, session=None, nodeid=None, - path: Optional[Path] = None, + path: Path | None = None, ) -> None: # NOTE: Could be just the following, but kept as-is for compat. # super().__init__(self, fspath, parent=parent) @@ -680,13 +677,13 @@ def setup(self) -> None: func = partial(_call_with_optional_argument, teardown_module, init_mod) self.addfinalizer(func) - def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: + def collect(self) -> Iterable[nodes.Item | nodes.Collector]: # Always collect __init__.py first. - def sort_key(entry: "os.DirEntry[str]") -> object: + def sort_key(entry: os.DirEntry[str]) -> object: return (entry.name != "__init__.py", entry.name) config = self.config - col: Optional[nodes.Collector] + col: nodes.Collector | None cols: Sequence[nodes.Collector] ihook = self.ihook for direntry in scandir(self.path, sort_key): @@ -720,12 +717,12 @@ def _call_with_optional_argument(func, arg) -> None: func() -def _get_first_non_fixture_func(obj: object, names: Iterable[str]) -> Optional[object]: +def _get_first_non_fixture_func(obj: object, names: Iterable[str]) -> object | None: """Return the attribute from the given object to be used as a setup/teardown xunit-style function, but only if not marked as a fixture to avoid calling it twice. """ for name in names: - meth: Optional[object] = getattr(obj, name, None) + meth: object | None = getattr(obj, name, None) if meth is not None and fixtures.getfixturemarker(meth) is None: return meth return None @@ -735,14 +732,14 @@ class Class(PyCollector): """Collector for test methods (and nested classes) in a Python class.""" @classmethod - def from_parent(cls, parent, *, name, obj=None, **kw) -> "Self": # type: ignore[override] + def from_parent(cls, parent, *, name, obj=None, **kw) -> Self: # type: ignore[override] """The public constructor.""" return super().from_parent(name=name, parent=parent, **kw) def newinstance(self): return self.obj() - def collect(self) -> Iterable[Union[nodes.Item, nodes.Collector]]: + def collect(self) -> Iterable[nodes.Item | nodes.Collector]: if not safe_getattr(self.obj, "__test__", True): return [] if hasinit(self.obj): @@ -872,21 +869,21 @@ class IdMaker: parametersets: Sequence[ParameterSet] # Optionally, a user-provided callable to make IDs for parameters in a # ParameterSet. - idfn: Optional[Callable[[Any], Optional[object]]] + idfn: Callable[[Any], object | None] | None # Optionally, explicit IDs for ParameterSets by index. - ids: Optional[Sequence[Optional[object]]] + ids: Sequence[object | None] | None # Optionally, the pytest config. # Used for controlling ASCII escaping, and for calling the # :hook:`pytest_make_parametrize_id` hook. - config: Optional[Config] + config: Config | None # Optionally, the ID of the node being parametrized. # Used only for clearer error messages. - nodeid: Optional[str] + nodeid: str | None # Optionally, the ID of the function being parametrized. # Used only for clearer error messages. - func_name: Optional[str] + func_name: str | None - def make_unique_parameterset_ids(self) -> List[str]: + def make_unique_parameterset_ids(self) -> list[str]: """Make a unique identifier for each ParameterSet, that may be used to identify the parametrization in a node ID. @@ -903,7 +900,7 @@ def make_unique_parameterset_ids(self) -> List[str]: # Record the number of occurrences of each ID. id_counts = Counter(resolved_ids) # Map the ID to its next suffix. - id_suffixes: Dict[str, int] = defaultdict(int) + id_suffixes: dict[str, int] = defaultdict(int) # Suffix non-unique IDs to make them unique. for index, id in enumerate(resolved_ids): if id_counts[id] > 1: @@ -950,9 +947,7 @@ def _idval(self, val: object, argname: str, idx: int) -> str: return idval return self._idval_from_argname(argname, idx) - def _idval_from_function( - self, val: object, argname: str, idx: int - ) -> Optional[str]: + def _idval_from_function(self, val: object, argname: str, idx: int) -> str | None: """Try to make an ID for a parameter in a ParameterSet using the user-provided id callable, if given.""" if self.idfn is None: @@ -968,17 +963,17 @@ def _idval_from_function( return None return self._idval_from_value(id) - def _idval_from_hook(self, val: object, argname: str) -> Optional[str]: + def _idval_from_hook(self, val: object, argname: str) -> str | None: """Try to make an ID for a parameter in a ParameterSet by calling the :hook:`pytest_make_parametrize_id` hook.""" if self.config: - id: Optional[str] = self.config.hook.pytest_make_parametrize_id( + id: str | None = self.config.hook.pytest_make_parametrize_id( config=self.config, val=val, argname=argname ) return id return None - def _idval_from_value(self, val: object) -> Optional[str]: + def _idval_from_value(self, val: object) -> str | None: """Try to make an ID for a parameter in a ParameterSet from its value, if the value type is supported.""" if isinstance(val, (str, bytes)): @@ -1036,15 +1031,15 @@ class CallSpec2: # arg name -> arg value which will be passed to a fixture or pseudo-fixture # of the same name. (indirect or direct parametrization respectively) - params: Dict[str, object] = dataclasses.field(default_factory=dict) + params: dict[str, object] = dataclasses.field(default_factory=dict) # arg name -> arg index. - indices: Dict[str, int] = dataclasses.field(default_factory=dict) + indices: dict[str, int] = dataclasses.field(default_factory=dict) # Used for sorting parametrized resources. _arg2scope: Mapping[str, Scope] = dataclasses.field(default_factory=dict) # Parts which will be added to the item's name in `[..]` separated by "-". _idlist: Sequence[str] = dataclasses.field(default_factory=tuple) # Marks which will be applied to the item. - marks: List[Mark] = dataclasses.field(default_factory=list) + marks: list[Mark] = dataclasses.field(default_factory=list) def setmulti( self, @@ -1052,10 +1047,10 @@ def setmulti( argnames: Iterable[str], valset: Iterable[object], id: str, - marks: Iterable[Union[Mark, MarkDecorator]], + marks: Iterable[Mark | MarkDecorator], scope: Scope, param_index: int, - ) -> "CallSpec2": + ) -> CallSpec2: params = self.params.copy() indices = self.indices.copy() arg2scope = dict(self._arg2scope) @@ -1103,7 +1098,7 @@ class Metafunc: def __init__( self, - definition: "FunctionDefinition", + definition: FunctionDefinition, fixtureinfo: fixtures.FuncFixtureInfo, config: Config, cls=None, @@ -1134,19 +1129,17 @@ def __init__( self._arg2fixturedefs = fixtureinfo.name2fixturedefs # Result of parametrize(). - self._calls: List[CallSpec2] = [] + self._calls: list[CallSpec2] = [] def parametrize( self, - argnames: Union[str, Sequence[str]], - argvalues: Iterable[Union[ParameterSet, Sequence[object], object]], - indirect: Union[bool, Sequence[str]] = False, - ids: Optional[ - Union[Iterable[Optional[object]], Callable[[Any], Optional[object]]] - ] = None, - scope: Optional[_ScopeName] = None, + argnames: str | Sequence[str], + argvalues: Iterable[ParameterSet | Sequence[object] | object], + indirect: bool | Sequence[str] = False, + ids: Iterable[object | None] | Callable[[Any], object | None] | None = None, + scope: _ScopeName | None = None, *, - _param_mark: Optional[Mark] = None, + _param_mark: Mark | None = None, ) -> None: """Add new invocations to the underlying test function using the list of argvalues for the given argnames. Parametrization is performed @@ -1275,7 +1268,7 @@ def parametrize( if node is None: name2pseudofixturedef = None else: - default: Dict[str, FixtureDef[Any]] = {} + default: dict[str, FixtureDef[Any]] = {} name2pseudofixturedef = node.stash.setdefault( name2pseudofixturedef_key, default ) @@ -1322,12 +1315,10 @@ def parametrize( def _resolve_parameter_set_ids( self, argnames: Sequence[str], - ids: Optional[ - Union[Iterable[Optional[object]], Callable[[Any], Optional[object]]] - ], + ids: Iterable[object | None] | Callable[[Any], object | None] | None, parametersets: Sequence[ParameterSet], nodeid: str, - ) -> List[str]: + ) -> list[str]: """Resolve the actual ids for the given parameter sets. :param argnames: @@ -1365,10 +1356,10 @@ def _resolve_parameter_set_ids( def _validate_ids( self, - ids: Iterable[Optional[object]], + ids: Iterable[object | None], parametersets: Sequence[ParameterSet], func_name: str, - ) -> List[Optional[object]]: + ) -> list[object | None]: try: num_ids = len(ids) # type: ignore[arg-type] except TypeError: @@ -1388,8 +1379,8 @@ def _validate_ids( def _resolve_args_directness( self, argnames: Sequence[str], - indirect: Union[bool, Sequence[str]], - ) -> Dict[str, Literal["indirect", "direct"]]: + indirect: bool | Sequence[str], + ) -> dict[str, Literal["indirect", "direct"]]: """Resolve if each parametrized argument must be considered an indirect parameter to a fixture of the same name, or a direct parameter to the parametrized function, based on the ``indirect`` parameter of the @@ -1402,7 +1393,7 @@ def _resolve_args_directness( :returns A dict mapping each arg name to either "indirect" or "direct". """ - arg_directness: Dict[str, Literal["indirect", "direct"]] + arg_directness: dict[str, Literal["indirect", "direct"]] if isinstance(indirect, bool): arg_directness = dict.fromkeys( argnames, "indirect" if indirect else "direct" @@ -1427,7 +1418,7 @@ def _resolve_args_directness( def _validate_if_using_arg_names( self, argnames: Sequence[str], - indirect: Union[bool, Sequence[str]], + indirect: bool | Sequence[str], ) -> None: """Check if all argnames are being used, by default values, or directly/indirectly. @@ -1458,7 +1449,7 @@ def _validate_if_using_arg_names( def _find_parametrized_scope( argnames: Sequence[str], arg2fixturedefs: Mapping[str, Sequence[fixtures.FixtureDef[object]]], - indirect: Union[bool, Sequence[str]], + indirect: bool | Sequence[str], ) -> Scope: """Find the most appropriate scope for a parametrized call based on its arguments. @@ -1487,7 +1478,7 @@ def _find_parametrized_scope( return Scope.Function -def _ascii_escaped_by_config(val: Union[str, bytes], config: Optional[Config]) -> str: +def _ascii_escaped_by_config(val: str | bytes, config: Config | None) -> str: if config is None: escape_option = False else: @@ -1536,13 +1527,13 @@ def __init__( self, name: str, parent, - config: Optional[Config] = None, - callspec: Optional[CallSpec2] = None, + config: Config | None = None, + callspec: CallSpec2 | None = None, callobj=NOTSET, - keywords: Optional[Mapping[str, Any]] = None, - session: Optional[Session] = None, - fixtureinfo: Optional[FuncFixtureInfo] = None, - originalname: Optional[str] = None, + keywords: Mapping[str, Any] | None = None, + session: Session | None = None, + fixtureinfo: FuncFixtureInfo | None = None, + originalname: str | None = None, ) -> None: super().__init__(name, parent, config=config, session=session) @@ -1585,12 +1576,12 @@ def __init__( # todo: determine sound type limitations @classmethod - def from_parent(cls, parent, **kw) -> "Self": + def from_parent(cls, parent, **kw) -> Self: """The public constructor.""" return super().from_parent(parent=parent, **kw) def _initrequest(self) -> None: - self.funcargs: Dict[str, object] = {} + self.funcargs: dict[str, object] = {} self._request = fixtures.TopRequest(self, _ispytest=True) @property @@ -1671,7 +1662,7 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: def repr_failure( # type: ignore[override] self, excinfo: ExceptionInfo[BaseException], - ) -> Union[str, TerminalRepr]: + ) -> str | TerminalRepr: style = self.config.getoption("tbstyle", "auto") if style == "auto": style = "long" diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index bfc8dc33445..c1e851391b0 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from collections.abc import Collection from collections.abc import Sized from decimal import Decimal @@ -11,9 +13,7 @@ from typing import cast from typing import ContextManager from typing import final -from typing import List from typing import Mapping -from typing import Optional from typing import overload from typing import Pattern from typing import Sequence @@ -21,7 +21,6 @@ from typing import Type from typing import TYPE_CHECKING from typing import TypeVar -from typing import Union import _pytest._code from _pytest.outcomes import fail @@ -33,12 +32,12 @@ def _compare_approx( full_object: object, - message_data: Sequence[Tuple[str, str, str]], + message_data: Sequence[tuple[str, str, str]], number_of_elements: int, different_ids: Sequence[object], max_abs_diff: float, max_rel_diff: float, -) -> List[str]: +) -> list[str]: message_list = list(message_data) message_list.insert(0, ("Index", "Obtained", "Expected")) max_sizes = [0, 0, 0] @@ -79,7 +78,7 @@ def __init__(self, expected, rel=None, abs=None, nan_ok: bool = False) -> None: def __repr__(self) -> str: raise NotImplementedError - def _repr_compare(self, other_side: Any) -> List[str]: + def _repr_compare(self, other_side: Any) -> list[str]: return [ "comparison failed", f"Obtained: {other_side}", @@ -103,7 +102,7 @@ def __bool__(self): def __ne__(self, actual) -> bool: return not (actual == self) - def _approx_scalar(self, x) -> "ApproxScalar": + def _approx_scalar(self, x) -> ApproxScalar: if isinstance(x, Decimal): return ApproxDecimal(x, rel=self.rel, abs=self.abs, nan_ok=self.nan_ok) return ApproxScalar(x, rel=self.rel, abs=self.abs, nan_ok=self.nan_ok) @@ -144,12 +143,12 @@ def __repr__(self) -> str: ) return f"approx({list_scalars!r})" - def _repr_compare(self, other_side: Union["ndarray", List[Any]]) -> List[str]: + def _repr_compare(self, other_side: ndarray | list[Any]) -> list[str]: import itertools import math def get_value_from_nested_list( - nested_list: List[Any], nd_index: Tuple[Any, ...] + nested_list: list[Any], nd_index: tuple[Any, ...] ) -> Any: """ Helper function to get the value out of a nested list, given an n-dimensional index. @@ -246,7 +245,7 @@ class ApproxMapping(ApproxBase): def __repr__(self) -> str: return f"approx({({k: self._approx_scalar(v) for k, v in self.expected.items()})!r})" - def _repr_compare(self, other_side: Mapping[object, float]) -> List[str]: + def _repr_compare(self, other_side: Mapping[object, float]) -> list[str]: import math approx_side_as_map = { @@ -321,7 +320,7 @@ def __repr__(self) -> str: seq_type = list return f"approx({seq_type(self._approx_scalar(x) for x in self.expected)!r})" - def _repr_compare(self, other_side: Sequence[float]) -> List[str]: + def _repr_compare(self, other_side: Sequence[float]) -> list[str]: import math if len(self.expected) != len(other_side): @@ -386,8 +385,8 @@ class ApproxScalar(ApproxBase): # Using Real should be better than this Union, but not possible yet: # https://github.com/python/typeshed/pull/3108 - DEFAULT_ABSOLUTE_TOLERANCE: Union[float, Decimal] = 1e-12 - DEFAULT_RELATIVE_TOLERANCE: Union[float, Decimal] = 1e-6 + DEFAULT_ABSOLUTE_TOLERANCE: float | Decimal = 1e-12 + DEFAULT_RELATIVE_TOLERANCE: float | Decimal = 1e-6 def __repr__(self) -> str: """Return a string communicating both the expected value and the @@ -717,7 +716,7 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: __tracebackhide__ = True if isinstance(expected, Decimal): - cls: Type[ApproxBase] = ApproxDecimal + cls: type[ApproxBase] = ApproxDecimal elif isinstance(expected, Mapping): cls = ApproxMapping elif _is_numpy_array(expected): @@ -750,7 +749,7 @@ def _is_numpy_array(obj: object) -> bool: return _as_numpy_array(obj) is not None -def _as_numpy_array(obj: object) -> Optional["ndarray"]: +def _as_numpy_array(obj: object) -> ndarray | None: """ Return an ndarray if the given object is implicitly convertible to ndarray, and numpy is already imported, otherwise None. @@ -776,15 +775,15 @@ def _as_numpy_array(obj: object) -> Optional["ndarray"]: @overload def raises( - expected_exception: Union[Type[E], Tuple[Type[E], ...]], + expected_exception: type[E] | tuple[type[E], ...], *, - match: Optional[Union[str, Pattern[str]]] = ..., -) -> "RaisesContext[E]": ... + match: str | Pattern[str] | None = ..., +) -> RaisesContext[E]: ... @overload def raises( - expected_exception: Union[Type[E], Tuple[Type[E], ...]], + expected_exception: type[E] | tuple[type[E], ...], func: Callable[..., Any], *args: Any, **kwargs: Any, @@ -792,8 +791,8 @@ def raises( def raises( - expected_exception: Union[Type[E], Tuple[Type[E], ...]], *args: Any, **kwargs: Any -) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]: + expected_exception: type[E] | tuple[type[E], ...], *args: Any, **kwargs: Any +) -> RaisesContext[E] | _pytest._code.ExceptionInfo[E]: r"""Assert that a code block/function call raises an exception type, or one of its subclasses. :param expected_exception: @@ -941,7 +940,7 @@ def raises( f"any special code to say 'this should never raise an exception'." ) if isinstance(expected_exception, type): - expected_exceptions: Tuple[Type[E], ...] = (expected_exception,) + expected_exceptions: tuple[type[E], ...] = (expected_exception,) else: expected_exceptions = expected_exception for exc in expected_exceptions: @@ -953,7 +952,7 @@ def raises( message = f"DID NOT RAISE {expected_exception}" if not args: - match: Optional[Union[str, Pattern[str]]] = kwargs.pop("match", None) + match: str | Pattern[str] | None = kwargs.pop("match", None) if kwargs: msg = "Unexpected keyword arguments passed to pytest.raises: " msg += ", ".join(sorted(kwargs)) @@ -979,14 +978,14 @@ def raises( class RaisesContext(ContextManager[_pytest._code.ExceptionInfo[E]]): def __init__( self, - expected_exception: Union[Type[E], Tuple[Type[E], ...]], + expected_exception: type[E] | tuple[type[E], ...], message: str, - match_expr: Optional[Union[str, Pattern[str]]] = None, + match_expr: str | Pattern[str] | None = None, ) -> None: self.expected_exception = expected_exception self.message = message self.match_expr = match_expr - self.excinfo: Optional[_pytest._code.ExceptionInfo[E]] = None + self.excinfo: _pytest._code.ExceptionInfo[E] | None = None def __enter__(self) -> _pytest._code.ExceptionInfo[E]: self.excinfo = _pytest._code.ExceptionInfo.for_later() @@ -994,9 +993,9 @@ def __enter__(self) -> _pytest._code.ExceptionInfo[E]: def __exit__( self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, ) -> bool: __tracebackhide__ = True if exc_type is None: diff --git a/src/_pytest/python_path.py b/src/_pytest/python_path.py index cceabbca12a..6e33c8a39f2 100644 --- a/src/_pytest/python_path.py +++ b/src/_pytest/python_path.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys import pytest diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 63e7a4bd6dc..3fc00d94736 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Record warnings during test function execution.""" +from __future__ import annotations + from pprint import pformat import re from types import TracebackType @@ -9,14 +11,15 @@ from typing import final from typing import Generator from typing import Iterator -from typing import List -from typing import Optional from typing import overload from typing import Pattern -from typing import Tuple -from typing import Type +from typing import TYPE_CHECKING from typing import TypeVar -from typing import Union + + +if TYPE_CHECKING: + from typing_extensions import Self + import warnings from _pytest.deprecated import check_ispytest @@ -29,7 +32,7 @@ @fixture -def recwarn() -> Generator["WarningsRecorder", None, None]: +def recwarn() -> Generator[WarningsRecorder, None, None]: """Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information @@ -42,9 +45,7 @@ def recwarn() -> Generator["WarningsRecorder", None, None]: @overload -def deprecated_call( - *, match: Optional[Union[str, Pattern[str]]] = ... -) -> "WarningsRecorder": ... +def deprecated_call(*, match: str | Pattern[str] | None = ...) -> WarningsRecorder: ... @overload @@ -52,8 +53,8 @@ def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: ... def deprecated_call( - func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any -) -> Union["WarningsRecorder", Any]: + func: Callable[..., Any] | None = None, *args: Any, **kwargs: Any +) -> WarningsRecorder | Any: """Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning`` or ``FutureWarning``. This function can be used as a context manager:: @@ -87,15 +88,15 @@ def deprecated_call( @overload def warns( - expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = ..., + expected_warning: type[Warning] | tuple[type[Warning], ...] = ..., *, - match: Optional[Union[str, Pattern[str]]] = ..., -) -> "WarningsChecker": ... + match: str | Pattern[str] | None = ..., +) -> WarningsChecker: ... @overload def warns( - expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]], + expected_warning: type[Warning] | tuple[type[Warning], ...], func: Callable[..., T], *args: Any, **kwargs: Any, @@ -103,11 +104,11 @@ def warns( def warns( - expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning, + expected_warning: type[Warning] | tuple[type[Warning], ...] = Warning, *args: Any, - match: Optional[Union[str, Pattern[str]]] = None, + match: str | Pattern[str] | None = None, **kwargs: Any, -) -> Union["WarningsChecker", Any]: +) -> WarningsChecker | Any: r"""Assert that code raises a particular class of warning. Specifically, the parameter ``expected_warning`` can be a warning class or tuple @@ -183,18 +184,18 @@ def __init__(self, *, _ispytest: bool = False) -> None: check_ispytest(_ispytest) super().__init__(record=True) self._entered = False - self._list: List[warnings.WarningMessage] = [] + self._list: list[warnings.WarningMessage] = [] @property - def list(self) -> List["warnings.WarningMessage"]: + def list(self) -> list[warnings.WarningMessage]: """The list of recorded warnings.""" return self._list - def __getitem__(self, i: int) -> "warnings.WarningMessage": + def __getitem__(self, i: int) -> warnings.WarningMessage: """Get a recorded warning by index.""" return self._list[i] - def __iter__(self) -> Iterator["warnings.WarningMessage"]: + def __iter__(self) -> Iterator[warnings.WarningMessage]: """Iterate through the recorded warnings.""" return iter(self._list) @@ -202,12 +203,12 @@ def __len__(self) -> int: """The number of recorded warnings.""" return len(self._list) - def pop(self, cls: Type[Warning] = Warning) -> "warnings.WarningMessage": + def pop(self, cls: type[Warning] = Warning) -> warnings.WarningMessage: """Pop the first recorded warning which is an instance of ``cls``, but not an instance of a child class of any other match. Raises ``AssertionError`` if there is no match. """ - best_idx: Optional[int] = None + best_idx: int | None = None for i, w in enumerate(self._list): if w.category == cls: return self._list.pop(i) # exact match, stop looking @@ -225,9 +226,7 @@ def clear(self) -> None: """Clear the list of recorded warnings.""" self._list[:] = [] - # Type ignored because it doesn't exactly warnings.catch_warnings.__enter__ - # -- it returns a List but we only emulate one. - def __enter__(self) -> "WarningsRecorder": # type: ignore + def __enter__(self) -> Self: if self._entered: __tracebackhide__ = True raise RuntimeError(f"Cannot enter {self!r} twice") @@ -240,9 +239,9 @@ def __enter__(self) -> "WarningsRecorder": # type: ignore def __exit__( self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, ) -> None: if not self._entered: __tracebackhide__ = True @@ -259,8 +258,8 @@ def __exit__( class WarningsChecker(WarningsRecorder): def __init__( self, - expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning, - match_expr: Optional[Union[str, Pattern[str]]] = None, + expected_warning: type[Warning] | tuple[type[Warning], ...] = Warning, + match_expr: str | Pattern[str] | None = None, *, _ispytest: bool = False, ) -> None: @@ -291,9 +290,9 @@ def matches(self, warning: warnings.WarningMessage) -> bool: def __exit__( self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, ) -> None: super().__exit__(exc_type, exc_val, exc_tb) diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 2064183d0f7..2f39adbfa6f 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -1,24 +1,19 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import dataclasses from io import StringIO import os from pprint import pprint from typing import Any from typing import cast -from typing import Dict from typing import final from typing import Iterable from typing import Iterator -from typing import List from typing import Literal from typing import Mapping from typing import NoReturn -from typing import Optional -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING -from typing import TypeVar -from typing import Union from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ExceptionInfo @@ -39,6 +34,8 @@ if TYPE_CHECKING: + from typing_extensions import Self + from _pytest.runner import CallInfo @@ -54,16 +51,13 @@ def getworkerinfoline(node): return s -_R = TypeVar("_R", bound="BaseReport") - - class BaseReport: - when: Optional[str] - location: Optional[Tuple[str, Optional[int], str]] - longrepr: Union[ - None, ExceptionInfo[BaseException], Tuple[str, int, str], str, TerminalRepr - ] - sections: List[Tuple[str, str]] + when: str | None + location: tuple[str, int | None, str] | None + longrepr: ( + None | ExceptionInfo[BaseException] | tuple[str, int, str] | str | TerminalRepr + ) + sections: list[tuple[str, str]] nodeid: str outcome: Literal["passed", "failed", "skipped"] @@ -94,7 +88,7 @@ def toterminal(self, out: TerminalWriter) -> None: s = "" out.line(s) - def get_sections(self, prefix: str) -> Iterator[Tuple[str, str]]: + def get_sections(self, prefix: str) -> Iterator[tuple[str, str]]: for name, content in self.sections: if name.startswith(prefix): yield prefix, content @@ -176,7 +170,7 @@ def count_towards_summary(self) -> bool: return True @property - def head_line(self) -> Optional[str]: + def head_line(self) -> str | None: """**Experimental** The head line shown with longrepr output for this report, more commonly during traceback representation during failures:: @@ -202,7 +196,7 @@ def _get_verbose_word(self, config: Config): ) return verbose - def _to_json(self) -> Dict[str, Any]: + def _to_json(self) -> dict[str, Any]: """Return the contents of this report as a dict of builtin entries, suitable for serialization. @@ -213,7 +207,7 @@ def _to_json(self) -> Dict[str, Any]: return _report_to_json(self) @classmethod - def _from_json(cls: Type[_R], reportdict: Dict[str, object]) -> _R: + def _from_json(cls, reportdict: dict[str, object]) -> Self: """Create either a TestReport or CollectReport, depending on the calling class. It is the callers responsibility to know which class to pass here. @@ -227,7 +221,7 @@ def _from_json(cls: Type[_R], reportdict: Dict[str, object]) -> _R: def _report_unserialization_failure( - type_name: str, report_class: Type[BaseReport], reportdict + type_name: str, report_class: type[BaseReport], reportdict ) -> NoReturn: url = "https://github.com/pytest-dev/pytest/issues" stream = StringIO() @@ -256,18 +250,20 @@ class TestReport(BaseReport): def __init__( self, nodeid: str, - location: Tuple[str, Optional[int], str], + location: tuple[str, int | None, str], keywords: Mapping[str, Any], outcome: Literal["passed", "failed", "skipped"], - longrepr: Union[ - None, ExceptionInfo[BaseException], Tuple[str, int, str], str, TerminalRepr - ], + longrepr: None + | ExceptionInfo[BaseException] + | tuple[str, int, str] + | str + | TerminalRepr, when: Literal["setup", "call", "teardown"], - sections: Iterable[Tuple[str, str]] = (), + sections: Iterable[tuple[str, str]] = (), duration: float = 0, start: float = 0, stop: float = 0, - user_properties: Optional[Iterable[Tuple[str, object]]] = None, + user_properties: Iterable[tuple[str, object]] | None = None, **extra, ) -> None: #: Normalized collection nodeid. @@ -278,7 +274,7 @@ def __init__( #: collected one e.g. if a method is inherited from a different module. #: The filesystempath may be relative to ``config.rootdir``. #: The line number is 0-based. - self.location: Tuple[str, Optional[int], str] = location + self.location: tuple[str, int | None, str] = location #: A name -> value dictionary containing all keywords and #: markers associated with a test invocation. @@ -317,7 +313,7 @@ def __repr__(self) -> str: return f"<{self.__class__.__name__} {self.nodeid!r} when={self.when!r} outcome={self.outcome!r}>" @classmethod - def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport": + def from_item_and_call(cls, item: Item, call: CallInfo[None]) -> TestReport: """Create and fill a TestReport with standard item and call info. :param item: The item. @@ -334,13 +330,13 @@ def from_item_and_call(cls, item: Item, call: "CallInfo[None]") -> "TestReport": sections = [] if not call.excinfo: outcome: Literal["passed", "failed", "skipped"] = "passed" - longrepr: Union[ - None, - ExceptionInfo[BaseException], - Tuple[str, int, str], - str, - TerminalRepr, - ] = None + longrepr: ( + None + | ExceptionInfo[BaseException] + | tuple[str, int, str] + | str + | TerminalRepr + ) = None else: if not isinstance(excinfo, ExceptionInfo): outcome = "failed" @@ -394,12 +390,14 @@ class CollectReport(BaseReport): def __init__( self, nodeid: str, - outcome: "Literal['passed', 'failed', 'skipped']", - longrepr: Union[ - None, ExceptionInfo[BaseException], Tuple[str, int, str], str, TerminalRepr - ], - result: Optional[List[Union[Item, Collector]]], - sections: Iterable[Tuple[str, str]] = (), + outcome: Literal["passed", "failed", "skipped"], + longrepr: None + | ExceptionInfo[BaseException] + | tuple[str, int, str] + | str + | TerminalRepr, + result: list[Item | Collector] | None, + sections: Iterable[tuple[str, str]] = (), **extra, ) -> None: #: Normalized collection nodeid. @@ -425,7 +423,7 @@ def __init__( @property def location( # type:ignore[override] self, - ) -> Optional[Tuple[str, Optional[int], str]]: + ) -> tuple[str, int | None, str] | None: return (self.fspath, None, self.fspath) def __repr__(self) -> str: @@ -441,8 +439,8 @@ def toterminal(self, out: TerminalWriter) -> None: def pytest_report_to_serializable( - report: Union[CollectReport, TestReport], -) -> Optional[Dict[str, Any]]: + report: CollectReport | TestReport, +) -> dict[str, Any] | None: if isinstance(report, (TestReport, CollectReport)): data = report._to_json() data["$report_type"] = report.__class__.__name__ @@ -452,8 +450,8 @@ def pytest_report_to_serializable( def pytest_report_from_serializable( - data: Dict[str, Any], -) -> Optional[Union[CollectReport, TestReport]]: + data: dict[str, Any], +) -> CollectReport | TestReport | None: if "$report_type" in data: if data["$report_type"] == "TestReport": return TestReport._from_json(data) @@ -465,7 +463,7 @@ def pytest_report_from_serializable( return None -def _report_to_json(report: BaseReport) -> Dict[str, Any]: +def _report_to_json(report: BaseReport) -> dict[str, Any]: """Return the contents of this report as a dict of builtin entries, suitable for serialization. @@ -473,8 +471,8 @@ def _report_to_json(report: BaseReport) -> Dict[str, Any]: """ def serialize_repr_entry( - entry: Union[ReprEntry, ReprEntryNative], - ) -> Dict[str, Any]: + entry: ReprEntry | ReprEntryNative, + ) -> dict[str, Any]: data = dataclasses.asdict(entry) for key, value in data.items(): if hasattr(value, "__dict__"): @@ -482,7 +480,7 @@ def serialize_repr_entry( entry_data = {"type": type(entry).__name__, "data": data} return entry_data - def serialize_repr_traceback(reprtraceback: ReprTraceback) -> Dict[str, Any]: + def serialize_repr_traceback(reprtraceback: ReprTraceback) -> dict[str, Any]: result = dataclasses.asdict(reprtraceback) result["reprentries"] = [ serialize_repr_entry(x) for x in reprtraceback.reprentries @@ -490,18 +488,18 @@ def serialize_repr_traceback(reprtraceback: ReprTraceback) -> Dict[str, Any]: return result def serialize_repr_crash( - reprcrash: Optional[ReprFileLocation], - ) -> Optional[Dict[str, Any]]: + reprcrash: ReprFileLocation | None, + ) -> dict[str, Any] | None: if reprcrash is not None: return dataclasses.asdict(reprcrash) else: return None - def serialize_exception_longrepr(rep: BaseReport) -> Dict[str, Any]: + def serialize_exception_longrepr(rep: BaseReport) -> dict[str, Any]: assert rep.longrepr is not None # TODO: Investigate whether the duck typing is really necessary here. longrepr = cast(ExceptionRepr, rep.longrepr) - result: Dict[str, Any] = { + result: dict[str, Any] = { "reprcrash": serialize_repr_crash(longrepr.reprcrash), "reprtraceback": serialize_repr_traceback(longrepr.reprtraceback), "sections": longrepr.sections, @@ -538,7 +536,7 @@ def serialize_exception_longrepr(rep: BaseReport) -> Dict[str, Any]: return d -def _report_kwargs_from_json(reportdict: Dict[str, Any]) -> Dict[str, Any]: +def _report_kwargs_from_json(reportdict: dict[str, Any]) -> dict[str, Any]: """Return **kwargs that can be used to construct a TestReport or CollectReport instance. @@ -559,7 +557,7 @@ def deserialize_repr_entry(entry_data): if data["reprlocals"]: reprlocals = ReprLocals(data["reprlocals"]["lines"]) - reprentry: Union[ReprEntry, ReprEntryNative] = ReprEntry( + reprentry: ReprEntry | ReprEntryNative = ReprEntry( lines=data["lines"], reprfuncargs=reprfuncargs, reprlocals=reprlocals, @@ -578,7 +576,7 @@ def deserialize_repr_traceback(repr_traceback_dict): ] return ReprTraceback(**repr_traceback_dict) - def deserialize_repr_crash(repr_crash_dict: Optional[Dict[str, Any]]): + def deserialize_repr_crash(repr_crash_dict: dict[str, Any] | None): if repr_crash_dict is not None: return ReprFileLocation(**repr_crash_dict) else: @@ -605,8 +603,8 @@ def deserialize_repr_crash(repr_crash_dict: Optional[Dict[str, Any]]): description, ) ) - exception_info: Union[ExceptionChainRepr, ReprExceptionInfo] = ( - ExceptionChainRepr(chain) + exception_info: ExceptionChainRepr | ReprExceptionInfo = ExceptionChainRepr( + chain ) else: exception_info = ReprExceptionInfo( diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index e5af60e388b..bf30a7d2d27 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Basic collect and runtest protocol implementations.""" +from __future__ import annotations + import bdb import dataclasses import os @@ -8,17 +10,11 @@ import types from typing import Callable from typing import cast -from typing import Dict from typing import final from typing import Generic -from typing import List from typing import Literal -from typing import Optional -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING from typing import TypeVar -from typing import Union from .reports import BaseReport from .reports import CollectErrorRepr @@ -72,7 +68,7 @@ def pytest_addoption(parser: Parser) -> None: ) -def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None: +def pytest_terminal_summary(terminalreporter: TerminalReporter) -> None: durations = terminalreporter.config.option.durations durations_min = terminalreporter.config.option.durations_min verbose = terminalreporter.config.getvalue("verbose") @@ -103,15 +99,15 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None: tr.write_line(f"{rep.duration:02.2f}s {rep.when:<8} {rep.nodeid}") -def pytest_sessionstart(session: "Session") -> None: +def pytest_sessionstart(session: Session) -> None: session._setupstate = SetupState() -def pytest_sessionfinish(session: "Session") -> None: +def pytest_sessionfinish(session: Session) -> None: session._setupstate.teardown_exact(None) -def pytest_runtest_protocol(item: Item, nextitem: Optional[Item]) -> bool: +def pytest_runtest_protocol(item: Item, nextitem: Item | None) -> bool: ihook = item.ihook ihook.pytest_runtest_logstart(nodeid=item.nodeid, location=item.location) runtestprotocol(item, nextitem=nextitem) @@ -120,8 +116,8 @@ def pytest_runtest_protocol(item: Item, nextitem: Optional[Item]) -> bool: def runtestprotocol( - item: Item, log: bool = True, nextitem: Optional[Item] = None -) -> List[TestReport]: + item: Item, log: bool = True, nextitem: Item | None = None +) -> list[TestReport]: hasrequest = hasattr(item, "_request") if hasrequest and not item._request: # type: ignore[attr-defined] # This only happens if the item is re-run, as is done by @@ -188,14 +184,14 @@ def pytest_runtest_call(item: Item) -> None: raise -def pytest_runtest_teardown(item: Item, nextitem: Optional[Item]) -> None: +def pytest_runtest_teardown(item: Item, nextitem: Item | None) -> None: _update_current_test_var(item, "teardown") item.session._setupstate.teardown_exact(nextitem) _update_current_test_var(item, None) def _update_current_test_var( - item: Item, when: Optional[Literal["setup", "call", "teardown"]] + item: Item, when: Literal["setup", "call", "teardown"] | None ) -> None: """Update :envvar:`PYTEST_CURRENT_TEST` to reflect the current item and stage. @@ -211,7 +207,7 @@ def _update_current_test_var( os.environ.pop(var_name) -def pytest_report_teststatus(report: BaseReport) -> Optional[Tuple[str, str, str]]: +def pytest_report_teststatus(report: BaseReport) -> tuple[str, str, str] | None: if report.when in ("setup", "teardown"): if report.failed: # category, shortletter, verbose-word @@ -239,7 +235,7 @@ def call_and_report( runtest_hook = ihook.pytest_runtest_teardown else: assert False, f"Unhandled runtest hook case: {when}" - reraise: Tuple[Type[BaseException], ...] = (Exit,) + reraise: tuple[type[BaseException], ...] = (Exit,) if not item.config.getoption("usepdb", False): reraise += (KeyboardInterrupt,) call = CallInfo.from_call( @@ -253,7 +249,7 @@ def call_and_report( return report -def check_interactive_exception(call: "CallInfo[object]", report: BaseReport) -> bool: +def check_interactive_exception(call: CallInfo[object], report: BaseReport) -> bool: """Check whether the call raised an exception that should be reported as interactive.""" if call.excinfo is None: @@ -276,9 +272,9 @@ def check_interactive_exception(call: "CallInfo[object]", report: BaseReport) -> class CallInfo(Generic[TResult]): """Result/Exception info of a function invocation.""" - _result: Optional[TResult] + _result: TResult | None #: The captured exception of the call, if it raised. - excinfo: Optional[ExceptionInfo[BaseException]] + excinfo: ExceptionInfo[BaseException] | None #: The system time when the call started, in seconds since the epoch. start: float #: The system time when the call ended, in seconds since the epoch. @@ -290,8 +286,8 @@ class CallInfo(Generic[TResult]): def __init__( self, - result: Optional[TResult], - excinfo: Optional[ExceptionInfo[BaseException]], + result: TResult | None, + excinfo: ExceptionInfo[BaseException] | None, start: float, stop: float, duration: float, @@ -325,10 +321,8 @@ def from_call( cls, func: Callable[[], TResult], when: Literal["collect", "setup", "call", "teardown"], - reraise: Optional[ - Union[Type[BaseException], Tuple[Type[BaseException], ...]] - ] = None, - ) -> "CallInfo[TResult]": + reraise: type[BaseException] | tuple[type[BaseException], ...] | None = None, + ) -> CallInfo[TResult]: """Call func, wrapping the result in a CallInfo. :param func: @@ -343,7 +337,7 @@ def from_call( start = timing.time() precise_start = timing.perf_counter() try: - result: Optional[TResult] = func() + result: TResult | None = func() except BaseException: excinfo = ExceptionInfo.from_current() if reraise is not None and isinstance(excinfo.value, reraise): @@ -374,7 +368,7 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> TestReport: def pytest_make_collect_report(collector: Collector) -> CollectReport: - def collect() -> List[Union[Item, Collector]]: + def collect() -> list[Item | Collector]: # Before collecting, if this is a Directory, load the conftests. # If a conftest import fails to load, it is considered a collection # error of the Directory collector. This is why it's done inside of the @@ -396,7 +390,7 @@ def collect() -> List[Union[Item, Collector]]: call = CallInfo.from_call( collect, "collect", reraise=(KeyboardInterrupt, SystemExit) ) - longrepr: Union[None, Tuple[str, int, str], str, TerminalRepr] = None + longrepr: None | tuple[str, int, str] | str | TerminalRepr = None if not call.excinfo: outcome: Literal["passed", "skipped", "failed"] = "passed" else: @@ -490,18 +484,13 @@ class SetupState: def __init__(self) -> None: # The stack is in the dict insertion order. - self.stack: Dict[ + self.stack: dict[ Node, - Tuple[ + tuple[ # Node's finalizers. - List[Callable[[], object]], + list[Callable[[], object]], # Node's exception and original traceback, if its setup raised. - Optional[ - Tuple[ - Union[OutcomeException, Exception], - Optional[types.TracebackType], - ] - ], + tuple[OutcomeException | Exception, types.TracebackType | None] | None, ], ] = {} @@ -536,7 +525,7 @@ def addfinalizer(self, finalizer: Callable[[], object], node: Node) -> None: assert node in self.stack, (node, self.stack) self.stack[node][0].append(finalizer) - def teardown_exact(self, nextitem: Optional[Item]) -> None: + def teardown_exact(self, nextitem: Item | None) -> None: """Teardown the current stack up until reaching nodes that nextitem also descends from. @@ -544,7 +533,7 @@ def teardown_exact(self, nextitem: Optional[Item]) -> None: stack is torn down. """ needed_collectors = nextitem and nextitem.listchain() or [] - exceptions: List[BaseException] = [] + exceptions: list[BaseException] = [] while self.stack: if list(self.stack.keys()) == needed_collectors[: len(self.stack)]: break diff --git a/src/_pytest/scope.py b/src/_pytest/scope.py index 2c6e23208f2..976a3ba242e 100644 --- a/src/_pytest/scope.py +++ b/src/_pytest/scope.py @@ -8,10 +8,11 @@ Also this makes the module light to import, as it should. """ +from __future__ import annotations + from enum import Enum from functools import total_ordering from typing import Literal -from typing import Optional _ScopeName = Literal["session", "package", "module", "class", "function"] @@ -38,29 +39,29 @@ class Scope(Enum): Package: _ScopeName = "package" Session: _ScopeName = "session" - def next_lower(self) -> "Scope": + def next_lower(self) -> Scope: """Return the next lower scope.""" index = _SCOPE_INDICES[self] if index == 0: raise ValueError(f"{self} is the lower-most scope") return _ALL_SCOPES[index - 1] - def next_higher(self) -> "Scope": + def next_higher(self) -> Scope: """Return the next higher scope.""" index = _SCOPE_INDICES[self] if index == len(_SCOPE_INDICES) - 1: raise ValueError(f"{self} is the upper-most scope") return _ALL_SCOPES[index + 1] - def __lt__(self, other: "Scope") -> bool: + def __lt__(self, other: Scope) -> bool: self_index = _SCOPE_INDICES[self] other_index = _SCOPE_INDICES[other] return self_index < other_index @classmethod def from_user( - cls, scope_name: _ScopeName, descr: str, where: Optional[str] = None - ) -> "Scope": + cls, scope_name: _ScopeName, descr: str, where: str | None = None + ) -> Scope: """ Given a scope name from the user, return the equivalent Scope enum. Should be used whenever we want to convert a user provided scope name to its enum object. diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index 39ab28b466b..de297f408d3 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -1,6 +1,6 @@ +from __future__ import annotations + from typing import Generator -from typing import Optional -from typing import Union from _pytest._io.saferepr import saferepr from _pytest.config import Config @@ -96,7 +96,7 @@ def _show_fixture_action( @pytest.hookimpl(tryfirst=True) -def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: +def pytest_cmdline_main(config: Config) -> int | ExitCode | None: if config.option.setuponly: config.option.setupshow = True return None diff --git a/src/_pytest/setupplan.py b/src/_pytest/setupplan.py index 13c0df84ea1..4e124cce243 100644 --- a/src/_pytest/setupplan.py +++ b/src/_pytest/setupplan.py @@ -1,5 +1,4 @@ -from typing import Optional -from typing import Union +from __future__ import annotations from _pytest.config import Config from _pytest.config import ExitCode @@ -23,7 +22,7 @@ def pytest_addoption(parser: Parser) -> None: @pytest.hookimpl(tryfirst=True) def pytest_fixture_setup( fixturedef: FixtureDef[object], request: SubRequest -) -> Optional[object]: +) -> object | None: # Will return a dummy fixture if the setuponly option is provided. if request.config.option.setupplan: my_cache_key = fixturedef.cache_key(request) @@ -33,7 +32,7 @@ def pytest_fixture_setup( @pytest.hookimpl(tryfirst=True) -def pytest_cmdline_main(config: Config) -> Optional[Union[int, ExitCode]]: +def pytest_cmdline_main(config: Config) -> int | ExitCode | None: if config.option.setupplan: config.option.setuponly = True config.option.setupshow = True diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 54500b2851b..08fcb283eb2 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Support for skip/xfail functions and markers.""" +from __future__ import annotations + from collections.abc import Mapping import dataclasses import os @@ -9,8 +11,6 @@ import traceback from typing import Generator from typing import Optional -from typing import Tuple -from typing import Type from _pytest.config import Config from _pytest.config import hookimpl @@ -84,7 +84,7 @@ def nop(*args, **kwargs): ) -def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool, str]: +def evaluate_condition(item: Item, mark: Mark, condition: object) -> tuple[bool, str]: """Evaluate a single skipif/xfail condition. If an old-style string condition is given, it is eval()'d, otherwise the @@ -164,7 +164,7 @@ class Skip: reason: str = "unconditional skip" -def evaluate_skip_marks(item: Item) -> Optional[Skip]: +def evaluate_skip_marks(item: Item) -> Skip | None: """Evaluate skip and skipif marks on item, returning Skip if triggered.""" for mark in item.iter_markers(name="skipif"): if "condition" not in mark.kwargs: @@ -201,10 +201,10 @@ class Xfail: reason: str run: bool strict: bool - raises: Optional[Tuple[Type[BaseException], ...]] + raises: tuple[type[BaseException], ...] | None -def evaluate_xfail_marks(item: Item) -> Optional[Xfail]: +def evaluate_xfail_marks(item: Item) -> Xfail | None: """Evaluate xfail marks on item, returning Xfail if triggered.""" for mark in item.iter_markers(name="xfail"): run = mark.kwargs.get("run", True) @@ -292,7 +292,7 @@ def pytest_runtest_makereport( return rep -def pytest_report_teststatus(report: BaseReport) -> Optional[Tuple[str, str, str]]: +def pytest_report_teststatus(report: BaseReport) -> tuple[str, str, str] | None: if hasattr(report, "wasxfail"): if report.skipped: return "xfailed", "x", "XFAIL" diff --git a/src/_pytest/stash.py b/src/_pytest/stash.py index a4b829fc6dd..6a9ff884e04 100644 --- a/src/_pytest/stash.py +++ b/src/_pytest/stash.py @@ -1,9 +1,9 @@ +from __future__ import annotations + from typing import Any from typing import cast -from typing import Dict from typing import Generic from typing import TypeVar -from typing import Union __all__ = ["Stash", "StashKey"] @@ -70,7 +70,7 @@ class Stash: __slots__ = ("_storage",) def __init__(self) -> None: - self._storage: Dict[StashKey[Any], object] = {} + self._storage: dict[StashKey[Any], object] = {} def __setitem__(self, key: StashKey[T], value: T) -> None: """Set a value for key.""" @@ -83,7 +83,7 @@ def __getitem__(self, key: StashKey[T]) -> T: """ return cast(T, self._storage[key]) - def get(self, key: StashKey[T], default: D) -> Union[T, D]: + def get(self, key: StashKey[T], default: D) -> T | D: """Get the value for key, or return default if the key wasn't set before.""" try: diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index 1e3a09d9678..bd906ce63c1 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -1,5 +1,4 @@ -from typing import List -from typing import Optional +from __future__ import annotations from _pytest import nodes from _pytest.cacheprovider import Cache @@ -55,18 +54,18 @@ def pytest_sessionfinish(session: Session) -> None: class StepwisePlugin: def __init__(self, config: Config) -> None: self.config = config - self.session: Optional[Session] = None + self.session: Session | None = None self.report_status = "" assert config.cache is not None self.cache: Cache = config.cache - self.lastfailed: Optional[str] = self.cache.get(STEPWISE_CACHE_DIR, None) + self.lastfailed: str | None = self.cache.get(STEPWISE_CACHE_DIR, None) self.skip: bool = config.getoption("stepwise_skip") def pytest_sessionstart(self, session: Session) -> None: self.session = session def pytest_collection_modifyitems( - self, config: Config, items: List[nodes.Item] + self, config: Config, items: list[nodes.Item] ) -> None: if not self.lastfailed: self.report_status = "no previously failed tests, not skipping." @@ -113,7 +112,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: if report.nodeid == self.lastfailed: self.lastfailed = None - def pytest_report_collectionfinish(self) -> Optional[str]: + def pytest_report_collectionfinish(self) -> str | None: if self.config.getoption("verbose") >= 0 and self.report_status: return f"stepwise: {self.report_status}" return None diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 2eef8d1f227..26c573f583e 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -4,6 +4,8 @@ This is a good source for looking at the various reporting hooks. """ +from __future__ import annotations + import argparse from collections import Counter import dataclasses @@ -17,20 +19,14 @@ from typing import Any from typing import Callable from typing import ClassVar -from typing import Dict from typing import final from typing import Generator -from typing import List from typing import Literal from typing import Mapping from typing import NamedTuple -from typing import Optional from typing import Sequence -from typing import Set from typing import TextIO -from typing import Tuple from typing import TYPE_CHECKING -from typing import Union import warnings import pluggy @@ -90,7 +86,7 @@ def __init__( dest: str, default: object = None, required: bool = False, - help: Optional[str] = None, + help: str | None = None, ) -> None: super().__init__( option_strings=option_strings, @@ -105,8 +101,8 @@ def __call__( self, parser: argparse.ArgumentParser, namespace: argparse.Namespace, - values: Union[str, Sequence[object], None], - option_string: Optional[str] = None, + values: str | Sequence[object] | None, + option_string: str | None = None, ) -> None: new_count = getattr(namespace, self.dest, 0) - 1 setattr(namespace, self.dest, new_count) @@ -131,7 +127,7 @@ class TestShortLogReport(NamedTuple): category: str letter: str - word: Union[str, Tuple[str, Mapping[str, bool]]] + word: str | tuple[str, Mapping[str, bool]] def pytest_addoption(parser: Parser) -> None: @@ -311,7 +307,7 @@ def getreportopt(config: Config) -> str: @hookimpl(trylast=True) # after _pytest.runner -def pytest_report_teststatus(report: BaseReport) -> Tuple[str, str, str]: +def pytest_report_teststatus(report: BaseReport) -> tuple[str, str, str]: letter = "F" if report.passed: letter = "." @@ -339,12 +335,12 @@ class WarningReport: """ message: str - nodeid: Optional[str] = None - fslocation: Optional[Tuple[str, int]] = None + nodeid: str | None = None + fslocation: tuple[str, int] | None = None count_towards_summary: ClassVar = True - def get_location(self, config: Config) -> Optional[str]: + def get_location(self, config: Config) -> str | None: """Return the more user-friendly information about the location of a warning, or None.""" if self.nodeid: return self.nodeid @@ -357,31 +353,31 @@ def get_location(self, config: Config) -> Optional[str]: @final class TerminalReporter: - def __init__(self, config: Config, file: Optional[TextIO] = None) -> None: + def __init__(self, config: Config, file: TextIO | None = None) -> None: import _pytest.config self.config = config self._numcollected = 0 - self._session: Optional[Session] = None - self._showfspath: Optional[bool] = None + self._session: Session | None = None + self._showfspath: bool | None = None - self.stats: Dict[str, List[Any]] = {} - self._main_color: Optional[str] = None - self._known_types: Optional[List[str]] = None + self.stats: dict[str, list[Any]] = {} + self._main_color: str | None = None + self._known_types: list[str] | None = None self.startpath = config.invocation_params.dir if file is None: file = sys.stdout self._tw = _pytest.config.create_terminal_writer(config, file) self._screen_width = self._tw.fullwidth - self.currentfspath: Union[None, Path, str, int] = None + self.currentfspath: None | Path | str | int = None self.reportchars = getreportopt(config) self.hasmarkup = self._tw.hasmarkup self.isatty = file.isatty() - self._progress_nodeids_reported: Set[str] = set() + self._progress_nodeids_reported: set[str] = set() self._show_progress_info = self._determine_show_progress_info() - self._collect_report_last_write: Optional[float] = None - self._already_displayed_warnings: Optional[int] = None - self._keyboardinterrupt_memo: Optional[ExceptionRepr] = None + self._collect_report_last_write: float | None = None + self._already_displayed_warnings: int | None = None + self._keyboardinterrupt_memo: ExceptionRepr | None = None def _determine_show_progress_info(self) -> Literal["progress", "count", False]: """Return whether we should display progress information based on the current config.""" @@ -428,7 +424,7 @@ def showfspath(self) -> bool: return self._showfspath @showfspath.setter - def showfspath(self, value: Optional[bool]) -> None: + def showfspath(self, value: bool | None) -> None: self._showfspath = value @property @@ -492,7 +488,7 @@ def write(self, content: str, *, flush: bool = False, **markup: bool) -> None: def flush(self) -> None: self._tw.flush() - def write_line(self, line: Union[str, bytes], **markup: bool) -> None: + def write_line(self, line: str | bytes, **markup: bool) -> None: if not isinstance(line, str): line = str(line, errors="replace") self.ensure_newline() @@ -519,8 +515,8 @@ def rewrite(self, line: str, **markup: bool) -> None: def write_sep( self, sep: str, - title: Optional[str] = None, - fullwidth: Optional[int] = None, + title: str | None = None, + fullwidth: int | None = None, **markup: bool, ) -> None: self.ensure_newline() @@ -570,7 +566,7 @@ def pytest_deselected(self, items: Sequence[Item]) -> None: self._add_stats("deselected", items) def pytest_runtest_logstart( - self, nodeid: str, location: Tuple[str, Optional[int], str] + self, nodeid: str, location: tuple[str, int | None, str] ) -> None: fspath, lineno, domain = location # Ensure that the path is printed before the @@ -777,7 +773,7 @@ def report_collect(self, final: bool = False) -> None: self.write_line(line) @hookimpl(trylast=True) - def pytest_sessionstart(self, session: "Session") -> None: + def pytest_sessionstart(self, session: Session) -> None: self._session = session self._sessionstarttime = timing.time() if not self.showheader: @@ -804,7 +800,7 @@ def pytest_sessionstart(self, session: "Session") -> None: self._write_report_lines_from_hooks(lines) def _write_report_lines_from_hooks( - self, lines: Sequence[Union[str, Sequence[str]]] + self, lines: Sequence[str | Sequence[str]] ) -> None: for line_or_lines in reversed(lines): if isinstance(line_or_lines, str): @@ -813,14 +809,14 @@ def _write_report_lines_from_hooks( for line in line_or_lines: self.write_line(line) - def pytest_report_header(self, config: Config) -> List[str]: + def pytest_report_header(self, config: Config) -> list[str]: result = [f"rootdir: {config.rootpath}"] if config.inipath: result.append("configfile: " + bestrelpath(config.rootpath, config.inipath)) if config.args_source == Config.ArgsSource.TESTPATHS: - testpaths: List[str] = config.getini("testpaths") + testpaths: list[str] = config.getini("testpaths") result.append("testpaths: {}".format(", ".join(testpaths))) plugininfo = config.pluginmanager.list_plugin_distinfo() @@ -830,7 +826,7 @@ def pytest_report_header(self, config: Config) -> List[str]: ) return result - def pytest_collection_finish(self, session: "Session") -> None: + def pytest_collection_finish(self, session: Session) -> None: self.report_collect(True) lines = self.config.hook.pytest_report_collectionfinish( @@ -863,7 +859,7 @@ def _printcollecteditems(self, items: Sequence[Item]) -> None: for item in items: self._tw.line(item.nodeid) return - stack: List[Node] = [] + stack: list[Node] = [] indent = "" for item in items: needed_collectors = item.listchain()[1:] # strip root node @@ -884,7 +880,7 @@ def _printcollecteditems(self, items: Sequence[Item]) -> None: @hookimpl(wrapper=True) def pytest_sessionfinish( - self, session: "Session", exitstatus: Union[int, ExitCode] + self, session: Session, exitstatus: int | ExitCode ) -> Generator[None, None, None]: result = yield self._tw.line("") @@ -948,7 +944,7 @@ def _report_keyboardinterrupt(self) -> None: ) def _locationline( - self, nodeid: str, fspath: str, lineno: Optional[int], domain: str + self, nodeid: str, fspath: str, lineno: int | None, domain: str ) -> str: def mkrel(nodeid: str) -> str: line = self.config.cwd_relative_nodeid(nodeid) @@ -993,7 +989,7 @@ def getreports(self, name: str): def summary_warnings(self) -> None: if self.hasopt("w"): - all_warnings: Optional[List[WarningReport]] = self.stats.get("warnings") + all_warnings: list[WarningReport] | None = self.stats.get("warnings") if not all_warnings: return @@ -1006,11 +1002,11 @@ def summary_warnings(self) -> None: if not warning_reports: return - reports_grouped_by_message: Dict[str, List[WarningReport]] = {} + reports_grouped_by_message: dict[str, list[WarningReport]] = {} for wr in warning_reports: reports_grouped_by_message.setdefault(wr.message, []).append(wr) - def collapsed_location_report(reports: List[WarningReport]) -> str: + def collapsed_location_report(reports: list[WarningReport]) -> str: locations = [] for w in reports: location = w.get_location(self.config) @@ -1056,7 +1052,7 @@ def summary_passes_combined( ) -> None: if self.config.option.tbstyle != "no": if self.hasopt(needed_opt): - reports: List[TestReport] = self.getreports(which_reports) + reports: list[TestReport] = self.getreports(which_reports) if not reports: return self.write_sep("=", sep_title) @@ -1067,7 +1063,7 @@ def summary_passes_combined( self._outrep_summary(rep) self._handle_teardown_sections(rep.nodeid) - def _get_teardown_reports(self, nodeid: str) -> List[TestReport]: + def _get_teardown_reports(self, nodeid: str) -> list[TestReport]: reports = self.getreports("") return [ report @@ -1107,11 +1103,11 @@ def summary_failures_combined( sep_title: str, *, style: str, - needed_opt: Optional[str] = None, + needed_opt: str | None = None, ) -> None: if style != "no": if not needed_opt or self.hasopt(needed_opt): - reports: List[BaseReport] = self.getreports(which_reports) + reports: list[BaseReport] = self.getreports(which_reports) if not reports: return self.write_sep("=", sep_title) @@ -1128,7 +1124,7 @@ def summary_failures_combined( def summary_errors(self) -> None: if self.config.option.tbstyle != "no": - reports: List[BaseReport] = self.getreports("error") + reports: list[BaseReport] = self.getreports("error") if not reports: return self.write_sep("=", "ERRORS") @@ -1195,7 +1191,7 @@ def short_test_summary(self) -> None: if not self.reportchars: return - def show_simple(lines: List[str], *, stat: str) -> None: + def show_simple(lines: list[str], *, stat: str) -> None: failed = self.stats.get(stat, []) if not failed: return @@ -1207,7 +1203,7 @@ def show_simple(lines: List[str], *, stat: str) -> None: ) lines.append(line) - def show_xfailed(lines: List[str]) -> None: + def show_xfailed(lines: list[str]) -> None: xfailed = self.stats.get("xfailed", []) for rep in xfailed: verbose_word = rep._get_verbose_word(self.config) @@ -1222,7 +1218,7 @@ def show_xfailed(lines: List[str]) -> None: lines.append(line) - def show_xpassed(lines: List[str]) -> None: + def show_xpassed(lines: list[str]) -> None: xpassed = self.stats.get("xpassed", []) for rep in xpassed: verbose_word = rep._get_verbose_word(self.config) @@ -1236,8 +1232,8 @@ def show_xpassed(lines: List[str]) -> None: line += " - " + str(reason) lines.append(line) - def show_skipped(lines: List[str]) -> None: - skipped: List[CollectReport] = self.stats.get("skipped", []) + def show_skipped(lines: list[str]) -> None: + skipped: list[CollectReport] = self.stats.get("skipped", []) fskips = _folded_skips(self.startpath, skipped) if skipped else [] if not fskips: return @@ -1256,7 +1252,7 @@ def show_skipped(lines: List[str]) -> None: else: lines.append("%s [%d] %s: %s" % (markup_word, num, fspath, reason)) - REPORTCHAR_ACTIONS: Mapping[str, Callable[[List[str]], None]] = { + REPORTCHAR_ACTIONS: Mapping[str, Callable[[list[str]], None]] = { "x": show_xfailed, "X": show_xpassed, "f": partial(show_simple, stat="failed"), @@ -1265,7 +1261,7 @@ def show_skipped(lines: List[str]) -> None: "E": partial(show_simple, stat="error"), } - lines: List[str] = [] + lines: list[str] = [] for char in self.reportchars: action = REPORTCHAR_ACTIONS.get(char) if action: # skipping e.g. "P" (passed with output) here. @@ -1276,7 +1272,7 @@ def show_skipped(lines: List[str]) -> None: for line in lines: self.write_line(line) - def _get_main_color(self) -> Tuple[str, List[str]]: + def _get_main_color(self) -> tuple[str, list[str]]: if self._main_color is None or self._known_types is None or self._is_last_item: self._set_main_color() assert self._main_color @@ -1296,7 +1292,7 @@ def _determine_main_color(self, unknown_type_seen: bool) -> str: return main_color def _set_main_color(self) -> None: - unknown_types: List[str] = [] + unknown_types: list[str] = [] for found_type in self.stats: if found_type: # setup/teardown reports have an empty key, ignore them if found_type not in KNOWN_TYPES and found_type not in unknown_types: @@ -1304,7 +1300,7 @@ def _set_main_color(self) -> None: self._known_types = list(KNOWN_TYPES) + unknown_types self._main_color = self._determine_main_color(bool(unknown_types)) - def build_summary_stats_line(self) -> Tuple[List[Tuple[str, Dict[str, bool]]], str]: + def build_summary_stats_line(self) -> tuple[list[tuple[str, dict[str, bool]]], str]: """ Build the parts used in the last summary stats line. @@ -1329,14 +1325,14 @@ def build_summary_stats_line(self) -> Tuple[List[Tuple[str, Dict[str, bool]]], s else: return self._build_normal_summary_stats_line() - def _get_reports_to_display(self, key: str) -> List[Any]: + def _get_reports_to_display(self, key: str) -> list[Any]: """Get test/collection reports for the given status key, such as `passed` or `error`.""" reports = self.stats.get(key, []) return [x for x in reports if getattr(x, "count_towards_summary", True)] def _build_normal_summary_stats_line( self, - ) -> Tuple[List[Tuple[str, Dict[str, bool]]], str]: + ) -> tuple[list[tuple[str, dict[str, bool]]], str]: main_color, known_types = self._get_main_color() parts = [] @@ -1355,7 +1351,7 @@ def _build_normal_summary_stats_line( def _build_collect_only_summary_stats_line( self, - ) -> Tuple[List[Tuple[str, Dict[str, bool]]], str]: + ) -> tuple[list[tuple[str, dict[str, bool]]], str]: deselected = len(self._get_reports_to_display("deselected")) errors = len(self._get_reports_to_display("error")) @@ -1396,7 +1392,7 @@ def _get_node_id_with_markup(tw: TerminalWriter, config: Config, rep: BaseReport return path -def _format_trimmed(format: str, msg: str, available_width: int) -> Optional[str]: +def _format_trimmed(format: str, msg: str, available_width: int) -> str | None: """Format msg into format, ellipsizing it if doesn't fit in available_width. Returns None if even the ellipsis can't fit. @@ -1422,7 +1418,7 @@ def _format_trimmed(format: str, msg: str, available_width: int) -> Optional[str def _get_line_with_reprcrash_message( - config: Config, rep: BaseReport, tw: TerminalWriter, word_markup: Dict[str, bool] + config: Config, rep: BaseReport, tw: TerminalWriter, word_markup: dict[str, bool] ) -> str: """Get summary line for a report, trying to add reprcrash message.""" verbose_word = rep._get_verbose_word(config) @@ -1452,8 +1448,8 @@ def _get_line_with_reprcrash_message( def _folded_skips( startpath: Path, skipped: Sequence[CollectReport], -) -> List[Tuple[int, str, Optional[int], str]]: - d: Dict[Tuple[str, Optional[int], str], List[CollectReport]] = {} +) -> list[tuple[int, str, int | None, str]]: + d: dict[tuple[str, int | None, str], list[CollectReport]] = {} for event in skipped: assert event.longrepr is not None assert isinstance(event.longrepr, tuple), (event, event.longrepr) @@ -1470,11 +1466,11 @@ def _folded_skips( and "skip" in keywords and "pytestmark" not in keywords ): - key: Tuple[str, Optional[int], str] = (fspath, None, reason) + key: tuple[str, int | None, str] = (fspath, None, reason) else: key = (fspath, lineno, reason) d.setdefault(key, []).append(event) - values: List[Tuple[int, str, Optional[int], str]] = [] + values: list[tuple[int, str, int | None, str]] = [] for key, events in d.items(): values.append((len(events), *key)) return values @@ -1489,7 +1485,7 @@ def _folded_skips( _color_for_type_default = "yellow" -def pluralize(count: int, noun: str) -> Tuple[int, str]: +def pluralize(count: int, noun: str) -> tuple[int, str]: # No need to pluralize words such as `failed` or `passed`. if noun not in ["error", "warnings", "test"]: return count, noun @@ -1502,8 +1498,8 @@ def pluralize(count: int, noun: str) -> Tuple[int, str]: return count, noun + "s" if count != 1 else noun -def _plugin_nameversions(plugininfo) -> List[str]: - values: List[str] = [] +def _plugin_nameversions(plugininfo) -> list[str]: + values: list[str] = [] for plugin, dist in plugininfo: # Gets us name and version! name = f"{dist.project_name}-{dist.version}" diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index 603a1777c92..d78c32c852f 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -1,16 +1,21 @@ +from __future__ import annotations + import threading import traceback from types import TracebackType from typing import Any from typing import Callable from typing import Generator -from typing import Optional -from typing import Type +from typing import TYPE_CHECKING import warnings import pytest +if TYPE_CHECKING: + from typing_extensions import Self + + # Copied from cpython/Lib/test/support/threading_helper.py, with modifications. class catch_threading_exception: """Context manager catching threading.Thread exception using @@ -34,22 +39,22 @@ class catch_threading_exception: """ def __init__(self) -> None: - self.args: Optional[threading.ExceptHookArgs] = None - self._old_hook: Optional[Callable[[threading.ExceptHookArgs], Any]] = None + self.args: threading.ExceptHookArgs | None = None + self._old_hook: Callable[[threading.ExceptHookArgs], Any] | None = None - def _hook(self, args: "threading.ExceptHookArgs") -> None: + def _hook(self, args: threading.ExceptHookArgs) -> None: self.args = args - def __enter__(self) -> "catch_threading_exception": + def __enter__(self) -> Self: self._old_hook = threading.excepthook threading.excepthook = self._hook return self def __exit__( self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, ) -> None: assert self._old_hook is not None threading.excepthook = self._old_hook diff --git a/src/_pytest/timing.py b/src/_pytest/timing.py index 0541dc8e0a1..b23c7f69e2d 100644 --- a/src/_pytest/timing.py +++ b/src/_pytest/timing.py @@ -6,6 +6,8 @@ Fixture "mock_timing" also interacts with this module for pytest's own tests. """ +from __future__ import annotations + from time import perf_counter from time import sleep from time import time diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 72efed3e87a..91109ea69ef 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Support for providing temporary directories to test functions.""" +from __future__ import annotations + import dataclasses import os from pathlib import Path @@ -12,8 +14,6 @@ from typing import final from typing import Generator from typing import Literal -from typing import Optional -from typing import Union from .pathlib import cleanup_dead_symlinks from .pathlib import LOCK_TIMEOUT @@ -46,20 +46,20 @@ class TempPathFactory: The base directory can be configured using the ``--basetemp`` option. """ - _given_basetemp: Optional[Path] + _given_basetemp: Path | None # pluggy TagTracerSub, not currently exposed, so Any. _trace: Any - _basetemp: Optional[Path] + _basetemp: Path | None _retention_count: int _retention_policy: RetentionType def __init__( self, - given_basetemp: Optional[Path], + given_basetemp: Path | None, retention_count: int, retention_policy: RetentionType, trace, - basetemp: Optional[Path] = None, + basetemp: Path | None = None, *, _ispytest: bool = False, ) -> None: @@ -82,7 +82,7 @@ def from_config( config: Config, *, _ispytest: bool = False, - ) -> "TempPathFactory": + ) -> TempPathFactory: """Create a factory according to pytest configuration. :meta private: @@ -198,7 +198,7 @@ def getbasetemp(self) -> Path: return basetemp -def get_user() -> Optional[str]: +def get_user() -> str | None: """Return the current user name, or None if getuser() does not work in the current environment (see #1010).""" try: @@ -286,7 +286,7 @@ def tmp_path( del request.node.stash[tmppath_result_key] -def pytest_sessionfinish(session, exitstatus: Union[int, ExitCode]): +def pytest_sessionfinish(session, exitstatus: int | ExitCode): """After each session, remove base directory if all the tests passed, the policy is "failed", and the basetemp is not specified by a user. """ @@ -317,6 +317,6 @@ def pytest_runtest_makereport( ) -> Generator[None, TestReport, TestReport]: rep = yield assert rep.when is not None - empty: Dict[str, bool] = {} + empty: dict[str, bool] = {} item.stash.setdefault(tmppath_result_key, empty)[rep.when] = rep.passed return rep diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 0f201d0f3f5..aefea1333d9 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Discover and run std-library "unittest" style tests.""" +from __future__ import annotations + import inspect import sys import traceback @@ -9,8 +11,6 @@ from typing import Callable from typing import Generator from typing import Iterable -from typing import List -from typing import Optional from typing import Tuple from typing import Type from typing import TYPE_CHECKING @@ -49,8 +49,8 @@ def pytest_pycollect_makeitem( - collector: Union[Module, Class], name: str, obj: object -) -> Optional["UnitTestCase"]: + collector: Module | Class, name: str, obj: object +) -> UnitTestCase | None: try: # Has unittest been imported? ut = sys.modules["unittest"] @@ -81,7 +81,7 @@ def newinstance(self): # it. return self.obj("runTest") - def collect(self) -> Iterable[Union[Item, Collector]]: + def collect(self) -> Iterable[Item | Collector]: from unittest import TestLoader cls = self.obj @@ -201,7 +201,7 @@ def unittest_setup_method_fixture( class TestCaseFunction(Function): nofuncargs = True - _excinfo: Optional[List[_pytest._code.ExceptionInfo[BaseException]]] = None + _excinfo: list[_pytest._code.ExceptionInfo[BaseException]] | None = None def _getinstance(self): assert isinstance(self.parent, UnitTestCase) @@ -215,7 +215,7 @@ def _testcase(self): def setup(self) -> None: # A bound method to be called during teardown() if set (see 'runtest()'). - self._explicit_tearDown: Optional[Callable[[], None]] = None + self._explicit_tearDown: Callable[[], None] | None = None super().setup() def teardown(self) -> None: @@ -226,7 +226,7 @@ def teardown(self) -> None: del self._instance super().teardown() - def startTest(self, testcase: "unittest.TestCase") -> None: + def startTest(self, testcase: unittest.TestCase) -> None: pass def _addexcinfo(self, rawexcinfo: _SysExcInfoType) -> None: @@ -265,7 +265,7 @@ def _addexcinfo(self, rawexcinfo: _SysExcInfoType) -> None: self.__dict__.setdefault("_excinfo", []).append(excinfo) def addError( - self, testcase: "unittest.TestCase", rawexcinfo: _SysExcInfoType + self, testcase: unittest.TestCase, rawexcinfo: _SysExcInfoType ) -> None: try: if isinstance(rawexcinfo[1], exit.Exception): @@ -275,11 +275,11 @@ def addError( self._addexcinfo(rawexcinfo) def addFailure( - self, testcase: "unittest.TestCase", rawexcinfo: _SysExcInfoType + self, testcase: unittest.TestCase, rawexcinfo: _SysExcInfoType ) -> None: self._addexcinfo(rawexcinfo) - def addSkip(self, testcase: "unittest.TestCase", reason: str) -> None: + def addSkip(self, testcase: unittest.TestCase, reason: str) -> None: try: raise pytest.skip.Exception(reason, _use_item_location=True) except skip.Exception: @@ -287,7 +287,7 @@ def addSkip(self, testcase: "unittest.TestCase", reason: str) -> None: def addExpectedFailure( self, - testcase: "unittest.TestCase", + testcase: unittest.TestCase, rawexcinfo: _SysExcInfoType, reason: str = "", ) -> None: @@ -298,8 +298,8 @@ def addExpectedFailure( def addUnexpectedSuccess( self, - testcase: "unittest.TestCase", - reason: Optional["twisted.trial.unittest.Todo"] = None, + testcase: unittest.TestCase, + reason: twisted.trial.unittest.Todo | None = None, ) -> None: msg = "Unexpected success" if reason: @@ -310,13 +310,13 @@ def addUnexpectedSuccess( except fail.Exception: self._addexcinfo(sys.exc_info()) - def addSuccess(self, testcase: "unittest.TestCase") -> None: + def addSuccess(self, testcase: unittest.TestCase) -> None: pass - def stopTest(self, testcase: "unittest.TestCase") -> None: + def stopTest(self, testcase: unittest.TestCase) -> None: pass - def addDuration(self, testcase: "unittest.TestCase", elapsed: float) -> None: + def addDuration(self, testcase: unittest.TestCase, elapsed: float) -> None: pass def runtest(self) -> None: diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index 50b121e8811..c191703a3de 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -1,16 +1,21 @@ +from __future__ import annotations + import sys import traceback from types import TracebackType from typing import Any from typing import Callable from typing import Generator -from typing import Optional -from typing import Type +from typing import TYPE_CHECKING import warnings import pytest +if TYPE_CHECKING: + from typing_extensions import Self + + # Copied from cpython/Lib/test/support/__init__.py, with modifications. class catch_unraisable_exception: """Context manager catching unraisable exception using sys.unraisablehook. @@ -34,24 +39,24 @@ class catch_unraisable_exception: """ def __init__(self) -> None: - self.unraisable: Optional[sys.UnraisableHookArgs] = None - self._old_hook: Optional[Callable[[sys.UnraisableHookArgs], Any]] = None + self.unraisable: sys.UnraisableHookArgs | None = None + self._old_hook: Callable[[sys.UnraisableHookArgs], Any] | None = None - def _hook(self, unraisable: "sys.UnraisableHookArgs") -> None: + def _hook(self, unraisable: sys.UnraisableHookArgs) -> None: # Storing unraisable.object can resurrect an object which is being # finalized. Storing unraisable.exc_value creates a reference cycle. self.unraisable = unraisable - def __enter__(self) -> "catch_unraisable_exception": + def __enter__(self) -> Self: self._old_hook = sys.unraisablehook sys.unraisablehook = self._hook return self def __exit__( self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: TracebackType | None, ) -> None: assert self._old_hook is not None sys.unraisablehook = self._old_hook diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index a5884f29582..4ab14e48c92 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -1,10 +1,11 @@ +from __future__ import annotations + import dataclasses import inspect from types import FunctionType from typing import Any from typing import final from typing import Generic -from typing import Type from typing import TypeVar import warnings @@ -72,7 +73,7 @@ class PytestExperimentalApiWarning(PytestWarning, FutureWarning): __module__ = "pytest" @classmethod - def simple(cls, apiname: str) -> "PytestExperimentalApiWarning": + def simple(cls, apiname: str) -> PytestExperimentalApiWarning: return cls(f"{apiname} is an experimental api that may change over time") @@ -132,7 +133,7 @@ class UnformattedWarning(Generic[_W]): as opposed to a direct message. """ - category: Type["_W"] + category: type[_W] template: str def format(self, **kwargs: Any) -> _W: diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index 22590892f8d..5c59e55c5db 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -1,9 +1,10 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from contextlib import contextmanager import sys from typing import Generator from typing import Literal -from typing import Optional import warnings from _pytest.config import apply_warning_filters @@ -28,7 +29,7 @@ def catch_warnings_for_item( config: Config, ihook, when: Literal["config", "collect", "runtest"], - item: Optional[Item], + item: Item | None, ) -> Generator[None, None, None]: """Context manager that catches warnings generated in the contained execution block. @@ -142,7 +143,7 @@ def pytest_sessionfinish(session: Session) -> Generator[None, None, None]: @pytest.hookimpl(wrapper=True) def pytest_load_initial_conftests( - early_config: "Config", + early_config: Config, ) -> Generator[None, None, None]: with catch_warnings_for_item( config=early_config, ihook=early_config.hook, when="config", item=None diff --git a/src/py.py b/src/py.py index d1c39d203a8..5c661e66c1f 100644 --- a/src/py.py +++ b/src/py.py @@ -1,6 +1,8 @@ # shim for pylib going away # if pylib is installed this file will get skipped # (`py/__init__.py` has higher precedence) +from __future__ import annotations + import sys import _pytest._py.error as error diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index c6b6de827e9..90abcdab036 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -1,6 +1,8 @@ # PYTHON_ARGCOMPLETE_OK """pytest: unit and functional testing with Python.""" +from __future__ import annotations + from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo diff --git a/src/pytest/__main__.py b/src/pytest/__main__.py index e4cb67d5dd5..cccab5d57b8 100644 --- a/src/pytest/__main__.py +++ b/src/pytest/__main__.py @@ -1,5 +1,7 @@ """The pytest entry point.""" +from __future__ import annotations + import pytest diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 0215aba9695..4a95e2d0cd9 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import contextlib import multiprocessing import os diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 0f3b35036d7..01d911e8ca4 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import dataclasses import importlib.metadata import os diff --git a/testing/code/test_code.py b/testing/code/test_code.py index 57ab4cdfddb..7ae5ad46100 100644 --- a/testing/code/test_code.py +++ b/testing/code/test_code.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import re import sys from types import FrameType diff --git a/testing/conftest.py b/testing/conftest.py index b7e2d6111af..24e5d183094 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -1,9 +1,10 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import dataclasses import re import sys from typing import Generator -from typing import List from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester @@ -190,22 +191,22 @@ class ColorMapping: NO_COLORS = {k: "" for k in COLORS.keys()} @classmethod - def format(cls, lines: List[str]) -> List[str]: + def format(cls, lines: list[str]) -> list[str]: """Straightforward replacement of color names to their ASCII codes.""" return [line.format(**cls.COLORS) for line in lines] @classmethod - def format_for_fnmatch(cls, lines: List[str]) -> List[str]: + def format_for_fnmatch(cls, lines: list[str]) -> list[str]: """Replace color names for use with LineMatcher.fnmatch_lines""" return [line.format(**cls.COLORS).replace("[", "[[]") for line in lines] @classmethod - def format_for_rematch(cls, lines: List[str]) -> List[str]: + def format_for_rematch(cls, lines: list[str]) -> list[str]: """Replace color names for use with LineMatcher.re_match_lines""" return [line.format(**cls.RE_COLORS) for line in lines] @classmethod - def strip_colors(cls, lines: List[str]) -> List[str]: + def strip_colors(cls, lines: list[str]) -> list[str]: """Entirely remove every color code""" return [line.format(**cls.NO_COLORS) for line in lines] diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index 9e83a49d554..5d0e69c58c1 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from pathlib import Path import re import sys diff --git a/testing/example_scripts/acceptance/fixture_mock_integration.py b/testing/example_scripts/acceptance/fixture_mock_integration.py index d802a7f8728..e612ae01e66 100644 --- a/testing/example_scripts/acceptance/fixture_mock_integration.py +++ b/testing/example_scripts/acceptance/fixture_mock_integration.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Reproduces issue #3774""" +from __future__ import annotations + from unittest import mock import pytest diff --git a/testing/example_scripts/collect/collect_init_tests/tests/__init__.py b/testing/example_scripts/collect/collect_init_tests/tests/__init__.py index 58c41942d1c..5e30bb15883 100644 --- a/testing/example_scripts/collect/collect_init_tests/tests/__init__.py +++ b/testing/example_scripts/collect/collect_init_tests/tests/__init__.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_init(): pass diff --git a/testing/example_scripts/collect/collect_init_tests/tests/test_foo.py b/testing/example_scripts/collect/collect_init_tests/tests/test_foo.py index d88c001c2cc..3cb8f1be095 100644 --- a/testing/example_scripts/collect/collect_init_tests/tests/test_foo.py +++ b/testing/example_scripts/collect/collect_init_tests/tests/test_foo.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_foo(): pass diff --git a/testing/example_scripts/collect/package_infinite_recursion/conftest.py b/testing/example_scripts/collect/package_infinite_recursion/conftest.py index bba5db8b2fd..c2d2b918874 100644 --- a/testing/example_scripts/collect/package_infinite_recursion/conftest.py +++ b/testing/example_scripts/collect/package_infinite_recursion/conftest.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def pytest_ignore_collect(collection_path): return False diff --git a/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py b/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py index 2809d0cc689..38c51e586fc 100644 --- a/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py +++ b/testing/example_scripts/collect/package_infinite_recursion/tests/test_basic.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test(): pass diff --git a/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py b/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py index 58c41942d1c..5e30bb15883 100644 --- a/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py +++ b/testing/example_scripts/collect/package_init_given_as_arg/pkg/__init__.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_init(): pass diff --git a/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py b/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py index d88c001c2cc..3cb8f1be095 100644 --- a/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py +++ b/testing/example_scripts/collect/package_init_given_as_arg/pkg/test_foo.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_foo(): pass diff --git a/testing/example_scripts/config/collect_pytest_prefix/conftest.py b/testing/example_scripts/config/collect_pytest_prefix/conftest.py index 2da4ffe2fed..5e0ab54411b 100644 --- a/testing/example_scripts/config/collect_pytest_prefix/conftest.py +++ b/testing/example_scripts/config/collect_pytest_prefix/conftest.py @@ -1,2 +1,5 @@ +from __future__ import annotations + + class pytest_something: pass diff --git a/testing/example_scripts/config/collect_pytest_prefix/test_foo.py b/testing/example_scripts/config/collect_pytest_prefix/test_foo.py index d88c001c2cc..3cb8f1be095 100644 --- a/testing/example_scripts/config/collect_pytest_prefix/test_foo.py +++ b/testing/example_scripts/config/collect_pytest_prefix/test_foo.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_foo(): pass diff --git a/testing/example_scripts/conftest_usageerror/conftest.py b/testing/example_scripts/conftest_usageerror/conftest.py index 64bbeefac1d..a6690bdc303 100644 --- a/testing/example_scripts/conftest_usageerror/conftest.py +++ b/testing/example_scripts/conftest_usageerror/conftest.py @@ -1,4 +1,7 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def pytest_configure(config): import pytest diff --git a/testing/example_scripts/customdirectory/conftest.py b/testing/example_scripts/customdirectory/conftest.py index fe1c743a686..4718d7d5be3 100644 --- a/testing/example_scripts/customdirectory/conftest.py +++ b/testing/example_scripts/customdirectory/conftest.py @@ -1,5 +1,7 @@ # mypy: allow-untyped-defs # content of conftest.py +from __future__ import annotations + import json import pytest diff --git a/testing/example_scripts/customdirectory/tests/test_first.py b/testing/example_scripts/customdirectory/tests/test_first.py index 890ca3dea38..06f40ca4733 100644 --- a/testing/example_scripts/customdirectory/tests/test_first.py +++ b/testing/example_scripts/customdirectory/tests/test_first.py @@ -1,4 +1,7 @@ # mypy: allow-untyped-defs # content of test_first.py +from __future__ import annotations + + def test_1(): pass diff --git a/testing/example_scripts/customdirectory/tests/test_second.py b/testing/example_scripts/customdirectory/tests/test_second.py index 42108d5da84..79bcc099e65 100644 --- a/testing/example_scripts/customdirectory/tests/test_second.py +++ b/testing/example_scripts/customdirectory/tests/test_second.py @@ -1,4 +1,7 @@ # mypy: allow-untyped-defs # content of test_second.py +from __future__ import annotations + + def test_2(): pass diff --git a/testing/example_scripts/customdirectory/tests/test_third.py b/testing/example_scripts/customdirectory/tests/test_third.py index ede0f3e6025..5af476ad44d 100644 --- a/testing/example_scripts/customdirectory/tests/test_third.py +++ b/testing/example_scripts/customdirectory/tests/test_third.py @@ -1,4 +1,7 @@ # mypy: allow-untyped-defs # content of test_third.py +from __future__ import annotations + + def test_3(): pass diff --git a/testing/example_scripts/dataclasses/test_compare_dataclasses.py b/testing/example_scripts/dataclasses/test_compare_dataclasses.py index d96c90a91bd..18180b99f2d 100644 --- a/testing/example_scripts/dataclasses/test_compare_dataclasses.py +++ b/testing/example_scripts/dataclasses/test_compare_dataclasses.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from dataclasses import dataclass from dataclasses import field diff --git a/testing/example_scripts/dataclasses/test_compare_dataclasses_field_comparison_off.py b/testing/example_scripts/dataclasses/test_compare_dataclasses_field_comparison_off.py index 7479c66c1be..0dcc7ab2802 100644 --- a/testing/example_scripts/dataclasses/test_compare_dataclasses_field_comparison_off.py +++ b/testing/example_scripts/dataclasses/test_compare_dataclasses_field_comparison_off.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from dataclasses import dataclass from dataclasses import field diff --git a/testing/example_scripts/dataclasses/test_compare_dataclasses_verbose.py b/testing/example_scripts/dataclasses/test_compare_dataclasses_verbose.py index 4737ef904e0..4985c69ff30 100644 --- a/testing/example_scripts/dataclasses/test_compare_dataclasses_verbose.py +++ b/testing/example_scripts/dataclasses/test_compare_dataclasses_verbose.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from dataclasses import dataclass from dataclasses import field diff --git a/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py b/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py index e026fe3d192..b787cb39ee2 100644 --- a/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py +++ b/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from dataclasses import dataclass from dataclasses import field diff --git a/testing/example_scripts/dataclasses/test_compare_initvar.py b/testing/example_scripts/dataclasses/test_compare_initvar.py index d687fc22530..fc589e1fde4 100644 --- a/testing/example_scripts/dataclasses/test_compare_initvar.py +++ b/testing/example_scripts/dataclasses/test_compare_initvar.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from dataclasses import dataclass from dataclasses import InitVar diff --git a/testing/example_scripts/dataclasses/test_compare_recursive_dataclasses.py b/testing/example_scripts/dataclasses/test_compare_recursive_dataclasses.py index 801aa0a732e..885edd7d9d7 100644 --- a/testing/example_scripts/dataclasses/test_compare_recursive_dataclasses.py +++ b/testing/example_scripts/dataclasses/test_compare_recursive_dataclasses.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from dataclasses import dataclass diff --git a/testing/example_scripts/dataclasses/test_compare_two_different_dataclasses.py b/testing/example_scripts/dataclasses/test_compare_two_different_dataclasses.py index 0a4820c69ba..b45a6772c59 100644 --- a/testing/example_scripts/dataclasses/test_compare_two_different_dataclasses.py +++ b/testing/example_scripts/dataclasses/test_compare_two_different_dataclasses.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from dataclasses import dataclass from dataclasses import field diff --git a/testing/example_scripts/doctest/main_py/__main__.py b/testing/example_scripts/doctest/main_py/__main__.py index c8a124f5416..3a0f6bed1d6 100644 --- a/testing/example_scripts/doctest/main_py/__main__.py +++ b/testing/example_scripts/doctest/main_py/__main__.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_this_is_ignored(): assert True diff --git a/testing/example_scripts/doctest/main_py/test_normal_module.py b/testing/example_scripts/doctest/main_py/test_normal_module.py index 26a4d90bc89..8c150da5c02 100644 --- a/testing/example_scripts/doctest/main_py/test_normal_module.py +++ b/testing/example_scripts/doctest/main_py/test_normal_module.py @@ -1,4 +1,7 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_doc(): """ >>> 10 > 5 diff --git a/testing/example_scripts/fixtures/custom_item/conftest.py b/testing/example_scripts/fixtures/custom_item/conftest.py index fe1ae620aa6..274ab97d01b 100644 --- a/testing/example_scripts/fixtures/custom_item/conftest.py +++ b/testing/example_scripts/fixtures/custom_item/conftest.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/custom_item/foo/test_foo.py b/testing/example_scripts/fixtures/custom_item/foo/test_foo.py index 2809d0cc689..38c51e586fc 100644 --- a/testing/example_scripts/fixtures/custom_item/foo/test_foo.py +++ b/testing/example_scripts/fixtures/custom_item/foo/test_foo.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test(): pass diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/conftest.py index 3a5d3ac33fe..94eaa3e0796 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/conftest.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/test_in_sub1.py b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/test_in_sub1.py index d0c4bdbdfd9..cb3f9fbf469 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/test_in_sub1.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub1/test_in_sub1.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_1(arg1): pass diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/conftest.py index a1f3b2d58b9..112d1e05f27 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/conftest.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/test_in_sub2.py b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/test_in_sub2.py index 45e9744786a..3dea97f544c 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/test_in_sub2.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_conftest_funcargs_only_available_in_subdir/sub2/test_in_sub2.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_2(arg2): pass diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_detect_recursive_dependency_error.py b/testing/example_scripts/fixtures/fill_fixtures/test_detect_recursive_dependency_error.py index 84e5256f070..d90961ae3c4 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_detect_recursive_dependency_error.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_detect_recursive_dependency_error.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/conftest.py index 7f1769beb9b..b4fcc17bfc7 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/conftest.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/conftest.py index ad26fdd8cdc..b933b70edf3 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/conftest.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/test_spam.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/test_spam.py index 9ee74a47186..d31ab971f2b 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/test_spam.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_conftest/pkg/test_spam.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_spam(spam): assert spam == "spamspam" diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/conftest.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/conftest.py index 7f1769beb9b..b4fcc17bfc7 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/conftest.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/conftest.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/test_extend_fixture_conftest_module.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/test_extend_fixture_conftest_module.py index fa688f0a844..2d6d7faef61 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/test_extend_fixture_conftest_module.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_conftest_module/test_extend_fixture_conftest_module.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_module_class.py b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_module_class.py index f78a57c322b..45e5deaafea 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_module_class.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_extend_fixture_module_class.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_basic.py b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_basic.py index 12e0e3e91d4..1c7a710cd0c 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_basic.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_basic.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py index 8b6e8697e06..96f0cacfafd 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_classlevel.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_modulelevel.py b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_modulelevel.py index 40587cf2bd1..b78ca04b3ab 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_modulelevel.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookup_modulelevel.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookupfails.py b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookupfails.py index 0cc8446d8ee..0dd782e4285 100644 --- a/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookupfails.py +++ b/testing/example_scripts/fixtures/fill_fixtures/test_funcarg_lookupfails.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/test_fixture_named_request.py b/testing/example_scripts/fixtures/test_fixture_named_request.py index a2ab7ee330d..db88bcdabb9 100644 --- a/testing/example_scripts/fixtures/test_fixture_named_request.py +++ b/testing/example_scripts/fixtures/test_fixture_named_request.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/fixtures/test_getfixturevalue_dynamic.py b/testing/example_scripts/fixtures/test_getfixturevalue_dynamic.py index 0f316f0e449..0559905cea4 100644 --- a/testing/example_scripts/fixtures/test_getfixturevalue_dynamic.py +++ b/testing/example_scripts/fixtures/test_getfixturevalue_dynamic.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/issue88_initial_file_multinodes/conftest.py b/testing/example_scripts/issue88_initial_file_multinodes/conftest.py index bde5c0711ac..2e88c5ad5a9 100644 --- a/testing/example_scripts/issue88_initial_file_multinodes/conftest.py +++ b/testing/example_scripts/issue88_initial_file_multinodes/conftest.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/issue88_initial_file_multinodes/test_hello.py b/testing/example_scripts/issue88_initial_file_multinodes/test_hello.py index dd18e1741f0..b10f874e78d 100644 --- a/testing/example_scripts/issue88_initial_file_multinodes/test_hello.py +++ b/testing/example_scripts/issue88_initial_file_multinodes/test_hello.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_hello(): pass diff --git a/testing/example_scripts/issue_519.py b/testing/example_scripts/issue_519.py index 39766164490..138c07e95be 100644 --- a/testing/example_scripts/issue_519.py +++ b/testing/example_scripts/issue_519.py @@ -1,7 +1,7 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pprint -from typing import List -from typing import Tuple import pytest @@ -16,7 +16,7 @@ def pytest_generate_tests(metafunc): @pytest.fixture(scope="session") def checked_order(): - order: List[Tuple[str, str, str]] = [] + order: list[tuple[str, str, str]] = [] yield order pprint.pprint(order) diff --git a/testing/example_scripts/marks/marks_considered_keywords/test_marks_as_keywords.py b/testing/example_scripts/marks/marks_considered_keywords/test_marks_as_keywords.py index d95ad0a83d9..c98e58316eb 100644 --- a/testing/example_scripts/marks/marks_considered_keywords/test_marks_as_keywords.py +++ b/testing/example_scripts/marks/marks_considered_keywords/test_marks_as_keywords.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/perf_examples/collect_stats/generate_folders.py b/testing/example_scripts/perf_examples/collect_stats/generate_folders.py index 17085e50b54..3b580aa341a 100644 --- a/testing/example_scripts/perf_examples/collect_stats/generate_folders.py +++ b/testing/example_scripts/perf_examples/collect_stats/generate_folders.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import argparse import pathlib diff --git a/testing/example_scripts/perf_examples/collect_stats/template_test.py b/testing/example_scripts/perf_examples/collect_stats/template_test.py index f50eb65525c..d9449485db6 100644 --- a/testing/example_scripts/perf_examples/collect_stats/template_test.py +++ b/testing/example_scripts/perf_examples/collect_stats/template_test.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_x(): pass diff --git a/testing/example_scripts/tmpdir/tmp_path_fixture.py b/testing/example_scripts/tmpdir/tmp_path_fixture.py index 4aa35faa0b6..503ead473e7 100644 --- a/testing/example_scripts/tmpdir/tmp_path_fixture.py +++ b/testing/example_scripts/tmpdir/tmp_path_fixture.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/example_scripts/unittest/test_parametrized_fixture_error_message.py b/testing/example_scripts/unittest/test_parametrized_fixture_error_message.py index d66b66df5b7..733202915e4 100644 --- a/testing/example_scripts/unittest/test_parametrized_fixture_error_message.py +++ b/testing/example_scripts/unittest/test_parametrized_fixture_error_message.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import unittest import pytest diff --git a/testing/example_scripts/unittest/test_setup_skip.py b/testing/example_scripts/unittest/test_setup_skip.py index 7550a097576..52ff96ea8be 100644 --- a/testing/example_scripts/unittest/test_setup_skip.py +++ b/testing/example_scripts/unittest/test_setup_skip.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Skipping an entire subclass with unittest.skip() should *not* call setUp from a base class.""" +from __future__ import annotations + import unittest diff --git a/testing/example_scripts/unittest/test_setup_skip_class.py b/testing/example_scripts/unittest/test_setup_skip_class.py index 48f7e476f40..fe431d8e794 100644 --- a/testing/example_scripts/unittest/test_setup_skip_class.py +++ b/testing/example_scripts/unittest/test_setup_skip_class.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Skipping an entire subclass with unittest.skip() should *not* call setUpClass from a base class.""" +from __future__ import annotations + import unittest diff --git a/testing/example_scripts/unittest/test_setup_skip_module.py b/testing/example_scripts/unittest/test_setup_skip_module.py index eee4263d22b..07fd96c9cef 100644 --- a/testing/example_scripts/unittest/test_setup_skip_module.py +++ b/testing/example_scripts/unittest/test_setup_skip_module.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """setUpModule is always called, even if all tests in the module are skipped""" +from __future__ import annotations + import unittest diff --git a/testing/example_scripts/unittest/test_unittest_asyncio.py b/testing/example_scripts/unittest/test_unittest_asyncio.py index a82ddaebcc3..8792492b38d 100644 --- a/testing/example_scripts/unittest/test_unittest_asyncio.py +++ b/testing/example_scripts/unittest/test_unittest_asyncio.py @@ -1,9 +1,10 @@ # mypy: allow-untyped-defs -from typing import List +from __future__ import annotations + from unittest import IsolatedAsyncioTestCase -teardowns: List[None] = [] +teardowns: list[None] = [] class AsyncArguments(IsolatedAsyncioTestCase): diff --git a/testing/example_scripts/unittest/test_unittest_asynctest.py b/testing/example_scripts/unittest/test_unittest_asynctest.py index e9b10171e8d..8a93366b9a3 100644 --- a/testing/example_scripts/unittest/test_unittest_asynctest.py +++ b/testing/example_scripts/unittest/test_unittest_asynctest.py @@ -1,13 +1,14 @@ # mypy: allow-untyped-defs """Issue #7110""" +from __future__ import annotations + import asyncio -from typing import List import asynctest -teardowns: List[None] = [] +teardowns: list[None] = [] class Test(asynctest.TestCase): diff --git a/testing/example_scripts/unittest/test_unittest_plain_async.py b/testing/example_scripts/unittest/test_unittest_plain_async.py index 2a4a66509a4..ea1ae371551 100644 --- a/testing/example_scripts/unittest/test_unittest_plain_async.py +++ b/testing/example_scripts/unittest/test_unittest_plain_async.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import unittest diff --git a/testing/example_scripts/warnings/test_group_warnings_by_message.py b/testing/example_scripts/warnings/test_group_warnings_by_message.py index be64a1ff2c8..ee3bc2bbee4 100644 --- a/testing/example_scripts/warnings/test_group_warnings_by_message.py +++ b/testing/example_scripts/warnings/test_group_warnings_by_message.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import warnings import pytest diff --git a/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_1.py b/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_1.py index 95fa795efe0..cc514bafbe9 100644 --- a/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_1.py +++ b/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_1.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import warnings import pytest diff --git a/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_2.py b/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_2.py index 5204fde8a85..33d5ce8ce34 100644 --- a/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_2.py +++ b/testing/example_scripts/warnings/test_group_warnings_by_message_summary/test_2.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from test_1 import func diff --git a/testing/examples/test_issue519.py b/testing/examples/test_issue519.py index 7b9c109889e..80f78d843a2 100644 --- a/testing/examples/test_issue519.py +++ b/testing/examples/test_issue519.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from _pytest.pytester import Pytester diff --git a/testing/freeze/create_executable.py b/testing/freeze/create_executable.py index fbfda2e5d94..2015d22c7c0 100644 --- a/testing/freeze/create_executable.py +++ b/testing/freeze/create_executable.py @@ -1,5 +1,8 @@ """Generate an executable with pytest runner embedded using PyInstaller.""" +from __future__ import annotations + + if __name__ == "__main__": import subprocess diff --git a/testing/freeze/runtests_script.py b/testing/freeze/runtests_script.py index ef63a2d15b9..286c98ac539 100644 --- a/testing/freeze/runtests_script.py +++ b/testing/freeze/runtests_script.py @@ -3,6 +3,9 @@ pytest main(). """ +from __future__ import annotations + + if __name__ == "__main__": import sys diff --git a/testing/freeze/tests/test_trivial.py b/testing/freeze/tests/test_trivial.py index 425f29a649c..000ca97310c 100644 --- a/testing/freeze/tests/test_trivial.py +++ b/testing/freeze/tests/test_trivial.py @@ -1,4 +1,7 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_upper(): assert "foo".upper() == "FOO" diff --git a/testing/freeze/tox_run.py b/testing/freeze/tox_run.py index 1230fcce140..38c1e75cf10 100644 --- a/testing/freeze/tox_run.py +++ b/testing/freeze/tox_run.py @@ -3,6 +3,9 @@ directory. """ +from __future__ import annotations + + if __name__ == "__main__": import os import sys diff --git a/testing/io/test_pprint.py b/testing/io/test_pprint.py index 15fe6611280..1326ef34b2e 100644 --- a/testing/io/test_pprint.py +++ b/testing/io/test_pprint.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from collections import ChainMap from collections import Counter from collections import defaultdict diff --git a/testing/io/test_saferepr.py b/testing/io/test_saferepr.py index f627434c4e9..075d40cdf44 100644 --- a/testing/io/test_saferepr.py +++ b/testing/io/test_saferepr.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import saferepr from _pytest._io.saferepr import saferepr_unlimited diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index afa8d5cae87..043c2d1d904 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import io import os from pathlib import Path @@ -6,7 +8,6 @@ import shutil import sys from typing import Generator -from typing import Optional from unittest import mock from _pytest._io import terminalwriter @@ -166,7 +167,7 @@ def test_attr_hasmarkup() -> None: assert "\x1b[0m" in s -def assert_color(expected: bool, default: Optional[bool] = None) -> None: +def assert_color(expected: bool, default: bool | None = None) -> None: file = io.StringIO() if default is None: default = not expected diff --git a/testing/io/test_wcwidth.py b/testing/io/test_wcwidth.py index 82503b8300c..9ff1ad06e60 100644 --- a/testing/io/test_wcwidth.py +++ b/testing/io/test_wcwidth.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from _pytest._io.wcwidth import wcswidth from _pytest._io.wcwidth import wcwidth import pytest diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index c1cfff632af..0603eaba218 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -1,5 +1,7 @@ # mypy: disable-error-code="attr-defined" # mypy: disallow-untyped-defs +from __future__ import annotations + import logging from typing import Iterator diff --git a/testing/logging/test_formatter.py b/testing/logging/test_formatter.py index 37971293726..cfe3bee68c4 100644 --- a/testing/logging/test_formatter.py +++ b/testing/logging/test_formatter.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging from typing import Any diff --git a/testing/logging/test_reporting.py b/testing/logging/test_reporting.py index 7e592febf56..cf54788e246 100644 --- a/testing/logging/test_reporting.py +++ b/testing/logging/test_reporting.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import io import os import re diff --git a/testing/plugins_integration/bdd_wallet.py b/testing/plugins_integration/bdd_wallet.py index 2bdb1545424..d748028842a 100644 --- a/testing/plugins_integration/bdd_wallet.py +++ b/testing/plugins_integration/bdd_wallet.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from pytest_bdd import given from pytest_bdd import scenario from pytest_bdd import then diff --git a/testing/plugins_integration/django_settings.py b/testing/plugins_integration/django_settings.py index 0715f476531..e36e554db9a 100644 --- a/testing/plugins_integration/django_settings.py +++ b/testing/plugins_integration/django_settings.py @@ -1 +1,4 @@ +from __future__ import annotations + + SECRET_KEY = "mysecret" diff --git a/testing/plugins_integration/pytest_anyio_integration.py b/testing/plugins_integration/pytest_anyio_integration.py index 383d7a0b5db..41ffad18a6e 100644 --- a/testing/plugins_integration/pytest_anyio_integration.py +++ b/testing/plugins_integration/pytest_anyio_integration.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import anyio import pytest diff --git a/testing/plugins_integration/pytest_asyncio_integration.py b/testing/plugins_integration/pytest_asyncio_integration.py index b216c4beecd..cef67f83ea6 100644 --- a/testing/plugins_integration/pytest_asyncio_integration.py +++ b/testing/plugins_integration/pytest_asyncio_integration.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import asyncio import pytest diff --git a/testing/plugins_integration/pytest_mock_integration.py b/testing/plugins_integration/pytest_mock_integration.py index 5494c44270a..a49129cf0c9 100644 --- a/testing/plugins_integration/pytest_mock_integration.py +++ b/testing/plugins_integration/pytest_mock_integration.py @@ -1,3 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + + def test_mocker(mocker): mocker.MagicMock() diff --git a/testing/plugins_integration/pytest_rerunfailures_integration.py b/testing/plugins_integration/pytest_rerunfailures_integration.py index 9a13a3279a9..449661f7294 100644 --- a/testing/plugins_integration/pytest_rerunfailures_integration.py +++ b/testing/plugins_integration/pytest_rerunfailures_integration.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import unittest diff --git a/testing/plugins_integration/pytest_trio_integration.py b/testing/plugins_integration/pytest_trio_integration.py index 60f48ec609b..eceac5076a9 100644 --- a/testing/plugins_integration/pytest_trio_integration.py +++ b/testing/plugins_integration/pytest_trio_integration.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import trio import pytest diff --git a/testing/plugins_integration/pytest_twisted_integration.py b/testing/plugins_integration/pytest_twisted_integration.py index 0dbf5faeb8a..4f386bf1b9f 100644 --- a/testing/plugins_integration/pytest_twisted_integration.py +++ b/testing/plugins_integration/pytest_twisted_integration.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest_twisted from twisted.internet.task import deferLater diff --git a/testing/plugins_integration/simple_integration.py b/testing/plugins_integration/simple_integration.py index 48089afcc7e..ed504ae4bf1 100644 --- a/testing/plugins_integration/simple_integration.py +++ b/testing/plugins_integration/simple_integration.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import pytest diff --git a/testing/python/approx.py b/testing/python/approx.py index 31e64c4df3d..69743cdbe17 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from contextlib import contextmanager from decimal import Decimal from fractions import Fraction @@ -6,7 +8,6 @@ import operator from operator import eq from operator import ne -from typing import Optional from _pytest.pytester import Pytester from _pytest.python_api import _recursive_sequence_map @@ -415,9 +416,7 @@ def test_zero_tolerance(self): (-1e100, -1e100), ], ) - def test_negative_tolerance( - self, rel: Optional[float], abs: Optional[float] - ) -> None: + def test_negative_tolerance(self, rel: float | None, abs: float | None) -> None: # Negative tolerances are not allowed. with pytest.raises(ValueError): 1.1 == approx(1, rel, abs) diff --git a/testing/python/collect.py b/testing/python/collect.py index 843fa3c0e6b..06386611279 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -1,9 +1,10 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os import sys import textwrap from typing import Any -from typing import Dict import _pytest._code from _pytest.config import ExitCode @@ -1129,7 +1130,7 @@ def test_filter_traceback_generated_code(self) -> None: tb = None try: - ns: Dict[str, Any] = {} + ns: dict[str, Any] = {} exec("def foo(): raise ValueError", ns) ns["foo"]() except ValueError: diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index d3cff38f977..bc091bb1f27 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os from pathlib import Path import sys @@ -4514,7 +4516,7 @@ def test_fixture_named_request(pytester: Pytester) -> None: result.stdout.fnmatch_lines( [ "*'request' is a reserved word for fixtures, use another name:", - " *test_fixture_named_request.py:6", + " *test_fixture_named_request.py:8", ] ) diff --git a/testing/python/integration.py b/testing/python/integration.py index c20aaeed839..c52a683a322 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from _pytest._code import getfslineno from _pytest.fixtures import getfixturemarker from _pytest.pytester import Pytester diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 3d0058fa0a7..2dd85607e71 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import dataclasses import itertools import re @@ -8,11 +10,7 @@ from typing import cast from typing import Dict from typing import Iterator -from typing import List -from typing import Optional from typing import Sequence -from typing import Tuple -from typing import Union import hypothesis from hypothesis import strategies @@ -35,7 +33,7 @@ def Metafunc(self, func, config=None) -> python.Metafunc: # on the funcarg level, so we don't need a full blown # initialization. class FuncFixtureInfoMock: - name2fixturedefs: Dict[str, List[fixtures.FixtureDef[object]]] = {} + name2fixturedefs: dict[str, list[fixtures.FixtureDef[object]]] = {} def __init__(self, names): self.names_closure = names @@ -101,7 +99,7 @@ class Exc(Exception): def __repr__(self): return "Exc(from_gen)" - def gen() -> Iterator[Union[int, None, Exc]]: + def gen() -> Iterator[int | None | Exc]: yield 0 yield None yield Exc() @@ -346,7 +344,7 @@ def getini(self, name): option = "disable_test_id_escaping_and_forfeit_all_rights_to_community_support" - values: List[Tuple[str, Any, str]] = [ + values: list[tuple[str, Any, str]] = [ ("ação", MockConfig({option: True}), "ação"), ("ação", MockConfig({option: False}), "a\\xe7\\xe3o"), ] @@ -516,7 +514,7 @@ def test_idmaker_enum(self) -> None: def test_idmaker_idfn(self) -> None: """#351""" - def ids(val: object) -> Optional[str]: + def ids(val: object) -> str | None: if isinstance(val, Exception): return repr(val) return None @@ -579,7 +577,7 @@ def getini(self, name): option = "disable_test_id_escaping_and_forfeit_all_rights_to_community_support" - values: List[Tuple[Any, str]] = [ + values: list[tuple[Any, str]] = [ (MockConfig({option: True}), "ação"), (MockConfig({option: False}), "a\\xe7\\xe3o"), ] @@ -617,7 +615,7 @@ def getini(self, name): option = "disable_test_id_escaping_and_forfeit_all_rights_to_community_support" - values: List[Tuple[Any, str]] = [ + values: list[tuple[Any, str]] = [ (MockConfig({option: True}), "ação"), (MockConfig({option: False}), "a\\xe7\\xe3o"), ] @@ -1748,9 +1746,9 @@ def test_parametrize_some_arguments_auto_scope( self, pytester: Pytester, monkeypatch ) -> None: """Integration test for (#3941)""" - class_fix_setup: List[object] = [] + class_fix_setup: list[object] = [] monkeypatch.setattr(sys, "class_fix_setup", class_fix_setup, raising=False) - func_fix_setup: List[object] = [] + func_fix_setup: list[object] = [] monkeypatch.setattr(sys, "func_fix_setup", func_fix_setup, raising=False) pytester.makepyfile( diff --git a/testing/python/raises.py b/testing/python/raises.py index 929865e31a0..271dd3e5a8c 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import re import sys diff --git a/testing/python/show_fixtures_per_test.py b/testing/python/show_fixtures_per_test.py index f756dca41c7..c860b61e21b 100644 --- a/testing/python/show_fixtures_per_test.py +++ b/testing/python/show_fixtures_per_test.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from _pytest.pytester import Pytester diff --git a/testing/test_argcomplete.py b/testing/test_argcomplete.py index 0c41c0286a4..5d1513b6206 100644 --- a/testing/test_argcomplete.py +++ b/testing/test_argcomplete.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from pathlib import Path import subprocess import sys diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 726235999b4..d4325ab4b62 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1,11 +1,11 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import sys import textwrap from typing import Any -from typing import List from typing import MutableSequence from typing import NamedTuple -from typing import Optional import attr @@ -19,7 +19,7 @@ import pytest -def mock_config(verbose: int = 0, assertion_override: Optional[int] = None): +def mock_config(verbose: int = 0, assertion_override: int | None = None): class TerminalWriter: def _highlight(self, source, lexer="python"): return source @@ -28,7 +28,7 @@ class Config: def get_terminal_writer(self): return TerminalWriter() - def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: + def get_verbosity(self, verbosity_type: str | None = None) -> int: if verbosity_type is None: return verbose if verbosity_type == _Config.VERBOSITY_ASSERTIONS: @@ -369,12 +369,12 @@ def test_check(list): result.stdout.fnmatch_lines(["*test_hello*FAIL*", "*test_check*PASS*"]) -def callop(op: str, left: Any, right: Any, verbose: int = 0) -> Optional[List[str]]: +def callop(op: str, left: Any, right: Any, verbose: int = 0) -> list[str] | None: config = mock_config(verbose=verbose) return plugin.pytest_assertrepr_compare(config, op, left, right) -def callequal(left: Any, right: Any, verbose: int = 0) -> Optional[List[str]]: +def callequal(left: Any, right: Any, verbose: int = 0) -> list[str] | None: return callop("==", left, right, verbose) @@ -1316,7 +1316,7 @@ class TestTruncateExplanation: LINES_IN_TRUNCATION_MSG = 2 def test_doesnt_truncate_when_input_is_empty_list(self) -> None: - expl: List[str] = [] + expl: list[str] = [] result = truncate._truncate_explanation(expl, max_lines=8, max_chars=100) assert result == expl diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 8db9dbbe5ff..185cd5ef2eb 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import ast import errno from functools import partial @@ -12,12 +14,8 @@ import sys import textwrap from typing import cast -from typing import Dict from typing import Generator -from typing import List from typing import Mapping -from typing import Optional -from typing import Set from unittest import mock import zipfile @@ -45,13 +43,13 @@ def rewrite(src: str) -> ast.Module: def getmsg( - f, extra_ns: Optional[Mapping[str, object]] = None, *, must_pass: bool = False -) -> Optional[str]: + f, extra_ns: Mapping[str, object] | None = None, *, must_pass: bool = False +) -> str | None: """Rewrite the assertions in f, run it, and get the failure message.""" src = "\n".join(_pytest._code.Code.from_function(f).source().lines) mod = rewrite(src) code = compile(mod, "", "exec") - ns: Dict[str, object] = {} + ns: dict[str, object] = {} if extra_ns is not None: ns.update(extra_ns) exec(code, ns) @@ -1638,8 +1636,8 @@ def hook( """ import importlib.machinery - self.find_spec_calls: List[str] = [] - self.initial_paths: Set[Path] = set() + self.find_spec_calls: list[str] = [] + self.initial_paths: set[Path] = set() class StubSession: _initialpaths = self.initial_paths @@ -2059,7 +2057,7 @@ class TestReprSizeVerbosity: ) def test_get_maxsize_for_saferepr(self, verbose: int, expected_size) -> None: class FakeConfig: - def get_verbosity(self, verbosity_type: Optional[str] = None) -> int: + def get_verbosity(self, verbosity_type: str | None = None) -> int: return verbose config = FakeConfig() diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 08158f6191a..72b4265cf75 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from enum import auto from enum import Enum import os @@ -5,9 +7,7 @@ import shutil from typing import Any from typing import Generator -from typing import List from typing import Sequence -from typing import Tuple from _pytest.compat import assert_never from _pytest.config import ExitCode @@ -579,7 +579,7 @@ def test_pass(): def rlf( fail_import: int, fail_run: int, args: Sequence[str] = () - ) -> Tuple[Any, Any]: + ) -> tuple[Any, Any]: monkeypatch.setenv("FAILIMPORT", str(fail_import)) monkeypatch.setenv("FAILTEST", str(fail_run)) @@ -693,7 +693,7 @@ def test_lf_and_ff_prints_no_needless_message( else: assert "rerun previous" in result.stdout.str() - def get_cached_last_failed(self, pytester: Pytester) -> List[str]: + def get_cached_last_failed(self, pytester: Pytester) -> list[str]: config = pytester.parseconfigure() assert config.cache is not None return sorted(config.cache.get("cache/lastfailed", {})) diff --git a/testing/test_capture.py b/testing/test_capture.py index b6c206ec47c..fe6bd7d14fa 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import contextlib import io from io import UnsupportedOperation diff --git a/testing/test_collection.py b/testing/test_collection.py index 8ff38a334f4..821c424196f 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os from pathlib import Path import pprint @@ -6,8 +8,6 @@ import sys import tempfile import textwrap -from typing import List -from typing import Type from _pytest.assertion.util import running_on_ci from _pytest.config import ExitCode @@ -536,7 +536,7 @@ def test_collect_topdir(self, pytester: Pytester) -> None: assert len(colitems) == 1 assert colitems[0].path == topdir - def get_reported_items(self, hookrec: HookRecorder) -> List[Item]: + def get_reported_items(self, hookrec: HookRecorder) -> list[Item]: """Return pytest.Item instances reported by the pytest_collectreport hook""" calls = hookrec.getcalls("pytest_collectreport") return [ @@ -1885,7 +1885,7 @@ def test_do_not_collect_symlink_siblings( ) def test_respect_system_exceptions( pytester: Pytester, - exception_class: Type[BaseException], + exception_class: type[BaseException], msg: str, ): head = "Before exception" diff --git a/testing/test_compat.py b/testing/test_compat.py index 73ac1bad858..2c6b0269c27 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -1,11 +1,12 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import enum from functools import cached_property from functools import partial from functools import wraps import sys from typing import TYPE_CHECKING -from typing import Union from _pytest.compat import _PytestWrapper from _pytest.compat import assert_never @@ -216,7 +217,7 @@ def prop(self) -> int: def test_assert_never_union() -> None: - x: Union[int, str] = 10 + x: int | str = 10 if isinstance(x, int): pass diff --git a/testing/test_config.py b/testing/test_config.py index 1cb31fed06d..232839399e2 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import dataclasses import importlib.metadata import os @@ -7,12 +9,7 @@ import sys import textwrap from typing import Any -from typing import Dict -from typing import List from typing import Sequence -from typing import Tuple -from typing import Type -from typing import Union import _pytest._code from _pytest.config import _get_plugin_specs_as_list @@ -633,7 +630,7 @@ def test_absolute_win32_path(self, pytester: Pytester) -> None: class TestConfigAPI: def test_config_trace(self, pytester: Pytester) -> None: config = pytester.parseconfig() - values: List[str] = [] + values: list[str] = [] config.trace.root.setwriter(values.append) config.trace("hello") assert len(values) == 1 @@ -996,7 +993,7 @@ def test_basic_behavior(self, _sys_snapshot) -> None: def test_invocation_params_args(self, _sys_snapshot) -> None: """Show that fromdictargs can handle args in their "orig" format""" - option_dict: Dict[str, object] = {} + option_dict: dict[str, object] = {} args = ["-vvvv", "-s", "a", "b"] config = Config.fromdictargs(option_dict, args) @@ -1210,7 +1207,7 @@ def distributions(): def test_disable_plugin_autoload( pytester: Pytester, monkeypatch: MonkeyPatch, - parse_args: Union[Tuple[str, str], Tuple[()]], + parse_args: tuple[str, str] | tuple[()], should_load: bool, ) -> None: class DummyEntryPoint: @@ -1304,7 +1301,7 @@ def test_invalid_options_show_extra_information(pytester: Pytester) -> None: ], ) def test_consider_args_after_options_for_rootdir( - pytester: Pytester, args: List[str] + pytester: Pytester, args: list[str] ) -> None: """ Consider all arguments in the command-line for rootdir @@ -2241,7 +2238,7 @@ def test_strtobool() -> None: ], ) def test_parse_warning_filter( - arg: str, escape: bool, expected: Tuple[str, str, Type[Warning], str, int] + arg: str, escape: bool, expected: tuple[str, str, type[Warning], str, int] ) -> None: assert parse_warning_filter(arg, escape=escape) == expected diff --git a/testing/test_conftest.py b/testing/test_conftest.py index eb3ebecdc98..d51846f2f5f 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,14 +1,13 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os from pathlib import Path import textwrap from typing import cast -from typing import Dict from typing import Generator from typing import List -from typing import Optional from typing import Sequence -from typing import Union from _pytest.config import ExitCode from _pytest.config import PytestPluginManager @@ -27,8 +26,8 @@ def ConftestWithSetinitial(path) -> PytestPluginManager: def conftest_setinitial( conftest: PytestPluginManager, - args: Sequence[Union[str, Path]], - confcutdir: Optional[Path] = None, + args: Sequence[str | Path], + confcutdir: Path | None = None, ) -> None: conftest._set_initial_conftests( args=args, @@ -536,7 +535,7 @@ def pytest_addoption(parser): class TestConftestVisibility: - def _setup_tree(self, pytester: Pytester) -> Dict[str, Path]: # for issue616 + def _setup_tree(self, pytester: Pytester) -> dict[str, Path]: # for issue616 # example mostly taken from: # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html runner = pytester.mkdir("empty") diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 1f3422947de..37032f92354 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import sys -from typing import List import _pytest._code from _pytest.debugging import _validate_usepdb_cls @@ -35,7 +36,7 @@ def runpdb_and_get_report(pytester: Pytester, source: str): @pytest.fixture -def custom_pdb_calls() -> List[str]: +def custom_pdb_calls() -> list[str]: called = [] # install dummy debugger class and track which methods were called on it @@ -854,7 +855,7 @@ def test_post_mortem(): self.flush(child) def test_pdb_custom_cls( - self, pytester: Pytester, custom_pdb_calls: List[str] + self, pytester: Pytester, custom_pdb_calls: list[str] ) -> None: p1 = pytester.makepyfile("""xxx """) result = pytester.runpytest_inprocess( @@ -880,7 +881,7 @@ def test_pdb_validate_usepdb_cls(self): assert _validate_usepdb_cls("pdb:DoesNotExist") == ("pdb", "DoesNotExist") def test_pdb_custom_cls_without_pdb( - self, pytester: Pytester, custom_pdb_calls: List[str] + self, pytester: Pytester, custom_pdb_calls: list[str] ) -> None: p1 = pytester.makepyfile("""xxx """) result = pytester.runpytest_inprocess("--pdbcls=_pytest:_CustomPdb", p1) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 9b33d641a14..4aa4876c711 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,10 +1,11 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import inspect from pathlib import Path import sys import textwrap from typing import Callable -from typing import Optional from _pytest.doctest import _get_checker from _pytest.doctest import _is_main_py @@ -1595,7 +1596,7 @@ def __getattr__(self, _): "stop", [None, _is_mocked, lambda f: None, lambda f: False, lambda f: True] ) def test_warning_on_unwrap_of_broken_object( - stop: Optional[Callable[[object], object]], + stop: Callable[[object], object] | None, ) -> None: bad_instance = Broken() assert inspect.unwrap.__module__ == "inspect" diff --git a/testing/test_entry_points.py b/testing/test_entry_points.py index 68e3a8a92e4..543f3252b22 100644 --- a/testing/test_entry_points.py +++ b/testing/test_entry_points.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import importlib.metadata diff --git a/testing/test_error_diffs.py b/testing/test_error_diffs.py index f290eb1679f..741a6ca82d0 100644 --- a/testing/test_error_diffs.py +++ b/testing/test_error_diffs.py @@ -5,6 +5,8 @@ """ +from __future__ import annotations + from _pytest.pytester import Pytester import pytest diff --git a/testing/test_faulthandler.py b/testing/test_faulthandler.py index e5016976130..c416e81d2d9 100644 --- a/testing/test_faulthandler.py +++ b/testing/test_faulthandler.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import io import sys diff --git a/testing/test_findpaths.py b/testing/test_findpaths.py index 260b9d07c9c..9532f1eef75 100644 --- a/testing/test_findpaths.py +++ b/testing/test_findpaths.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os from pathlib import Path from textwrap import dedent diff --git a/testing/test_helpconfig.py b/testing/test_helpconfig.py index 4906ef5c8f0..daf2bb12714 100644 --- a/testing/test_helpconfig.py +++ b/testing/test_helpconfig.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from _pytest.config import ExitCode from _pytest.pytester import Pytester import pytest diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 1ebc3ed3a51..67234302a89 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1,14 +1,12 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from datetime import datetime import os from pathlib import Path import platform from typing import cast -from typing import List -from typing import Optional -from typing import Tuple from typing import TYPE_CHECKING -from typing import Union from xml.dom import minidom import xmlschema @@ -39,8 +37,8 @@ def __init__(self, pytester: Pytester, schema: xmlschema.XMLSchema) -> None: self.schema = schema def __call__( - self, *args: Union[str, "os.PathLike[str]"], family: Optional[str] = "xunit1" - ) -> Tuple[RunResult, "DomNode"]: + self, *args: str | os.PathLike[str], family: str | None = "xunit1" + ) -> tuple[RunResult, DomNode]: if family: args = ("-o", "junit_family=" + family, *args) xml_path = self.pytester.path.joinpath("junit.xml") @@ -940,7 +938,7 @@ def test_mangle_test_address() -> None: def test_dont_configure_on_workers(tmp_path: Path) -> None: - gotten: List[object] = [] + gotten: list[object] = [] class FakeConfig: if TYPE_CHECKING: @@ -1183,7 +1181,7 @@ def test_unicode_issue368(pytester: Pytester) -> None: class Report(BaseReport): longrepr = ustr - sections: List[Tuple[str, str]] = [] + sections: list[tuple[str, str]] = [] nodeid = "something" location = "tests/filename.py", 42, "TestClass.method" when = "teardown" @@ -1495,7 +1493,7 @@ def test_global_properties(pytester: Pytester, xunit_family: str) -> None: log = LogXML(str(path), None, family=xunit_family) class Report(BaseReport): - sections: List[Tuple[str, str]] = [] + sections: list[tuple[str, str]] = [] nodeid = "test_node_id" log.pytest_sessionstart() @@ -1531,7 +1529,7 @@ def test_url_property(pytester: Pytester) -> None: class Report(BaseReport): longrepr = "FooBarBaz" - sections: List[Tuple[str, str]] = [] + sections: list[tuple[str, str]] = [] nodeid = "something" location = "tests/filename.py", 42, "TestClass.method" url = test_url diff --git a/testing/test_legacypath.py b/testing/test_legacypath.py index d2b33b4fb8b..72854e4e5c0 100644 --- a/testing/test_legacypath.py +++ b/testing/test_legacypath.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from pathlib import Path from _pytest.compat import LEGACY_PATH diff --git a/testing/test_link_resolve.py b/testing/test_link_resolve.py index 0461cd75554..0557dae669d 100644 --- a/testing/test_link_resolve.py +++ b/testing/test_link_resolve.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from contextlib import contextmanager import os.path from pathlib import Path diff --git a/testing/test_main.py b/testing/test_main.py index 6294f66b360..94eac02ce63 100644 --- a/testing/test_main.py +++ b/testing/test_main.py @@ -1,9 +1,10 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import argparse import os from pathlib import Path import re -from typing import Optional from _pytest.config import ExitCode from _pytest.config import UsageError @@ -66,7 +67,7 @@ def pytest_internalerror(excrepr, excinfo): @pytest.mark.parametrize("returncode", (None, 42)) def test_wrap_session_exit_sessionfinish( - returncode: Optional[int], pytester: Pytester + returncode: int | None, pytester: Pytester ) -> None: pytester.makeconftest( f""" diff --git a/testing/test_mark.py b/testing/test_mark.py index 2896afa4532..090e10ee9c4 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1,8 +1,8 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os import sys -from typing import List -from typing import Optional from unittest import mock from _pytest.config import ExitCode @@ -214,7 +214,7 @@ def test_hello(): ], ) def test_mark_option( - expr: str, expected_passed: List[Optional[str]], pytester: Pytester + expr: str, expected_passed: list[str | None], pytester: Pytester ) -> None: pytester.makepyfile( """ @@ -238,7 +238,7 @@ def test_two(): [("interface", ["test_interface"]), ("not interface", ["test_nointer"])], ) def test_mark_option_custom( - expr: str, expected_passed: List[str], pytester: Pytester + expr: str, expected_passed: list[str], pytester: Pytester ) -> None: pytester.makeconftest( """ @@ -276,7 +276,7 @@ def test_nointer(): ], ) def test_keyword_option_custom( - expr: str, expected_passed: List[str], pytester: Pytester + expr: str, expected_passed: list[str], pytester: Pytester ) -> None: pytester.makepyfile( """ @@ -314,7 +314,7 @@ def test_keyword_option_considers_mark(pytester: Pytester) -> None: ], ) def test_keyword_option_parametrize( - expr: str, expected_passed: List[str], pytester: Pytester + expr: str, expected_passed: list[str], pytester: Pytester ) -> None: pytester.makepyfile( """ @@ -895,7 +895,7 @@ def test_ddd(): pass ) monkeypatch.chdir(pytester.path / "suite") - def get_collected_names(*args: str) -> List[str]: + def get_collected_names(*args: str) -> list[str]: _, rec = pytester.inline_genitems(*args) calls = rec.getcalls("pytest_collection_finish") assert len(calls) == 1 @@ -930,7 +930,7 @@ def test_aliases(self) -> None: @pytest.mark.parametrize("mark", [None, "", "skip", "xfail"]) def test_parameterset_for_parametrize_marks( - pytester: Pytester, mark: Optional[str] + pytester: Pytester, mark: str | None ) -> None: if mark is not None: pytester.makeini( diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index 07c89f90838..5bce004cb1c 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Callable from _pytest.mark.expression import Expression diff --git a/testing/test_meta.py b/testing/test_meta.py index 40ed95d6b47..e7d836f7ace 100644 --- a/testing/test_meta.py +++ b/testing/test_meta.py @@ -4,16 +4,17 @@ namespace being set, which is critical for the initialization of xdist. """ +from __future__ import annotations + import pkgutil import subprocess import sys -from typing import List import _pytest import pytest -def _modules() -> List[str]: +def _modules() -> list[str]: pytest_pkg: str = _pytest.__path__ # type: ignore return sorted( n diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 2ad3ccc4ddc..079d8ff60ad 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -1,12 +1,12 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os from pathlib import Path import re import sys import textwrap -from typing import Dict from typing import Generator -from typing import Type from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester @@ -135,7 +135,7 @@ def test_setitem() -> None: def test_setitem_deleted_meanwhile() -> None: - d: Dict[str, object] = {} + d: dict[str, object] = {} monkeypatch = MonkeyPatch() monkeypatch.setitem(d, "x", 2) del d["x"] @@ -160,7 +160,7 @@ def test_setenv_deleted_meanwhile(before: bool) -> None: def test_delitem() -> None: - d: Dict[str, object] = {"x": 1} + d: dict[str, object] = {"x": 1} monkeypatch = MonkeyPatch() monkeypatch.delitem(d, "x") assert "x" not in d @@ -360,7 +360,7 @@ class SampleInherit(Sample): [Sample, SampleInherit], ids=["new", "new-inherit"], ) -def test_issue156_undo_staticmethod(Sample: Type[Sample]) -> None: +def test_issue156_undo_staticmethod(Sample: type[Sample]) -> None: monkeypatch = MonkeyPatch() monkeypatch.setattr(Sample, "hello", None) diff --git a/testing/test_nodes.py b/testing/test_nodes.py index a3caf471f70..f039acf243b 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -1,8 +1,9 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from pathlib import Path import re from typing import cast -from typing import Type import warnings from _pytest import nodes @@ -73,7 +74,7 @@ def runtest(self): "warn_type, msg", [(DeprecationWarning, "deprecated"), (PytestWarning, "pytest")] ) def test_node_warn_is_no_longer_only_pytest_warnings( - pytester: Pytester, warn_type: Type[Warning], msg: str + pytester: Pytester, warn_type: type[Warning], msg: str ) -> None: items = pytester.getitems( """ diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index e959dfd631b..14e2b5f69fb 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import argparse import locale import os diff --git a/testing/test_pastebin.py b/testing/test_pastebin.py index 9ca0da8f69d..8fdd60bac75 100644 --- a/testing/test_pastebin.py +++ b/testing/test_pastebin.py @@ -1,8 +1,8 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import email.message import io -from typing import List -from typing import Union from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester @@ -11,8 +11,8 @@ class TestPasteCapture: @pytest.fixture - def pastebinlist(self, monkeypatch, request) -> List[Union[str, bytes]]: - pastebinlist: List[Union[str, bytes]] = [] + def pastebinlist(self, monkeypatch, request) -> list[str | bytes]: + pastebinlist: list[str | bytes] = [] plugin = request.config.pluginmanager.getplugin("pastebin") monkeypatch.setattr(plugin, "create_new_paste", pastebinlist.append) return pastebinlist diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 688d13f2f05..81aba25f78f 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import errno import importlib.abc import importlib.machinery @@ -12,9 +14,7 @@ from typing import Any from typing import Generator from typing import Iterator -from typing import Optional from typing import Sequence -from typing import Tuple import unittest.mock from _pytest.monkeypatch import MonkeyPatch @@ -865,7 +865,7 @@ def test_my_test(): def create_installed_doctests_and_tests_dir( self, path: Path, monkeypatch: MonkeyPatch - ) -> Tuple[Path, Path, Path]: + ) -> tuple[Path, Path, Path]: """ Create a directory structure where the application code is installed in a virtual environment, and the tests are in an outside ".tests" directory. @@ -1267,8 +1267,8 @@ def setup_imports_tracking(self, monkeypatch: MonkeyPatch) -> None: monkeypatch.setattr(sys, "pytest_namespace_packages_test", [], raising=False) def setup_directories( - self, tmp_path: Path, monkeypatch: Optional[MonkeyPatch], pytester: Pytester - ) -> Tuple[Path, Path]: + self, tmp_path: Path, monkeypatch: MonkeyPatch | None, pytester: Pytester + ) -> tuple[Path, Path]: # Use a code to guard against modules being imported more than once. # This is a safeguard in case future changes break this invariant. code = dedent( @@ -1438,7 +1438,7 @@ class CustomImporter(importlib.abc.MetaPathFinder): def find_spec( self, name: str, path: Any = None, target: Any = None - ) -> Optional[importlib.machinery.ModuleSpec]: + ) -> importlib.machinery.ModuleSpec | None: if name == "com": spec = importlib.machinery.ModuleSpec("com", loader=None) spec.submodule_search_locations = [str(com_root_2), str(com_root_1)] diff --git a/testing/test_pluginmanager.py b/testing/test_pluginmanager.py index 99b003b66ed..db85124bf0d 100644 --- a/testing/test_pluginmanager.py +++ b/testing/test_pluginmanager.py @@ -1,9 +1,10 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os import shutil import sys import types -from typing import List from _pytest.config import Config from _pytest.config import ExitCode @@ -152,7 +153,7 @@ def pytest_plugin_registered(self): saveindent.append(pytestpm.trace.root.indent) raise ValueError() - values: List[str] = [] + values: list[str] = [] pytestpm.trace.root.setwriter(values.append) undo = pytestpm.enable_tracing() try: diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 9c6081a56db..87714b4708f 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -1,10 +1,11 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os import subprocess import sys import time from types import ModuleType -from typing import List from _pytest.config import ExitCode from _pytest.config import PytestPluginManager @@ -227,7 +228,7 @@ def test_inline_run_test_module_not_cleaned_up(self, pytester: Pytester) -> None def spy_factory(self): class SysModulesSnapshotSpy: - instances: List["SysModulesSnapshotSpy"] = [] + instances: list[SysModulesSnapshotSpy] = [] def __init__(self, preserve=None) -> None: SysModulesSnapshotSpy.instances.append(self) @@ -399,7 +400,7 @@ def test_preserve_container(self, monkeypatch: MonkeyPatch, path_type) -> None: original_data = list(getattr(sys, path_type)) original_other = getattr(sys, other_path_type) original_other_data = list(original_other) - new: List[object] = [] + new: list[object] = [] snapshot = SysPathsSnapshot() monkeypatch.setattr(sys, path_type, new) snapshot.restore() diff --git a/testing/test_python_path.py b/testing/test_python_path.py index 73a8725680f..1db02252d22 100644 --- a/testing/test_python_path.py +++ b/testing/test_python_path.py @@ -1,9 +1,9 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import sys from textwrap import dedent from typing import Generator -from typing import List -from typing import Optional from _pytest.pytester import Pytester import pytest @@ -91,8 +91,8 @@ def test_clean_up(pytester: Pytester) -> None: pytester.makefile(".ini", pytest="[pytest]\npythonpath=I_SHALL_BE_REMOVED\n") pytester.makepyfile(test_foo="""def test_foo(): pass""") - before: Optional[List[str]] = None - after: Optional[List[str]] = None + before: list[str] | None = None + after: list[str] | None = None class Plugin: @pytest.hookimpl(wrapper=True, tryfirst=True) diff --git a/testing/test_recwarn.py b/testing/test_recwarn.py index 27ee9aa72f0..384f2b66a15 100644 --- a/testing/test_recwarn.py +++ b/testing/test_recwarn.py @@ -1,9 +1,7 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import sys -from typing import List -from typing import Optional -from typing import Type -from typing import Union import warnings import pytest @@ -54,7 +52,7 @@ class ChildOfChildWarning(ChildWarning): pass @staticmethod - def raise_warnings_from_list(_warnings: List[Type[Warning]]): + def raise_warnings_from_list(_warnings: list[type[Warning]]): for warn in _warnings: warnings.warn(f"Warning {warn().__repr__()}", warn) @@ -134,7 +132,7 @@ def test_invalid_enter_exit(self) -> None: class TestDeprecatedCall: """test pytest.deprecated_call()""" - def dep(self, i: int, j: Optional[int] = None) -> int: + def dep(self, i: int, j: int | None = None) -> int: if i == 0: warnings.warn("is deprecated", DeprecationWarning, stacklevel=1) return 42 @@ -563,7 +561,7 @@ def test_raise_type_error_on_invalid_warning() -> None: pytest.param(Warning(), id="Warning"), ], ) -def test_no_raise_type_error_on_valid_warning(message: Union[str, Warning]) -> None: +def test_no_raise_type_error_on_valid_warning(message: str | Warning) -> None: """Check pytest.warns validates warning messages are strings (#10865) or Warning instances (#11959).""" with pytest.warns(Warning): diff --git a/testing/test_reports.py b/testing/test_reports.py index 7987b401771..3e314d2aade 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from typing import Sequence -from typing import Union from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ExceptionRepr @@ -294,8 +295,8 @@ def test_a(): reprec = pytester.inline_run() if report_class is TestReport: - reports: Union[Sequence[TestReport], Sequence[CollectReport]] = ( - reprec.getreports("pytest_runtest_logreport") + reports: Sequence[TestReport] | Sequence[CollectReport] = reprec.getreports( + "pytest_runtest_logreport" ) # we have 3 reports: setup/call/teardown assert len(reports) == 3 diff --git a/testing/test_runner.py b/testing/test_runner.py index 3ec5678274e..79f7a3fd4d3 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1,14 +1,12 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from functools import partial import inspect import os from pathlib import Path import sys import types -from typing import Dict -from typing import List -from typing import Tuple -from typing import Type import warnings from _pytest import outcomes @@ -523,7 +521,7 @@ class TestClass(object): assert res[1].name == "TestClass" -reporttypes: List[Type[reports.BaseReport]] = [ +reporttypes: list[type[reports.BaseReport]] = [ reports.BaseReport, reports.TestReport, reports.CollectReport, @@ -533,9 +531,9 @@ class TestClass(object): @pytest.mark.parametrize( "reporttype", reporttypes, ids=[x.__name__ for x in reporttypes] ) -def test_report_extra_parameters(reporttype: Type[reports.BaseReport]) -> None: +def test_report_extra_parameters(reporttype: type[reports.BaseReport]) -> None: args = list(inspect.signature(reporttype.__init__).parameters.keys())[1:] - basekw: Dict[str, List[object]] = dict.fromkeys(args, []) + basekw: dict[str, list[object]] = dict.fromkeys(args, []) report = reporttype(newthing=1, **basekw) assert report.newthing == 1 @@ -1048,7 +1046,7 @@ def runtest(self): def test_current_test_env_var(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: - pytest_current_test_vars: List[Tuple[str, str]] = [] + pytest_current_test_vars: list[tuple[str, str]] = [] monkeypatch.setattr( sys, "pytest_current_test_vars", pytest_current_test_vars, raising=False ) diff --git a/testing/test_runner_xunit.py b/testing/test_runner_xunit.py index 587c9eb9fef..75e838a49e8 100644 --- a/testing/test_runner_xunit.py +++ b/testing/test_runner_xunit.py @@ -1,7 +1,7 @@ # mypy: allow-untyped-defs """Test correct setup/teardowns at module, class, and instance level.""" -from typing import List +from __future__ import annotations from _pytest.pytester import Pytester import pytest @@ -251,7 +251,7 @@ def test_setup_teardown_function_level_with_optional_argument( """Parameter to setup/teardown xunit-style functions parameter is now optional (#1728).""" import sys - trace_setups_teardowns: List[str] = [] + trace_setups_teardowns: list[str] = [] monkeypatch.setattr( sys, "trace_setups_teardowns", trace_setups_teardowns, raising=False ) diff --git a/testing/test_scope.py b/testing/test_scope.py index 1727c2ee1bb..3cb811469a9 100644 --- a/testing/test_scope.py +++ b/testing/test_scope.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import re from _pytest.scope import Scope diff --git a/testing/test_session.py b/testing/test_session.py index 8624af478b1..ba904916033 100644 --- a/testing/test_session.py +++ b/testing/test_session.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester diff --git a/testing/test_setuponly.py b/testing/test_setuponly.py index 8638f5a6140..87123bd9a16 100644 --- a/testing/test_setuponly.py +++ b/testing/test_setuponly.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import sys from _pytest.config import ExitCode diff --git a/testing/test_setupplan.py b/testing/test_setupplan.py index d51a1873959..5a9211d7806 100644 --- a/testing/test_setupplan.py +++ b/testing/test_setupplan.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from _pytest.pytester import Pytester diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 459216a6d6b..558e3d35c6a 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import sys import textwrap diff --git a/testing/test_stash.py b/testing/test_stash.py index e523c4e6f2b..c7f6f4f95fe 100644 --- a/testing/test_stash.py +++ b/testing/test_stash.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from _pytest.stash import Stash from _pytest.stash import StashKey import pytest diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index 472afea6620..affdb73375e 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + from pathlib import Path from _pytest.cacheprovider import Cache diff --git a/testing/test_terminal.py b/testing/test_terminal.py index ce9fdc50c8a..01a84fd8d2c 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs """Terminal reporting of the full testing process.""" +from __future__ import annotations + from io import StringIO import os from pathlib import Path @@ -8,10 +10,7 @@ import textwrap from types import SimpleNamespace from typing import cast -from typing import Dict -from typing import List from typing import NamedTuple -from typing import Tuple import pluggy @@ -1929,9 +1928,9 @@ def tr() -> TerminalReporter: ) def test_summary_stats( tr: TerminalReporter, - exp_line: List[Tuple[str, Dict[str, bool]]], + exp_line: list[tuple[str, dict[str, bool]]], exp_color: str, - stats_arg: Dict[str, List[object]], + stats_arg: dict[str, list[object]], ) -> None: tr.stats = stats_arg diff --git a/testing/test_threadexception.py b/testing/test_threadexception.py index 99837b94e8a..abd30144914 100644 --- a/testing/test_threadexception.py +++ b/testing/test_threadexception.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from _pytest.pytester import Pytester import pytest diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index f424998e50f..865d8e0b05c 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import dataclasses import os from pathlib import Path @@ -6,8 +8,6 @@ import sys from typing import Callable from typing import cast -from typing import List -from typing import Union import warnings from _pytest import pathlib @@ -34,7 +34,7 @@ def test_tmp_path_fixture(pytester: Pytester) -> None: @dataclasses.dataclass class FakeConfig: - basetemp: Union[str, Path] + basetemp: str | Path @property def trace(self): @@ -394,7 +394,7 @@ def test_cleanup_lock_create(self, tmp_path): def test_lock_register_cleanup_removal(self, tmp_path: Path) -> None: lock = create_cleanup_lock(tmp_path) - registry: List[Callable[..., None]] = [] + registry: list[Callable[..., None]] = [] register_cleanup_lock_removal(lock, register=registry.append) (cleanup_func,) = registry diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 9561cad5eb5..56224c08228 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import sys -from typing import List from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch @@ -1214,7 +1215,7 @@ def test_pdb_teardown_called(pytester: Pytester, monkeypatch: MonkeyPatch) -> No We delay the normal tearDown() calls when --pdb is given, so this ensures we are calling tearDown() eventually to avoid memory leaks when using --pdb. """ - teardowns: List[str] = [] + teardowns: list[str] = [] monkeypatch.setattr( pytest, "test_pdb_teardown_called_teardowns", teardowns, raising=False ) @@ -1251,7 +1252,7 @@ def test_pdb_teardown_skipped_for_functions( With --pdb, setUp and tearDown should not be called for tests skipped via a decorator (#7215). """ - tracked: List[str] = [] + tracked: list[str] = [] monkeypatch.setattr(pytest, "track_pdb_teardown_skipped", tracked, raising=False) pytester.makepyfile( @@ -1286,7 +1287,7 @@ def test_pdb_teardown_skipped_for_classes( With --pdb, setUp and tearDown should not be called for tests skipped via a decorator on the class (#10060). """ - tracked: List[str] = [] + tracked: list[str] = [] monkeypatch.setattr(pytest, "track_pdb_teardown_skipped", tracked, raising=False) pytester.makepyfile( diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index 1657cfe4a84..a15c754d067 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys from _pytest.pytester import Pytester diff --git a/testing/test_warning_types.py b/testing/test_warning_types.py index a50d278bde2..19fe0f8a272 100644 --- a/testing/test_warning_types.py +++ b/testing/test_warning_types.py @@ -1,4 +1,6 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import inspect from _pytest import warning_types diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 73c8c1b3231..d4d0e0b7f93 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -1,9 +1,8 @@ # mypy: allow-untyped-defs +from __future__ import annotations + import os import sys -from typing import List -from typing import Optional -from typing import Tuple import warnings from _pytest.fixtures import FixtureRequest @@ -618,11 +617,11 @@ def test_group_warnings_by_message_summary(pytester: Pytester) -> None: f"*== {WARNINGS_SUMMARY_HEADER} ==*", "test_1.py: 21 warnings", "test_2.py: 1 warning", - " */test_1.py:8: UserWarning: foo", + " */test_1.py:10: UserWarning: foo", " warnings.warn(UserWarning(msg))", "", "test_1.py: 20 warnings", - " */test_1.py:8: UserWarning: bar", + " */test_1.py:10: UserWarning: bar", " warnings.warn(UserWarning(msg))", "", "-- Docs: *", @@ -654,8 +653,8 @@ class TestStackLevel: @pytest.fixture def capwarn(self, pytester: Pytester): class CapturedWarnings: - captured: List[ - Tuple[warnings.WarningMessage, Optional[Tuple[str, int, str]]] + captured: list[ + tuple[warnings.WarningMessage, tuple[str, int, str] | None] ] = [] @classmethod diff --git a/testing/typing_checks.py b/testing/typing_checks.py index 4b146a25110..d4d6a97aea6 100644 --- a/testing/typing_checks.py +++ b/testing/typing_checks.py @@ -5,6 +5,8 @@ none of the code triggers any mypy errors. """ +from __future__ import annotations + import contextlib from typing import Optional From b7c0295e1a5186214fa6919f15dfaf379681e8e5 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 17 Jun 2024 17:12:34 +0200 Subject: [PATCH 0711/1271] use runtime union for EXCEPTION_OR_MORE --- src/_pytest/_code/code.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 750195b94e9..229c7deee90 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -30,7 +30,10 @@ from typing import Pattern from typing import Sequence from typing import SupportsIndex +from typing import Tuple +from typing import Type from typing import TypeVar +from typing import Union import pluggy @@ -53,9 +56,7 @@ TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] -EXCEPTION_OR_MORE = type[Exception] | tuple[type[Exception], ...] - -type_alias = type # to sidestep shadowing +EXCEPTION_OR_MORE = Union[Type[Exception], Tuple[Type[Exception], ...]] class Code: From 5e1649f59ace652a6feb84dafa591f3f06cdd6c2 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Mon, 17 Jun 2024 18:03:10 +0200 Subject: [PATCH 0712/1271] resolve most sphinx lookup errors add the extra sphinx annotations to refer to Path instances add Path to nitpicky ignore --- doc/en/conf.py | 8 +++- src/_pytest/_code/code.py | 3 +- src/_pytest/config/__init__.py | 68 +++++++++++++++++----------------- src/_pytest/hookspec.py | 6 +++ src/_pytest/main.py | 1 + src/_pytest/pytester.py | 4 ++ src/_pytest/python.py | 2 +- src/_pytest/runner.py | 1 + tox.ini | 8 +++- 9 files changed, 62 insertions(+), 39 deletions(-) diff --git a/doc/en/conf.py b/doc/en/conf.py index 670d6adf74b..53056024b37 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -23,9 +23,11 @@ from textwrap import dedent from typing import TYPE_CHECKING -from _pytest import __version__ as version +from _pytest import __version__ as full_version +version = full_version.split("+")[0] + if TYPE_CHECKING: import sphinx.application @@ -191,6 +193,7 @@ ("py:class", "SubRequest"), ("py:class", "TerminalReporter"), ("py:class", "_pytest._code.code.TerminalRepr"), + ("py:class", "TerminalRepr"), ("py:class", "_pytest.fixtures.FixtureFunctionMarker"), ("py:class", "_pytest.logging.LogCaptureHandler"), ("py:class", "_pytest.mark.structures.ParameterSet"), @@ -212,13 +215,16 @@ ("py:class", "_PluggyPlugin"), # TypeVars ("py:class", "_pytest._code.code.E"), + ("py:class", "E"), # due to delayed annotation ("py:class", "_pytest.fixtures.FixtureFunction"), ("py:class", "_pytest.nodes._NodeType"), + ("py:class", "_NodeType"), # due to delayed annotation ("py:class", "_pytest.python_api.E"), ("py:class", "_pytest.recwarn.T"), ("py:class", "_pytest.runner.TResult"), ("py:obj", "_pytest.fixtures.FixtureValue"), ("py:obj", "_pytest.stash.T"), + ("py:class", "_ScopeName"), ] diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 229c7deee90..e7452825756 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -620,7 +620,8 @@ def getrepr( showlocals: bool = False, style: TracebackStyle = "long", abspath: bool = False, - tbfilter: bool | Callable[[ExceptionInfo[BaseException]], Traceback] = True, + tbfilter: bool + | Callable[[ExceptionInfo[BaseException]], _pytest._code.code.Traceback] = True, funcargs: bool = False, truncate_locals: bool = True, truncate_args: bool = True, diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 47e3f5b5a50..23a2c47970a 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -13,7 +13,7 @@ import importlib.metadata import inspect import os -from pathlib import Path +import pathlib import re import shlex import sys @@ -114,7 +114,7 @@ class ExitCode(enum.IntEnum): class ConftestImportFailure(Exception): def __init__( self, - path: Path, + path: pathlib.Path, *, cause: Exception, ) -> None: @@ -290,7 +290,7 @@ def get_config( invocation_params=Config.InvocationParams( args=args or (), plugins=plugins, - dir=Path.cwd(), + dir=pathlib.Path.cwd(), ), ) @@ -347,7 +347,7 @@ def _prepareconfig( raise -def _get_directory(path: Path) -> Path: +def _get_directory(path: pathlib.Path) -> pathlib.Path: """Get the directory of a path - itself if already a directory.""" if path.is_file(): return path.parent @@ -408,9 +408,9 @@ def __init__(self) -> None: # All conftest modules applicable for a directory. # This includes the directory's own conftest modules as well # as those of its parent directories. - self._dirpath2confmods: dict[Path, list[types.ModuleType]] = {} + self._dirpath2confmods: dict[pathlib.Path, list[types.ModuleType]] = {} # Cutoff directory above which conftests are no longer discovered. - self._confcutdir: Path | None = None + self._confcutdir: pathlib.Path | None = None # If set, conftest loading is skipped. self._noconftest = False @@ -544,12 +544,12 @@ def pytest_configure(self, config: Config) -> None: # def _set_initial_conftests( self, - args: Sequence[str | Path], + args: Sequence[str | pathlib.Path], pyargs: bool, noconftest: bool, - rootpath: Path, - confcutdir: Path | None, - invocation_dir: Path, + rootpath: pathlib.Path, + confcutdir: pathlib.Path | None, + invocation_dir: pathlib.Path, importmode: ImportMode | str, *, consider_namespace_packages: bool, @@ -593,7 +593,7 @@ def _set_initial_conftests( consider_namespace_packages=consider_namespace_packages, ) - def _is_in_confcutdir(self, path: Path) -> bool: + def _is_in_confcutdir(self, path: pathlib.Path) -> bool: """Whether to consider the given path to load conftests from.""" if self._confcutdir is None: return True @@ -610,9 +610,9 @@ def _is_in_confcutdir(self, path: Path) -> bool: def _try_load_conftest( self, - anchor: Path, + anchor: pathlib.Path, importmode: str | ImportMode, - rootpath: Path, + rootpath: pathlib.Path, *, consider_namespace_packages: bool, ) -> None: @@ -635,9 +635,9 @@ def _try_load_conftest( def _loadconftestmodules( self, - path: Path, + path: pathlib.Path, importmode: str | ImportMode, - rootpath: Path, + rootpath: pathlib.Path, *, consider_namespace_packages: bool, ) -> None: @@ -665,14 +665,14 @@ def _loadconftestmodules( clist.append(mod) self._dirpath2confmods[directory] = clist - def _getconftestmodules(self, path: Path) -> Sequence[types.ModuleType]: + def _getconftestmodules(self, path: pathlib.Path) -> Sequence[types.ModuleType]: directory = self._get_directory(path) return self._dirpath2confmods.get(directory, ()) def _rget_with_confmod( self, name: str, - path: Path, + path: pathlib.Path, ) -> tuple[types.ModuleType, Any]: modules = self._getconftestmodules(path) for mod in reversed(modules): @@ -684,9 +684,9 @@ def _rget_with_confmod( def _importconftest( self, - conftestpath: Path, + conftestpath: pathlib.Path, importmode: str | ImportMode, - rootpath: Path, + rootpath: pathlib.Path, *, consider_namespace_packages: bool, ) -> types.ModuleType: @@ -738,7 +738,7 @@ def _importconftest( def _check_non_top_pytest_plugins( self, mod: types.ModuleType, - conftestpath: Path, + conftestpath: pathlib.Path, ) -> None: if ( hasattr(mod, "pytest_plugins") @@ -995,15 +995,15 @@ class InvocationParams: """The command-line arguments as passed to :func:`pytest.main`.""" plugins: Sequence[str | _PluggyPlugin] | None """Extra plugins, might be `None`.""" - dir: Path - """The directory from which :func:`pytest.main` was invoked.""" + dir: pathlib.Path + """The directory from which :func:`pytest.main` was invoked. :type: pathlib.Path""" def __init__( self, *, args: Iterable[str], plugins: Sequence[str | _PluggyPlugin] | None, - dir: Path, + dir: pathlib.Path, ) -> None: object.__setattr__(self, "args", tuple(args)) object.__setattr__(self, "plugins", plugins) @@ -1037,7 +1037,7 @@ def __init__( if invocation_params is None: invocation_params = self.InvocationParams( - args=(), plugins=None, dir=Path.cwd() + args=(), plugins=None, dir=pathlib.Path.cwd() ) self.option = argparse.Namespace() @@ -1088,7 +1088,7 @@ def __init__( self.args: list[str] = [] @property - def rootpath(self) -> Path: + def rootpath(self) -> pathlib.Path: """The path to the :ref:`rootdir `. :type: pathlib.Path @@ -1098,11 +1098,9 @@ def rootpath(self) -> Path: return self._rootpath @property - def inipath(self) -> Path | None: + def inipath(self) -> pathlib.Path | None: """The path to the :ref:`configfile `. - :type: Optional[pathlib.Path] - .. versionadded:: 6.1 """ return self._inipath @@ -1313,8 +1311,8 @@ def _decide_args( args: list[str], pyargs: bool, testpaths: list[str], - invocation_dir: Path, - rootpath: Path, + invocation_dir: pathlib.Path, + rootpath: pathlib.Path, warn: bool, ) -> tuple[list[str], ArgsSource]: """Decide the args (initial paths/nodeids) to use given the relevant inputs. @@ -1640,17 +1638,19 @@ def _getini(self, name: str): else: return self._getini_unknown_type(name, type, value) - def _getconftest_pathlist(self, name: str, path: Path) -> list[Path] | None: + def _getconftest_pathlist( + self, name: str, path: pathlib.Path + ) -> list[pathlib.Path] | None: try: mod, relroots = self.pluginmanager._rget_with_confmod(name, path) except KeyError: return None assert mod.__file__ is not None - modpath = Path(mod.__file__).parent - values: list[Path] = [] + modpath = pathlib.Path(mod.__file__).parent + values: list[pathlib.Path] = [] for relroot in relroots: if isinstance(relroot, os.PathLike): - relroot = Path(relroot) + relroot = pathlib.Path(relroot) else: relroot = relroot.replace("/", os.sep) relroot = absolutepath(modpath / relroot) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 13f4fddbddb..99614899994 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -321,6 +321,7 @@ def pytest_ignore_collect( Stops at first non-None result, see :ref:`firstresult`. :param collection_path: The path to analyze. + :type collection_path: pathlib.Path :param path: The path to analyze (deprecated). :param config: The pytest config object. @@ -354,6 +355,7 @@ def pytest_collect_directory(path: Path, parent: Collector) -> Collector | None: Stops at first non-None result, see :ref:`firstresult`. :param path: The path to analyze. + :type path: pathlib.Path See :ref:`custom directory collectors` for a simple example of use of this hook. @@ -386,6 +388,7 @@ def pytest_collect_file( The new node needs to have the specified ``parent`` as a parent. :param file_path: The path to analyze. + :type file_path: pathlib.Path :param path: The path to collect (deprecated). .. versionchanged:: 7.0.0 @@ -507,6 +510,7 @@ def pytest_pycollect_makemodule( Stops at first non-None result, see :ref:`firstresult`. :param module_path: The path of the module to collect. + :type module_path: pathlib.Path :param path: The path of the module to collect (deprecated). .. versionchanged:: 7.0.0 @@ -1026,6 +1030,7 @@ def pytest_report_header( # type:ignore[empty-body] :param config: The pytest config object. :param start_path: The starting dir. + :type start_path: pathlib.Path :param startdir: The starting dir (deprecated). .. note:: @@ -1069,6 +1074,7 @@ def pytest_report_collectionfinish( # type:ignore[empty-body] :param config: The pytest config object. :param start_path: The starting dir. + :type start_path: pathlib.Path :param startdir: The starting dir (deprecated). :param items: List of pytest items that are going to be executed; this list should not be modified. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index a19ddef58fb..47ebad4713d 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -510,6 +510,7 @@ def from_parent( # type: ignore[override] :param parent: The parent collector of this Dir. :param path: The directory's path. + :type path: pathlib.Path """ return super().from_parent(parent=parent, path=path) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index e27648507e9..5c6ce5e889f 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -909,6 +909,7 @@ def mkdir(self, name: str | os.PathLike[str]) -> Path: The name of the directory, relative to the pytester path. :returns: The created directory. + :rtype: pathlib.Path """ p = self.path / name p.mkdir() @@ -932,6 +933,7 @@ def copy_example(self, name: str | None = None) -> Path: The name of the file to copy. :return: Path to the copied directory (inside ``self.path``). + :rtype: pathlib.Path """ example_dir_ = self._request.config.getini("pytester_example_dir") if example_dir_ is None: @@ -1390,8 +1392,10 @@ def run( - Otherwise, it is passed through to :py:class:`subprocess.Popen`. For further information in this case, consult the document of the ``stdin`` parameter in :py:class:`subprocess.Popen`. + :type stdin: _pytest.compat.NotSetType | bytes | IO[Any] | int :returns: The result. + """ __tracebackhide__ = True diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 2904c3a1e0f..9182ce7dfe9 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1168,7 +1168,7 @@ def parametrize( If N argnames were specified, argvalues must be a list of N-tuples, where each tuple-element specifies a value for its respective argname. - + :type argvalues: Iterable[_pytest.mark.structures.ParameterSet | Sequence[object] | object] :param indirect: A list of arguments' names (subset of argnames) or a boolean. If True the list contains all names from the argnames. Each diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index bf30a7d2d27..716c4948f4a 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -327,6 +327,7 @@ def from_call( :param func: The function to call. Called without arguments. + :type func: Callable[[], _pytest.runner.TResult] :param when: The phase in which the function is called. :param reraise: diff --git a/tox.ini b/tox.ini index dae89975467..c421a63b4dd 100644 --- a/tox.ini +++ b/tox.ini @@ -81,7 +81,7 @@ setenv = PYTHONWARNDEFAULTENCODING= [testenv:docs] -basepython = python3 +basepython = python3.9 # sync with rtd to get errors usedevelop = True deps = -r{toxinidir}/doc/en/requirements.txt @@ -92,7 +92,11 @@ commands = -git fetch --unshallow -git fetch --tags - sphinx-build -W --keep-going -b html doc/en doc/en/_build/html {posargs:} + sphinx-build \ + -j auto \ + -W --keep-going \ + -b html doc/en doc/en/_build/html \ + {posargs:} setenv = # Sphinx is not clean of this warning. PYTHONWARNDEFAULTENCODING= From 4e54f19be1d45b2dee778becfe766e90906ef274 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 20 Jun 2024 11:00:21 +0200 Subject: [PATCH 0713/1271] update tox:docs python to rtd python --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index c421a63b4dd..2cd8c72a62f 100644 --- a/tox.ini +++ b/tox.ini @@ -81,7 +81,7 @@ setenv = PYTHONWARNDEFAULTENCODING= [testenv:docs] -basepython = python3.9 # sync with rtd to get errors +basepython = python3.12 # sync with rtd to get errors usedevelop = True deps = -r{toxinidir}/doc/en/requirements.txt From 85e451a2cc45315dc39ae905d3f6774bf97d75c0 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 20 Jun 2024 11:09:48 +0200 Subject: [PATCH 0714/1271] add changelog entry --- changelog/12467.improvement.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog/12467.improvement.rst diff --git a/changelog/12467.improvement.rst b/changelog/12467.improvement.rst new file mode 100644 index 00000000000..b1e0581ed16 --- /dev/null +++ b/changelog/12467.improvement.rst @@ -0,0 +1,3 @@ +Migrated all internal type-annotations to the python3.10+ style by using the `annotations` future import. + +-- by :user:`RonnyPfannschmidt` From 43815b6fc25368c1f52c450f3d3d995a5384e357 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 22:04:32 +0200 Subject: [PATCH 0715/1271] =?UTF-8?q?=F0=9F=9A=91=F0=9F=A7=AA=F0=9F=93=9D?= =?UTF-8?q?=20Allow=20invoking=20`git`=20in=20tox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is called when building the docs. Apparently, `tox -e docs` is not invoked in CI, neither is it called in RTD, resulting in the regression having been caught only in local development environments. This is a follow-up for #12493. --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index dae89975467..66ce3f24c3e 100644 --- a/tox.ini +++ b/tox.ini @@ -87,6 +87,8 @@ deps = -r{toxinidir}/doc/en/requirements.txt # https://github.com/twisted/towncrier/issues/340 towncrier<21.3.0 +allowlist_externals = + git commands = # Retrieve possibly missing commits: -git fetch --unshallow From dc2568a683202a5f096fcaa06cca83fc11979e17 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 22:09:25 +0200 Subject: [PATCH 0716/1271] =?UTF-8?q?=F0=9F=9A=91=F0=9F=A7=AA=F0=9F=93=9D?= =?UTF-8?q?=20Stop=20capping=20Towncrier=20@=20local=20docs=20builds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is uncapped in RTD. Apparently, `tox -e docs` is not invoked in CI, neither is it called in RTD, resulting in the regression having been caught only in local development environments. This is a follow-up for #12493. --- tox.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/tox.ini b/tox.ini index 66ce3f24c3e..88708d47bb5 100644 --- a/tox.ini +++ b/tox.ini @@ -85,8 +85,6 @@ basepython = python3 usedevelop = True deps = -r{toxinidir}/doc/en/requirements.txt - # https://github.com/twisted/towncrier/issues/340 - towncrier<21.3.0 allowlist_externals = git commands = From 6a8e9ed43ade6ea60d0cf72819b187613e592354 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Fri, 21 Jun 2024 09:42:24 +0200 Subject: [PATCH 0717/1271] fixup: Config.cache cannot be None --- src/_pytest/config/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 23a2c47970a..0a96d1a31f5 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1024,7 +1024,7 @@ class ArgsSource(enum.Enum): TESTPATHS = enum.auto() # Set by cacheprovider plugin. - cache: Cache | None + cache: Cache def __init__( self, From 0cf92cfa4cd4a0c156dbf3dc0e83b7274996a03b Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 18:30:08 +0200 Subject: [PATCH 0718/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20comments=20to=20?= =?UTF-8?q?change=20note=20categories?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 734c508ca70..895cedb5f0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -372,42 +372,58 @@ directory = "changelog/" title_format = "pytest {version} ({project_date})" template = "changelog/_template.rst" +# NOTE: The types are declared because: +# NOTE: - there is no mechanism to override just the value of +# NOTE: `tool.towncrier.type.misc.showcontent`; +# NOTE: - and, we want to declare extra non-default types for +# NOTE: clarity and flexibility. + [[tool.towncrier.type]] +# When something public gets removed in a breaking way. Could be +# deprecated in an earlier release. directory = "breaking" name = "Breaking Changes" showcontent = true [[tool.towncrier.type]] +# Declarations of future API removals and breaking changes in behavior. directory = "deprecation" name = "Deprecations" showcontent = true [[tool.towncrier.type]] +# New behaviors, public APIs. That sort of stuff. directory = "feature" name = "Features" showcontent = true [[tool.towncrier.type]] +# New behaviors in existing features. directory = "improvement" name = "Improvements" showcontent = true [[tool.towncrier.type]] +# Something we deemed an improper undesired behavior that got corrected +# in the release to match pre-agreed expectations. directory = "bugfix" name = "Bug Fixes" showcontent = true [[tool.towncrier.type]] +# Updates regarding bundling dependencies. directory = "vendor" name = "Vendored Libraries" showcontent = true [[tool.towncrier.type]] +# Notable updates to the documentation structure or build process. directory = "doc" name = "Improved Documentation" showcontent = true [[tool.towncrier.type]] +# Changes that might not even be worth exposing to the end users. directory = "trivial" name = "Trivial/Internal Changes" showcontent = true From 45a89ec61f9a9552236b07cde457ed38a7217e58 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 19:17:40 +0200 Subject: [PATCH 0719/1271] =?UTF-8?q?=F0=9F=93=9D=20Extend=20change=20log?= =?UTF-8?q?=20title=20meanings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch makes them more verbose so that they are clearer to the readers. --- pyproject.toml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 895cedb5f0e..c850284f4ca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -382,50 +382,50 @@ template = "changelog/_template.rst" # When something public gets removed in a breaking way. Could be # deprecated in an earlier release. directory = "breaking" -name = "Breaking Changes" +name = "Removals and backward incompatible breaking changes" showcontent = true [[tool.towncrier.type]] # Declarations of future API removals and breaking changes in behavior. directory = "deprecation" -name = "Deprecations" +name = "Deprecations (removal in next major release)" showcontent = true [[tool.towncrier.type]] # New behaviors, public APIs. That sort of stuff. directory = "feature" -name = "Features" +name = "New features" showcontent = true [[tool.towncrier.type]] # New behaviors in existing features. directory = "improvement" -name = "Improvements" +name = "Improvements in existing functionality" showcontent = true [[tool.towncrier.type]] # Something we deemed an improper undesired behavior that got corrected # in the release to match pre-agreed expectations. directory = "bugfix" -name = "Bug Fixes" +name = "Bug fixes" showcontent = true [[tool.towncrier.type]] # Updates regarding bundling dependencies. directory = "vendor" -name = "Vendored Libraries" +name = "Vendored libraries" showcontent = true [[tool.towncrier.type]] # Notable updates to the documentation structure or build process. directory = "doc" -name = "Improved Documentation" +name = "Improved documentation" showcontent = true [[tool.towncrier.type]] # Changes that might not even be worth exposing to the end users. directory = "trivial" -name = "Trivial/Internal Changes" +name = "Trivial/internal changes" showcontent = true [tool.mypy] From 03be1ed8b1794f837dddc7f26aabebe203d90bea Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 19:35:40 +0200 Subject: [PATCH 0720/1271] =?UTF-8?q?=F0=9F=93=9D=F0=9F=92=85=20Split=20`t?= =?UTF-8?q?rivial`=20change=20log=20category=20into=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new change note types are `packaging`, `contrib` and `misc`. `packaging` is intended for the audience of downstream redistributors. The `contrib` notes are meant to be documenting news affecting the project contributors, their development, and processes. Finally, `misc` is for things that don't fit anywhere but are still desired to be documented for some reason. --- .pre-commit-config.yaml | 37 +++++++++++++++++++++++++++++++++++-- changelog/README.rst | 14 +++++++++++++- pyproject.toml | 20 +++++++++++++++++--- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5a3d75ff874..c85175f2928 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -66,8 +66,41 @@ repos: - id: changelogs-rst name: changelog filenames language: fail - entry: 'changelog files must be named ####.(breaking|bugfix|deprecation|doc|feature|improvement|trivial|vendor).rst' - exclude: changelog/(\d+\.(breaking|bugfix|deprecation|doc|feature|improvement|trivial|vendor).rst|README.rst|_template.rst) + entry: >- + changelog files must be named + ####.( + breaking + | deprecation + | feature + | improvement + | bugfix + | vendor + | doc + | packaging + | contrib + | misc + )(.#)?(.rst)? + exclude: >- + (?x) + ^ + changelog/( + \.gitignore + |\d+\.( + breaking + |deprecation + |feature + |improvement + |bugfix + |vendor + |doc + |packaging + |contrib + |misc + )(\.\d+)?(\.rst)? + |README\.rst + |_template\.rst + ) + $ files: ^changelog/ - id: py-deprecated name: py library is deprecated diff --git a/changelog/README.rst b/changelog/README.rst index 88956ef28d8..fdaa573d427 100644 --- a/changelog/README.rst +++ b/changelog/README.rst @@ -20,10 +20,22 @@ Each file should be named like ``..rst``, where * ``deprecation``: feature deprecation. * ``breaking``: a change which may break existing suites, such as feature removal or behavior change. * ``vendor``: changes in packages vendored in pytest. -* ``trivial``: fixing a small typo or internal change that might be noteworthy. +* ``packaging``: notes for downstreams about unobvious side effects + and tooling. changes in the test invocation considerations and + runtime assumptions. +* ``contrib``: stuff that affects the contributor experience. e.g. + Running tests, building the docs, setting up the development + environment. +* ``misc``: changes that are hard to assign to any of the above + categories. So for example: ``123.feature.rst``, ``456.bugfix.rst``. +.. tip:: + + See :file:`pyproject.toml` for all available categories + (``tool.towncrier.type``). + If your PR fixes an issue, use that number here. If there is no issue, then after you submit the PR and get the PR number you can add a changelog using that instead. diff --git a/pyproject.toml b/pyproject.toml index c850284f4ca..14f69bc3422 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -423,9 +423,23 @@ name = "Improved documentation" showcontent = true [[tool.towncrier.type]] -# Changes that might not even be worth exposing to the end users. -directory = "trivial" -name = "Trivial/internal changes" +# Notes for downstreams about unobvious side effects and tooling. Changes +# in the test invocation considerations and runtime assumptions. +directory = "packaging" +name = "Packaging updates and notes for downstreams" +showcontent = true + +[[tool.towncrier.type]] +# Stuff that affects the contributor experience. e.g. Running tests, +# building the docs, setting up the development environment. +directory = "contrib" +name = "Contributor-facing changes" +showcontent = true + +[[tool.towncrier.type]] +# Changes that are hard to assign to any of the above categories. +directory = "misc" +name = "Miscellaneous internal changes" showcontent = true [tool.mypy] From 3ce1d658bd4e952a28774525ed5235987f1883fc Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 21:59:39 +0200 Subject: [PATCH 0721/1271] =?UTF-8?q?=F0=9F=8E=A8=20Set=20up=20Git=20to=20?= =?UTF-8?q?only=20allow=20certain=20change=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/.gitignore | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 changelog/.gitignore diff --git a/changelog/.gitignore b/changelog/.gitignore new file mode 100644 index 00000000000..3b34da34bc6 --- /dev/null +++ b/changelog/.gitignore @@ -0,0 +1,34 @@ +* +!.gitignore +!_template.rst +!README.rst +!*.bugfix +!*.bugfix.rst +!*.bugfix.*.rst +!*.breaking +!*.breaking.rst +!*.breaking.*.rst +!*.contrib +!*.contrib.rst +!*.contrib.*.rst +!*.deprecation +!*.deprecation.rst +!*.deprecation.*.rst +!*.doc +!*.doc.rst +!*.doc.*.rst +!*.feature +!*.feature.rst +!*.feature.*.rst +!*.improvement +!*.improvement.rst +!*.improvement.*.rst +!*.misc +!*.misc.rst +!*.misc.*.rst +!*.packaging +!*.packaging.rst +!*.packaging.*.rst +!*.vendor +!*.vendor.rst +!*.vendor.*.rst From e73db6864208dba4e6722a208419c7fc730335d5 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 20:06:02 +0200 Subject: [PATCH 0722/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20for=20PR=20#12501?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12501.contrib.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 changelog/12501.contrib.rst diff --git a/changelog/12501.contrib.rst b/changelog/12501.contrib.rst new file mode 100644 index 00000000000..6f434c287b3 --- /dev/null +++ b/changelog/12501.contrib.rst @@ -0,0 +1,11 @@ +The changelog configuration has been updated to introduce more accurate +audience-tailored categories. Previously, there was a ``trivial`` +change log fragment type with an unclear and broad meaning. It was +removed and we now have ``contrib``, ``misc`` and ``packaging`` in +place of it. + +The new change note types target the readers who are downstream +packagers and project contributors. Additionally, the miscellaneous +section is kept for unspecified updates that do not fit anywhere else. + +-- by :user:`webknjaz` From 323b0bd8535f812da7332afd916aa323f0e6d79d Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 20:14:31 +0200 Subject: [PATCH 0723/1271] =?UTF-8?q?=F0=9F=A7=AA=20Make=20a=20draft=20bas?= =?UTF-8?q?ed=20plugin=20bump=20PR=20CI=20trigger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normally, PRs/commits published using the default GitHub Actions CI/CD API token are not propagated to any integrations. This patch marks the plugin update PR as a draft and leaves a comment asking the maintainers to mark it as ready for review in order to actually trigger a CI run. This idea is found in GitHub's own repos: * https://github.com/github/codeql-action/pull/2263#issuecomment-2078311173 * https://github.com/github/codeql-action/blob/4ebadbc7/.github/workflows/update-dependencies.yml#L38-L41 * https://github.com/github/codeql-action/pull/1868 * https://github.com/github/codeql-action/pull/679 --- .github/workflows/test.yml | 5 +++++ .github/workflows/update-plugin-list.yml | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d16ce0edf93..adc03a8c284 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,6 +14,11 @@ on: branches: - main - "[0-9]+.[0-9]+.x" + types: + - opened # default + - synchronize # default + - reopened # default + - ready_for_review # used in PRs created from the release workflow env: PYTEST_ADDOPTS: "--color=yes" diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 1015d01c9c6..4da55e6d5a2 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -46,6 +46,7 @@ jobs: run: python scripts/update-plugin-list.py - name: Create Pull Request + id: pr uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e with: commit-message: '[automated] Update plugin list' @@ -55,3 +56,13 @@ jobs: branch-suffix: short-commit-hash title: '[automated] Update plugin list' body: '[automated] Update plugin list' + draft: true + + - name: Instruct the maintainers to trigger CI by undrafting the PR + env: + GITHUB_TOKEN: ${{ github.token }} + run: >- + gh pr comment + --body 'Please mark the PR as ready for review to trigger PR checks.' + --repo '${{ github.repository }}' + '${{ steps.pr.outputs.pull-request-number }}' From 072cb5250e23073deb2c0bbe94419810e605e54f Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 20:22:29 +0200 Subject: [PATCH 0724/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20for=20PR=20#12502?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12502.contrib.rst | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelog/12502.contrib.rst diff --git a/changelog/12502.contrib.rst b/changelog/12502.contrib.rst new file mode 100644 index 00000000000..a7db422526f --- /dev/null +++ b/changelog/12502.contrib.rst @@ -0,0 +1,7 @@ +The UX of the GitHub automation making pull requests to update the +plugin list has been updated. Previously, the maintainers had to close +the automatically created pull requests and re-open them to trigger the +CI runs. From now on, they only need to click the `Ready for review` +button instead. + +-- by :user:`webknjaz`. From a69230ea5ff6d9f584713b2cf411bd0642debd87 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 16:51:50 +0200 Subject: [PATCH 0725/1271] =?UTF-8?q?=F0=9F=8E=A8=20Add=20descriptions=20t?= =?UTF-8?q?o=20all=20`tox`=20environments?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, a part of the environments weren't documented in the config, making it difficult for the newbies to figure out what their purposes are. This patch sets the descriptions for all the envs listed with the `tox -av` command, leveraging the dynamic factor-dependent explanation fragments. ```console default environments: linting -> run pre-commit-defined linters under `python3` py38 -> run the tests under `py38` py39 -> run the tests under `py39` py310 -> run the tests under `py310` py311 -> run the tests under `py311` py312 -> run the tests under `py312` py313 -> run the tests under `py313` pypy3 -> run the tests under `pypy3` py38-pexpect -> run the tests against `pexpect` under `py38` py38-xdist -> run the tests with pytest in parallel mode under `py38` py38-unittestextras -> run the tests against the unit test extras under `py38` py38-numpy -> run the tests against `numpy` under `py38` py38-pluggymain -> run the tests against the bleeding edge `pluggy` from Git under `py38` py38-pylib -> run the tests against `py` lib under `py38` doctesting -> run the tests under `~/.pyenv/versions/3.12.3/envs/pytest-pyenv-py3.12.3/bin/python` including doctests doctesting-coverage -> run the tests collecting coverage under `~/.pyenv/versions/3.12.3/envs/pytest-pyenv-py3.12.3/bin/python` including doctests plugins -> run reverse dependency testing against pytest plugins under `~/.pyenv/versions/3.12.3/envs/pytest-pyenv-py3.12.3/bin/python` py38-freeze -> test pytest frozen with `pyinstaller` under `py38` docs -> build the documentation site under `~/src/github/pytest-dev/pytest/doc/en/_build/html` with `python3` docs-checklinks -> check the links in the documentation with `python3` py311-exceptiongroup -> run the tests against `exceptiongroup` under `py311` additional environments: regen -> regenerate documentation examples under `python3` release -> do a release, required posarg of the version number prepare-release-pr -> prepare a release PR from a manual trigger in GitHub actions generate-gh-release-notes -> generate release notes that can be published as GitHub Release nobyte -> run the tests in no-bytecode mode under `~/.pyenv/versions/3.12.3/envs/pytest-pyenv-py3.12.3/bin/python` lsof -> run the tests with `--lsof` pytest CLI option under `~/.pyenv/versions/3.12.3/envs/pytest-pyenv-py3.12.3/bin/python` ``` --- tox.ini | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tox.ini b/tox.ini index ec74fc94b0d..61563ca2c5f 100644 --- a/tox.ini +++ b/tox.ini @@ -26,6 +26,20 @@ envlist = [testenv] +description = + run the tests + coverage: collecting coverage + exceptiongroup: against `exceptiongroup` + nobyte: in no-bytecode mode + lsof: with `--lsof` pytest CLI option + numpy: against `numpy` + pexpect: against `pexpect` + pluggymain: against the bleeding edge `pluggy` from Git + pylib: against `py` lib + unittestextras: against the unit test extras + xdist: with pytest in parallel mode + under `{basepython}` + doctesting: including doctests commands = {env:_PYTEST_TOX_COVERAGE_RUN:} pytest {posargs:{env:_PYTEST_TOX_DEFAULT_POSARGS:}} doctesting: {env:_PYTEST_TOX_COVERAGE_RUN:} pytest --doctest-modules --pyargs _pytest @@ -72,6 +86,8 @@ deps = {env:_PYTEST_TOX_EXTRA_DEP:} [testenv:linting] +description = + run pre-commit-defined linters under `{basepython}` skip_install = True basepython = python3 deps = pre-commit>=2.9.3 @@ -81,6 +97,9 @@ setenv = PYTHONWARNDEFAULTENCODING= [testenv:docs] +description = + build the documentation site under \ + `{toxinidir}{/}doc{/}en{/}_build{/}html` with `{basepython}` basepython = python3.12 # sync with rtd to get errors usedevelop = True deps = @@ -102,6 +121,8 @@ setenv = PYTHONWARNDEFAULTENCODING= [testenv:docs-checklinks] +description = + check the links in the documentation with `{basepython}` basepython = python3 usedevelop = True changedir = doc/en @@ -113,6 +134,8 @@ setenv = PYTHONWARNDEFAULTENCODING= [testenv:regen] +description = + regenerate documentation examples under `{basepython}` changedir = doc/en basepython = python3 passenv = @@ -130,6 +153,8 @@ setenv = PYTHONWARNDEFAULTENCODING= [testenv:plugins] +description = + run reverse dependency testing against pytest plugins under `{basepython}` # use latest versions of all plugins, including pre-releases pip_pre=true # use latest pip to get new dependency resolver (#7783) @@ -154,6 +179,8 @@ commands = pytest simple_integration.py --force-sugar --flakes [testenv:py38-freeze] +description = + test pytest frozen with `pyinstaller` under `{basepython}` changedir = testing/freeze deps = pyinstaller From a67327ac8ebf04bde81ac7d9bccc3d70f56c331d Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 20 Jun 2024 17:12:57 +0200 Subject: [PATCH 0726/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20to=20PR=20#12498?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12498.contrib.rst | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/12498.contrib.rst diff --git a/changelog/12498.contrib.rst b/changelog/12498.contrib.rst new file mode 100644 index 00000000000..436c6f0e9ed --- /dev/null +++ b/changelog/12498.contrib.rst @@ -0,0 +1,5 @@ +All the undocumented ``tox`` environments now have descriptions. +They can be listed in one's development environment by invoking +``tox -av`` in a terminal. + +-- by :user:`webknjaz` From 5d95f09b2acc8a1605aee64784c466ff409828df Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 21 Jun 2024 15:03:36 +0200 Subject: [PATCH 0727/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20for=20PR=20#12493?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12493.contrib.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 changelog/12493.contrib.rst diff --git a/changelog/12493.contrib.rst b/changelog/12493.contrib.rst new file mode 100644 index 00000000000..db3d045697e --- /dev/null +++ b/changelog/12493.contrib.rst @@ -0,0 +1,13 @@ +The change log draft preview integration has been refactored to use a +third party extension ``sphinxcontib-towncrier``. The previous in-repo +script was putting the change log preview file at +:file:`doc/en/_changelog_towncrier_draft.rst`. Said file is no longer +ignored in Git and might show up among untracked files in the +development environments of the contributors. To address that, the +contributors can run the following command that will clean it up: + +.. code-block:: console + + $ git clean -x -i -- doc/en/_changelog_towncrier_draft.rst + +-- by :user:`webknjaz` From 9947ec3ad1a0fb9f85b092a50b0866b3870e37ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Fri, 21 Jun 2024 17:47:23 +0200 Subject: [PATCH 0728/1271] =?UTF-8?q?=F0=9F=A7=AA=F0=9F=9A=91=20Pass=20a?= =?UTF-8?q?=20Codecov=20config=20to=20the=20action=20@=20GHA=20(#12508)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The #11921 update broke uploading coverage of the `main` branch (or any in-repo pushes for that matter) to Codecov 4 months ago. Version 4 requires an upload token to be provided and since there was no configuration for it, the upload was failing. But the step itself was showing up as successful due to `fail_ci_if_error: true` being set. The error is visible in the console output, though. This patch flips the setting to `fail_ci_if_error: false` and sets the Codecov upload token in the config in clear text. The non-secret part allows the PRs uploads to be more stable. Co-authored-by: Ronny Pfannschmidt --- .github/workflows/test.yml | 3 +-- codecov.yml | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index adc03a8c284..ab4ea3db75c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -247,9 +247,8 @@ jobs: - name: Upload coverage to Codecov if: "matrix.use_coverage" uses: codecov/codecov-action@v4 - continue-on-error: true with: - fail_ci_if_error: true + fail_ci_if_error: false files: ./coverage.xml verbose: true diff --git a/codecov.yml b/codecov.yml index f1cc8697338..0841ab049ff 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,4 +1,9 @@ # reference: https://docs.codecov.io/docs/codecovyml-reference +--- + +codecov: + token: 1eca3b1f-31a2-4fb8-a8c3-138b441b50a7 #repo token + coverage: status: patch: true From 34e28295a7bf0bdd37a5d7620ad8bfe981accb4e Mon Sep 17 00:00:00 2001 From: Farbod Ahmadian Date: Fri, 21 Jun 2024 18:20:44 +0200 Subject: [PATCH 0729/1271] refactor: simplify bound method representation (#12492) Co-authored-by: Sviatoslav Sydorenko Co-authored-by: Farbod Ahmadian --- AUTHORS | 1 + changelog/389.improvement.rst | 38 ++++++++++++++++++++++++++++++++ src/_pytest/_io/saferepr.py | 1 - src/_pytest/assertion/rewrite.py | 4 ++++ testing/test_assertrewrite.py | 29 +++++++++++++++++++++++- 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 changelog/389.improvement.rst diff --git a/AUTHORS b/AUTHORS index 347efad57b3..4d34d2ba9b4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -149,6 +149,7 @@ Evgeny Seliverstov Fabian Sturm Fabien Zarifian Fabio Zadrozny +Farbod Ahmadian faph Felix Hofstätter Felix Nieuwenhuizen diff --git a/changelog/389.improvement.rst b/changelog/389.improvement.rst new file mode 100644 index 00000000000..f8e2c19fde0 --- /dev/null +++ b/changelog/389.improvement.rst @@ -0,0 +1,38 @@ +The readability of assertion introspection of bound methods has been enhanced +-- by :user:`farbodahm`, :user:`webknjaz`, :user:`obestwalter`, :user:`flub` +and :user:`glyphack`. + +Earlier, it was like: + +.. code-block:: console + + =================================== FAILURES =================================== + _____________________________________ test _____________________________________ + + def test(): + > assert Help().fun() == 2 + E assert 1 == 2 + E + where 1 = >() + E + where > = .fun + E + where = Help() + + example.py:7: AssertionError + =========================== 1 failed in 0.03 seconds =========================== + + +And now it's like: + +.. code-block:: console + + =================================== FAILURES =================================== + _____________________________________ test _____________________________________ + + def test(): + > assert Help().fun() == 2 + E assert 1 == 2 + E + where 1 = fun() + E + where fun = .fun + E + where = Help() + + test_local.py:13: AssertionError + =========================== 1 failed in 0.03 seconds =========================== diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index 5ace418227d..13b793f0a77 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -60,7 +60,6 @@ def repr(self, x: object) -> str: s = ascii(x) else: s = super().repr(x) - except (KeyboardInterrupt, SystemExit): raise except BaseException as exc: diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 442fc5d9f30..bfcbcbd3f8d 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -417,6 +417,10 @@ def _saferepr(obj: object) -> str: sequences, especially '\n{' and '\n}' are likely to be present in JSON reprs. """ + if isinstance(obj, types.MethodType): + # for bound methods, skip redundant information + return obj.__name__ + maxsize = _get_maxsize_for_saferepr(util._config) return saferepr(obj, maxsize=maxsize).replace("\n", "\\n") diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 185cd5ef2eb..5ee40ee6568 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -10,6 +10,7 @@ import os from pathlib import Path import py_compile +import re import stat import sys import textwrap @@ -24,6 +25,7 @@ from _pytest.assertion import util from _pytest.assertion.rewrite import _get_assertion_exprs from _pytest.assertion.rewrite import _get_maxsize_for_saferepr +from _pytest.assertion.rewrite import _saferepr from _pytest.assertion.rewrite import AssertionRewritingHook from _pytest.assertion.rewrite import get_cache_dir from _pytest.assertion.rewrite import PYC_TAIL @@ -2036,7 +2038,9 @@ def test_foo(): assert test_foo_pyc.is_file() # normal file: not touched by pytest, normal cache tag - bar_init_pyc = get_cache_dir(bar_init) / f"__init__.{sys.implementation.cache_tag}.pyc" + bar_init_pyc = ( + get_cache_dir(bar_init) / f"__init__.{sys.implementation.cache_tag}.pyc" + ) assert bar_init_pyc.is_file() @@ -2103,3 +2107,26 @@ def test_foo(): ) result = pytester.runpytest() assert result.ret == 0 + + +class TestSafereprUnbounded: + class Help: + def bound_method(self): # pragma: no cover + pass + + def test_saferepr_bound_method(self): + """saferepr() of a bound method should show only the method name""" + assert _saferepr(self.Help().bound_method) == "bound_method" + + def test_saferepr_unbounded(self): + """saferepr() of an unbound method should still show the full information""" + obj = self.Help() + # using id() to fetch memory address fails on different platforms + pattern = re.compile( + rf"<{Path(__file__).stem}.{self.__class__.__name__}.Help object at 0x[0-9a-fA-F]*>", + ) + assert pattern.match(_saferepr(obj)) + assert ( + _saferepr(self.Help) + == f"" + ) From 27b255028320ac3837893298012d437cec0354ea Mon Sep 17 00:00:00 2001 From: pytest bot Date: Fri, 21 Jun 2024 13:51:03 +0000 Subject: [PATCH 0730/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 76 ++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 83d074e7f03..48f7cf9722e 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =2.7) :pypi:`pytest-assurka` A pytest plugin for Assurka Studio Aug 04, 2022 N/A N/A :pypi:`pytest-ast-back-to-python` A plugin for pytest devs to view how assertion rewriting recodes the AST Sep 29, 2019 4 - Beta N/A @@ -125,7 +126,7 @@ This list contains 1477 plugins. :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest - :pypi:`pytest-aux` templates/examples and aux for pytest Jun 10, 2024 N/A N/A + :pypi:`pytest-aux` templates/examples and aux for pytest Jun 18, 2024 N/A N/A :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -150,7 +151,7 @@ This list contains 1477 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jun 12, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jun 21, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -236,7 +237,7 @@ This list contains 1477 plugins. :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) - :pypi:`pytest-cleanslate` Collects and executes pytest tests separately May 30, 2024 N/A pytest + :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Jun 17, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Apr 19, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -304,7 +305,7 @@ This list contains 1477 plugins. :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A :pypi:`pytest-custom-exit-code` Exit pytest test session with custom exit code in different scenarios Aug 07, 2019 4 - Beta pytest (>=4.0.2) :pypi:`pytest-custom-nodeid` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 07, 2021 N/A N/A - :pypi:`pytest-custom-outputs` A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail May 30, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-custom-outputs` A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail. Also allows users to retrieve test results in fixtures. Jun 17, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A :pypi:`pytest-cython` A plugin for testing Cython extension modules Apr 05, 2024 5 - Production/Stable pytest>=8 @@ -487,7 +488,7 @@ This list contains 1477 plugins. :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 :pypi:`pytest-exasol-itde` Feb 15, 2024 N/A pytest (>=7,<9) :pypi:`pytest-exasol-saas` Jun 07, 2024 N/A pytest<9,>=7 - :pypi:`pytest-excel` pytest plugin for generating excel reports Sep 14, 2023 5 - Production/Stable N/A + :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest :pypi:`pytest-executable` pytest plugin for testing executables Oct 07, 2023 N/A pytest <8,>=5 @@ -636,7 +637,7 @@ This list contains 1477 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jun 12, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 16, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -724,7 +725,7 @@ This list contains 1477 plugins. :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-json` Generate JSON test reports Jan 18, 2016 4 - Beta N/A - :pypi:`pytest-json-ctrf` Pytest plugin to generate json report in CTRF (Common Test Report Format) May 21, 2024 N/A pytest>6.0.0 + :pypi:`pytest-json-ctrf` Pytest plugin to generate json report in CTRF (Common Test Report Format) Jun 15, 2024 N/A pytest>6.0.0 :pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Mar 14, 2023 4 - Beta N/A :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) @@ -839,7 +840,7 @@ This list contains 1477 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Apr 11, 2024 N/A pytest>=1.0 + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jun 20, 2024 N/A pytest>=1.0 :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -886,7 +887,7 @@ This list contains 1477 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jun 11, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jun 18, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Apr 11, 2024 N/A N/A @@ -1016,7 +1017,7 @@ This list contains 1477 plugins. :pypi:`pytest-proceed` Apr 10, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-progress` pytest plugin for instant test progress status Jan 31, 2022 5 - Production/Stable N/A + :pypi:`pytest-progress` pytest plugin for instant test progress status Jun 18, 2024 5 - Production/Stable pytest>=2.7 :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest :pypi:`pytest-prosper` Test helpers for Prosper projects Sep 24, 2018 N/A N/A @@ -1086,7 +1087,7 @@ This list contains 1477 plugins. :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 Dec 06, 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. Jun 10, 2024 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Jun 19, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) @@ -1198,7 +1199,7 @@ This list contains 1477 plugins. :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers May 09, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-servers` pytest servers Jun 17, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-service` May 11, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest @@ -1261,7 +1262,7 @@ This list contains 1477 plugins. :pypi:`pytest-spiratest` Exports unit tests as test runs in Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Feb 01, 2024 6 - Mature pytest >=8.0.0 - :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Jan 29, 2024 4 - Beta pytest (>=5,<9) + :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Jun 19, 2024 4 - Beta pytest<9,>=5 :pypi:`pytest-split-ext` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Sep 23, 2023 4 - Beta pytest (>=5,<8) :pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) @@ -1280,7 +1281,7 @@ This list contains 1477 plugins. :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A - :pypi:`pytest-static` pytest-static Jan 15, 2024 1 - Planning pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-static` pytest-static Jun 20, 2024 1 - Planning pytest<8.0.0,>=7.4.3 :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A @@ -1978,6 +1979,13 @@ This list contains 1477 plugins. Useful assertion utilities for use with pytest + :pypi:`pytest-assist` + *last release*: Jun 21, 2024, + *status*: N/A, + *requires*: pytest + + load testing library + :pypi:`pytest-assume` *last release*: Jun 24, 2021, *status*: N/A, @@ -2154,7 +2162,7 @@ This list contains 1477 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: Jun 10, 2024, + *last release*: Jun 18, 2024, *status*: N/A, *requires*: N/A @@ -2329,7 +2337,7 @@ This list contains 1477 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jun 12, 2024, + *last release*: Jun 21, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2931,7 +2939,7 @@ This list contains 1477 plugins. Easy quality control for CLDF datasets using pytest :pypi:`pytest-cleanslate` - *last release*: May 30, 2024, + *last release*: Jun 17, 2024, *status*: N/A, *requires*: pytest @@ -3407,11 +3415,11 @@ This list contains 1477 plugins. Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report :pypi:`pytest-custom-outputs` - *last release*: May 30, 2024, + *last release*: Jun 17, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 - A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail + A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail. Also allows users to retrieve test results in fixtures. :pypi:`pytest-custom-report` *last release*: Jan 30, 2019, @@ -4688,9 +4696,9 @@ This list contains 1477 plugins. :pypi:`pytest-excel` - *last release*: Sep 14, 2023, + *last release*: Jun 18, 2024, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest>3.6 pytest plugin for generating excel reports @@ -5731,7 +5739,7 @@ This list contains 1477 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 12, 2024, + *last release*: Jun 16, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 @@ -6347,7 +6355,7 @@ This list contains 1477 plugins. Generate JSON test reports :pypi:`pytest-json-ctrf` - *last release*: May 21, 2024, + *last release*: Jun 15, 2024, *status*: N/A, *requires*: pytest>6.0.0 @@ -7152,7 +7160,7 @@ This list contains 1477 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Apr 11, 2024, + *last release*: Jun 20, 2024, *status*: N/A, *requires*: pytest>=1.0 @@ -7481,7 +7489,7 @@ This list contains 1477 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Jun 11, 2024, + *last release*: Jun 18, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -8391,9 +8399,9 @@ This list contains 1477 plugins. Profiling plugin for py.test :pypi:`pytest-progress` - *last release*: Jan 31, 2022, + *last release*: Jun 18, 2024, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest>=2.7 pytest plugin for instant test progress status @@ -8881,7 +8889,7 @@ This list contains 1477 plugins. Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal :pypi:`pytest-redis` - *last release*: Jun 10, 2024, + *last release*: Jun 19, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.2 @@ -9665,7 +9673,7 @@ This list contains 1477 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: May 09, 2024, + *last release*: Jun 17, 2024, *status*: 3 - Alpha, *requires*: pytest>=6.2 @@ -10106,9 +10114,9 @@ This list contains 1477 plugins. Pytest plugin for the splinter automation library :pypi:`pytest-split` - *last release*: Jan 29, 2024, + *last release*: Jun 19, 2024, *status*: 4 - Beta, - *requires*: pytest (>=5,<9) + *requires*: pytest<9,>=5 Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. @@ -10239,9 +10247,9 @@ This list contains 1477 plugins. A package to prevent Dependency Confusion attacks against Yandex. :pypi:`pytest-static` - *last release*: Jan 15, 2024, + *last release*: Jun 20, 2024, *status*: 1 - Planning, - *requires*: pytest (>=7.4.3,<8.0.0) + *requires*: pytest<8.0.0,>=7.4.3 pytest-static From 15c33fbaa3e8569af0efa7532ac59f5f0fb3ba4a Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Thu, 20 Jun 2024 23:09:14 +0200 Subject: [PATCH 0731/1271] feat: support keyword arguments in marker expressions Fixes #12281 --- src/_pytest/mark/__init__.py | 34 +++++++-- src/_pytest/mark/expression.py | 110 ++++++++++++++++++++++++--- testing/test_mark.py | 48 ++++++++++++ testing/test_mark_expression.py | 129 +++++++++++++++++++++++++++++++- 4 files changed, 304 insertions(+), 17 deletions(-) diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index b8a3092151f..ae6940a6256 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -2,6 +2,7 @@ from __future__ import annotations +import collections import dataclasses from typing import AbstractSet from typing import Collection @@ -181,7 +182,9 @@ def from_item(cls, item: Item) -> KeywordMatcher: return cls(mapped_names) - def __call__(self, subname: str) -> bool: + def __call__(self, subname: str, /, **kwargs: object) -> bool: + if kwargs: + raise UsageError("Keyword expressions do not support call parameters.") subname = subname.lower() names = (name.lower() for name in self._names) @@ -211,6 +214,9 @@ def deselect_by_keyword(items: list[Item], config: Config) -> None: items[:] = remaining +NOT_NONE_SENTINEL = object() + + @dataclasses.dataclass class MarkMatcher: """A matcher for markers which are present. @@ -218,17 +224,31 @@ class MarkMatcher: Tries to match on any marker names, attached to the given colitem. """ - __slots__ = ("own_mark_names",) + __slots__ = ("own_mark_name_mapping",) - own_mark_names: AbstractSet[str] + own_mark_name_mapping: dict[str, list[Mark]] @classmethod def from_item(cls, item: Item) -> MarkMatcher: - mark_names = {mark.name for mark in item.iter_markers()} - return cls(mark_names) + mark_name_mapping = collections.defaultdict(list) + for mark in item.iter_markers(): + mark_name_mapping[mark.name].append(mark) + return cls(mark_name_mapping) + + def __call__(self, name: str, /, **kwargs: object) -> bool: + if not (matches := self.own_mark_name_mapping.get(name, [])): + return False + + if not kwargs: + return True - def __call__(self, name: str) -> bool: - return name in self.own_mark_names + for mark in matches: + if all( + mark.kwargs.get(k, NOT_NONE_SENTINEL) == v for k, v in kwargs.items() + ): + return True + + return False def deselect_by_mark(items: list[Item], config: Config) -> None: diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index e65b028589b..16883c6b7f5 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -5,7 +5,8 @@ expression: expr? EOF expr: and_expr ('or' and_expr)* and_expr: not_expr ('and' not_expr)* -not_expr: 'not' not_expr | '(' expr ')' | ident +not_expr: 'not' not_expr | '(' expr ')' | ident ( '(' name '=' value ( ', ' name '=' value )* ')')* + ident: (\w|:|\+|-|\.|\[|\]|\\|/)+ The semantics are: @@ -20,12 +21,13 @@ import ast import dataclasses import enum +import keyword import re import types -from typing import Callable from typing import Iterator from typing import Mapping from typing import NoReturn +from typing import Protocol from typing import Sequence @@ -43,6 +45,9 @@ class TokenType(enum.Enum): NOT = "not" IDENT = "identifier" EOF = "end of input" + EQUAL = "=" + STRING = "str" + COMMA = "," @dataclasses.dataclass(frozen=True) @@ -86,6 +91,27 @@ def lex(self, input: str) -> Iterator[Token]: elif input[pos] == ")": yield Token(TokenType.RPAREN, ")", pos) pos += 1 + elif input[pos] == "=": + yield Token(TokenType.EQUAL, "=", pos) + pos += 1 + elif input[pos] == ",": + yield Token(TokenType.COMMA, ",", pos) + pos += 1 + elif (quote_char := input[pos]) == "'" or input[pos] == '"': + quote_position = input[pos + 1 :].find(quote_char) + if quote_position == -1: + raise ParseError( + pos + 1, + f'closing quote "{quote_char}" is missing', + ) + value = input[pos : pos + 2 + quote_position] + if "\\" in value: + raise ParseError( + pos + 1, + "escaping not supported in marker expression", + ) + yield Token(TokenType.STRING, value, pos) + pos += len(value) else: match = re.match(r"(:?\w|:|\+|-|\.|\[|\]|\\|/)+", input[pos:]) if match: @@ -166,18 +192,84 @@ def not_expr(s: Scanner) -> ast.expr: return ret ident = s.accept(TokenType.IDENT) if ident: - return ast.Name(IDENT_PREFIX + ident.value, ast.Load()) + name = ast.Name(IDENT_PREFIX + ident.value, ast.Load()) + if s.accept(TokenType.LPAREN): + ret = ast.Call(func=name, args=[], keywords=all_kwargs(s)) + s.accept(TokenType.RPAREN, reject=True) + else: + ret = name + return ret + s.reject((TokenType.NOT, TokenType.LPAREN, TokenType.IDENT)) -class MatcherAdapter(Mapping[str, bool]): +BUILTIN_MATCHERS = {"True": True, "False": False, "None": None} + + +def single_kwarg(s: Scanner) -> ast.keyword: + keyword_name = s.accept(TokenType.IDENT, reject=True) + assert keyword_name is not None # for mypy + if not keyword_name.value.isidentifier() or keyword.iskeyword(keyword_name.value): + raise ParseError( + keyword_name.pos + 1, + f'unexpected character/s "{keyword_name.value}"', + ) + s.accept(TokenType.EQUAL, reject=True) + + if value_token := s.accept(TokenType.STRING): + value: str | int | bool | None = value_token.value[1:-1] # strip quotes + else: + value_token = s.accept(TokenType.IDENT, reject=True) + assert value_token is not None # for mypy + if ( + (number := value_token.value).isdigit() + or number.startswith("-") + and number[1:].isdigit() + ): + value = int(number) + elif value_token.value in BUILTIN_MATCHERS: + value = BUILTIN_MATCHERS[value_token.value] + else: + raise ParseError( + value_token.pos + 1, + f'unexpected character/s "{value_token.value}"', + ) + + ret = ast.keyword(keyword_name.value, ast.Constant(value)) + return ret + + +def all_kwargs(s: Scanner) -> list[ast.keyword]: + ret = [single_kwarg(s)] + while s.accept(TokenType.COMMA): + ret.append(single_kwarg(s)) + return ret + + +class MatcherCall(Protocol): + def __call__(self, name: str, /, **kwargs: object) -> bool: ... + + +@dataclasses.dataclass +class MatcherNameAdapter: + matcher: MatcherCall + name: str + + def __bool__(self) -> bool: + return self.matcher(self.name) + + def __call__(self, **kwargs: object) -> bool: + return self.matcher(self.name, **kwargs) + + +class MatcherAdapter(Mapping[str, MatcherNameAdapter]): """Adapts a matcher function to a locals mapping as required by eval().""" - def __init__(self, matcher: Callable[[str], bool]) -> None: + def __init__(self, matcher: MatcherCall) -> None: self.matcher = matcher - def __getitem__(self, key: str) -> bool: - return self.matcher(key[len(IDENT_PREFIX) :]) + def __getitem__(self, key: str) -> MatcherNameAdapter: + return MatcherNameAdapter(matcher=self.matcher, name=key[len(IDENT_PREFIX) :]) def __iter__(self) -> Iterator[str]: raise NotImplementedError() @@ -211,7 +303,7 @@ def compile(self, input: str) -> Expression: ) return Expression(code) - def evaluate(self, matcher: Callable[[str], bool]) -> bool: + def evaluate(self, matcher: MatcherCall) -> bool: """Evaluate the match expression. :param matcher: @@ -220,5 +312,5 @@ def evaluate(self, matcher: Callable[[str], bool]) -> bool: :returns: Whether the expression matches or not. """ - ret: bool = eval(self.code, {"__builtins__": {}}, MatcherAdapter(matcher)) + ret: bool = bool(eval(self.code, {"__builtins__": {}}, MatcherAdapter(matcher))) return ret diff --git a/testing/test_mark.py b/testing/test_mark.py index 090e10ee9c4..721bb71d3da 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -233,6 +233,54 @@ def test_two(): assert passed_str == expected_passed +@pytest.mark.parametrize( + ("expr", "expected_passed"), + [ # TODO: improve/sort out + ("car(color='red')", ["test_one"]), + ("car(color='red') or car(color='blue')", ["test_one", "test_two"]), + ("car and not car(temp=5)", ["test_one", "test_three"]), + ("car(temp=4)", ["test_one"]), + ("car(temp=4) or car(temp=5)", ["test_one", "test_two"]), + ("car(temp=4) and car(temp=5)", []), + ("car(temp=-5)", ["test_three"]), + ("car(ac=True)", ["test_one"]), + ("car(ac=False)", ["test_two"]), + ("car(ac=None)", ["test_three"]), # test NOT_NONE_SENTINEL + ], + ids=str, +) +def test_mark_option_with_kwargs( + expr: str, expected_passed: list[str | None], pytester: Pytester +) -> None: + pytester.makepyfile( + """ + import pytest + @pytest.mark.car + @pytest.mark.car(ac=True) + @pytest.mark.car(temp=4) + @pytest.mark.car(color="red") + def test_one(): + pass + @pytest.mark.car + @pytest.mark.car(ac=False) + @pytest.mark.car(temp=5) + @pytest.mark.car(color="blue") + def test_two(): + pass + @pytest.mark.car + @pytest.mark.car(ac=None) + @pytest.mark.car(temp=-5) + def test_three(): + pass + + """ + ) + rec = pytester.inline_run("-m", expr) + passed, skipped, fail = rec.listoutcomes() + passed_str = [x.nodeid.split("::")[-1] for x in passed] + assert passed_str == expected_passed + + @pytest.mark.parametrize( ("expr", "expected_passed"), [("interface", ["test_interface"]), ("not interface", ["test_nointer"])], diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index 5bce004cb1c..0c1e73809f7 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -1,14 +1,19 @@ from __future__ import annotations +import collections from typing import Callable +from typing import cast +from _pytest.mark import MarkMatcher +from _pytest.mark import structures from _pytest.mark.expression import Expression +from _pytest.mark.expression import MatcherCall from _pytest.mark.expression import ParseError import pytest def evaluate(input: str, matcher: Callable[[str], bool]) -> bool: - return Expression.compile(input).evaluate(matcher) + return Expression.compile(input).evaluate(cast(MatcherCall, matcher)) def test_empty_is_false() -> None: @@ -153,6 +158,8 @@ def test_syntax_errors(expr: str, column: int, message: str) -> None: "1234", "1234abcd", "1234and", + "1234or", + "1234not", "notandor", "not_and_or", "not[and]or", @@ -195,3 +202,123 @@ def test_valid_idents(ident: str) -> None: def test_invalid_idents(ident: str) -> None: with pytest.raises(ParseError): evaluate(ident, lambda ident: True) + + +@pytest.mark.parametrize( + "expr, expected_error_msg", + ( + ("mark(1=2)", 'unexpected character/s "1"'), + ("mark(/=2)", 'unexpected character/s "/"'), + ("mark(True=False)", 'unexpected character/s "True"'), + ("mark(def=False)", 'unexpected character/s "def"'), + ("mark(class=False)", 'unexpected character/s "class"'), + ("mark(if=False)", 'unexpected character/s "if"'), + ("mark(else=False)", 'unexpected character/s "else"'), + ("mark(1)", 'unexpected character/s "1"'), + ("mark(var:=False", 'unexpected character/s "var:"'), + ("mark(valid=False, def=1)", 'unexpected character/s "def"'), + ("mark(var==", "expected identifier; got ="), + ("mark(var=none)", 'unexpected character/s "none"'), + ("mark(var=1.1)", 'unexpected character/s "1.1"'), + ("mark(var)", "expected =; got right parenthesis"), + ("mark(var=')", """closing quote "'" is missing"""), + ('mark(var=")', 'closing quote """ is missing'), + ("""mark(var="')""", 'closing quote """ is missing'), + ("""mark(var='")""", """closing quote "'" is missing"""), + (r"mark(var='\hugo')", "escaping not supported in marker expression"), + ), +) +def test_invalid_kwarg_name_or_value( # TODO: move to `test_syntax_errors` ? + expr: str, expected_error_msg: str, mark_matcher: MarkMatcher +) -> None: + with pytest.raises(ParseError, match=expected_error_msg): + assert evaluate(expr, mark_matcher) + + +@pytest.fixture(scope="session") +def mark_matcher() -> MarkMatcher: + markers = [] + mark_name_mapping = collections.defaultdict(list) + + def create_marker(name: str, kwargs: dict[str, object]) -> structures.Mark: + return structures.Mark(name=name, args=tuple(), kwargs=kwargs, _ispytest=True) + + markers.append(create_marker("number_mark", {"a": 1, "b": 2, "c": 3, "d": 999_999})) + markers.append( + create_marker("builtin_matchers_mark", {"x": True, "y": False, "z": None}) + ) + markers.append( + create_marker( + "str_mark", + {"m": "M", "space": "with space", "aaאבגדcc": "aaאבגדcc", "אבגד": "אבגד"}, + ) + ) + + for marker in markers: + mark_name_mapping[marker.name].append(marker) + + return MarkMatcher(mark_name_mapping) + + +@pytest.mark.parametrize( + "expr, expected", + ( + # happy cases + ("number_mark(a=1)", True), + ("number_mark(b=2)", True), + ("number_mark(a=1,b=2)", True), + ("number_mark(a=1, b=2)", True), + ("number_mark(d=999999)", True), + ("number_mark(a = 1,b= 2, c = 3)", True), + # sad cases + ("number_mark(a=6)", False), + ("number_mark(b=6)", False), + ("number_mark(a=1,b=6)", False), + ("number_mark(a=6,b=2)", False), + ("number_mark(a = 1,b= 2, c = 6)", False), + ("number_mark(a='1')", False), + ), +) +def test_keyword_expressions_with_numbers( + expr: str, expected: bool, mark_matcher: MarkMatcher +) -> None: + assert evaluate(expr, mark_matcher) is expected + + +@pytest.mark.parametrize( + "expr, expected", + ( + ("builtin_matchers_mark(x=True)", True), + ("builtin_matchers_mark(x=False)", False), + ("builtin_matchers_mark(y=True)", False), + ("builtin_matchers_mark(y=False)", True), + ("builtin_matchers_mark(z=None)", True), + ("builtin_matchers_mark(z=False)", False), + ("builtin_matchers_mark(z=True)", False), + ("builtin_matchers_mark(z=0)", False), + ("builtin_matchers_mark(z=1)", False), + ), +) +def test_builtin_matchers_keyword_expressions( # TODO: naming when decided + expr: str, expected: bool, mark_matcher: MarkMatcher +) -> None: + assert evaluate(expr, mark_matcher) is expected + + +@pytest.mark.parametrize( + "expr, expected", + ( + ("str_mark(m='M')", True), + ('str_mark(m="M")', True), + ("str_mark(aaאבגדcc='aaאבגדcc')", True), + ("str_mark(אבגד='אבגד')", True), + ("str_mark(space='with space')", True), + ("str_mark(m='wrong')", False), + ("str_mark(aaאבגדcc='wrong')", False), + ("str_mark(אבגד='wrong')", False), + ), +) +def test_str_keyword_expressions( + expr: str, expected: bool, mark_matcher: MarkMatcher +) -> None: + assert evaluate(expr, mark_matcher) is expected From 04f457c4f4fb38ea7ba8c88cd3a15fdc83722840 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Thu, 20 Jun 2024 23:05:22 +0200 Subject: [PATCH 0732/1271] style: use `@overload` to get rid of mypy only assertions --- src/_pytest/mark/expression.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 16883c6b7f5..39d262c801a 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -25,8 +25,10 @@ import re import types from typing import Iterator +from typing import Literal from typing import Mapping from typing import NoReturn +from typing import overload from typing import Protocol from typing import Sequence @@ -132,6 +134,14 @@ def lex(self, input: str) -> Iterator[Token]: ) yield Token(TokenType.EOF, "", pos) + @overload + def accept(self, type: TokenType, *, reject: Literal[True]) -> Token: ... + + @overload + def accept( + self, type: TokenType, *, reject: Literal[False] = False + ) -> Token | None: ... + def accept(self, type: TokenType, *, reject: bool = False) -> Token | None: if self.current.type is type: token = self.current @@ -208,7 +218,6 @@ def not_expr(s: Scanner) -> ast.expr: def single_kwarg(s: Scanner) -> ast.keyword: keyword_name = s.accept(TokenType.IDENT, reject=True) - assert keyword_name is not None # for mypy if not keyword_name.value.isidentifier() or keyword.iskeyword(keyword_name.value): raise ParseError( keyword_name.pos + 1, @@ -220,7 +229,6 @@ def single_kwarg(s: Scanner) -> ast.keyword: value: str | int | bool | None = value_token.value[1:-1] # strip quotes else: value_token = s.accept(TokenType.IDENT, reject=True) - assert value_token is not None # for mypy if ( (number := value_token.value).isdigit() or number.startswith("-") From 1cc35ecc3fdf28c201fbaf775945bae24be17ce7 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Thu, 20 Jun 2024 23:23:02 +0200 Subject: [PATCH 0733/1271] test: add empty string keyword argument marker test cases --- testing/test_mark_expression.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index 0c1e73809f7..e7ecaa7db10 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -250,7 +250,13 @@ def create_marker(name: str, kwargs: dict[str, object]) -> structures.Mark: markers.append( create_marker( "str_mark", - {"m": "M", "space": "with space", "aaאבגדcc": "aaאבגדcc", "אבגד": "אבגד"}, + { + "m": "M", + "space": "with space", + "aaאבגדcc": "aaאבגדcc", + "אבגד": "אבגד", + "empty": "", + }, ) ) @@ -313,9 +319,13 @@ def test_builtin_matchers_keyword_expressions( # TODO: naming when decided ("str_mark(aaאבגדcc='aaאבגדcc')", True), ("str_mark(אבגד='אבגד')", True), ("str_mark(space='with space')", True), + ("str_mark(empty='')", True), + ('str_mark(empty="")', True), ("str_mark(m='wrong')", False), ("str_mark(aaאבגדcc='wrong')", False), ("str_mark(אבגד='wrong')", False), + ("str_mark(m='')", False), + ('str_mark(m="")', False), ), ) def test_str_keyword_expressions( From f4897391ec65b6f7b162d93b7b48a6587f9b659b Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 14:04:42 +0200 Subject: [PATCH 0734/1271] refactor(mark): use existing `NOT_SET` sentinel --- src/_pytest/mark/__init__.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index ae6940a6256..ddfa8355a73 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -22,6 +22,7 @@ from _pytest.config import ExitCode from _pytest.config import hookimpl from _pytest.config import UsageError +from _pytest.config.argparsing import NOT_SET from _pytest.config.argparsing import Parser from _pytest.stash import StashKey @@ -214,9 +215,6 @@ def deselect_by_keyword(items: list[Item], config: Config) -> None: items[:] = remaining -NOT_NONE_SENTINEL = object() - - @dataclasses.dataclass class MarkMatcher: """A matcher for markers which are present. @@ -243,9 +241,7 @@ def __call__(self, name: str, /, **kwargs: object) -> bool: return True for mark in matches: - if all( - mark.kwargs.get(k, NOT_NONE_SENTINEL) == v for k, v in kwargs.items() - ): + if all(mark.kwargs.get(k, NOT_SET) == v for k, v in kwargs.items()): return True return False From 1e7eb20347819eb86cd22be998fef0dc50db47da Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 12:07:31 +0200 Subject: [PATCH 0735/1271] perf(expression): improve string lexing & error messages --- src/_pytest/mark/expression.py | 23 ++++++++++++++--------- testing/test_mark_expression.py | 28 ++++++++++++++++------------ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 39d262c801a..c1770c197b8 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -99,18 +99,18 @@ def lex(self, input: str) -> Iterator[Token]: elif input[pos] == ",": yield Token(TokenType.COMMA, ",", pos) pos += 1 - elif (quote_char := input[pos]) == "'" or input[pos] == '"': - quote_position = input[pos + 1 :].find(quote_char) - if quote_position == -1: + elif (quote_char := input[pos]) in ("'", '"'): + end_quote_pos = input.find(quote_char, pos + 1) + if end_quote_pos == -1: raise ParseError( pos + 1, f'closing quote "{quote_char}" is missing', ) - value = input[pos : pos + 2 + quote_position] - if "\\" in value: + value = input[pos : end_quote_pos + 1] + if (backslash_pos := input.find("\\")) != -1: raise ParseError( - pos + 1, - "escaping not supported in marker expression", + backslash_pos + 1, + r'escaping with "\" not supported in marker expression', ) yield Token(TokenType.STRING, value, pos) pos += len(value) @@ -218,10 +218,15 @@ def not_expr(s: Scanner) -> ast.expr: def single_kwarg(s: Scanner) -> ast.keyword: keyword_name = s.accept(TokenType.IDENT, reject=True) - if not keyword_name.value.isidentifier() or keyword.iskeyword(keyword_name.value): + if not keyword_name.value.isidentifier(): + raise ParseError( + keyword_name.pos + 1, + f"not a valid python identifier {keyword_name.value}", + ) + if keyword.iskeyword(keyword_name.value): raise ParseError( keyword_name.pos + 1, - f'unexpected character/s "{keyword_name.value}"', + f"unexpected reserved python keyword `{keyword_name.value}`", ) s.accept(TokenType.EQUAL, reject=True) diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index e7ecaa7db10..3c42cc96737 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -207,25 +207,29 @@ def test_invalid_idents(ident: str) -> None: @pytest.mark.parametrize( "expr, expected_error_msg", ( - ("mark(1=2)", 'unexpected character/s "1"'), - ("mark(/=2)", 'unexpected character/s "/"'), - ("mark(True=False)", 'unexpected character/s "True"'), - ("mark(def=False)", 'unexpected character/s "def"'), - ("mark(class=False)", 'unexpected character/s "class"'), - ("mark(if=False)", 'unexpected character/s "if"'), - ("mark(else=False)", 'unexpected character/s "else"'), - ("mark(1)", 'unexpected character/s "1"'), - ("mark(var:=False", 'unexpected character/s "var:"'), - ("mark(valid=False, def=1)", 'unexpected character/s "def"'), + ("mark(True=False)", "unexpected reserved python keyword `True`"), + ("mark(def=False)", "unexpected reserved python keyword `def`"), + ("mark(class=False)", "unexpected reserved python keyword `class`"), + ("mark(if=False)", "unexpected reserved python keyword `if`"), + ("mark(else=False)", "unexpected reserved python keyword `else`"), + ("mark(valid=False, def=1)", "unexpected reserved python keyword `def`"), + ("mark(1)", "not a valid python identifier 1"), + ("mark(var:=False", "not a valid python identifier var:"), + ("mark(1=2)", "not a valid python identifier 1"), + ("mark(/=2)", "not a valid python identifier /"), ("mark(var==", "expected identifier; got ="), + ("mark(var)", "expected =; got right parenthesis"), ("mark(var=none)", 'unexpected character/s "none"'), ("mark(var=1.1)", 'unexpected character/s "1.1"'), - ("mark(var)", "expected =; got right parenthesis"), ("mark(var=')", """closing quote "'" is missing"""), ('mark(var=")', 'closing quote """ is missing'), ("""mark(var="')""", 'closing quote """ is missing'), ("""mark(var='")""", """closing quote "'" is missing"""), - (r"mark(var='\hugo')", "escaping not supported in marker expression"), + ( + r"mark(var='\hugo')", + r'escaping with "\\" not supported in marker expression', + ), + ("mark(empty_list=[])", r'unexpected character/s "\[\]"'), ), ) def test_invalid_kwarg_name_or_value( # TODO: move to `test_syntax_errors` ? From 6dd8ad60a49d3ba1e4071cf40a955c050ad78b08 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 14:41:22 +0200 Subject: [PATCH 0736/1271] refactor(MarkMatcher): replace `from_item` with `from_markers` method --- src/_pytest/mark/__init__.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index ddfa8355a73..dccc6c529c9 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -6,6 +6,7 @@ import dataclasses from typing import AbstractSet from typing import Collection +from typing import Iterable from typing import Optional from typing import TYPE_CHECKING @@ -227,9 +228,9 @@ class MarkMatcher: own_mark_name_mapping: dict[str, list[Mark]] @classmethod - def from_item(cls, item: Item) -> MarkMatcher: + def from_markers(cls, markers: Iterable[Mark]) -> MarkMatcher: mark_name_mapping = collections.defaultdict(list) - for mark in item.iter_markers(): + for mark in markers: mark_name_mapping[mark.name].append(mark) return cls(mark_name_mapping) @@ -256,7 +257,7 @@ def deselect_by_mark(items: list[Item], config: Config) -> None: remaining: list[Item] = [] deselected: list[Item] = [] for item in items: - if expr.evaluate(MarkMatcher.from_item(item)): + if expr.evaluate(MarkMatcher.from_markers(item.iter_markers())): remaining.append(item) else: deselected.append(item) From 3921d94316866954db9b60f05e6d7c627cd20bbf Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 14:45:27 +0200 Subject: [PATCH 0737/1271] test: use new `MarkMatcher.from_markers` method & register test markers --- pyproject.toml | 3 +++ testing/test_mark_expression.py | 38 ++++++++------------------------- 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 14f69bc3422..e0ed2b90061 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -358,6 +358,9 @@ markers = [ "foo", "bar", "baz", + "number_mark", + "builtin_matchers_mark", + "str_mark", # conftest.py reorders tests moving slow ones to the end of the list "slow", # experimental mark for all tests using pexpect diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index 3c42cc96737..c31ab44704c 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -1,11 +1,9 @@ from __future__ import annotations -import collections from typing import Callable from typing import cast from _pytest.mark import MarkMatcher -from _pytest.mark import structures from _pytest.mark.expression import Expression from _pytest.mark.expression import MatcherCall from _pytest.mark.expression import ParseError @@ -241,33 +239,15 @@ def test_invalid_kwarg_name_or_value( # TODO: move to `test_syntax_errors` ? @pytest.fixture(scope="session") def mark_matcher() -> MarkMatcher: - markers = [] - mark_name_mapping = collections.defaultdict(list) - - def create_marker(name: str, kwargs: dict[str, object]) -> structures.Mark: - return structures.Mark(name=name, args=tuple(), kwargs=kwargs, _ispytest=True) - - markers.append(create_marker("number_mark", {"a": 1, "b": 2, "c": 3, "d": 999_999})) - markers.append( - create_marker("builtin_matchers_mark", {"x": True, "y": False, "z": None}) - ) - markers.append( - create_marker( - "str_mark", - { - "m": "M", - "space": "with space", - "aaאבגדcc": "aaאבגדcc", - "אבגד": "אבגד", - "empty": "", - }, - ) - ) - - for marker in markers: - mark_name_mapping[marker.name].append(marker) - - return MarkMatcher(mark_name_mapping) + markers = [ + pytest.mark.number_mark(a=1, b=2, c=3, d=999_999).mark, + pytest.mark.builtin_matchers_mark(x=True, y=False, z=None).mark, + pytest.mark.str_mark( + m="M", space="with space", empty="", aaאבגדcc="aaאבגדcc", אבגד="אבגד" + ).mark, + ] + + return MarkMatcher.from_markers(markers) @pytest.mark.parametrize( From 7c7c36d7e07134242b2af4c8a291268a94cd4619 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 15:11:56 +0200 Subject: [PATCH 0738/1271] test(test_mark.py): add sad case that `-k` doesn't support keyword expressions --- testing/test_mark.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testing/test_mark.py b/testing/test_mark.py index 721bb71d3da..6a94cc9f7c2 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -420,6 +420,10 @@ def test_func(arg): "not or", "at column 5: expected not OR left parenthesis OR identifier; got or", ), + ( + "nonexistent_mark(non_supported='kwarg')", + "Keyword expressions do not support call parameters", + ), ], ) def test_keyword_option_wrong_arguments( From 598d881c9c21e47c00755b9a40e66aca8eec17d1 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 15:57:13 +0200 Subject: [PATCH 0739/1271] docs: document keyword argument support in marker expressions --- doc/en/example/markers.rst | 24 ++++++++++++++++++++++++ doc/en/how-to/usage.rst | 10 +++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index c04d2a078dd..33c5cf95fe2 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -25,10 +25,12 @@ You can "mark" a test function with custom metadata like this: pass # perform some webtest test for your app + @pytest.mark.device(serial="123") def test_something_quick(): pass + @pytest.mark.device(serial="abc") def test_another(): pass @@ -71,6 +73,28 @@ Or the inverse, running all tests except the webtest ones: ===================== 3 passed, 1 deselected in 0.12s ====================== +.. _`marker_keyword_expression_example`: + +Additionally, you can restrict a test run to only run tests matching one or multiple marker +keyword arguments, e.g. to run only tests marked with ``device`` and the specific ``serial="123"``: + +.. code-block:: pytest + + $ pytest -v -m 'device(serial="123")' + =========================== test session starts ============================ + platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python + cachedir: .pytest_cache + rootdir: /home/sweet/project + collecting ... collected 4 items / 3 deselected / 1 selected + + test_server.py::test_something_quick PASSED [100%] + + ===================== 1 passed, 3 deselected in 0.12s ====================== + +.. note:: Only keyword argument matching is supported in marker expressions. + +.. note:: Only ``int``, (unescaped) ``str``, ``bool`` & ``None`` values are supported in marker expressions. + Selecting tests based on their node ID -------------------------------------- diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 705fa009ed5..05ee0460019 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -76,11 +76,19 @@ Specifying a specific parametrization of a test: **Run tests by marker expressions** +To run all tests which are decorated with the ``@pytest.mark.slow`` decorator: + .. code-block:: bash pytest -m slow -Will run all tests which are decorated with the ``@pytest.mark.slow`` decorator. + +To run all tests which are decorated with the annotated ``@pytest.mark.slow(phase=1)`` decorator, +with the ``phase`` keyword argument set to ``1``: + +.. code-block:: bash + + pytest -m slow(phase=1) For more information see :ref:`marks `. From 9cf9cfabcb2dfa41c9f168259e84b7d658cbf690 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 16:23:16 +0200 Subject: [PATCH 0740/1271] docs(12281.feature.rst): add changelog fragment --- changelog/12281.feature.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 changelog/12281.feature.rst diff --git a/changelog/12281.feature.rst b/changelog/12281.feature.rst new file mode 100644 index 00000000000..e5dd63824e4 --- /dev/null +++ b/changelog/12281.feature.rst @@ -0,0 +1,8 @@ +Added support for keyword matching in marker expressions. + +Now tests can be selected by marker keyword arguments. +Supported values are ``int``, (unescaped) ``str``, ``bool`` & ``None``. + +See :ref:`marker examples ` for more information. + +-- by :user:`lovetheguitar`. From c3e898353bda6fb7954e1634a0cadddd1c73b1a4 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 16:31:30 +0200 Subject: [PATCH 0741/1271] docs(AUTHORS): add myself as contributor --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 4d34d2ba9b4..5ae80eb02d3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -245,6 +245,7 @@ Levon Saldamli Lewis Cowles Llandy Riveron Del Risco Loic Esteve +lovetheguitar Lukas Bednar Luke Murphy Maciek Fijalkowski From b1255a9aae1bd94d8c226b207c38942c857d4794 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Fri, 21 Jun 2024 17:11:39 +0200 Subject: [PATCH 0742/1271] style(mark): type hint `**kwargs` as `str | int | bool | None` --- src/_pytest/mark/__init__.py | 4 ++-- src/_pytest/mark/expression.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index dccc6c529c9..702732c9708 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -184,7 +184,7 @@ def from_item(cls, item: Item) -> KeywordMatcher: return cls(mapped_names) - def __call__(self, subname: str, /, **kwargs: object) -> bool: + def __call__(self, subname: str, /, **kwargs: str | int | bool | None) -> bool: if kwargs: raise UsageError("Keyword expressions do not support call parameters.") subname = subname.lower() @@ -234,7 +234,7 @@ def from_markers(cls, markers: Iterable[Mark]) -> MarkMatcher: mark_name_mapping[mark.name].append(mark) return cls(mark_name_mapping) - def __call__(self, name: str, /, **kwargs: object) -> bool: + def __call__(self, name: str, /, **kwargs: str | int | bool | None) -> bool: if not (matches := self.own_mark_name_mapping.get(name, [])): return False diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index c1770c197b8..3f4071dcef8 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -260,7 +260,7 @@ def all_kwargs(s: Scanner) -> list[ast.keyword]: class MatcherCall(Protocol): - def __call__(self, name: str, /, **kwargs: object) -> bool: ... + def __call__(self, name: str, /, **kwargs: str | int | bool | None) -> bool: ... @dataclasses.dataclass @@ -271,7 +271,7 @@ class MatcherNameAdapter: def __bool__(self) -> bool: return self.matcher(self.name) - def __call__(self, **kwargs: object) -> bool: + def __call__(self, **kwargs: str | int | bool | None) -> bool: return self.matcher(self.name, **kwargs) From 24450e33e364f1aa7f4e2cc3e029e7d1b186774b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Fri, 21 Jun 2024 22:05:43 +0200 Subject: [PATCH 0743/1271] =?UTF-8?q?=F0=9F=93=9D=20Use=20explicit=20RST?= =?UTF-8?q?=20roles=20for=20built-in=20types=20in=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12281.feature.rst | 2 +- doc/en/example/markers.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/12281.feature.rst b/changelog/12281.feature.rst index e5dd63824e4..bcf882c511b 100644 --- a/changelog/12281.feature.rst +++ b/changelog/12281.feature.rst @@ -1,7 +1,7 @@ Added support for keyword matching in marker expressions. Now tests can be selected by marker keyword arguments. -Supported values are ``int``, (unescaped) ``str``, ``bool`` & ``None``. +Supported values are :class:`int`, (unescaped) :class:`str`, :class:`bool` & :data:`None`. See :ref:`marker examples ` for more information. diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 33c5cf95fe2..159ff2cd1d7 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -93,7 +93,7 @@ keyword arguments, e.g. to run only tests marked with ``device`` and the specifi .. note:: Only keyword argument matching is supported in marker expressions. -.. note:: Only ``int``, (unescaped) ``str``, ``bool`` & ``None`` values are supported in marker expressions. +.. note:: Only :class:`int`, (unescaped) :class:`str`, :class:`bool` & :data:`None` values are supported in marker expressions. Selecting tests based on their node ID -------------------------------------- From 329662e2eca801be53678fde7e1ef23583eb5fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Fri, 21 Jun 2024 22:06:33 +0200 Subject: [PATCH 0744/1271] =?UTF-8?q?=F0=9F=93=9D=20Drop=20stray=20trailin?= =?UTF-8?q?g=20period=20from=20the=20change=20note=20byline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12281.feature.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/12281.feature.rst b/changelog/12281.feature.rst index bcf882c511b..c6e8e3b3098 100644 --- a/changelog/12281.feature.rst +++ b/changelog/12281.feature.rst @@ -5,4 +5,4 @@ Supported values are :class:`int`, (unescaped) :class:`str`, :class:`bool` & :da See :ref:`marker examples ` for more information. --- by :user:`lovetheguitar`. +-- by :user:`lovetheguitar` From 75a2225ed1d387e6a224be9b0f9d7297bfb08284 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Fri, 21 Jun 2024 22:09:45 +0200 Subject: [PATCH 0745/1271] =?UTF-8?q?=F0=9F=94=A5=20Drop=20the=20missing?= =?UTF-8?q?=20kwargs=20case?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/_pytest/mark/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index 702732c9708..a4f942c5ae3 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -238,9 +238,6 @@ def __call__(self, name: str, /, **kwargs: str | int | bool | None) -> bool: if not (matches := self.own_mark_name_mapping.get(name, [])): return False - if not kwargs: - return True - for mark in matches: if all(mark.kwargs.get(k, NOT_SET) == v for k, v in kwargs.items()): return True From 1b85ac126eb5490f7afa1499a502d01c64be2cf5 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 21 Jun 2024 22:52:17 +0200 Subject: [PATCH 0746/1271] =?UTF-8?q?=F0=9F=9A=91=F0=9F=A7=AA=20Set=20the?= =?UTF-8?q?=20Codecov=20token=20directly=20in=20GHA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's necessary since it seems that the currently used Codecov uploader doesn't read the token from config sometimes. This is a follow-up for #12508 which wasn't enough. --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ab4ea3db75c..e9d0f233c42 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -250,6 +250,7 @@ jobs: with: fail_ci_if_error: false files: ./coverage.xml + token: 1eca3b1f-31a2-4fb8-a8c3-138b441b50a7 #repo token; cfg read fails verbose: true check: # This job does nothing and is only used for the branch protection From c716e0baefb31e62ae8275c3b8d7c8e976b010b4 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 21 Jun 2024 23:06:26 +0200 Subject: [PATCH 0747/1271] =?UTF-8?q?=F0=9F=A7=AA=20Bump=20the=20`alls-gre?= =?UTF-8?q?en`=20action=20to=20223erbb7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This version drops the use of the outdated GHA syntax for setting action output values. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ab4ea3db75c..d78e0900fd9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -262,6 +262,6 @@ jobs: steps: - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@198badcb65a1a44528f27d5da555c4be9f12eac6 + uses: re-actors/alls-green@223e4bb7a751b91f43eda76992bcfbf23b8b0302 with: jobs: ${{ toJSON(needs) }} From 66eff85e5424f0274e15081eb4185a2e23b4c167 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Sat, 22 Jun 2024 19:48:15 +0200 Subject: [PATCH 0748/1271] docs: use double quotes for cross-platform compatibility in example code --- doc/en/example/markers.rst | 2 +- doc/en/how-to/usage.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/example/markers.rst b/doc/en/example/markers.rst index 159ff2cd1d7..babcd9e2f3a 100644 --- a/doc/en/example/markers.rst +++ b/doc/en/example/markers.rst @@ -80,7 +80,7 @@ keyword arguments, e.g. to run only tests marked with ``device`` and the specifi .. code-block:: pytest - $ pytest -v -m 'device(serial="123")' + $ pytest -v -m "device(serial='123')" =========================== test session starts ============================ platform linux -- Python 3.x.y, pytest-8.x.y, pluggy-1.x.y -- $PYTHON_PREFIX/bin/python cachedir: .pytest_cache diff --git a/doc/en/how-to/usage.rst b/doc/en/how-to/usage.rst index 05ee0460019..0e0a0310fd8 100644 --- a/doc/en/how-to/usage.rst +++ b/doc/en/how-to/usage.rst @@ -88,7 +88,7 @@ with the ``phase`` keyword argument set to ``1``: .. code-block:: bash - pytest -m slow(phase=1) + pytest -m "slow(phase=1)" For more information see :ref:`marks `. From 73bc35ce2b22723a87c26cad6aa7835dcdc060cf Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Sat, 22 Jun 2024 19:49:59 +0200 Subject: [PATCH 0749/1271] docs(expression.py): correct grammar definition of lexer --- src/_pytest/mark/expression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 3f4071dcef8..3b7f4c51b42 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -5,7 +5,7 @@ expression: expr? EOF expr: and_expr ('or' and_expr)* and_expr: not_expr ('and' not_expr)* -not_expr: 'not' not_expr | '(' expr ')' | ident ( '(' name '=' value ( ', ' name '=' value )* ')')* +not_expr: 'not' not_expr | '(' expr ')' | ident ('(' name '=' value ( ', ' name '=' value )* ')')? ident: (\w|:|\+|-|\.|\[|\]|\\|/)+ From 3cce243774b03125bb123a7b69f684ea0abba34b Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Sat, 22 Jun 2024 19:50:26 +0200 Subject: [PATCH 0750/1271] docs(expression.py): fix typo --- src/_pytest/mark/expression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 3b7f4c51b42..2067110d23a 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -12,7 +12,7 @@ The semantics are: - Empty expression evaluates to False. -- ident evaluates to True of False according to a provided matcher function. +- ident evaluates to True or False according to a provided matcher function. - or/and/not evaluate according to the usual boolean semantics. """ From 66dbab697bb2a14801cd744a0d78c3cd69c3f809 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 22 Jun 2024 21:54:45 +0200 Subject: [PATCH 0751/1271] =?UTF-8?q?=F0=9F=93=9D=20Rename=20`:pull:`=20RS?= =?UTF-8?q?T=20role=20to=20`:pr:`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a preparatory patch for integrating the third party `sphinx-issues` extension. --- doc/en/announce/release-2.9.0.rst | 2 +- doc/en/announce/release-2.9.1.rst | 2 +- doc/en/announce/release-2.9.2.rst | 4 +- doc/en/changelog.rst | 98 +++++++++++++++---------------- doc/en/conf.py | 2 +- doc/en/historical-notes.rst | 2 +- 6 files changed, 55 insertions(+), 55 deletions(-) diff --git a/doc/en/announce/release-2.9.0.rst b/doc/en/announce/release-2.9.0.rst index 3aea08cb225..753bb7bf6f0 100644 --- a/doc/en/announce/release-2.9.0.rst +++ b/doc/en/announce/release-2.9.0.rst @@ -45,7 +45,7 @@ The py.test Development Team **New Features** * New ``pytest.mark.skip`` mark, which unconditionally skips marked tests. - Thanks :user:`MichaelAquilina` for the complete PR (:pull:`1040`). + Thanks :user:`MichaelAquilina` for the complete PR (:pr:`1040`). * ``--doctest-glob`` may now be passed multiple times in the command-line. Thanks :user:`jab` and :user:`nicoddemus` for the PR. diff --git a/doc/en/announce/release-2.9.1.rst b/doc/en/announce/release-2.9.1.rst index 6a627ad3cd6..7a46d2ae690 100644 --- a/doc/en/announce/release-2.9.1.rst +++ b/doc/en/announce/release-2.9.1.rst @@ -44,7 +44,7 @@ The py.test Development Team Thanks :user:`nicoddemus` for the PR. * Fix (:issue:`469`): junit parses report.nodeid incorrectly, when params IDs - contain ``::``. Thanks :user:`tomviner` for the PR (:pull:`1431`). + contain ``::``. Thanks :user:`tomviner` for the PR (:pr:`1431`). * Fix (:issue:`578`): SyntaxErrors containing non-ascii lines at the point of failure generated an internal diff --git a/doc/en/announce/release-2.9.2.rst b/doc/en/announce/release-2.9.2.rst index 2dc82a1117b..3e75af7fe69 100644 --- a/doc/en/announce/release-2.9.2.rst +++ b/doc/en/announce/release-2.9.2.rst @@ -44,14 +44,14 @@ The py.test Development Team * Fix Xfail does not work with condition keyword argument. Thanks :user:`astraw38` for reporting the issue (:issue:`1496`) and :user:`tomviner` - for PR the (:pull:`1524`). + for PR the (:pr:`1524`). * Fix win32 path issue when putting custom config file with absolute path in ``pytest.main("-c your_absolute_path")``. * Fix maximum recursion depth detection when raised error class is not aware of unicode/encoded bytes. - Thanks :user:`prusse-martin` for the PR (:pull:`1506`). + Thanks :user:`prusse-martin` for the PR (:pr:`1506`). * Fix ``pytest.mark.skip`` mark when used in strict mode. Thanks :user:`pquentin` for the PR and :user:`RonnyPfannschmidt` for diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 7e32b943446..2c07f208ac3 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -268,7 +268,7 @@ Bug Fixes - `#11904 `_: Fixed a regression in pytest 8.0.0 that would cause test collection to fail due to permission errors when using ``--pyargs``. - This change improves the collection tree for tests specified using ``--pyargs``, see :pull:`12043` for a comparison with pytest 8.0 and <8. + This change improves the collection tree for tests specified using ``--pyargs``, see :pr:`12043` for a comparison with pytest 8.0 and <8. - `#12011 `_: Fixed a regression in 8.0.1 whereby ``setup_module`` xunit-style fixtures are not executed when ``--doctest-modules`` is passed. @@ -1422,7 +1422,7 @@ Bug Fixes tests/link -> tests/real running ``pytest tests`` now imports the conftest twice, once as ``tests/real/conftest.py`` and once as ``tests/link/conftest.py``. - This is a fix to match a similar change made to test collection itself in pytest 6.0 (see :pull:`6523` for details). + This is a fix to match a similar change made to test collection itself in pytest 6.0 (see :pr:`6523` for details). - `#9626 `_: Fixed count of selected tests on terminal collection summary when there were errors or skipped modules. @@ -2591,7 +2591,7 @@ Breaking Changes Resolving symlinks for the current directory and during collection was introduced as a bugfix in 3.9.0, but it actually is a new feature which had unfortunate consequences in Windows and surprising results in other platforms. The team decided to step back on resolving symlinks at all, planning to review this in the future with a more solid solution (see discussion in - :pull:`6523` for details). + :pr:`6523` for details). This might break test suites which made use of this feature; the fix is to create a symlink for the entire test tree, and not only to partial files/tress as it was possible previously. @@ -2874,7 +2874,7 @@ Bug Fixes - :issue:`6871`: Fix crash with captured output when using :fixture:`capsysbinary`. -- :issue:`6909`: Revert the change introduced by :pull:`6330`, which required all arguments to ``@pytest.mark.parametrize`` to be explicitly defined in the function signature. +- :issue:`6909`: Revert the change introduced by :pr:`6330`, which required all arguments to ``@pytest.mark.parametrize`` to be explicitly defined in the function signature. The intention of the original change was to remove what was expected to be an unintended/surprising behavior, but it turns out many people relied on it, so the restriction has been reverted. @@ -3044,7 +3044,7 @@ pytest 5.4.1 (2020-03-13) Bug Fixes --------- -- :issue:`6909`: Revert the change introduced by :pull:`6330`, which required all arguments to ``@pytest.mark.parametrize`` to be explicitly defined in the function signature. +- :issue:`6909`: Revert the change introduced by :pr:`6330`, which required all arguments to ``@pytest.mark.parametrize`` to be explicitly defined in the function signature. The intention of the original change was to remove what was expected to be an unintended/surprising behavior, but it turns out many people relied on it, so the restriction has been reverted. @@ -4067,7 +4067,7 @@ Bug Fixes (``--collect-only``) when ``--log-cli-level`` is used. -- :issue:`5389`: Fix regressions of :pull:`5063` for ``importlib_metadata.PathDistribution`` which have their ``files`` attribute being ``None``. +- :issue:`5389`: Fix regressions of :pr:`5063` for ``importlib_metadata.PathDistribution`` which have their ``files`` attribute being ``None``. - :issue:`5390`: Fix regression where the ``obj`` attribute of ``TestCase`` items was no longer bound to methods. @@ -4268,7 +4268,7 @@ Bug Fixes (``--collect-only``) when ``--log-cli-level`` is used. -- :issue:`5389`: Fix regressions of :pull:`5063` for ``importlib_metadata.PathDistribution`` which have their ``files`` attribute being ``None``. +- :issue:`5389`: Fix regressions of :pr:`5063` for ``importlib_metadata.PathDistribution`` which have their ``files`` attribute being ``None``. - :issue:`5390`: Fix regression where the ``obj`` attribute of ``TestCase`` items was no longer bound to methods. @@ -7229,10 +7229,10 @@ New Features * Added ``junit_suite_name`` ini option to specify root ```` name for JUnit XML reports (:issue:`533`). * Added an ini option ``doctest_encoding`` to specify which encoding to use for doctest files. - Thanks :user:`wheerd` for the PR (:pull:`2101`). + Thanks :user:`wheerd` for the PR (:pr:`2101`). * ``pytest.warns`` now checks for subclass relationship rather than - class equality. Thanks :user:`lesteve` for the PR (:pull:`2166`) + class equality. Thanks :user:`lesteve` for the PR (:pr:`2166`) * ``pytest.raises`` now asserts that the error message matches a text or regex with the ``match`` keyword argument. Thanks :user:`Kriechi` for the PR. @@ -7260,7 +7260,7 @@ Changes the failure. (:issue:`2228`) Thanks to :user:`kkoukiou` for the PR. * Testcase reports with a ``url`` attribute will now properly write this to junitxml. - Thanks :user:`fushi` for the PR (:pull:`1874`). + Thanks :user:`fushi` for the PR (:pr:`1874`). * Remove common items from dict comparison output when verbosity=1. Also update the truncation message to make it clearer that pytest truncates all @@ -7269,7 +7269,7 @@ Changes * ``--pdbcls`` no longer implies ``--pdb``. This makes it possible to use ``addopts=--pdbcls=module.SomeClass`` on ``pytest.ini``. Thanks :user:`davidszotten` for - the PR (:pull:`1952`). + the PR (:pr:`1952`). * fix :issue:`2013`: turn RecordedWarning into ``namedtuple``, to give it a comprehensible repr while preventing unwarranted modification. @@ -7523,7 +7523,7 @@ Bug Fixes a sequence of strings) when modules are considered for assertion rewriting. Due to this bug, much more modules were being rewritten than necessary if a test suite uses ``pytest_plugins`` to load internal plugins (:issue:`1888`). - Thanks :user:`jaraco` for the report and :user:`nicoddemus` for the PR (:pull:`1891`). + Thanks :user:`jaraco` for the report and :user:`nicoddemus` for the PR (:pr:`1891`). * Do not call tearDown and cleanups when running tests from ``unittest.TestCase`` subclasses with ``--pdb`` @@ -7578,12 +7578,12 @@ time or change existing behaviors in order to make them less surprising/more use * ``--nomagic``: use ``--assert=plain`` instead; * ``--report``: use ``-r`` instead; - Thanks to :user:`RedBeardCode` for the PR (:pull:`1664`). + Thanks to :user:`RedBeardCode` for the PR (:pr:`1664`). * ImportErrors in plugins now are a fatal error instead of issuing a pytest warning (:issue:`1479`). Thanks to :user:`The-Compiler` for the PR. -* Removed support code for Python 3 versions < 3.3 (:pull:`1627`). +* Removed support code for Python 3 versions < 3.3 (:pr:`1627`). * Removed all ``py.test-X*`` entry points. The versioned, suffixed entry points were never documented and a leftover from a pre-virtualenv era. These entry @@ -7594,19 +7594,19 @@ time or change existing behaviors in order to make them less surprising/more use * ``pytest.skip()`` now raises an error when used to decorate a test function, as opposed to its original intent (to imperatively skip a test inside a test function). Previously this usage would cause the entire module to be skipped (:issue:`607`). - Thanks :user:`omarkohl` for the complete PR (:pull:`1519`). + Thanks :user:`omarkohl` for the complete PR (:pr:`1519`). * Exit tests if a collection error occurs. A poll indicated most users will hit CTRL-C anyway as soon as they see collection errors, so pytest might as well make that the default behavior (:issue:`1421`). A ``--continue-on-collection-errors`` option has been added to restore the previous behaviour. - Thanks :user:`olegpidsadnyi` and :user:`omarkohl` for the complete PR (:pull:`1628`). + Thanks :user:`olegpidsadnyi` and :user:`omarkohl` for the complete PR (:pr:`1628`). * Renamed the pytest ``pdb`` module (plugin) into ``debugging`` to avoid clashes with the builtin ``pdb`` module. * Raise a helpful failure message when requesting a parametrized fixture at runtime, e.g. with ``request.getfixturevalue``. Previously these parameters were simply never defined, so a fixture decorated like ``@pytest.fixture(params=[0, 1, 2])`` - only ran once (:pull:`460`). + only ran once (:pr:`460`). Thanks to :user:`nikratio` for the bug report, :user:`RedBeardCode` and :user:`tomviner` for the PR. * ``_pytest.monkeypatch.monkeypatch`` class has been renamed to ``_pytest.monkeypatch.MonkeyPatch`` @@ -7624,7 +7624,7 @@ time or change existing behaviors in order to make them less surprising/more use * New ``doctest_namespace`` fixture for injecting names into the namespace in which doctests run. - Thanks :user:`milliams` for the complete PR (:pull:`1428`). + Thanks :user:`milliams` for the complete PR (:pr:`1428`). * New ``--doctest-report`` option available to change the output format of diffs when running (failing) doctests (implements :issue:`1749`). @@ -7632,23 +7632,23 @@ time or change existing behaviors in order to make them less surprising/more use * New ``name`` argument to ``pytest.fixture`` decorator which allows a custom name for a fixture (to solve the funcarg-shadowing-fixture problem). - Thanks :user:`novas0x2a` for the complete PR (:pull:`1444`). + Thanks :user:`novas0x2a` for the complete PR (:pr:`1444`). * New ``approx()`` function for easily comparing floating-point numbers in tests. - Thanks :user:`kalekundert` for the complete PR (:pull:`1441`). + Thanks :user:`kalekundert` for the complete PR (:pr:`1441`). * Ability to add global properties in the final xunit output file by accessing the internal ``junitxml`` plugin (experimental). - Thanks :user:`tareqalayan` for the complete PR :pull:`1454`). + Thanks :user:`tareqalayan` for the complete PR :pr:`1454`). * New ``ExceptionInfo.match()`` method to match a regular expression on the string representation of an exception (:issue:`372`). - Thanks :user:`omarkohl` for the complete PR (:pull:`1502`). + Thanks :user:`omarkohl` for the complete PR (:pr:`1502`). * ``__tracebackhide__`` can now also be set to a callable which then can decide whether to filter the traceback based on the ``ExceptionInfo`` object passed - to it. Thanks :user:`The-Compiler` for the complete PR (:pull:`1526`). + to it. Thanks :user:`The-Compiler` for the complete PR (:pr:`1526`). * New ``pytest_make_parametrize_id(config, val)`` hook which can be used by plugins to provide friendly strings for custom types. @@ -7666,7 +7666,7 @@ time or change existing behaviors in order to make them less surprising/more use * Introduce ``pytest`` command as recommended entry point. Note that ``py.test`` still works and is not scheduled for removal. Closes proposal :issue:`1629`. Thanks :user:`obestwalter` and :user:`davehunt` for the complete PR - (:pull:`1633`). + (:pr:`1633`). * New cli flags: @@ -7710,19 +7710,19 @@ time or change existing behaviors in order to make them less surprising/more use * Change ``report.outcome`` for ``xpassed`` tests to ``"passed"`` in non-strict mode and ``"failed"`` in strict mode. Thanks to :user:`hackebrot` for the PR - (:pull:`1795`) and :user:`gprasad84` for report (:issue:`1546`). + (:pr:`1795`) and :user:`gprasad84` for report (:issue:`1546`). * Tests marked with ``xfail(strict=False)`` (the default) now appear in JUnitXML reports as passing tests instead of skipped. - Thanks to :user:`hackebrot` for the PR (:pull:`1795`). + Thanks to :user:`hackebrot` for the PR (:pr:`1795`). * Highlight path of the file location in the error report to make it easier to copy/paste. - Thanks :user:`suzaku` for the PR (:pull:`1778`). + Thanks :user:`suzaku` for the PR (:pr:`1778`). * Fixtures marked with ``@pytest.fixture`` can now use ``yield`` statements exactly like those marked with the ``@pytest.yield_fixture`` decorator. This change renders ``@pytest.yield_fixture`` deprecated and makes ``@pytest.fixture`` with ``yield`` statements - the preferred way to write teardown code (:pull:`1461`). + the preferred way to write teardown code (:pr:`1461`). Thanks :user:`csaftoiu` for bringing this to attention and :user:`nicoddemus` for the PR. * Explicitly passed parametrize ids do not get escaped to ascii (:issue:`1351`). @@ -7733,11 +7733,11 @@ time or change existing behaviors in order to make them less surprising/more use Thanks :user:`nicoddemus` for the PR. * ``pytest_terminal_summary`` hook now receives the ``exitstatus`` - of the test session as argument. Thanks :user:`blueyed` for the PR (:pull:`1809`). + of the test session as argument. Thanks :user:`blueyed` for the PR (:pr:`1809`). * Parametrize ids can accept ``None`` as specific test id, in which case the automatically generated id for that argument will be used. - Thanks :user:`palaviv` for the complete PR (:pull:`1468`). + Thanks :user:`palaviv` for the complete PR (:pr:`1468`). * The parameter to xunit-style setup/teardown methods (``setup_method``, ``setup_module``, etc.) is now optional and may be omitted. @@ -7745,32 +7745,32 @@ time or change existing behaviors in order to make them less surprising/more use * Improved automatic id generation selection in case of duplicate ids in parametrize. - Thanks :user:`palaviv` for the complete PR (:pull:`1474`). + Thanks :user:`palaviv` for the complete PR (:pr:`1474`). * Now pytest warnings summary is shown up by default. Added a new flag ``--disable-pytest-warnings`` to explicitly disable the warnings summary (:issue:`1668`). * Make ImportError during collection more explicit by reminding the user to check the name of the test module/package(s) (:issue:`1426`). - Thanks :user:`omarkohl` for the complete PR (:pull:`1520`). + Thanks :user:`omarkohl` for the complete PR (:pr:`1520`). * Add ``build/`` and ``dist/`` to the default ``--norecursedirs`` list. Thanks :user:`mikofski` for the report and :user:`tomviner` for the PR (:issue:`1544`). * ``pytest.raises`` in the context manager form accepts a custom ``message`` to raise when no exception occurred. - Thanks :user:`palaviv` for the complete PR (:pull:`1616`). + Thanks :user:`palaviv` for the complete PR (:pr:`1616`). * ``conftest.py`` files now benefit from assertion rewriting; previously it was only available for test modules. Thanks :user:`flub`, :user:`sober7` and :user:`nicoddemus` for the PR (:issue:`1619`). * Text documents without any doctests no longer appear as "skipped". - Thanks :user:`graingert` for reporting and providing a full PR (:pull:`1580`). + Thanks :user:`graingert` for reporting and providing a full PR (:pr:`1580`). * Ensure that a module within a namespace package can be found when it is specified on the command line together with the ``--pyargs`` - option. Thanks to :user:`taschini` for the PR (:pull:`1597`). + option. Thanks to :user:`taschini` for the PR (:pr:`1597`). * Always include full assertion explanation during assertion rewriting. The previous behaviour was hiding sub-expressions that happened to be ``False``, assuming this was redundant information. @@ -7786,20 +7786,20 @@ time or change existing behaviors in order to make them less surprising/more use Thanks :user:`nicoddemus` for the PR. * ``[pytest]`` sections in ``setup.cfg`` files should now be named ``[tool:pytest]`` - to avoid conflicts with other distutils commands (see :pull:`567`). ``[pytest]`` sections in + to avoid conflicts with other distutils commands (see :pr:`567`). ``[pytest]`` sections in ``pytest.ini`` or ``tox.ini`` files are supported and unchanged. Thanks :user:`nicoddemus` for the PR. * Using ``pytest_funcarg__`` prefix to declare fixtures is considered deprecated and will be - removed in pytest-4.0 (:pull:`1684`). + removed in pytest-4.0 (:pr:`1684`). Thanks :user:`nicoddemus` for the PR. * Passing a command-line string to ``pytest.main()`` is considered deprecated and scheduled - for removal in pytest-4.0. It is recommended to pass a list of arguments instead (:pull:`1723`). + for removal in pytest-4.0. It is recommended to pass a list of arguments instead (:pr:`1723`). * Rename ``getfuncargvalue`` to ``getfixturevalue``. ``getfuncargvalue`` is still present but is now considered deprecated. Thanks to :user:`RedBeardCode` and :user:`tomviner` - for the PR (:pull:`1626`). + for the PR (:pr:`1626`). * ``optparse`` type usage now triggers DeprecationWarnings (:issue:`1740`). @@ -7857,11 +7857,11 @@ time or change existing behaviors in order to make them less surprising/more use :user:`tomviner` for the PR. * ``ConftestImportFailure`` now shows the traceback making it easier to - identify bugs in ``conftest.py`` files (:pull:`1516`). Thanks :user:`txomon` for + identify bugs in ``conftest.py`` files (:pr:`1516`). Thanks :user:`txomon` for the PR. * Text documents without any doctests no longer appear as "skipped". - Thanks :user:`graingert` for reporting and providing a full PR (:pull:`1580`). + Thanks :user:`graingert` for reporting and providing a full PR (:pr:`1580`). * Fixed collection of classes with custom ``__new__`` method. Fixes :issue:`1579`. Thanks to :user:`Stranger6667` for the PR. @@ -7869,7 +7869,7 @@ time or change existing behaviors in order to make them less surprising/more use * Fixed scope overriding inside metafunc.parametrize (:issue:`634`). Thanks to :user:`Stranger6667` for the PR. -* Fixed the total tests tally in junit xml output (:pull:`1798`). +* Fixed the total tests tally in junit xml output (:pr:`1798`). Thanks to :user:`cboelsen` for the PR. * Fixed off-by-one error with lines from ``request.node.warn``. @@ -7886,14 +7886,14 @@ time or change existing behaviors in order to make them less surprising/more use * Fix Xfail does not work with condition keyword argument. Thanks :user:`astraw38` for reporting the issue (:issue:`1496`) and :user:`tomviner` - for PR the (:pull:`1524`). + for PR the (:pr:`1524`). * Fix win32 path issue when putting custom config file with absolute path in ``pytest.main("-c your_absolute_path")``. * Fix maximum recursion depth detection when raised error class is not aware of unicode/encoded bytes. - Thanks :user:`prusse-martin` for the PR (:pull:`1506`). + Thanks :user:`prusse-martin` for the PR (:pr:`1506`). * Fix ``pytest.mark.skip`` mark when used in strict mode. Thanks :user:`pquentin` for the PR and :user:`RonnyPfannschmidt` for @@ -7920,7 +7920,7 @@ time or change existing behaviors in order to make them less surprising/more use Thanks :user:`nicoddemus` for the PR. * Fix (:issue:`469`): junit parses report.nodeid incorrectly, when params IDs - contain ``::``. Thanks :user:`tomviner` for the PR (:pull:`1431`). + contain ``::``. Thanks :user:`tomviner` for the PR (:pr:`1431`). * Fix (:issue:`578`): SyntaxErrors containing non-ascii lines at the point of failure generated an internal @@ -7941,7 +7941,7 @@ time or change existing behaviors in order to make them less surprising/more use **New Features** * New ``pytest.mark.skip`` mark, which unconditionally skips marked tests. - Thanks :user:`MichaelAquilina` for the complete PR (:pull:`1040`). + Thanks :user:`MichaelAquilina` for the complete PR (:pr:`1040`). * ``--doctest-glob`` may now be passed multiple times in the command-line. Thanks :user:`jab` and :user:`nicoddemus` for the PR. @@ -7952,14 +7952,14 @@ time or change existing behaviors in order to make them less surprising/more use * ``pytest.mark.xfail`` now has a ``strict`` option, which makes ``XPASS`` tests to fail the test suite (defaulting to ``False``). There's also a ``xfail_strict`` ini option that can be used to configure it project-wise. - Thanks :user:`rabbbit` for the request and :user:`nicoddemus` for the PR (:pull:`1355`). + Thanks :user:`rabbbit` for the request and :user:`nicoddemus` for the PR (:pr:`1355`). * ``Parser.addini`` now supports options of type ``bool``. Thanks :user:`nicoddemus` for the PR. * New ``ALLOW_BYTES`` doctest option. This strips ``b`` prefixes from byte strings in doctest output (similar to ``ALLOW_UNICODE``). - Thanks :user:`jaraco` for the request and :user:`nicoddemus` for the PR (:pull:`1287`). + Thanks :user:`jaraco` for the request and :user:`nicoddemus` for the PR (:pr:`1287`). * Give a hint on ``KeyboardInterrupt`` to use the ``--fulltrace`` option to show the errors. Fixes :issue:`1366`. @@ -7991,7 +7991,7 @@ time or change existing behaviors in order to make them less surprising/more use * Removed code and documentation for Python 2.5 or lower versions, including removal of the obsolete ``_pytest.assertion.oldinterpret`` module. - Thanks :user:`nicoddemus` for the PR (:pull:`1226`). + Thanks :user:`nicoddemus` for the PR (:pr:`1226`). * Comparisons now always show up in full when ``CI`` or ``BUILD_NUMBER`` is found in the environment, even when ``-vv`` isn't used. diff --git a/doc/en/conf.py b/doc/en/conf.py index 53056024b37..c4dd252f9b4 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -175,7 +175,7 @@ "bpo": ("https://bugs.python.org/issue%s", "bpo-%s"), "pypi": ("https://pypi.org/project/%s/", "%s"), "issue": (f"{_repo}/issues/%s", "issue #%s"), - "pull": (f"{_repo}/pull/%s", "pull request #%s"), + "pr": (f"{_repo}/pull/%s", "pull request #%s"), "user": ("https://github.com/%s", "@%s"), } diff --git a/doc/en/historical-notes.rst b/doc/en/historical-notes.rst index 5eb527c582b..be67036d6ca 100644 --- a/doc/en/historical-notes.rst +++ b/doc/en/historical-notes.rst @@ -107,7 +107,7 @@ Here is a non-exhaustive list of issues fixed by the new implementation: * Marker transfer incompatible with inheritance (:issue:`535`). -More details can be found in the :pull:`original PR <3317>`. +More details can be found in the :pr:`original PR <3317>`. .. note:: From b919a711a44f329fa82fb65a944bcdb5ad3f1e93 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 22 Jun 2024 22:02:59 +0200 Subject: [PATCH 0752/1271] =?UTF-8?q?=F0=9F=93=9D=20Replace=20GH/PyPI=20`e?= =?UTF-8?q?xtlinks`=20w/=20`sphinx=5Fissues`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This extension implements more generic roles that can also be used more flexibly. Relying on an external extension allows to stop maintaining an in-repo copy of the commonly used behavior. --- doc/en/conf.py | 13 ++++++++----- doc/en/requirements.txt | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/en/conf.py b/doc/en/conf.py index c4dd252f9b4..f69021e94cf 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -89,6 +89,7 @@ "sphinx_removed_in", "sphinxcontrib_trio", "sphinxcontrib.towncrier.ext", # provides `towncrier-draft-entries` directive + "sphinx_issues", # implements `:issue:`, `:pr:` and other GH-related roles ] # Building PDF docs on readthedocs requires inkscape for svg to pdf @@ -170,13 +171,8 @@ linkcheck_workers = 5 -_repo = "https://github.com/pytest-dev/pytest" extlinks = { "bpo": ("https://bugs.python.org/issue%s", "bpo-%s"), - "pypi": ("https://pypi.org/project/%s/", "%s"), - "issue": (f"{_repo}/issues/%s", "issue #%s"), - "pr": (f"{_repo}/pull/%s", "pull request #%s"), - "user": ("https://github.com/%s", "@%s"), } @@ -451,6 +447,13 @@ towncrier_draft_config_path = "pyproject.toml" # relative to cwd +# -- Options for sphinx_issues extension ----------------------------------- + +issues_github_path = "pytest-dev/pytest" +issues_prefix = "issue #" +issues_pr_prefix = "pull request #" + + intersphinx_mapping = { "pluggy": ("https://pluggy.readthedocs.io/en/stable", None), "python": ("https://docs.python.org/3", None), diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index e40a15f1f15..0637c967b8a 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -10,3 +10,4 @@ sphinxcontrib-svg2pdfconverter packaging furo sphinxcontrib-towncrier +sphinx-issues From 0971a9590264b0be09ce269edbfea1ed1bff3ed2 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 22 Jun 2024 22:14:33 +0200 Subject: [PATCH 0753/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20for=20PR=20#12522?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12522.contrib.rst | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog/12522.contrib.rst diff --git a/changelog/12522.contrib.rst b/changelog/12522.contrib.rst new file mode 100644 index 00000000000..dd994317165 --- /dev/null +++ b/changelog/12522.contrib.rst @@ -0,0 +1,4 @@ +The ``:pull:`` RST role has been replaced with a shorter +``:pr:`` due to starting to use the implementation from +the third-party :pypi:`sphinx-issues` Sphinx extension +-- by :user:`webknjaz`. From 8f2ef30f4af63d435592b7338807dd7048b54ddf Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 22 Jun 2024 22:16:40 +0200 Subject: [PATCH 0754/1271] =?UTF-8?q?=F0=9F=9A=91=20Stop=20setting=20PR/is?= =?UTF-8?q?sue=20prefix=20@=20`sphinx-issues`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently, the extension only supports one of the pre-defined prefixes. --- doc/en/conf.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/en/conf.py b/doc/en/conf.py index f69021e94cf..7ec862a6064 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -450,8 +450,6 @@ # -- Options for sphinx_issues extension ----------------------------------- issues_github_path = "pytest-dev/pytest" -issues_prefix = "issue #" -issues_pr_prefix = "pull request #" intersphinx_mapping = { From 175340e06b10d520ec70a05ffc01bcc106285f4b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 23 Jun 2024 06:22:44 +0000 Subject: [PATCH 0755/1271] [automated] Update plugin list (#12524) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 48f7cf9722e..c8591ece5e6 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.1.1,<8.0.0) :pypi:`pytest-api-soup` Validate multiple endpoints with unit testing using a single source of truth. Aug 27, 2022 N/A N/A :pypi:`pytest-apistellar` apistellar plugin for pytest. Jun 18, 2019 N/A N/A + :pypi:`pytest-apiver` Jun 21, 2024 N/A pytest :pypi:`pytest-appengine` AppEngine integration that works well with pytest-django Feb 27, 2017 N/A N/A :pypi:`pytest-appium` Pytest plugin for appium Dec 05, 2019 N/A N/A :pypi:`pytest-approvaltests` A plugin to use approvaltests with pytest May 08, 2022 4 - Beta pytest (>=7.0.1) @@ -100,7 +101,7 @@ This list contains 1478 plugins. :pypi:`pytest-assertions` Pytest Assertions Apr 27, 2022 N/A N/A :pypi:`pytest-assertutil` pytest-assertutil May 10, 2019 N/A N/A :pypi:`pytest-assert-utils` Useful assertion utilities for use with pytest Apr 14, 2022 3 - Alpha N/A - :pypi:`pytest-assist` load testing library Jun 21, 2024 N/A pytest + :pypi:`pytest-assist` load testing library Jun 22, 2024 N/A pytest :pypi:`pytest-assume` A pytest plugin that allows multiple failures per test Jun 24, 2021 N/A pytest (>=2.7) :pypi:`pytest-assurka` A pytest plugin for Assurka Studio Aug 04, 2022 N/A N/A :pypi:`pytest-ast-back-to-python` A plugin for pytest devs to view how assertion rewriting recodes the AST Sep 29, 2019 4 - Beta N/A @@ -637,7 +638,7 @@ This list contains 1478 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jun 16, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 22, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -1881,6 +1882,13 @@ This list contains 1478 plugins. apistellar plugin for pytest. + :pypi:`pytest-apiver` + *last release*: Jun 21, 2024, + *status*: N/A, + *requires*: pytest + + + :pypi:`pytest-appengine` *last release*: Feb 27, 2017, *status*: N/A, @@ -1980,7 +1988,7 @@ This list contains 1478 plugins. Useful assertion utilities for use with pytest :pypi:`pytest-assist` - *last release*: Jun 21, 2024, + *last release*: Jun 22, 2024, *status*: N/A, *requires*: pytest @@ -5739,7 +5747,7 @@ This list contains 1478 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 16, 2024, + *last release*: Jun 22, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 From d582dcfc1676b1a35fe3c2d34be211d855a4afdb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:21:02 -0300 Subject: [PATCH 0756/1271] build(deps): Bump peter-evans/create-pull-request from 6.0.5 to 6.1.0 (#12527) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.0.5 to 6.1.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/6d6857d36972b65feb161a90e484f2984215f83e...c5a7806660adbe173f04e3e038b0ccdcd758773c) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 4da55e6d5a2..ade8452afd5 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -47,7 +47,7 @@ jobs: - name: Create Pull Request id: pr - uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e + uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 77416d64f5af575460b001c768ced541564a902b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 04:26:26 +0000 Subject: [PATCH 0757/1271] [pre-commit.ci] pre-commit autoupdate (#12528) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.9 → v0.4.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.9...v0.4.10) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c85175f2928..56d9a0c86cb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.9" + rev: "v0.4.10" hooks: - id: ruff args: ["--fix"] From 2b7eadf09042759c641f775a2541332eba52b5ad Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 25 Jun 2024 07:24:50 +0200 Subject: [PATCH 0758/1271] Update trainings (#12514) --- doc/en/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 58527ea7331..8de3b3993dd 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -4,8 +4,7 @@ .. sidebar:: **Next Open Trainings and Events** - - `pytest development sprint `_, **June 17th -- 22nd 2024**, Klaus (AT) / Remote - - `pytest tips and tricks for a better testsuite `_, at `Europython 2024 `_, **July 8th -- 14th 2024** (3h), Prague (CZ) + - `pytest tips and tricks for a better testsuite `_, at `Europython 2024 `_, **July 9th 2024** (3h), Prague (CZ) - `pytest: Professionelles Testen (nicht nur) für Python `_, at `CH Open Workshoptage `_, **September 2nd 2024**, HSLU Rotkreuz (CH) - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Leipzig (DE) / Remote From 540ede34397600794e2979f2ee952bb999496582 Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Sat, 22 Jun 2024 19:57:05 +0200 Subject: [PATCH 0759/1271] docs(expression.py): describe new `name` & `value` productions --- src/_pytest/mark/expression.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 2067110d23a..0daaaf22fc0 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -8,12 +8,15 @@ not_expr: 'not' not_expr | '(' expr ')' | ident ('(' name '=' value ( ', ' name '=' value )* ')')? ident: (\w|:|\+|-|\.|\[|\]|\\|/)+ +name: a valid ident, but not a reserved keyword +value: (unescaped) string literal | (-)?[0-9]+ | 'False' | 'True' | 'None' The semantics are: - Empty expression evaluates to False. - ident evaluates to True or False according to a provided matcher function. - or/and/not evaluate according to the usual boolean semantics. +- ident with parentheses and keyword arguments evaluates to True or False according to a provided matcher function. """ from __future__ import annotations From dd5719695376b19c2ad9db0789a08f459ad7c9fb Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Sat, 22 Jun 2024 20:44:50 +0200 Subject: [PATCH 0760/1271] perf(expression): define `TokenType.STRING` as "string literal" for clearer errors --- src/_pytest/mark/expression.py | 2 +- testing/test_mark_expression.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 0daaaf22fc0..ce98e9c7e06 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -51,7 +51,7 @@ class TokenType(enum.Enum): IDENT = "identifier" EOF = "end of input" EQUAL = "=" - STRING = "str" + STRING = "string literal" COMMA = "," diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index c31ab44704c..b5f1f330a78 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -228,6 +228,7 @@ def test_invalid_idents(ident: str) -> None: r'escaping with "\\" not supported in marker expression', ), ("mark(empty_list=[])", r'unexpected character/s "\[\]"'), + ("'str'", "expected not OR left parenthesis OR identifier; got string literal"), ), ) def test_invalid_kwarg_name_or_value( # TODO: move to `test_syntax_errors` ? From 3d07791c36804a0ebcd6b0446f852e8e6745d30d Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Sat, 22 Jun 2024 20:49:21 +0200 Subject: [PATCH 0761/1271] chore: remove obsolete `TODO`s --- testing/test_mark.py | 2 +- testing/test_mark_expression.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/testing/test_mark.py b/testing/test_mark.py index 6a94cc9f7c2..89eef7920cf 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -235,7 +235,7 @@ def test_two(): @pytest.mark.parametrize( ("expr", "expected_passed"), - [ # TODO: improve/sort out + [ ("car(color='red')", ["test_one"]), ("car(color='red') or car(color='blue')", ["test_one", "test_two"]), ("car and not car(temp=5)", ["test_one", "test_three"]), diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index b5f1f330a78..f8f5f9221cf 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -231,7 +231,7 @@ def test_invalid_idents(ident: str) -> None: ("'str'", "expected not OR left parenthesis OR identifier; got string literal"), ), ) -def test_invalid_kwarg_name_or_value( # TODO: move to `test_syntax_errors` ? +def test_invalid_kwarg_name_or_value( expr: str, expected_error_msg: str, mark_matcher: MarkMatcher ) -> None: with pytest.raises(ParseError, match=expected_error_msg): @@ -290,7 +290,7 @@ def test_keyword_expressions_with_numbers( ("builtin_matchers_mark(z=1)", False), ), ) -def test_builtin_matchers_keyword_expressions( # TODO: naming when decided +def test_builtin_matchers_keyword_expressions( expr: str, expected: bool, mark_matcher: MarkMatcher ) -> None: assert evaluate(expr, mark_matcher) is expected From 36b384afc7c2457a2772abcef1f3270a7067d0cb Mon Sep 17 00:00:00 2001 From: lovetheguitar Date: Tue, 25 Jun 2024 09:16:57 +0200 Subject: [PATCH 0762/1271] docs(expression.py): simplify grammar documentation by defining `kwargs` separately --- src/_pytest/mark/expression.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index ce98e9c7e06..89cc0e94d3b 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -5,9 +5,10 @@ expression: expr? EOF expr: and_expr ('or' and_expr)* and_expr: not_expr ('and' not_expr)* -not_expr: 'not' not_expr | '(' expr ')' | ident ('(' name '=' value ( ', ' name '=' value )* ')')? +not_expr: 'not' not_expr | '(' expr ')' | ident kwargs? ident: (\w|:|\+|-|\.|\[|\]|\\|/)+ +kwargs: ('(' name '=' value ( ', ' name '=' value )* ')') name: a valid ident, but not a reserved keyword value: (unescaped) string literal | (-)?[0-9]+ | 'False' | 'True' | 'None' From 634a83df94f9becbc06665cf52dd335c99af4fd6 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 25 Jun 2024 23:25:04 +0200 Subject: [PATCH 0763/1271] =?UTF-8?q?=F0=9F=A7=AA=20Unmeasure=20xfail=20te?= =?UTF-8?q?sts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These tests are known to only be executed partially or not at all. So we always get incomplete, missing, and sometimes flaky, coverage in the test functions that are expected to fail. This change updates the ``coverage.py`` config to prevent said tests from influencing the coverage level measurement. --- .coveragerc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.coveragerc b/.coveragerc index a335557d4f1..b810471417f 100644 --- a/.coveragerc +++ b/.coveragerc @@ -29,3 +29,5 @@ exclude_lines = ^\s*if TYPE_CHECKING: ^\s*@overload( |$) + + ^\s*@pytest\.mark\.xfail From f2acc65485d7b21a42631df507c78d4c7237766d Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 25 Jun 2024 23:33:43 +0200 Subject: [PATCH 0764/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20for=20PR=20#12531?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12531.contrib.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 changelog/12531.contrib.rst diff --git a/changelog/12531.contrib.rst b/changelog/12531.contrib.rst new file mode 100644 index 00000000000..fd83b211f94 --- /dev/null +++ b/changelog/12531.contrib.rst @@ -0,0 +1,6 @@ +The coverage reporting configuration has been updated to exclude +pytest's own tests marked as expected to fail from the coverage +report. This has an effect of reducing the influence of flaky +tests on the resulting number. + +-- by :user`webknjaz` From 29e4b6b9f010828594df599fcf0b6164a59da27b Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Wed, 26 Jun 2024 14:16:30 +0200 Subject: [PATCH 0765/1271] =?UTF-8?q?=F0=9F=93=9D=F0=9F=94=A5=20Remove=20t?= =?UTF-8?q?he=20`:bpo:`=20RST=20role=20declaration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BPO is in read-only mode and all issues have been migrated to GitHub. This patch replaces the use of that role with `:issue:`, recently integrated via #12522. It also disables the built-in `extlinks` Sphinx extension, as it's no longer in use. --- doc/en/changelog.rst | 4 +++- doc/en/conf.py | 6 ------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 2c07f208ac3..8e3efd0479b 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -3360,7 +3360,9 @@ Bug Fixes - :issue:`5914`: pytester: fix :py:func:`~pytest.LineMatcher.no_fnmatch_line` when used after positive matching. -- :issue:`6082`: Fix line detection for doctest samples inside :py:class:`python:property` docstrings, as a workaround to :bpo:`17446`. +- :issue:`6082`: Fix line detection for doctest samples inside + :py:class:`python:property` docstrings, as a workaround to + :issue:`python/cpython#61648`. - :issue:`6254`: Fix compatibility with pytest-parallel (regression in pytest 5.3.0). diff --git a/doc/en/conf.py b/doc/en/conf.py index 7ec862a6064..0d440ec448a 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -82,7 +82,6 @@ "pygments_pytest", "sphinx.ext.autodoc", "sphinx.ext.autosummary", - "sphinx.ext.extlinks", "sphinx.ext.intersphinx", "sphinx.ext.todo", "sphinx.ext.viewcode", @@ -171,11 +170,6 @@ linkcheck_workers = 5 -extlinks = { - "bpo": ("https://bugs.python.org/issue%s", "bpo-%s"), -} - - nitpicky = True nitpick_ignore = [ # TODO (fix in pluggy?) From d75fa9f9b420124b1ad3ee5a43d04367dba3054c Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Wed, 26 Jun 2024 14:22:56 +0200 Subject: [PATCH 0766/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20for=20PE=20#12533?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12533.contrib.rst | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 changelog/12533.contrib.rst diff --git a/changelog/12533.contrib.rst b/changelog/12533.contrib.rst new file mode 100644 index 00000000000..3da7007a0fd --- /dev/null +++ b/changelog/12533.contrib.rst @@ -0,0 +1,7 @@ +The ``extlinks`` Sphinx extension is no longer enabled. The ``:bpo:`` +role it used to declare has been removed with that. BPO itself has +migrated to GitHub some years ago and it is possible to link the +respective issues by using their GitHub issue numbers and the +``:issue:`` role that the ``sphinx-issues`` extension implements. + +-- by :user:`webknjaz` From 0ed2d79457b499119693588b71233db957e972c0 Mon Sep 17 00:00:00 2001 From: joseph-sentry <136376984+joseph-sentry@users.noreply.github.com> Date: Thu, 27 Jun 2024 08:41:02 -0400 Subject: [PATCH 0767/1271] junitxml: add timezone to testsuite timestamp (#12491) Signed-off-by: joseph-sentry Co-authored-by: Ronny Pfannschmidt --- AUTHORS | 1 + changelog/7662.improvement.rst | 1 + src/_pytest/junitxml.py | 5 ++++- testing/test_junitxml.py | 7 ++++--- 4 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 changelog/7662.improvement.rst diff --git a/AUTHORS b/AUTHORS index 5ae80eb02d3..ad7fccf6d59 100644 --- a/AUTHORS +++ b/AUTHORS @@ -213,6 +213,7 @@ Jordan Guymon Jordan Moldow Jordan Speicher Joseph Hunkeler +Joseph Sawaya Josh Karpel Joshua Bronson Jurko Gospodnetić diff --git a/changelog/7662.improvement.rst b/changelog/7662.improvement.rst new file mode 100644 index 00000000000..b6ae1ba7e4c --- /dev/null +++ b/changelog/7662.improvement.rst @@ -0,0 +1 @@ +Added timezone information to the testsuite timestamp in the JUnit XML report. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index a525f1d14de..3a2cb59a6c1 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -11,6 +11,7 @@ from __future__ import annotations from datetime import datetime +from datetime import timezone import functools import os import platform @@ -664,7 +665,9 @@ def pytest_sessionfinish(self) -> None: skipped=str(self.stats["skipped"]), tests=str(numtests), time=f"{suite_time_delta:.3f}", - timestamp=datetime.fromtimestamp(self.suite_start_time).isoformat(), + timestamp=datetime.fromtimestamp(self.suite_start_time, timezone.utc) + .astimezone() + .isoformat(), hostname=platform.node(), ) global_properties = self._get_global_properties_node() diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 67234302a89..fd1fecb54f1 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -2,6 +2,7 @@ from __future__ import annotations from datetime import datetime +from datetime import timezone import os from pathlib import Path import platform @@ -218,11 +219,11 @@ def test_pass(): pass """ ) - start_time = datetime.now() + start_time = datetime.now(timezone.utc) result, dom = run_and_parse(family=xunit_family) node = dom.find_first_by_tag("testsuite") - timestamp = datetime.strptime(node["timestamp"], "%Y-%m-%dT%H:%M:%S.%f") - assert start_time <= timestamp < datetime.now() + timestamp = datetime.strptime(node["timestamp"], "%Y-%m-%dT%H:%M:%S.%f%z") + assert start_time <= timestamp < datetime.now(timezone.utc) def test_timing_function( self, pytester: Pytester, run_and_parse: RunAndParse, mock_timing From 0adcc21f4833f4f5177e9d2b9ac377cab851159f Mon Sep 17 00:00:00 2001 From: Zach Snicker Date: Sat, 29 Jun 2024 03:00:51 +0530 Subject: [PATCH 0768/1271] Support venv detection on Windows with mingw Python (#12545) Closes #12544 --- AUTHORS | 1 + changelog/12544.improvement.rst | 4 +++ doc/en/reference/reference.rst | 14 ++++----- src/_pytest/main.py | 16 ++-------- testing/test_collection.py | 54 +++++---------------------------- 5 files changed, 23 insertions(+), 66 deletions(-) create mode 100644 changelog/12544.improvement.rst diff --git a/AUTHORS b/AUTHORS index ad7fccf6d59..26fa27f9b2a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -454,6 +454,7 @@ Yusuke Kadowaki Yutian Li Yuval Shimon Zac Hatfield-Dodds +Zach Snicker Zachary Kneupper Zachary OBrien Zhouxin Qiu diff --git a/changelog/12544.improvement.rst b/changelog/12544.improvement.rst new file mode 100644 index 00000000000..9edbf7c4fec --- /dev/null +++ b/changelog/12544.improvement.rst @@ -0,0 +1,4 @@ +The _in_venv function now detects Python virtual environments by checking +for a pyvenv.cfg file, ensuring reliable detection on various platforms. + +-- by :user:`zachsnickers`. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 7c7b99d81c0..6926cd61bd3 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1702,13 +1702,13 @@ passed multiple times. The expected format is ``name=value``. For example:: This would tell ``pytest`` to not look into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory. - Additionally, ``pytest`` will attempt to intelligently identify and ignore a - virtualenv by the presence of an activation script. Any directory deemed to - be the root of a virtual environment will not be considered during test - collection unless ``--collect-in-virtualenv`` is given. Note also that - ``norecursedirs`` takes precedence over ``--collect-in-virtualenv``; e.g. if - you intend to run tests in a virtualenv with a base directory that matches - ``'.*'`` you *must* override ``norecursedirs`` in addition to using the + Additionally, ``pytest`` will attempt to intelligently identify and ignore + a virtualenv. Any directory deemed to be the root of a virtual environment + will not be considered during test collection unless + ``--collect-in-virtualenv`` is given. Note also that ``norecursedirs`` + takes precedence over ``--collect-in-virtualenv``; e.g. if you intend to + run tests in a virtualenv with a base directory that matches ``'.*'`` you + *must* override ``norecursedirs`` in addition to using the ``--collect-in-virtualenv`` flag. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 47ebad4713d..8ec26906003 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -369,22 +369,12 @@ def pytest_runtestloop(session: Session) -> bool: def _in_venv(path: Path) -> bool: """Attempt to detect if ``path`` is the root of a Virtual Environment by - checking for the existence of the appropriate activate script.""" - bindir = path.joinpath("Scripts" if sys.platform.startswith("win") else "bin") + checking for the existence of the pyvenv.cfg file. + [https://peps.python.org/pep-0405/]""" try: - if not bindir.is_dir(): - return False + return path.joinpath("pyvenv.cfg").is_file() except OSError: return False - activates = ( - "activate", - "activate.csh", - "activate.fish", - "Activate", - "Activate.bat", - "Activate.ps1", - ) - return any(fname.name in activates for fname in bindir.iterdir()) def pytest_ignore_collect(collection_path: Path, config: Config) -> bool | None: diff --git a/testing/test_collection.py b/testing/test_collection.py index 821c424196f..f5822240335 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -152,20 +152,8 @@ def test_ignored_certain_directories(self, pytester: Pytester) -> None: assert "test_notfound" not in s assert "test_found" in s - @pytest.mark.parametrize( - "fname", - ( - "activate", - "activate.csh", - "activate.fish", - "Activate", - "Activate.bat", - "Activate.ps1", - ), - ) - def test_ignored_virtualenvs(self, pytester: Pytester, fname: str) -> None: - bindir = "Scripts" if sys.platform.startswith("win") else "bin" - ensure_file(pytester.path / "virtual" / bindir / fname) + def test_ignored_virtualenvs(self, pytester: Pytester) -> None: + ensure_file(pytester.path / "virtual" / "pyvenv.cfg") testfile = ensure_file(pytester.path / "virtual" / "test_invenv.py") testfile.write_text("def test_hello(): pass", encoding="utf-8") @@ -179,23 +167,11 @@ def test_ignored_virtualenvs(self, pytester: Pytester, fname: str) -> None: result = pytester.runpytest("virtual") assert "test_invenv" in result.stdout.str() - @pytest.mark.parametrize( - "fname", - ( - "activate", - "activate.csh", - "activate.fish", - "Activate", - "Activate.bat", - "Activate.ps1", - ), - ) def test_ignored_virtualenvs_norecursedirs_precedence( - self, pytester: Pytester, fname: str + self, pytester: Pytester ) -> None: - bindir = "Scripts" if sys.platform.startswith("win") else "bin" # norecursedirs takes priority - ensure_file(pytester.path / ".virtual" / bindir / fname) + ensure_file(pytester.path / ".virtual" / "pyvenv.cfg") testfile = ensure_file(pytester.path / ".virtual" / "test_invenv.py") testfile.write_text("def test_hello(): pass", encoding="utf-8") result = pytester.runpytest("--collect-in-virtualenv") @@ -204,27 +180,13 @@ def test_ignored_virtualenvs_norecursedirs_precedence( result = pytester.runpytest("--collect-in-virtualenv", ".virtual") assert "test_invenv" in result.stdout.str() - @pytest.mark.parametrize( - "fname", - ( - "activate", - "activate.csh", - "activate.fish", - "Activate", - "Activate.bat", - "Activate.ps1", - ), - ) - def test__in_venv(self, pytester: Pytester, fname: str) -> None: + def test__in_venv(self, pytester: Pytester) -> None: """Directly test the virtual env detection function""" - bindir = "Scripts" if sys.platform.startswith("win") else "bin" - # no bin/activate, not a virtualenv + # no pyvenv.cfg, not a virtualenv base_path = pytester.mkdir("venv") assert _in_venv(base_path) is False - # with bin/activate, totally a virtualenv - bin_path = base_path.joinpath(bindir) - bin_path.mkdir() - bin_path.joinpath(fname).touch() + # with pyvenv.cfg, totally a virtualenv + base_path.joinpath("pyvenv.cfg").touch() assert _in_venv(base_path) is True def test_custom_norecursedirs(self, pytester: Pytester) -> None: From dbf7dee8c8818de27d83d4593b0048ac5e06bfc7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 30 Jun 2024 12:05:11 +0000 Subject: [PATCH 0769/1271] [automated] Update plugin list (#12547) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 90 ++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index c8591ece5e6..38f855de03c 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =2.7) :pypi:`pytest-assurka` A pytest plugin for Assurka Studio Aug 04, 2022 N/A N/A :pypi:`pytest-ast-back-to-python` A plugin for pytest devs to view how assertion rewriting recodes the AST Sep 29, 2019 4 - Beta N/A @@ -119,7 +119,7 @@ This list contains 1479 plugins. :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-attributes` A plugin that allows users to add attributes to their tests. These attributes can then be referenced by fixtures or the test itself. Jun 06, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-attributes` A plugin that allows users to add attributes to their tests. These attributes can then be referenced by fixtures or the test itself. Jun 24, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A :pypi:`pytest-autocap` automatically capture test & fixture stdout/stderr to files May 15, 2022 N/A pytest (<7.2,>=7.1.2) :pypi:`pytest-autochecklog` automatically check condition and log all the checks Apr 25, 2015 4 - Beta N/A @@ -127,7 +127,7 @@ This list contains 1479 plugins. :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest - :pypi:`pytest-aux` templates/examples and aux for pytest Jun 18, 2024 N/A N/A + :pypi:`pytest-aux` templates/examples and aux for pytest Jun 27, 2024 N/A N/A :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -143,6 +143,7 @@ This list contains 1479 plugins. :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 + :pypi:`pytest-bazel` A pytest runner with bazel support Jun 29, 2024 4 - Beta pytest :pypi:`pytest-bdd` BDD for pytest Jun 04, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 @@ -152,7 +153,7 @@ This list contains 1479 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jun 21, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jun 28, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -241,7 +242,7 @@ This list contains 1479 plugins. :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Jun 17, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Apr 19, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Jun 27, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) @@ -279,7 +280,7 @@ This list contains 1479 plugins. :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-continuous` A pytest plugin to run tests continuously until failure or interruption. Apr 23, 2024 N/A N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) - :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Jan 27, 2024 3 - Alpha pytest + :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Jun 26, 2024 3 - Alpha pytest :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A @@ -306,7 +307,7 @@ This list contains 1479 plugins. :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A :pypi:`pytest-custom-exit-code` Exit pytest test session with custom exit code in different scenarios Aug 07, 2019 4 - Beta pytest (>=4.0.2) :pypi:`pytest-custom-nodeid` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 07, 2021 N/A N/A - :pypi:`pytest-custom-outputs` A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail. Also allows users to retrieve test results in fixtures. Jun 17, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-custom-outputs` A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail. Also allows users to retrieve test results in fixtures. Jun 28, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A :pypi:`pytest-cython` A plugin for testing Cython extension modules Apr 05, 2024 5 - Production/Stable pytest>=8 @@ -638,7 +639,7 @@ This list contains 1479 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jun 22, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jun 29, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -704,7 +705,7 @@ This list contains 1479 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Feb 09, 2024 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Feb 28, 2024 5 - Production/Stable pytest <7.2.0,>=6 + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 5 - Production/Stable pytest<7.2.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A @@ -790,7 +791,7 @@ This list contains 1479 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment May 23, 2024 5 - Production/Stable pytest==8.2.1 + :pypi:`pytest-logikal` Common testing environment Jun 27, 2024 5 - Production/Stable pytest==8.2.2 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest @@ -1085,7 +1086,7 @@ This list contains 1479 plugins. :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jun 07, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Mar 14, 2024 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-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jun 27, 2024 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Dec 06, 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. Jun 19, 2024 5 - Production/Stable pytest>=6.2 @@ -1110,7 +1111,7 @@ This list contains 1479 plugins. :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest - :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Feb 28, 2024 4 - Beta N/A + :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Jun 28, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) @@ -1181,7 +1182,7 @@ This list contains 1479 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 07, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 29, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1191,13 +1192,14 @@ This list contains 1479 plugins. :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 Feb 01, 2024 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. Jun 07, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jun 29, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Apr 25, 2024 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A + :pypi:`pytest-server` test server exec cmd Jun 24, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A :pypi:`pytest-servers` pytest servers Jun 17, 2024 3 - Alpha pytest>=6.2 @@ -1268,7 +1270,7 @@ This list contains 1479 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 Jun 03, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jun 26, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jun 14, 2024 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 @@ -1358,6 +1360,7 @@ This list contains 1479 plugins. :pypi:`pytest-testreport-new` Oct 07, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) + :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) @@ -1988,7 +1991,7 @@ This list contains 1479 plugins. Useful assertion utilities for use with pytest :pypi:`pytest-assist` - *last release*: Jun 22, 2024, + *last release*: Jun 24, 2024, *status*: N/A, *requires*: pytest @@ -2114,7 +2117,7 @@ This list contains 1479 plugins. pytest plugin to select tests based on attributes similar to the nose-attrib plugin :pypi:`pytest-attributes` - *last release*: Jun 06, 2024, + *last release*: Jun 24, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2170,7 +2173,7 @@ This list contains 1479 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: Jun 18, 2024, + *last release*: Jun 27, 2024, *status*: N/A, *requires*: N/A @@ -2281,6 +2284,13 @@ This list contains 1479 plugins. A pytest plugin to repeat the entire test suite in batches. + :pypi:`pytest-bazel` + *last release*: Jun 29, 2024, + *status*: 4 - Beta, + *requires*: pytest + + A pytest runner with bazel support + :pypi:`pytest-bdd` *last release*: Jun 04, 2024, *status*: 6 - Mature, @@ -2345,7 +2355,7 @@ This list contains 1479 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jun 21, 2024, + *last release*: Jun 28, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2968,7 +2978,7 @@ This list contains 1479 plugins. A cleanup plugin for pytest :pypi:`pytest-clerk` - *last release*: Apr 19, 2024, + *last release*: Jun 27, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -3234,7 +3244,7 @@ This list contains 1479 plugins. The pytest plugin for your Cookiecutter templates. 🍪 :pypi:`pytest-copie` - *last release*: Jan 27, 2024, + *last release*: Jun 26, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3423,7 +3433,7 @@ This list contains 1479 plugins. Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report :pypi:`pytest-custom-outputs` - *last release*: Jun 17, 2024, + *last release*: Jun 28, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -5747,7 +5757,7 @@ This list contains 1479 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 22, 2024, + *last release*: Jun 29, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 @@ -6209,9 +6219,9 @@ This list contains 1479 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Feb 28, 2024, + *last release*: Jun 27, 2024, *status*: 5 - Production/Stable, - *requires*: pytest <7.2.0,>=6 + *requires*: pytest<7.2.0,>=6 Pytest fixtures for Invenio. @@ -6811,9 +6821,9 @@ This list contains 1479 plugins. :pypi:`pytest-logikal` - *last release*: May 23, 2024, + *last release*: Jun 27, 2024, *status*: 5 - Production/Stable, - *requires*: pytest==8.2.1 + *requires*: pytest==8.2.2 Common testing environment @@ -8876,7 +8886,7 @@ This list contains 1479 plugins. Pytest fixtures for REANA. :pypi:`pytest-recorder` - *last release*: Nov 21, 2023, + *last release*: Jun 27, 2024, *status*: N/A, *requires*: N/A @@ -9051,7 +9061,7 @@ This list contains 1479 plugins. Generate Pytest reports with templates :pypi:`pytest-reporter-html1` - *last release*: Feb 28, 2024, + *last release*: Jun 28, 2024, *status*: 4 - Beta, *requires*: N/A @@ -9548,7 +9558,7 @@ This list contains 1479 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jun 07, 2024, + *last release*: Jun 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9618,7 +9628,7 @@ This list contains 1479 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jun 07, 2024, + *last release*: Jun 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9666,6 +9676,13 @@ This list contains 1479 plugins. Pytest plugin for sequencing markers for execution of tests + :pypi:`pytest-server` + *last release*: Jun 24, 2024, + *status*: N/A, + *requires*: N/A + + test server exec cmd + :pypi:`pytest-server-fixtures` *last release*: Dec 19, 2023, *status*: 5 - Production/Stable, @@ -10157,7 +10174,7 @@ This list contains 1479 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jun 03, 2024, + *last release*: Jun 26, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10786,6 +10803,13 @@ This list contains 1479 plugins. Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply + :pypi:`pytest-test-tracer-for-pytest` + *last release*: Jun 28, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A plugin that allows coll test data for use on Test Tracer + :pypi:`pytest-test-utils` *last release*: Feb 08, 2024, *status*: N/A, From 41ca4dd44eedd959f3fe562895519e3d9df185ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Tue, 18 Jun 2024 12:09:47 +0200 Subject: [PATCH 0770/1271] testresult: correctly apply verbose word markup and avoid crash MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following snippet would have resulted in crash on multiple places since `_get_verbose_word` expects only string, not a tuple. ```python @pytest.hookimpl(tryfirst=True) def pytest_report_teststatus(report: pytest.CollectReport | pytest.TestReport, config: pytest.Config): if report.when == "call": return ("error", "A", ("AVC", {"bold": True, "red": True})) return None ``` ``` Traceback (most recent call last): File "/home/pbrezina/workspace/sssd/.venv/bin/pytest", line 8, in sys.exit(console_main()) ^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/config/__init__.py", line 207, in console_main code = main() ^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/config/__init__.py", line 179, in main ret: Union[ExitCode, int] = config.hook.pytest_cmdline_main( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_hooks.py", line 513, in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_manager.py", line 120, in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_callers.py", line 139, in _multicall raise exception.with_traceback(exception.__traceback__) File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_callers.py", line 103, in _multicall res = hook_impl.function(*args) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/main.py", line 333, in pytest_cmdline_main return wrap_session(config, _main) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/main.py", line 321, in wrap_session config.hook.pytest_sessionfinish( File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_hooks.py", line 513, in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_manager.py", line 120, in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_callers.py", line 139, in _multicall raise exception.with_traceback(exception.__traceback__) File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_callers.py", line 122, in _multicall teardown.throw(exception) # type: ignore[union-attr] ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/logging.py", line 872, in pytest_sessionfinish return (yield) ^^^^^ File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_callers.py", line 124, in _multicall teardown.send(result) # type: ignore[union-attr] ^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/terminal.py", line 899, in pytest_sessionfinish self.config.hook.pytest_terminal_summary( File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_hooks.py", line 513, in __call__ return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_manager.py", line 120, in _hookexec return self._inner_hookexec(hook_name, methods, kwargs, firstresult) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_callers.py", line 139, in _multicall raise exception.with_traceback(exception.__traceback__) File "/home/pbrezina/workspace/sssd/.venv/lib64/python3.11/site-packages/pluggy/_callers.py", line 124, in _multicall teardown.send(result) # type: ignore[union-attr] ^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/terminal.py", line 923, in pytest_terminal_summary self.short_test_summary() File "/home/pbrezina/workspace/pytest/src/_pytest/terminal.py", line 1272, in short_test_summary action(lines) File "/home/pbrezina/workspace/pytest/src/_pytest/terminal.py", line 1205, in show_simple line = _get_line_with_reprcrash_message( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/terminal.py", line 1429, in _get_line_with_reprcrash_message word = tw.markup(verbose_word, **word_markup) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/pbrezina/workspace/pytest/src/_pytest/_io/terminalwriter.py", line 114, in markup text = "".join(f"\x1b[{cod}m" for cod in esc) + text + "\x1b[0m" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~ TypeError: can only concatenate str (not "tuple") to str ``` Signed-off-by: Pavel Březina --- changelog/12472.bugfix.rst | 1 + src/_pytest/reports.py | 21 +++++++++++++++++++-- src/_pytest/terminal.py | 24 +++++++++++++----------- testing/test_terminal.py | 13 ++++++++----- 4 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 changelog/12472.bugfix.rst diff --git a/changelog/12472.bugfix.rst b/changelog/12472.bugfix.rst new file mode 100644 index 00000000000..f08e9d1f90b --- /dev/null +++ b/changelog/12472.bugfix.rst @@ -0,0 +1 @@ +Fixed a crash when returning category ``"error"`` or ``"failed"`` with a custom test status from :hook:`pytest_report_teststatus` hook -- :user:`pbrezina`. diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 2f39adbfa6f..9e61d7def40 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -13,6 +13,7 @@ from typing import Literal from typing import Mapping from typing import NoReturn +from typing import Sequence from typing import TYPE_CHECKING from _pytest._code.code import ExceptionChainRepr @@ -30,6 +31,7 @@ from _pytest.config import Config from _pytest.nodes import Collector from _pytest.nodes import Item +from _pytest.outcomes import fail from _pytest.outcomes import skip @@ -190,11 +192,26 @@ def head_line(self) -> str | None: return domain return None - def _get_verbose_word(self, config: Config): + def _get_verbose_word_with_markup( + self, config: Config, default_markup: Mapping[str, bool] + ) -> tuple[str, Mapping[str, bool]]: _category, _short, verbose = config.hook.pytest_report_teststatus( report=self, config=config ) - return verbose + + if isinstance(verbose, str): + return verbose, default_markup + + if isinstance(verbose, Sequence) and len(verbose) == 2: + word, markup = verbose + if isinstance(word, str) and isinstance(markup, Mapping): + return word, markup + + fail( + "pytest_report_teststatus() hook (from a plugin) returned " + "an invalid verbose value: {verbose!r}.\nExpected either a string " + "or a tuple of (word, markup)." + ) def _to_json(self) -> dict[str, Any]: """Return the contents of this report as a dict of builtin entries, diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 26c573f583e..f364316e2e2 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1206,10 +1206,10 @@ def show_simple(lines: list[str], *, stat: str) -> None: def show_xfailed(lines: list[str]) -> None: xfailed = self.stats.get("xfailed", []) for rep in xfailed: - verbose_word = rep._get_verbose_word(self.config) - markup_word = self._tw.markup( - verbose_word, **{_color_for_type["warnings"]: True} + verbose_word, verbose_markup = rep._get_verbose_word_with_markup( + self.config, {_color_for_type["warnings"]: True} ) + markup_word = self._tw.markup(verbose_word, **verbose_markup) nodeid = _get_node_id_with_markup(self._tw, self.config, rep) line = f"{markup_word} {nodeid}" reason = rep.wasxfail @@ -1221,10 +1221,10 @@ def show_xfailed(lines: list[str]) -> None: def show_xpassed(lines: list[str]) -> None: xpassed = self.stats.get("xpassed", []) for rep in xpassed: - verbose_word = rep._get_verbose_word(self.config) - markup_word = self._tw.markup( - verbose_word, **{_color_for_type["warnings"]: True} + verbose_word, verbose_markup = rep._get_verbose_word_with_markup( + self.config, {_color_for_type["warnings"]: True} ) + markup_word = self._tw.markup(verbose_word, **verbose_markup) nodeid = _get_node_id_with_markup(self._tw, self.config, rep) line = f"{markup_word} {nodeid}" reason = rep.wasxfail @@ -1237,10 +1237,10 @@ def show_skipped(lines: list[str]) -> None: fskips = _folded_skips(self.startpath, skipped) if skipped else [] if not fskips: return - verbose_word = skipped[0]._get_verbose_word(self.config) - markup_word = self._tw.markup( - verbose_word, **{_color_for_type["warnings"]: True} + verbose_word, verbose_markup = skipped[0]._get_verbose_word_with_markup( + self.config, {_color_for_type["warnings"]: True} ) + markup_word = self._tw.markup(verbose_word, **verbose_markup) prefix = "Skipped: " for num, fspath, lineno, reason in fskips: if reason.startswith(prefix): @@ -1421,8 +1421,10 @@ def _get_line_with_reprcrash_message( config: Config, rep: BaseReport, tw: TerminalWriter, word_markup: dict[str, bool] ) -> str: """Get summary line for a report, trying to add reprcrash message.""" - verbose_word = rep._get_verbose_word(config) - word = tw.markup(verbose_word, **word_markup) + verbose_word, verbose_markup = rep._get_verbose_word_with_markup( + config, word_markup + ) + word = tw.markup(verbose_word, **verbose_markup) node = _get_node_id_with_markup(tw, config, rep) line = f"{word} {node}" diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 01a84fd8d2c..5e3f631e22b 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -326,16 +326,17 @@ def test_rewrite(self, pytester: Pytester, monkeypatch) -> None: tr.rewrite("hey", erase=True) assert f.getvalue() == "hello" + "\r" + "hey" + (6 * " ") + @pytest.mark.parametrize("category", ["foo", "failed", "error", "passed"]) def test_report_teststatus_explicit_markup( - self, monkeypatch: MonkeyPatch, pytester: Pytester, color_mapping + self, monkeypatch: MonkeyPatch, pytester: Pytester, color_mapping, category: str ) -> None: """Test that TerminalReporter handles markup explicitly provided by a pytest_report_teststatus hook.""" monkeypatch.setenv("PY_COLORS", "1") pytester.makeconftest( - """ + f""" def pytest_report_teststatus(report): - return 'foo', 'F', ('FOO', {'red': True}) + return {category !r}, 'F', ('FOO', {{'red': True}}) """ ) pytester.makepyfile( @@ -344,7 +345,9 @@ def test_foobar(): pass """ ) + result = pytester.runpytest("-v") + assert not result.stderr.lines result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch(["*{red}FOO{reset}*"]) ) @@ -2385,8 +2388,8 @@ def __init__(self): self.option = Namespace(verbose=0) class rep: - def _get_verbose_word(self, *args): - return mocked_verbose_word + def _get_verbose_word_with_markup(self, *args): + return mocked_verbose_word, {} class longrepr: class reprcrash: From 269ded17a6fabf632d5b270421b9ad4e6bbff9ac Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 27 Jun 2024 10:27:06 -0300 Subject: [PATCH 0771/1271] Update src/_pytest/reports.py --- src/_pytest/reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 9e61d7def40..1521ad7671f 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -208,7 +208,7 @@ def _get_verbose_word_with_markup( return word, markup fail( - "pytest_report_teststatus() hook (from a plugin) returned " + f"pytest_report_teststatus() hook (from a plugin) returned " "an invalid verbose value: {verbose!r}.\nExpected either a string " "or a tuple of (word, markup)." ) From 2c1ed505d9a969ad97d35000569cd603aae3fe62 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:27:33 +0000 Subject: [PATCH 0772/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 1521ad7671f..9e61d7def40 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -208,7 +208,7 @@ def _get_verbose_word_with_markup( return word, markup fail( - f"pytest_report_teststatus() hook (from a plugin) returned " + "pytest_report_teststatus() hook (from a plugin) returned " "an invalid verbose value: {verbose!r}.\nExpected either a string " "or a tuple of (word, markup)." ) From 201ed9f6a53445c6851881cb05fb552ff391cd86 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 27 Jun 2024 10:28:42 -0300 Subject: [PATCH 0773/1271] Update src/_pytest/reports.py --- src/_pytest/reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 9e61d7def40..f23ee0831c5 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -209,7 +209,7 @@ def _get_verbose_word_with_markup( fail( "pytest_report_teststatus() hook (from a plugin) returned " - "an invalid verbose value: {verbose!r}.\nExpected either a string " + f"an invalid verbose value: {verbose!r}.\nExpected either a string " "or a tuple of (word, markup)." ) From f502f1db31ec135b8b3aa73931a12e13d8d88ed7 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 27 Jun 2024 10:49:38 -0300 Subject: [PATCH 0774/1271] Update src/_pytest/reports.py --- src/_pytest/reports.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index f23ee0831c5..77cbf773e23 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -207,7 +207,7 @@ def _get_verbose_word_with_markup( if isinstance(word, str) and isinstance(markup, Mapping): return word, markup - fail( + fail( # pragma: no cover "pytest_report_teststatus() hook (from a plugin) returned " f"an invalid verbose value: {verbose!r}.\nExpected either a string " "or a tuple of (word, markup)." From de4e3cffc2309c7b9f41ca2e987a625e932ba0f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Mon, 1 Jul 2024 16:47:47 +0200 Subject: [PATCH 0775/1271] =?UTF-8?q?Revert=20"=F0=9F=9A=91=F0=9F=A7=AA=20?= =?UTF-8?q?Set=20the=20Codecov=20token=20directly=20in=20GHA"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 64b87eee217..d78e0900fd9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -250,7 +250,6 @@ jobs: with: fail_ci_if_error: false files: ./coverage.xml - token: 1eca3b1f-31a2-4fb8-a8c3-138b441b50a7 #repo token; cfg read fails verbose: true check: # This job does nothing and is only used for the branch protection From 2455e99ea33a49794caa84f3cd25f2e598fda642 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:00:26 +0200 Subject: [PATCH 0776/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20markup=20to=20th?= =?UTF-8?q?e=20PR=20#12545=20changelog=20entry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12544.improvement.rst | 7 +++---- changelog/12545.improvement.rst | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) create mode 120000 changelog/12545.improvement.rst diff --git a/changelog/12544.improvement.rst b/changelog/12544.improvement.rst index 9edbf7c4fec..41125f5d939 100644 --- a/changelog/12544.improvement.rst +++ b/changelog/12544.improvement.rst @@ -1,4 +1,3 @@ -The _in_venv function now detects Python virtual environments by checking -for a pyvenv.cfg file, ensuring reliable detection on various platforms. - --- by :user:`zachsnickers`. +The ``_in_venv()`` function now detects Python virtual environments by +checking for a :file:`pyvenv.cfg` file, ensuring reliable detection on +various platforms -- by :user:`zachsnickers`. diff --git a/changelog/12545.improvement.rst b/changelog/12545.improvement.rst new file mode 120000 index 00000000000..41a1e6bfa49 --- /dev/null +++ b/changelog/12545.improvement.rst @@ -0,0 +1 @@ +12544.improvement.rst \ No newline at end of file From 388cf8f381275f518d6626ca83b3e2855a20159a Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:12:27 +0200 Subject: [PATCH 0777/1271] Correct the `:user:` role @ PR #12531 change note --- changelog/12531.contrib.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/12531.contrib.rst b/changelog/12531.contrib.rst index fd83b211f94..12083fc320e 100644 --- a/changelog/12531.contrib.rst +++ b/changelog/12531.contrib.rst @@ -3,4 +3,4 @@ pytest's own tests marked as expected to fail from the coverage report. This has an effect of reducing the influence of flaky tests on the resulting number. --- by :user`webknjaz` +-- by :user:`webknjaz` From a34f2f06dbc9eb441f65022b5e61a2708351a526 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:15:31 +0200 Subject: [PATCH 0778/1271] =?UTF-8?q?=F0=9F=93=9D=F0=9F=92=84=20Drop=20tra?= =?UTF-8?q?iling=20period=20from=20#12502=20byline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12502.contrib.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/12502.contrib.rst b/changelog/12502.contrib.rst index a7db422526f..940a2d7a120 100644 --- a/changelog/12502.contrib.rst +++ b/changelog/12502.contrib.rst @@ -4,4 +4,4 @@ the automatically created pull requests and re-open them to trigger the CI runs. From now on, they only need to click the `Ready for review` button instead. --- by :user:`webknjaz`. +-- by :user:`webknjaz` From 9c319d6605683e2236c2d6261386b544dfcbfda8 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:21:24 +0200 Subject: [PATCH 0779/1271] =?UTF-8?q?=F0=9F=A7=AA=20Lint=20for=20typos=20i?= =?UTF-8?q?n=20`:user:`=20RST=20role?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is easy to forget backticks in change note bylines. It's happened in #12531 already, requiring a hotfix in #12560. The pre-commit based check idea is coming from the Tox project and have been battle-tested in aiohttp, CherryPy, and other ecosystems. --- .pre-commit-config.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 56d9a0c86cb..431b21f9942 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -102,6 +102,14 @@ repos: ) $ files: ^changelog/ + - id: changelogs-user-role + name: Changelog files should use a non-broken :user:`name` role + language: pygrep + entry: :user:([^`]+`?|`[^`]+[\s,]) + pass_filenames: true + types: + - file + - rst - id: py-deprecated name: py library is deprecated language: pygrep From 57fe9f53c64cd9bb127f650774d337a7f82f1445 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:26:35 +0200 Subject: [PATCH 0780/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20for=20PR=20#12562?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12562.contrib.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelog/12562.contrib.rst diff --git a/changelog/12562.contrib.rst b/changelog/12562.contrib.rst new file mode 100644 index 00000000000..0d30495983a --- /dev/null +++ b/changelog/12562.contrib.rst @@ -0,0 +1,2 @@ +Possible typos in using the ``:user:`` RST role is now being linted +through the pre-commit tool integration -- by :user:`webknjaz`. From 8398609f08360932bb1853da494e9a3cd04961f3 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:30:21 +0200 Subject: [PATCH 0781/1271] =?UTF-8?q?=F0=9F=93=9D=F0=9F=9A=91=20Fix=20RST?= =?UTF-8?q?=20list=20in=20#12264=20changelog=20entry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was being rendered inline and now it's not. --- changelog/12204.bugfix.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/changelog/12204.bugfix.rst b/changelog/12204.bugfix.rst index 9690f513a38..801daab994a 100644 --- a/changelog/12204.bugfix.rst +++ b/changelog/12204.bugfix.rst @@ -3,5 +3,8 @@ Fix a regression in pytest 8.0 where tracebacks get longer and longer when multi Also fix a similar regression in pytest 5.4 for collectors which raise during setup. The fix necessitated internal changes which may affect some plugins: -- ``FixtureDef.cached_result[2]`` is now a tuple ``(exc, tb)`` instead of ``exc``. -- ``SetupState.stack`` failures are now a tuple ``(exc, tb)`` instead of ``exc``. + +* ``FixtureDef.cached_result[2]`` is now a tuple ``(exc, tb)`` + instead of ``exc``. +* ``SetupState.stack`` failures are now a tuple ``(exc, tb)`` + instead of ``exc``. From 94c0122a17f1136b44b90d6a93441fae64c47a2b Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:35:43 +0200 Subject: [PATCH 0782/1271] =?UTF-8?q?=F0=9F=93=9D=20Use=20past=20tense=20i?= =?UTF-8?q?n=20#12204=20change=20note?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12204.bugfix.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/changelog/12204.bugfix.rst b/changelog/12204.bugfix.rst index 801daab994a..50f9cc744d4 100644 --- a/changelog/12204.bugfix.rst +++ b/changelog/12204.bugfix.rst @@ -1,6 +1,7 @@ -Fix a regression in pytest 8.0 where tracebacks get longer and longer when multiple tests fail due to a shared higher-scope fixture which raised. +Fixed a regression in pytest 8.0 where tracebacks get longer and longer when multiple +tests fail due to a shared higher-scope fixture which raised. -Also fix a similar regression in pytest 5.4 for collectors which raise during setup. +Also fixed a similar regression in pytest 5.4 for collectors which raise during setup. The fix necessitated internal changes which may affect some plugins: From ffcc001562bce004952547fc1462f94838071338 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:46:38 +0200 Subject: [PATCH 0783/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20byline=20to?= =?UTF-8?q?=20#12264=20change=20note?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12204.bugfix.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/12204.bugfix.rst b/changelog/12204.bugfix.rst index 50f9cc744d4..099ad70610a 100644 --- a/changelog/12204.bugfix.rst +++ b/changelog/12204.bugfix.rst @@ -1,5 +1,5 @@ Fixed a regression in pytest 8.0 where tracebacks get longer and longer when multiple -tests fail due to a shared higher-scope fixture which raised. +tests fail due to a shared higher-scope fixture which raised -- by :user:`bluetech`. Also fixed a similar regression in pytest 5.4 for collectors which raise during setup. From b62974e63f432d66b91ee2d48e73e80f02fe66a1 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Tue, 2 Jul 2024 15:47:23 +0200 Subject: [PATCH 0784/1271] =?UTF-8?q?=F0=9F=93=9D=F0=9F=92=85=20Link=20#12?= =?UTF-8?q?264=20change=20note=20to=20#12204?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/12264.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 120000 changelog/12264.bugfix.rst diff --git a/changelog/12264.bugfix.rst b/changelog/12264.bugfix.rst new file mode 120000 index 00000000000..e5704e6e819 --- /dev/null +++ b/changelog/12264.bugfix.rst @@ -0,0 +1 @@ +12204.bugfix.rst \ No newline at end of file From 49bb5c89a6111d39455482fa415a3fd526b3b497 Mon Sep 17 00:00:00 2001 From: Virendra Patil <70162563+virendrapatil24@users.noreply.github.com> Date: Wed, 3 Jul 2024 00:28:08 +0530 Subject: [PATCH 0785/1271] Improved handling of invalid regex pattern in pytest.raises (#12526) --- AUTHORS | 1 + changelog/12505.bugfix.rst | 1 + src/_pytest/python_api.py | 9 +++++++++ testing/python/raises.py | 20 ++++++++++++++++++++ 4 files changed, 31 insertions(+) create mode 100644 changelog/12505.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 26fa27f9b2a..7fd388505dd 100644 --- a/AUTHORS +++ b/AUTHORS @@ -430,6 +430,7 @@ Victor Rodriguez Victor Uriarte Vidar T. Fauske Vijay Arora +Virendra Patil Virgil Dupras Vitaly Lashmanov Vivaan Verma diff --git a/changelog/12505.bugfix.rst b/changelog/12505.bugfix.rst new file mode 100644 index 00000000000..f55a8a17e4b --- /dev/null +++ b/changelog/12505.bugfix.rst @@ -0,0 +1 @@ +Improve handling of invalid regex patterns in :func:`pytest.raises(match=r'...') ` by providing a clear error message. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index c1e851391b0..4174a55b589 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -7,6 +7,7 @@ import math from numbers import Complex import pprint +import re from types import TracebackType from typing import Any from typing import Callable @@ -986,6 +987,14 @@ def __init__( self.message = message self.match_expr = match_expr self.excinfo: _pytest._code.ExceptionInfo[E] | None = None + if self.match_expr is not None: + re_error = None + try: + re.compile(self.match_expr) + except re.error as e: + re_error = e + if re_error is not None: + fail(f"Invalid regex pattern provided to 'match': {re_error}") def __enter__(self) -> _pytest._code.ExceptionInfo[E]: self.excinfo = _pytest._code.ExceptionInfo.for_later() diff --git a/testing/python/raises.py b/testing/python/raises.py index 271dd3e5a8c..2011c81615e 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -132,6 +132,26 @@ def test_division(example_input, expectation): result = pytester.runpytest() result.stdout.fnmatch_lines(["*2 failed*"]) + def test_raises_with_invalid_regex(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + def test_invalid_regex(): + with pytest.raises(ValueError, match="invalid regex character ["): + raise ValueError() + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + "*Invalid regex pattern provided to 'match': unterminated character set at position 24*", + ] + ) + result.stdout.no_fnmatch_line("*Traceback*") + result.stdout.no_fnmatch_line("*File*") + result.stdout.no_fnmatch_line("*line*") + def test_noclass(self) -> None: with pytest.raises(TypeError): pytest.raises("wrong", lambda: None) # type: ignore[call-overload] From 3a6abcc55963df96d29d12bb67b76a672ab0d429 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 00:16:55 +0000 Subject: [PATCH 0786/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.4.10 → v0.5.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.4.10...v0.5.0) - [github.com/adamchainz/blacken-docs: 1.16.0 → 1.18.0](https://github.com/adamchainz/blacken-docs/compare/1.16.0...1.18.0) - [github.com/pre-commit/mirrors-mypy: v1.10.0 → v1.10.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.10.0...v1.10.1) - pyproject-fmt: 2.1.3 => 2.1.4 Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 431b21f9942..ebcc797cc1e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.10" + rev: "v0.5.0" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/adamchainz/blacken-docs - rev: 1.16.0 + rev: 1.18.0 hooks: - id: blacken-docs additional_dependencies: [black==24.1.1] @@ -21,7 +21,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.0 + rev: v1.10.1 hooks: - id: mypy files: ^(src/|testing/|scripts/) @@ -38,7 +38,7 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "2.1.3" + rev: "2.1.4" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version From 375e748e7f4ffd087fdc45062f2148c357a64ed6 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 4 Jul 2024 11:08:14 +0200 Subject: [PATCH 0787/1271] [lint] Handle misplaced-bare-raise with ruff instead of pylint --- pyproject.toml | 1 + src/_pytest/logging.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e0ed2b90061..d140ca43c06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -221,6 +221,7 @@ disable = [ "method-hidden", "missing-docstring", "missing-timeout", + "misplaced-bare-raise", # PLE0704 from ruff "multiple-statements", # multiple-statements-on-one-line-colon (E701) from ruff "no-else-break", "no-else-continue", diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index fe3be060fdd..44af8ff2041 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -399,7 +399,7 @@ def handleError(self, record: logging.LogRecord) -> None: # The default behavior of logging is to print "Logging error" # to stderr with the call stack and some extra details. # pytest wants to make such mistakes visible during testing. - raise # pylint: disable=misplaced-bare-raise + raise # noqa: PLE0704 @final From b2dc022b3039d23140a50faabdb37676f18d5a2d Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 4 Jul 2024 11:13:22 +0200 Subject: [PATCH 0788/1271] [ruff] Fix all RUF024 (no mutable objects as values in 'dict.fromkeys' --- testing/test_runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/test_runner.py b/testing/test_runner.py index 79f7a3fd4d3..1b59ff78633 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -533,7 +533,7 @@ class TestClass(object): ) def test_report_extra_parameters(reporttype: type[reports.BaseReport]) -> None: args = list(inspect.signature(reporttype.__init__).parameters.keys())[1:] - basekw: dict[str, list[object]] = dict.fromkeys(args, []) + basekw: dict[str, list[object]] = {arg: [] for arg in args} report = reporttype(newthing=1, **basekw) assert report.newthing == 1 From b2908fd56f998c17f70d74333f81474812aa2b93 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 4 Jul 2024 11:21:33 +0200 Subject: [PATCH 0789/1271] [pylint] Disable new messages raised since last pre-commit auto-update --- pyproject.toml | 3 ++- testing/test_mark_expression.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d140ca43c06..1eb4871bc21 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -284,7 +284,8 @@ disable = [ "useless-import-alias", "useless-return", "using-constant-test", - "wrong-import-order", + "wrong-import-order", # handled by isort / ruff + "wrong-import-position", # handled by isort / ruff ] [tool.check-wheel-contents] diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index f8f5f9221cf..a61a9f21560 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -243,7 +243,7 @@ def mark_matcher() -> MarkMatcher: markers = [ pytest.mark.number_mark(a=1, b=2, c=3, d=999_999).mark, pytest.mark.builtin_matchers_mark(x=True, y=False, z=None).mark, - pytest.mark.str_mark( + pytest.mark.str_mark( # pylint: disable-next=non-ascii-name m="M", space="with space", empty="", aaאבגדcc="aaאבגדcc", אבגד="אבגד" ).mark, ] From 92ec5c349dc92d59bc77233612471d048b19364e Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 4 Jul 2024 11:46:14 +0200 Subject: [PATCH 0790/1271] [python 3.13] Mark functool.partial test to be skipped Closes #12552 --- testing/python/fixtures.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index bc091bb1f27..5c3a6a35b34 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -76,6 +76,16 @@ class B(A): assert getfuncargnames(B.static, cls=B) == ("arg1", "arg2") +@pytest.mark.skipif( + sys.version_info >= (3, 13), + reason="""\ +In python 3.13, this will raise FutureWarning: +functools.partial will be a method descriptor in future Python versions; +wrap it in staticmethod() if you want to preserve the old behavior + +But the wrapped 'functools.partial' is tested by 'test_getfuncargnames_staticmethod_partial' below. +""", +) def test_getfuncargnames_partial(): """Check getfuncargnames for methods defined with functools.partial (#5701)""" import functools From cf5369db0f14df40c6145b0a90a85577782a13c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= Date: Fri, 5 Jul 2024 14:19:07 +0200 Subject: [PATCH 0791/1271] Add --no-fold-skipped cli option (#12567) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows users to disable the default behavior of folding skipped tests in the short summary. Fix #9876 Signed-off-by: Pavel Březina --- changelog/12567.feature.rst | 7 +++++++ doc/en/how-to/output.rst | 5 +++++ src/_pytest/terminal.py | 35 +++++++++++++++++++++++++++++++++- testing/test_terminal.py | 38 +++++++++++++++++++++++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 changelog/12567.feature.rst diff --git a/changelog/12567.feature.rst b/changelog/12567.feature.rst new file mode 100644 index 00000000000..3690d7aff68 --- /dev/null +++ b/changelog/12567.feature.rst @@ -0,0 +1,7 @@ +Added ``--no-fold-skipped`` command line option + +If this option is set, then skipped tests in short summary are no longer grouped +by reason but all tests are printed individually with correct nodeid in the same +way as other statuses. + +-- by :user:`pbrezina` diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index 7a4e32edc78..4994ad1af69 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -552,6 +552,11 @@ captured output: PASSED test_example.py::test_ok == 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s === +.. note:: + + By default, parametrized variants of skipped tests are grouped together if + they share the same skip reason. You can use ``--no-fold-skipped`` to print each skipped test separately. + Creating resultlog format files -------------------------------------------------- diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index f364316e2e2..8c722124d04 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -154,6 +154,13 @@ def pytest_addoption(parser: Parser) -> None: dest="no_summary", help="Disable summary", ) + group._addoption( + "--no-fold-skipped", + action="store_false", + dest="fold_skipped", + default=True, + help="Do not fold skipped tests in short summary.", + ) group._addoption( "-q", "--quiet", @@ -371,6 +378,7 @@ def __init__(self, config: Config, file: TextIO | None = None) -> None: self._screen_width = self._tw.fullwidth self.currentfspath: None | Path | str | int = None self.reportchars = getreportopt(config) + self.foldskipped = config.option.fold_skipped self.hasmarkup = self._tw.hasmarkup self.isatty = file.isatty() self._progress_nodeids_reported: set[str] = set() @@ -1232,7 +1240,7 @@ def show_xpassed(lines: list[str]) -> None: line += " - " + str(reason) lines.append(line) - def show_skipped(lines: list[str]) -> None: + def show_skipped_folded(lines: list[str]) -> None: skipped: list[CollectReport] = self.stats.get("skipped", []) fskips = _folded_skips(self.startpath, skipped) if skipped else [] if not fskips: @@ -1252,6 +1260,31 @@ def show_skipped(lines: list[str]) -> None: else: lines.append("%s [%d] %s: %s" % (markup_word, num, fspath, reason)) + def show_skipped_unfolded(lines: list[str]) -> None: + skipped: list[CollectReport] = self.stats.get("skipped", []) + + for rep in skipped: + assert rep.longrepr is not None + assert isinstance(rep.longrepr, tuple), (rep, rep.longrepr) + assert len(rep.longrepr) == 3, (rep, rep.longrepr) + + verbose_word, verbose_markup = rep._get_verbose_word_with_markup( + self.config, {_color_for_type["warnings"]: True} + ) + markup_word = self._tw.markup(verbose_word, **verbose_markup) + nodeid = _get_node_id_with_markup(self._tw, self.config, rep) + line = f"{markup_word} {nodeid}" + reason = rep.longrepr[2] + if reason: + line += " - " + str(reason) + lines.append(line) + + def show_skipped(lines: list[str]) -> None: + if self.foldskipped: + show_skipped_folded(lines) + else: + show_skipped_unfolded(lines) + REPORTCHAR_ACTIONS: Mapping[str, Callable[[list[str]], None]] = { "x": show_xfailed, "X": show_xpassed, diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 5e3f631e22b..11ad623fb6b 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1150,6 +1150,44 @@ def test(): result.stdout.fnmatch_lines([expected]) assert result.stdout.lines.count(expected) == 1 + def test_summary_s_folded(self, pytester: Pytester) -> None: + """Test that skipped tests are correctly folded""" + pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("param", [True, False]) + @pytest.mark.skip("Some reason") + def test(param): + pass + """ + ) + result = pytester.runpytest("-rs") + expected = "SKIPPED [2] test_summary_s_folded.py:3: Some reason" + result.stdout.fnmatch_lines([expected]) + assert result.stdout.lines.count(expected) == 1 + + def test_summary_s_unfolded(self, pytester: Pytester) -> None: + """Test that skipped tests are not folded if --no-fold-skipped is set""" + pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("param", [True, False]) + @pytest.mark.skip("Some reason") + def test(param): + pass + """ + ) + result = pytester.runpytest("-rs", "--no-fold-skipped") + expected = [ + "SKIPPED test_summary_s_unfolded.py::test[True] - Skipped: Some reason", + "SKIPPED test_summary_s_unfolded.py::test[False] - Skipped: Some reason", + ] + result.stdout.fnmatch_lines(expected) + assert result.stdout.lines.count(expected[0]) == 1 + assert result.stdout.lines.count(expected[1]) == 1 + @pytest.mark.parametrize( ("use_ci", "expected_message"), From 9de29bfe1b02e5b9924dac06ed24ecbaa7b192a5 Mon Sep 17 00:00:00 2001 From: Cornelius Riemenschneider Date: Sat, 6 Jul 2024 19:01:29 +0200 Subject: [PATCH 0792/1271] Cache class: Fix crash on data race on Windows. (#12579) * Cache class: Fix crash on data race on Windows. On Windows, the error gets mapped to a different errno when a race happens, see https://github.com/python/cpython/blob/cecd6012b0ed5dca3916ae341e705ae44172991d/PC/errmap.h#L107. Therefore, we were observing crashes from that code path, as the error wasn't being handled, but bubbled up. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- AUTHORS | 1 + changelog/12580.bugfix.rst | 1 + src/_pytest/cacheprovider.py | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelog/12580.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 7fd388505dd..8d31170560c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -96,6 +96,7 @@ Christopher Gilling Claire Cecil Claudio Madotto Clément M.T. Robert +Cornelius Riemenschneider CrazyMerlyn Cristian Vera Cyrus Maden diff --git a/changelog/12580.bugfix.rst b/changelog/12580.bugfix.rst new file mode 100644 index 00000000000..9186ef1a4c9 --- /dev/null +++ b/changelog/12580.bugfix.rst @@ -0,0 +1 @@ +Fixed a crash when using the cache class on Windows and the cache directory was created concurrently. diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 51778c456c4..20bb262e05d 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -232,7 +232,8 @@ def _ensure_cache_dir_and_supporting_files(self) -> None: # gets "Directory not empty" from the rename. In this case, # everything is handled so just continue (while letting the # temporary directory be cleaned up). - if e.errno != errno.ENOTEMPTY: + # On Windows, the error is a FileExistsError which translates to EEXIST. + if e.errno not in (errno.ENOTEMPTY, errno.EEXIST): raise else: # Create a directory in place of the one we just moved so that From aa70d2982d12c7bf47447a1dab65bbfe186962df Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 7 Jul 2024 00:22:31 +0000 Subject: [PATCH 0793/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 152 +++++++++++++++++-------------- 1 file changed, 84 insertions(+), 68 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 38f855de03c..c0020a2bfb7 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Apr 22, 2024 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jul 03, 2024 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -112,7 +112,7 @@ This list contains 1482 plugins. :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio May 19, 2024 4 - Beta pytest<9,>=7.0.0 - :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Feb 25, 2024 N/A N/A + :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -127,7 +127,7 @@ This list contains 1482 plugins. :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest - :pypi:`pytest-aux` templates/examples and aux for pytest Jun 27, 2024 N/A N/A + :pypi:`pytest-aux` templates/examples and aux for pytest Jul 05, 2024 N/A N/A :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -143,7 +143,7 @@ This list contains 1482 plugins. :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 - :pypi:`pytest-bazel` A pytest runner with bazel support Jun 29, 2024 4 - Beta pytest + :pypi:`pytest-bazel` A pytest runner with bazel support Jul 05, 2024 4 - Beta pytest :pypi:`pytest-bdd` BDD for pytest Jun 04, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 @@ -153,7 +153,7 @@ This list contains 1482 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jun 28, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jul 04, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -316,7 +316,7 @@ This list contains 1482 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Jun 11, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Jul 02, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -487,8 +487,8 @@ This list contains 1482 plugins. :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Apr 22, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 11, 2023 4 - Beta pytest>=7 - :pypi:`pytest-exasol-itde` Feb 15, 2024 N/A pytest (>=7,<9) + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 02, 2024 4 - Beta pytest>=7 + :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Jun 07, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A @@ -585,18 +585,18 @@ This list contains 1482 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 Feb 07, 2024 4 - Beta pytest >=6.0.0 + :pypi:`pytest-fzf` fzf-based test selector for pytest Jul 03, 2024 4 - Beta pytest>=6.0.0 :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A :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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Feb 15, 2024 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jun 30, 2024 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-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. Apr 12, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jul 02, 2024 N/A pytest>=3.6 :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 @@ -639,12 +639,12 @@ This list contains 1482 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jun 29, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 06, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 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. Feb 09, 2024 N/A pytest + :pypi:`pytest-houdini` pytest plugin for testing code in Houdini. Jul 05, 2024 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) @@ -679,7 +679,7 @@ This list contains 1482 plugins. :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 20, 2024 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. Dec 01, 2023 4 - Beta pytest >=3.5.0 + :pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Jul 01, 2024 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-infinity` Jun 09, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-influxdb` Plugin for influxdb and pytest integration. Apr 20, 2021 N/A N/A @@ -690,9 +690,9 @@ This list contains 1482 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :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. Dec 13, 2023 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package May 24, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules May 10, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Jul 05, 2024 5 - Production/Stable pytest + :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 05, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Jul 06, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest @@ -709,7 +709,7 @@ This list contains 1482 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Jun 06, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Jul 05, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -827,7 +827,7 @@ This list contains 1482 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 Feb 12, 2024 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 Jun 13, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Jul 02, 2024 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) @@ -881,7 +881,7 @@ This list contains 1482 plugins. :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) :pypi:`pytest-neos` Pytest plugin for neos Jun 11, 2024 1 - Planning N/A - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Mar 07, 2024 N/A pytest <7.3,>=3.5.0 + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jul 05, 2024 N/A pytest<7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -889,7 +889,7 @@ This list contains 1482 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jun 18, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jul 01, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Apr 11, 2024 N/A N/A @@ -981,7 +981,7 @@ This list contains 1482 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers May 06, 2024 N/A N/A + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Jul 03, 2024 N/A N/A :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright May 24, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1157,7 +1157,7 @@ This list contains 1482 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Jun 07, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1182,7 +1182,7 @@ This list contains 1482 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jun 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 06, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1192,7 +1192,7 @@ This list contains 1482 plugins. :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 Feb 01, 2024 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. Jun 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 06, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1270,7 +1270,7 @@ This list contains 1482 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 Jun 26, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jul 03, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jun 14, 2024 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 @@ -1285,6 +1285,7 @@ This list contains 1482 plugins. :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-static` pytest-static Jun 20, 2024 1 - Planning pytest<8.0.0,>=7.4.3 + :pypi:`pytest-stats` Collects tests metadata for future analysis, easy to extend for any data store Jul 03, 2024 N/A pytest>=8.0.0 :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A @@ -1361,6 +1362,7 @@ This list contains 1482 plugins. :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Jul 01, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) @@ -1432,7 +1434,7 @@ This list contains 1482 plugins. :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A - :pypi:`pytest-unordered` Test equality of unordered collections in pytest Mar 13, 2024 4 - Beta pytest >=7.0.0 + :pypi:`pytest-unordered` Test equality of unordered collections in pytest Jul 05, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Apr 08, 2024 4 - Beta pytest>7.3.2 :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A @@ -1494,9 +1496,9 @@ This list contains 1482 plugins. :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-xstress` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. May 29, 2023 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Oct 01, 2023 4 - Beta pytest >=7.1.0 + :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Jul 03, 2024 4 - Beta pytest>=7.2.2 :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 Apr 23, 2024 N/A pytest>=7.4.0 + :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Jul 02, 2024 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) @@ -1509,7 +1511,7 @@ This list contains 1482 plugins. :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) :pypi:`pytest-zap` OWASP ZAP plugin for py.test. May 12, 2014 4 - Beta N/A :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A - :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jan 08, 2024 5 - Production/Stable pytest (>=4.5.0) + :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A @@ -1802,7 +1804,7 @@ This list contains 1482 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Apr 22, 2024, + *last release*: Jul 03, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2068,7 +2070,7 @@ This list contains 1482 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-cooperative` - *last release*: Feb 25, 2024, + *last release*: Jul 04, 2024, *status*: N/A, *requires*: N/A @@ -2173,7 +2175,7 @@ This list contains 1482 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: Jun 27, 2024, + *last release*: Jul 05, 2024, *status*: N/A, *requires*: N/A @@ -2285,7 +2287,7 @@ This list contains 1482 plugins. A pytest plugin to repeat the entire test suite in batches. :pypi:`pytest-bazel` - *last release*: Jun 29, 2024, + *last release*: Jul 05, 2024, *status*: 4 - Beta, *requires*: pytest @@ -2355,7 +2357,7 @@ This list contains 1482 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jun 28, 2024, + *last release*: Jul 04, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3496,7 +3498,7 @@ This list contains 1482 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Jun 11, 2024, + *last release*: Jul 02, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4693,16 +4695,16 @@ This list contains 1482 plugins. Parse queries in Lucene and Elasticsearch syntaxes :pypi:`pytest-examples` - *last release*: Jul 11, 2023, + *last release*: Jul 02, 2024, *status*: 4 - Beta, *requires*: pytest>=7 Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-exasol-itde` - *last release*: Feb 15, 2024, + *last release*: Jul 01, 2024, *status*: N/A, - *requires*: pytest (>=7,<9) + *requires*: pytest<9,>=7 @@ -5379,9 +5381,9 @@ This list contains 1482 plugins. :pypi:`pytest-fzf` - *last release*: Feb 07, 2024, + *last release*: Jul 03, 2024, *status*: 4 - Beta, - *requires*: pytest >=6.0.0 + *requires*: pytest>=6.0.0 fzf-based test selector for pytest @@ -5421,7 +5423,7 @@ This list contains 1482 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Feb 15, 2024, + *last release*: Jun 30, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -5456,7 +5458,7 @@ This list contains 1482 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Apr 12, 2024, + *last release*: Jul 02, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5757,7 +5759,7 @@ This list contains 1482 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jun 29, 2024, + *last release*: Jul 06, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 @@ -5792,7 +5794,7 @@ This list contains 1482 plugins. A plugin that tracks test changes :pypi:`pytest-houdini` - *last release*: Feb 09, 2024, + *last release*: Jul 05, 2024, *status*: N/A, *requires*: pytest @@ -6037,9 +6039,9 @@ This list contains 1482 plugins. :pypi:`pytest-image-snapshot` - *last release*: Dec 01, 2023, + *last release*: Jul 01, 2024, *status*: 4 - Beta, - *requires*: pytest >=3.5.0 + *requires*: pytest>=3.5.0 A pytest plugin for image snapshot management and comparison. @@ -6114,21 +6116,21 @@ This list contains 1482 plugins. A pytest plugin for writing inline tests. :pypi:`pytest-inmanta` - *last release*: Dec 13, 2023, + *last release*: Jul 05, 2024, *status*: 5 - Production/Stable, *requires*: pytest A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: May 24, 2024, + *last release*: Jul 05, 2024, *status*: 5 - Production/Stable, *requires*: N/A Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: May 10, 2024, + *last release*: Jul 06, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6247,7 +6249,7 @@ This list contains 1482 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Jun 06, 2024, + *last release*: Jul 05, 2024, *status*: N/A, *requires*: pytest @@ -7073,7 +7075,7 @@ This list contains 1482 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Jun 13, 2024, + *last release*: Jul 02, 2024, *status*: N/A, *requires*: pytest @@ -7451,9 +7453,9 @@ This list contains 1482 plugins. Pytest plugin for neos :pypi:`pytest-netdut` - *last release*: Mar 07, 2024, + *last release*: Jul 05, 2024, *status*: N/A, - *requires*: pytest <7.3,>=3.5.0 + *requires*: pytest<7.3,>=3.5.0 "Automated software testing for switches using pytest" @@ -7507,7 +7509,7 @@ This list contains 1482 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Jun 18, 2024, + *last release*: Jul 01, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -8151,7 +8153,7 @@ This list contains 1482 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: May 06, 2024, + *last release*: Jul 03, 2024, *status*: N/A, *requires*: N/A @@ -9383,7 +9385,7 @@ This list contains 1482 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Jun 07, 2024, + *last release*: Jul 01, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9558,7 +9560,7 @@ This list contains 1482 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jun 29, 2024, + *last release*: Jul 06, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9628,7 +9630,7 @@ This list contains 1482 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jun 29, 2024, + *last release*: Jul 06, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10174,7 +10176,7 @@ This list contains 1482 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jun 26, 2024, + *last release*: Jul 03, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10278,6 +10280,13 @@ This list contains 1482 plugins. pytest-static + :pypi:`pytest-stats` + *last release*: Jul 03, 2024, + *status*: N/A, + *requires*: pytest>=8.0.0 + + Collects tests metadata for future analysis, easy to extend for any data store + :pypi:`pytest-statsd` *last release*: Nov 30, 2018, *status*: 5 - Production/Stable, @@ -10810,6 +10819,13 @@ This list contains 1482 plugins. A plugin that allows coll test data for use on Test Tracer + :pypi:`pytest-test-tracer-for-pytest-bdd` + *last release*: Jul 01, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A plugin that allows coll test data for use on Test Tracer + :pypi:`pytest-test-utils` *last release*: Feb 08, 2024, *status*: N/A, @@ -11308,9 +11324,9 @@ This list contains 1482 plugins. Run only unmarked tests :pypi:`pytest-unordered` - *last release*: Mar 13, 2024, + *last release*: Jul 05, 2024, *status*: 4 - Beta, - *requires*: pytest >=7.0.0 + *requires*: pytest>=7.0.0 Test equality of unordered collections in pytest @@ -11742,9 +11758,9 @@ This list contains 1482 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-xvirt` - *last release*: Oct 01, 2023, + *last release*: Jul 03, 2024, *status*: 4 - Beta, - *requires*: pytest >=7.1.0 + *requires*: pytest>=7.2.2 A pytest plugin to virtualize test. For example to transparently running them on a remote box. @@ -11756,7 +11772,7 @@ This list contains 1482 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Apr 23, 2024, + *last release*: Jul 02, 2024, *status*: N/A, *requires*: pytest>=7.4.0 @@ -11847,9 +11863,9 @@ This list contains 1482 plugins. eee :pypi:`pytest-zebrunner` - *last release*: Jan 08, 2024, + *last release*: Jul 04, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.5.0) + *requires*: pytest>=4.5.0 Pytest connector for Zebrunner reporting From 6933bef0b0f193a32a3716a72a26e7184542376b Mon Sep 17 00:00:00 2001 From: Marc Bresson <50196352+MarcBresson@users.noreply.github.com> Date: Mon, 8 Jul 2024 15:26:59 +0200 Subject: [PATCH 0794/1271] New docs about CI/BUILD_NUMBER env vars (#12578) Closes #12577 Co-authored-by: Marc Bresson Co-authored-by: Bruno Oliveira --- changelog/12577.doc.rst | 3 + doc/en/explanation/ci.rst | 70 ++++++++++++ doc/en/explanation/index.rst | 3 +- doc/en/reference/reference.rst | 203 +++++++++++++++++---------------- src/_pytest/helpconfig.py | 6 + 5 files changed, 183 insertions(+), 102 deletions(-) create mode 100644 changelog/12577.doc.rst create mode 100644 doc/en/explanation/ci.rst diff --git a/changelog/12577.doc.rst b/changelog/12577.doc.rst new file mode 100644 index 00000000000..0bd427e177d --- /dev/null +++ b/changelog/12577.doc.rst @@ -0,0 +1,3 @@ +`CI` and `BUILD_NUMBER` environment variables role is discribed in +the reference doc. They now also appears when doing `pytest -h` +-- by :user:`MarcBresson`. diff --git a/doc/en/explanation/ci.rst b/doc/en/explanation/ci.rst new file mode 100644 index 00000000000..45fe658d14f --- /dev/null +++ b/doc/en/explanation/ci.rst @@ -0,0 +1,70 @@ +.. _`ci-pipelines`: + +CI Pipelines +============ + +Rationale +--------- + +The goal of testing in a CI pipeline is different from testing locally. Indeed, +you can quickly edit some code and run your tests again on your computer, but +it is not possible with CI pipeline. They run on a separate server and are +triggered by specific actions. + +From that observation, pytest can detect when it is in a CI environment and +adapt some of its behaviours. + +How CI is detected +------------------ + +Pytest knows it is in a CI environment when either one of these environment variables are set, +regardless of their value: + +* `CI`: used by many CI systems. +* `BUILD_NUMBER`: used by Jenkins. + +Effects on CI +------------- + +For now, the effects on pytest of being in a CI environment are limited. + +When a CI environment is detected, the output of the short test summary info is no longer truncated to the terminal size i.e. the entire message will be shown. + + .. code-block:: python + + # content of test_ci.py + import pytest + + + def test_db_initialized(): + pytest.fail( + "deliberately failing for demo purpose, Lorem ipsum dolor sit amet, " + "consectetur adipiscing elit. Cras facilisis, massa in suscipit " + "dignissim, mauris lacus molestie nisi, quis varius metus nulla ut ipsum." + ) + + +Running this locally, without any extra options, will output: + + .. code-block:: pytest + + $ pytest test_ci.py + ... + ========================= short test summary info ========================== + FAILED test_backends.py::test_db_initialized[d2] - Failed: deliberately f... + +*(Note the truncated text)* + + +While running this on CI will output: + + .. code-block:: pytest + + $ export CI=true + $ pytest test_ci.py + ... + ========================= short test summary info ========================== + FAILED test_backends.py::test_db_initialized[d2] - Failed: deliberately failing + for demo purpose, Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras + facilisis, massa in suscipit dignissim, mauris lacus molestie nisi, quis varius + metus nulla ut ipsum. diff --git a/doc/en/explanation/index.rst b/doc/en/explanation/index.rst index 53910f1eb7b..2edf60a5d8b 100644 --- a/doc/en/explanation/index.rst +++ b/doc/en/explanation/index.rst @@ -11,5 +11,6 @@ Explanation anatomy fixtures goodpractices - flaky pythonpath + ci + flaky diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 6926cd61bd3..d1222728e13 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1120,11 +1120,11 @@ Environment variables that can be used to change pytest's behavior. .. envvar:: CI -When set (regardless of value), pytest acknowledges that is running in a CI process. Alternative to ``BUILD_NUMBER`` variable. +When set (regardless of value), pytest acknowledges that is running in a CI process. Alternative to ``BUILD_NUMBER`` variable. See also :ref:`ci-pipelines`. .. envvar:: BUILD_NUMBER -When set (regardless of value), pytest acknowledges that is running in a CI process. Alternative to CI variable. +When set (regardless of value), pytest acknowledges that is running in a CI process. Alternative to CI variable. See also :ref:`ci-pipelines`. .. envvar:: PYTEST_ADDOPTS @@ -1939,19 +1939,18 @@ All the command-line flags can be obtained by running ``pytest --help``:: general: -k EXPRESSION Only run tests which match the given substring expression. An expression is a Python evaluable - expression where all names are substring-matched - against test names and their parent classes. - Example: -k 'test_method or test_other' matches all - test functions and classes whose name contains - 'test_method' or 'test_other', while -k 'not - test_method' matches those that don't contain - 'test_method' in their names. -k 'not test_method - and not test_other' will eliminate the matches. - Additionally keywords are matched to classes and - functions containing extra names in their - 'extra_keyword_matches' set, as well as functions - which have names assigned directly to them. The - matching is case-insensitive. + expression where all names are substring-matched against + test names and their parent classes. Example: -k + 'test_method or test_other' matches all test functions + and classes whose name contains 'test_method' or + 'test_other', while -k 'not test_method' matches those + that don't contain 'test_method' in their names. -k 'not + test_method and not test_other' will eliminate the + matches. Additionally keywords are matched to classes + and functions containing extra names in their + 'extra_keyword_matches' set, as well as functions which + have names assigned directly to them. The matching is + case-insensitive. -m MARKEXPR Only run tests matching given mark expression. For example: -m 'mark1 and not mark2'. --markers show markers (builtin, plugin and per-project ones). @@ -1969,28 +1968,28 @@ All the command-line flags can be obtained by running ``pytest --help``:: --trace Immediately break when running each test --capture=method Per-test capturing method: one of fd|sys|no|tee-sys -s Shortcut for --capture=no - --runxfail Report the results of xfail tests as if they were - not marked - --lf, --last-failed Rerun only the tests that failed at the last run (or - all if none failed) - --ff, --failed-first Run all tests, but run the last failures first. This - may re-order tests and thus lead to repeated fixture + --runxfail Report the results of xfail tests as if they were not + marked + --lf, --last-failed Rerun only the tests that failed at the last run (or all + if none failed) + --ff, --failed-first Run all tests, but run the last failures first. This may + re-order tests and thus lead to repeated fixture setup/teardown. --nf, --new-first Run tests from new files first, then the rest of the tests sorted by file mtime --cache-show=[CACHESHOW] - Show cache contents, don't perform collection or - tests. Optional argument: glob (default: '*'). + Show cache contents, don't perform collection or tests. + Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run --lfnf={all,none}, --last-failed-no-failures={all,none} - With ``--lf``, determines whether to execute tests - when there are no previously (known) failures or - when no cached ``lastfailed`` data was found. - ``all`` (the default) runs the full test suite - again. ``none`` just emits a message about no known - failures and exits successfully. - --sw, --stepwise Exit on test failure and continue from last failing - test next time + With ``--lf``, determines whether to execute tests when + there are no previously (known) failures or when no + cached ``lastfailed`` data was found. ``all`` (the + default) runs the full test suite again. ``none`` just + emits a message about no known failures and exits + successfully. + --sw, --stepwise Exit on test failure and continue from last failing test + next time --sw-skip, --stepwise-skip Ignore the first failing test but stop on the next failing test. Implicitly enables --stepwise. @@ -2007,55 +2006,53 @@ All the command-line flags can be obtained by running ``pytest --help``:: -r chars Show extra test summary info as specified by chars: (f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed, (P)assed with output, (a)ll except passed - (p/P), or (A)ll. (w)arnings are enabled by default - (see --disable-warnings), 'N' can be used to reset - the list. (default: 'fE'). + (p/P), or (A)ll. (w)arnings are enabled by default (see + --disable-warnings), 'N' can be used to reset the list. + (default: 'fE'). --disable-warnings, --disable-pytest-warnings Disable warnings summary -l, --showlocals Show locals in tracebacks (disabled by default) - --no-showlocals Hide locals in tracebacks (negate --showlocals - passed through addopts) - --tb=style Traceback print mode - (auto/long/short/line/native/no) + --no-showlocals Hide locals in tracebacks (negate --showlocals passed + through addopts) + --tb=style Traceback print mode (auto/long/short/line/native/no) + --xfail-tb Show tracebacks for xfail (as long as --tb != no) --show-capture={no,stdout,stderr,log,all} Controls how captured stdout/stderr/log is shown on failed tests. Default: all. --full-trace Don't cut any tracebacks (default is to cut) --color=color Color terminal output (yes/no/auto) --code-highlight={yes,no} - Whether code should be highlighted (only if --color - is also enabled). Default: yes. + Whether code should be highlighted (only if --color is + also enabled). Default: yes. --pastebin=mode Send failed|all info to bpaste.net pastebin service --junit-xml=path Create junit-xml style report file at given path --junit-prefix=str Prepend prefix to classnames in junit-xml output pytest-warnings: -W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGS - Set which warnings to report, see -W option of - Python itself + Set which warnings to report, see -W option of Python + itself --maxfail=num Exit after first num failures or errors --strict-config Any warnings encountered while parsing the `pytest` section of the configuration file raise errors - --strict-markers Markers not registered in the `markers` section of - the configuration file raise errors + --strict-markers Markers not registered in the `markers` section of the + configuration file raise errors --strict (Deprecated) alias to --strict-markers -c FILE, --config-file=FILE Load configuration from `FILE` instead of trying to locate one of the implicit configuration files. --continue-on-collection-errors Force test execution even if collection errors occur - --rootdir=ROOTDIR Define root directory for tests. Can be relative - path: 'root_dir', './root_dir', - 'root_dir/another_dir/'; absolute path: - '/home/user/root_dir'; path with variables: - '$HOME/root_dir'. + --rootdir=ROOTDIR Define root directory for tests. Can be relative path: + 'root_dir', './root_dir', 'root_dir/another_dir/'; + absolute path: '/home/user/root_dir'; path with + variables: '$HOME/root_dir'. collection: --collect-only, --co Only collect tests, don't execute them --pyargs Try to interpret all arguments as Python packages --ignore=path Ignore path during collection (multi-allowed) - --ignore-glob=path Ignore path pattern during collection (multi- - allowed) + --ignore-glob=path Ignore path pattern during collection (multi-allowed) --deselect=nodeid_prefix Deselect item (via node id prefix) during collection (multi-allowed) @@ -2065,8 +2062,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: --collect-in-virtualenv Don't ignore tests in a local virtualenv directory --import-mode={prepend,append,importlib} - Prepend/append to sys.path when importing test - modules and conftest files. Default: prepend. + Prepend/append to sys.path when importing test modules + and conftest files. Default: prepend. --doctest-modules Run doctests in all .py modules --doctest-report={none,cdiff,ndiff,udiff,only_first_failure} Choose another output format for diffs on doctest @@ -2079,38 +2076,37 @@ All the command-line flags can be obtained by running ``pytest --help``:: failure test session debugging and configuration: - --basetemp=dir Base temporary directory for this test run. - (Warning: this directory is removed if it exists.) - -V, --version Display pytest version and information about - plugins. When given twice, also display information - about plugins. + --basetemp=dir Base temporary directory for this test run. (Warning: + this directory is removed if it exists.) + -V, --version Display pytest version and information about plugins. + When given twice, also display information about + plugins. -h, --help Show help message and configuration info -p name Early-load given plugin module name or entry point - (multi-allowed). To avoid loading of plugins, use - the `no:` prefix, e.g. `no:doctest`. + (multi-allowed). To avoid loading of plugins, use the + `no:` prefix, e.g. `no:doctest`. --trace-config Trace considerations of conftest.py files --debug=[DEBUG_FILE_NAME] Store internal tracing debug information in this log - file. This file is opened with 'w' and truncated as - a result, care advised. Default: pytestdebug.log. + file. This file is opened with 'w' and truncated as a + result, care advised. Default: pytestdebug.log. -o OVERRIDE_INI, --override-ini=OVERRIDE_INI - Override ini option with "option=value" style, e.g. - `-o xfail_strict=True -o cache_dir=cache`. + Override ini option with "option=value" style, e.g. `-o + xfail_strict=True -o cache_dir=cache`. --assert=MODE Control assertion debugging tools. 'plain' performs no assertion debugging. - 'rewrite' (the default) rewrites assert statements - in test modules on import to provide assert - expression information. + 'rewrite' (the default) rewrites assert statements in + test modules on import to provide assert expression + information. --setup-only Only setup fixtures, do not execute tests --setup-show Show setup of fixtures while executing tests - --setup-plan Show what fixtures and tests would be executed but - don't execute anything + --setup-plan Show what fixtures and tests would be executed but don't + execute anything logging: - --log-level=LEVEL Level of messages to catch/display. Not set by - default, so it depends on the root/parent log - handler's effective level, where it is "WARNING" by - default. + --log-level=LEVEL Level of messages to catch/display. Not set by default, + so it depends on the root/parent log handler's effective + level, where it is "WARNING" by default. --log-format=LOG_FORMAT Log format used by the logging module --log-date-format=LOG_DATE_FORMAT @@ -2134,8 +2130,13 @@ All the command-line flags can be obtained by running ``pytest --help``:: Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer. --log-disable=LOGGER_DISABLE - Disable a logger by name. Can be passed multiple - times. + Disable a logger by name. Can be passed multiple times. + + Custom options: + --lsof Run FD checks if lsof is available + --runpytest={inprocess,subprocess} + Run pytest sub runs in tests using an 'inprocess' or + 'subprocess' (python -m main) method [pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg|pyproject.toml file found: @@ -2150,37 +2151,33 @@ All the command-line flags can be obtained by running ``pytest --help``:: warnings.filterwarnings. Processed after -W/--pythonwarnings. consider_namespace_packages (bool): - Consider namespace packages when resolving module - names during import - usefixtures (args): List of default fixtures to be used with this - project + Consider namespace packages when resolving module names + during import + usefixtures (args): List of default fixtures to be used with this project python_files (args): Glob-style file patterns for Python test module discovery python_classes (args): - Prefixes or glob names for Python test class - discovery + Prefixes or glob names for Python test class discovery python_functions (args): Prefixes or glob names for Python test function and method discovery disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool): - Disable string escape non-ASCII characters, might - cause unwanted side effects(use at your own risk) + Disable string escape non-ASCII characters, might cause + unwanted side effects(use at your own risk) console_output_style (string): - Console output: "classic", or with additional - progress information ("progress" (percentage) | - "count" | "progress-even-when-capture-no" (forces - progress even when capture=no) + Console output: "classic", or with additional progress + information ("progress" (percentage) | "count" | + "progress-even-when-capture-no" (forces progress even + when capture=no) verbosity_test_cases (string): Specify a verbosity level for test case execution, - overriding the main level. Higher levels will - provide more detailed information about each test - case executed. - xfail_strict (bool): Default for the strict parameter of xfail markers - when not given explicitly (default: False) + overriding the main level. Higher levels will provide + more detailed information about each test case executed. + xfail_strict (bool): Default for the strict parameter of xfail markers when + not given explicitly (default: False) tmp_path_retention_count (string): How many sessions should we keep the `tmp_path` - directories, according to - `tmp_path_retention_policy`. + directories, according to `tmp_path_retention_policy`. tmp_path_retention_policy (string): Controls which directories created by the `tmp_path` fixture are kept around, based on test outcome. @@ -2189,9 +2186,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: Enables the pytest_assertion_pass hook. Make sure to delete any previously generated pyc cache files. verbosity_assertions (string): - Specify a verbosity level for assertions, overriding - the main level. Higher levels will provide more - detailed explanation when an assertion fails. + Specify a verbosity level for assertions, overriding the + main level. Higher levels will provide more detailed + explanation when an assertion fails. junit_suite_name (string): Test suite name for JUnit report junit_logging (string): @@ -2213,8 +2210,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: log_format (string): Default value for --log-format log_date_format (string): Default value for --log-date-format - log_cli (bool): Enable log display during test run (also known as - "live logging") + log_cli (bool): Enable log display during test run (also known as "live + logging") log_cli_level (string): Default value for --log-cli-level log_cli_format (string): @@ -2234,14 +2231,18 @@ All the command-line flags can be obtained by running ``pytest --help``:: Default value for --log-auto-indent pythonpath (paths): Add paths to sys.path faulthandler_timeout (string): - Dump the traceback of all threads if a test takes - more than TIMEOUT seconds to finish + Dump the traceback of all threads if a test takes more + than TIMEOUT seconds to finish addopts (args): Extra command line options minversion (string): Minimally required pytest version required_plugins (args): Plugins that must be present for pytest to run + pytester_example_dir (string): + Directory to take the pytester example files from Environment variables: + CI When set (regardless of value), pytest knows it is running in a CI process and does not truncate summary info + BUILD_NUMBER equivalent to CI PYTEST_ADDOPTS Extra command line options PYTEST_PLUGINS Comma-separated plugins to load during startup PYTEST_DISABLE_PLUGIN_AUTOLOAD Set to disable plugin auto-loading diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index f23b839943c..1433607a19b 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -212,6 +212,12 @@ def showhelp(config: Config) -> None: tw.line() tw.line("Environment variables:") vars = [ + ( + "CI", + "When set (regardless of value), pytest knows it is running in a " + "CI process and does not truncate summary info", + ), + ("BUILD_NUMBER", "Equivalent to CI"), ("PYTEST_ADDOPTS", "Extra command line options"), ("PYTEST_PLUGINS", "Comma-separated plugins to load during startup"), ("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "Set to disable plugin auto-loading"), From 99f0662def864400ae5698a1f874cbb0724c2624 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 22:49:38 +0000 Subject: [PATCH 0795/1271] [pre-commit.ci] pre-commit autoupdate (#12588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.0 → v0.5.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.0...v0.5.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ebcc797cc1e..ce365ddbef2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.0" + rev: "v0.5.1" hooks: - id: ruff args: ["--fix"] From 73e53ad6f4d87d4dcb68f3167b8dec6b194346cf Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 9 Jul 2024 14:27:17 +0200 Subject: [PATCH 0796/1271] Remove done Europython training --- doc/en/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 8de3b3993dd..378ed8face5 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -4,7 +4,6 @@ .. sidebar:: **Next Open Trainings and Events** - - `pytest tips and tricks for a better testsuite `_, at `Europython 2024 `_, **July 9th 2024** (3h), Prague (CZ) - `pytest: Professionelles Testen (nicht nur) für Python `_, at `CH Open Workshoptage `_, **September 2nd 2024**, HSLU Rotkreuz (CH) - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Leipzig (DE) / Remote From 05979bc4a97491c8b75f8baf95ec16f5b5516353 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Sun, 7 Jul 2024 12:53:55 +0100 Subject: [PATCH 0797/1271] Modernise Sphinx configuration This change brings the configuration closer with what the latest sphinx-quickstart generates. It also makes it easier to read through the documentation configuration file as well. - Remove unset configuration options - Drop configuration options that are set to their default values - Remove placeholder comments, including inline documentation of options - Group configuration options into sections with links to detailed docs - Move all custom logic toward the end of the file --- doc/en/conf.py | 373 +++++++++++++------------------------------------ 1 file changed, 99 insertions(+), 274 deletions(-) diff --git a/doc/en/conf.py b/doc/en/conf.py index 0d440ec448a..9f5f3787c1e 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -1,20 +1,3 @@ -# -# pytest documentation build configuration file, created by -# sphinx-quickstart on Fri Oct 8 17:54:28 2010. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The full version, including alpha/beta/rc tags. -# The short X.Y version. from __future__ import annotations import os @@ -23,61 +6,26 @@ from textwrap import dedent from typing import TYPE_CHECKING -from _pytest import __version__ as full_version +from pytest import __version__ as full_version -version = full_version.split("+")[0] - if TYPE_CHECKING: import sphinx.application - PROJECT_ROOT_DIR = Path(__file__).parents[2].resolve() -IS_RELEASE_ON_RTD = ( - os.getenv("READTHEDOCS", "False") == "True" - and os.environ["READTHEDOCS_VERSION_TYPE"] == "tag" -) -if IS_RELEASE_ON_RTD: - tags: set[str] - # pylint: disable-next=used-before-assignment - tags.add("is_release") # noqa: F821 - -release = ".".join(version.split(".")[:2]) - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) - -autodoc_member_order = "bysource" -autodoc_typehints = "description" -autodoc_typehints_description_target = "documented" -todo_include_todos = 1 - -latex_engine = "lualatex" - -latex_elements = { - "preamble": dedent( - r""" - \directlua{ - luaotfload.add_fallback("fallbacks", { - "Noto Serif CJK SC:style=Regular;", - "Symbola:Style=Regular;" - }) - } - \setmainfont{FreeSerif}[RawFeature={fallback=fallbacks}] - """ - ) -} +# -- Project information --------------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -# -- General configuration ----------------------------------------------------- +project = "pytest" +copyright = "2015, holger krekel and pytest-dev team" +version = full_version.split("+")[0] +release = ".".join(version.split(".")[:2]) -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' +# -- General configuration ------------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +root_doc = "contents" extensions = [ "pygments_pytest", "sphinx.ext.autodoc", @@ -98,35 +46,6 @@ if shutil.which("inkscape"): extensions.append("sphinxcontrib.inkscapeconverter") -# Add any paths that contain templates here, relative to this directory. -templates_path = ["_templates"] - -# The suffix of source filenames. -source_suffix = ".rst" - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = "contents" - -# General information about the project. -project = "pytest" -copyright = "2015, holger krekel and pytest-dev team" - - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. exclude_patterns = [ "_build", "naming20.rst", @@ -138,38 +57,9 @@ "setup.rst", "example/remoteinterp.rst", ] - - -# The reST default role (used for this markup: `text`) to use for all documents. +templates_path = ["_templates"] default_role = "literal" -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -add_module_names = False - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# A list of regular expressions that match URIs that should not be checked when -# doing a linkcheck. -linkcheck_ignore = [ - "https://blogs.msdn.microsoft.com/bharry/2017/06/28/testing-in-a-cloud-delivery-cadence/", - "http://pythontesting.net/framework/pytest-introduction/", - r"https://github.com/pytest-dev/pytest/issues/\d+", - r"https://github.com/pytest-dev/pytest/pull/\d+", -] - -# The number of worker threads to use when checking links (default=5). -linkcheck_workers = 5 - - nitpicky = True nitpick_ignore = [ # TODO (fix in pluggy?) @@ -217,53 +107,54 @@ ("py:class", "_ScopeName"), ] +add_module_names = False -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = "furo" +# -- Options for Autodoc -------------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#configuration -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# html_theme_options = {"index_logo": None} +autodoc_member_order = "bysource" +autodoc_typehints = "description" +autodoc_typehints_description_target = "documented" -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] +# -- Options for intersphinx ---------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html#configuration -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -html_title = "pytest documentation" +intersphinx_mapping = { + "pluggy": ("https://pluggy.readthedocs.io/en/stable", None), + "python": ("https://docs.python.org/3", None), + "numpy": ("https://numpy.org/doc/stable", None), + "pip": ("https://pip.pypa.io/en/stable", None), + "tox": ("https://tox.wiki/en/stable", None), + "virtualenv": ("https://virtualenv.pypa.io/en/stable", None), + "setuptools": ("https://setuptools.pypa.io/en/stable", None), + "packaging": ("https://packaging.python.org/en/latest", None), +} -# A shorter title for the navigation bar. Default is the same as html_title. -html_short_title = f"pytest-{release}" +# -- Options for todo ----------------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/extensions/todo.html#configuration -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -html_logo = "img/pytest_logo_curves.svg" +todo_include_todos = True -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -html_favicon = "img/favicon.png" +# -- Options for linkcheck builder ---------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-the-linkcheck-builder -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -# html_static_path = ['_static'] +linkcheck_ignore = [ + "https://blogs.msdn.microsoft.com/bharry/2017/06/28/testing-in-a-cloud-delivery-cadence/", + "http://pythontesting.net/framework/pytest-introduction/", + r"https://github.com/pytest-dev/pytest/issues/\d+", + r"https://github.com/pytest-dev/pytest/pull/\d+", +] +linkcheck_workers = 5 -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' +# -- Options for HTML output ---------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -# html_use_smartypants = True +html_theme = "furo" +html_title = "pytest documentation" +html_short_title = f"pytest-{release}" -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} -# html_sidebars = {'index': 'indexsidebar.html'} +html_logo = "img/pytest_logo_curves.svg" +html_favicon = "img/favicon.png" html_sidebars = { "index": [ @@ -288,55 +179,35 @@ ], } -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} -# html_additional_pages = {'index': 'index.html'} - - -# If false, no module index is generated. -html_domain_indices = True - -# If false, no index is generated. html_use_index = False - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. html_show_sourcelink = False -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True +html_baseurl = "https://docs.pytest.org/en/stable/" -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True +# -- Options for HTML Help output ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-help-output -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' +htmlhelp_basename = "pytestdoc" -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None -# Output file base name for HTML help builder. -htmlhelp_basename = "pytestdoc" +# -- Options for manual page output --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-manual-page-output -# The base URL which points to the root of the HTML documentation. It is used -# to indicate the location of document using the canonical link relation (#12363). -html_baseurl = "https://docs.pytest.org/en/stable/" +man_pages = [ + ("how-to/usage", "pytest", "pytest usage", ["holger krekel at merlinux eu"], 1) +] -# -- Options for LaTeX output -------------------------------------------------- +# -- Options for epub output ---------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-epub-output -# The paper size ('letter' or 'a4'). -# latex_paper_size = 'letter' +epub_title = "pytest" +epub_author = "holger krekel at merlinux eu" +epub_publisher = "holger krekel at merlinux eu" +epub_copyright = "2013, holger krekel et alii" -# The font size ('10pt', '11pt' or '12pt'). -# latex_font_size = '10pt' +# -- Options for LaTeX output -------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-latex-output -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ( "contents", @@ -346,80 +217,29 @@ "manual", ) ] - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Additional stuff for the LaTeX preamble. -# latex_preamble = '' - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. latex_domain_indices = False +latex_engine = "lualatex" +latex_elements = { + "preamble": dedent( + r""" + \directlua{ + luaotfload.add_fallback("fallbacks", { + "Noto Serif CJK SC:style=Regular;", + "Symbola:Style=Regular;" + }) + } -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ("how-to/usage", "pytest", "pytest usage", ["holger krekel at merlinux eu"], 1) -] - - -# -- Options for Epub output --------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = "pytest" -epub_author = "holger krekel at merlinux eu" -epub_publisher = "holger krekel at merlinux eu" -epub_copyright = "2013, holger krekel et alii" - -# The language of the text. It defaults to the language option -# or en if the language is not set. -# epub_language = '' - -# The scheme of the identifier. Typical schemes are ISBN or URL. -# epub_scheme = '' - -# The unique identifier of the text. This can be an ISBN number -# or the project homepage. -# epub_identifier = '' - -# A unique identification for the text. -# epub_uid = '' - -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -# epub_pre_files = [] - -# HTML files that should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -# epub_post_files = [] - -# A list of files that should not be packed into the epub file. -# epub_exclude_files = [] - -# The depth of the table of contents in toc.ncx. -# epub_tocdepth = 3 - -# Allow duplicate toc entries. -# epub_tocdup = True - + \setmainfont{FreeSerif}[RawFeature={fallback=fallbacks}] + """ + ) +} -# -- Options for texinfo output ------------------------------------------------ +# -- Options for texinfo output ------------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-texinfo-output texinfo_documents = [ ( - master_doc, + root_doc, "pytest", "pytest Documentation", ( @@ -433,29 +253,34 @@ ) ] -# -- Options for towncrier_draft extension ----------------------------------- +# -- Options for towncrier_draft extension -------------------------------------------- +# https://sphinxcontrib-towncrier.readthedocs.io/en/latest/#how-to-use-this towncrier_draft_autoversion_mode = "draft" # or: 'sphinx-version', 'sphinx-release' towncrier_draft_include_empty = True towncrier_draft_working_directory = PROJECT_ROOT_DIR towncrier_draft_config_path = "pyproject.toml" # relative to cwd - # -- Options for sphinx_issues extension ----------------------------------- +# https://github.com/sloria/sphinx-issues#installation-and-configuration issues_github_path = "pytest-dev/pytest" +# -- Custom Read the Docs build configuration ----------------------------------------- +# https://docs.readthedocs.io/en/stable/reference/environment-variables.html#environment-variable-reference +# https://www.sphinx-doc.org/en/master/usage/restructuredtext/directives.html#including-content-based-on-tags -intersphinx_mapping = { - "pluggy": ("https://pluggy.readthedocs.io/en/stable", None), - "python": ("https://docs.python.org/3", None), - "numpy": ("https://numpy.org/doc/stable", None), - "pip": ("https://pip.pypa.io/en/stable", None), - "tox": ("https://tox.wiki/en/stable", None), - "virtualenv": ("https://virtualenv.pypa.io/en/stable", None), - "setuptools": ("https://setuptools.pypa.io/en/stable", None), - "packaging": ("https://packaging.python.org/en/latest", None), -} +IS_RELEASE_ON_RTD = ( + os.getenv("READTHEDOCS", "False") == "True" + and os.environ["READTHEDOCS_VERSION_TYPE"] == "tag" +) +if IS_RELEASE_ON_RTD: + tags: set[str] + # pylint: disable-next=used-before-assignment + tags.add("is_release") # noqa: F821 + +# -- Custom documentation plugin ------------------------------------------------------ +# https://www.sphinx-doc.org/en/master/development/tutorials/extending_syntax.html#the-setup-function def setup(app: sphinx.application.Sphinx) -> None: From 9e265eee461866195a3835263dc3b350f59b097e Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Sun, 7 Jul 2024 13:13:28 +0100 Subject: [PATCH 0798/1271] Remove `layout.html` This file is not used with Furo. --- doc/en/_templates/layout.html | 52 ----------------------------------- 1 file changed, 52 deletions(-) delete mode 100644 doc/en/_templates/layout.html diff --git a/doc/en/_templates/layout.html b/doc/en/_templates/layout.html deleted file mode 100644 index f7096eaaa5e..00000000000 --- a/doc/en/_templates/layout.html +++ /dev/null @@ -1,52 +0,0 @@ -{# - - Copied from: - - https://raw.githubusercontent.com/pallets/pallets-sphinx-themes/b0c6c41849b4e15cbf62cc1d95c05ef2b3e155c8/src/pallets_sphinx_themes/themes/pocoo/layout.html - - And removed the warning version (see #7331). - -#} - -{% extends "basic/layout.html" %} - -{% set metatags %} - {{- metatags }} - -{%- endset %} - -{% block extrahead %} - {%- if page_canonical_url %} - - {%- endif %} - - {{ super() }} -{%- endblock %} - -{% block sidebarlogo %} - {% if pagename != "index" or theme_index_sidebar_logo %} - {{ super() }} - {% endif %} -{% endblock %} - -{% block relbar2 %}{% endblock %} - -{% block sidebar2 %} - - {{- super() }} -{%- endblock %} - -{% block footer %} - {{ super() }} - {%- if READTHEDOCS and not readthedocs_docsearch %} - - {%- endif %} - {{ js_tag("_static/version_warning_offset.js") }} -{% endblock %} From cc9bf0097df8d22441bea7cf03e38be5198988e2 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Sun, 7 Jul 2024 13:23:25 +0100 Subject: [PATCH 0799/1271] Improve how the documentation sidebar is managed Move away from injecting unstyled HTML into the sidebar, to using Furo's default sidebar with Sphinx's `doctree` instead. This also includes moving to a more typical Sphinx documentation structure with the `index` page serving as the "root" of the `doctree` for Sphinx. Additionally, move custom stylesheets into a `pytest-custom.css` file and use standard Sphinx tooling to inject these styles. --- doc/en/_static/pytest-custom.css | 21 +++++++++++++++++ doc/en/_templates/globaltoc.html | 31 ------------------------- doc/en/_templates/relations.html | 19 ---------------- doc/en/_templates/sidebar/brand.html | 7 ------ doc/en/_templates/sidebarintro.html | 5 ---- doc/en/_templates/style.html | 7 ------ doc/en/conf.py | 34 ++++++++-------------------- doc/en/contents.rst | 2 ++ doc/en/index.rst | 32 ++++++++++++++++++++++++-- 9 files changed, 62 insertions(+), 96 deletions(-) create mode 100644 doc/en/_static/pytest-custom.css delete mode 100644 doc/en/_templates/globaltoc.html delete mode 100644 doc/en/_templates/relations.html delete mode 100644 doc/en/_templates/sidebar/brand.html delete mode 100644 doc/en/_templates/sidebarintro.html delete mode 100644 doc/en/_templates/style.html diff --git a/doc/en/_static/pytest-custom.css b/doc/en/_static/pytest-custom.css new file mode 100644 index 00000000000..bc9eef457f1 --- /dev/null +++ b/doc/en/_static/pytest-custom.css @@ -0,0 +1,21 @@ +/* Tweak how the sidebar logo is presented */ +.sidebar-logo { + width: 70%; +} +.sidebar-brand { + padding: 0; +} + +/* The landing pages' sidebar-in-content highlights */ +#features ul { + padding-left: 1rem; + list-style: none; +} +#features ul li { + margin-bottom: 0; +} +@media (min-width: 46em) { + #features { + width: 50%; + } +} diff --git a/doc/en/_templates/globaltoc.html b/doc/en/_templates/globaltoc.html deleted file mode 100644 index 09d970b64ed..00000000000 --- a/doc/en/_templates/globaltoc.html +++ /dev/null @@ -1,31 +0,0 @@ -

Contents

- - - -

About the project

- - - -{%- if display_toc %} -
- {{ toc }} -{%- endif %} - -
diff --git a/doc/en/_templates/relations.html b/doc/en/_templates/relations.html deleted file mode 100644 index 3bbcde85bb4..00000000000 --- a/doc/en/_templates/relations.html +++ /dev/null @@ -1,19 +0,0 @@ -

Related Topics

- diff --git a/doc/en/_templates/sidebar/brand.html b/doc/en/_templates/sidebar/brand.html deleted file mode 100644 index f997c4cca5f..00000000000 --- a/doc/en/_templates/sidebar/brand.html +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/doc/en/_templates/sidebarintro.html b/doc/en/_templates/sidebarintro.html deleted file mode 100644 index ae860c172f0..00000000000 --- a/doc/en/_templates/sidebarintro.html +++ /dev/null @@ -1,5 +0,0 @@ -

About pytest

-

- pytest is a mature full-featured Python testing tool that helps - you write better programs. -

diff --git a/doc/en/_templates/style.html b/doc/en/_templates/style.html deleted file mode 100644 index 400cb75ff97..00000000000 --- a/doc/en/_templates/style.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/doc/en/conf.py b/doc/en/conf.py index 9f5f3787c1e..9558a75f927 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -25,7 +25,7 @@ # -- General configuration ------------------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration -root_doc = "contents" +root_doc = "index" extensions = [ "pygments_pytest", "sphinx.ext.autodoc", @@ -150,35 +150,19 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output html_theme = "furo" +html_theme_options = {"sidebar_hide_name": True} + +html_static_path = ["_static"] +html_css_files = [ + "pytest-custom.css", +] + html_title = "pytest documentation" html_short_title = f"pytest-{release}" -html_logo = "img/pytest_logo_curves.svg" +html_logo = "_static/pytest1.png" html_favicon = "img/favicon.png" -html_sidebars = { - "index": [ - "sidebar/brand.html", - "sidebar/search.html", - "sidebar/scroll-start.html", - "sidebarintro.html", - "globaltoc.html", - "links.html", - "sidebar/scroll-end.html", - "style.html", - ], - "**": [ - "sidebar/brand.html", - "sidebar/search.html", - "sidebar/scroll-start.html", - "globaltoc.html", - "relations.html", - "links.html", - "sidebar/scroll-end.html", - "style.html", - ], -} - html_use_index = False html_show_sourcelink = False diff --git a/doc/en/contents.rst b/doc/en/contents.rst index 181207203b2..07c0b3ff6b9 100644 --- a/doc/en/contents.rst +++ b/doc/en/contents.rst @@ -1,3 +1,5 @@ +:orphan: + .. _toc: Full pytest documentation diff --git a/doc/en/index.rst b/doc/en/index.rst index 8de3b3993dd..a907d1ff549 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -1,5 +1,3 @@ -:orphan: - .. _features: .. sidebar:: **Next Open Trainings and Events** @@ -13,6 +11,36 @@ pytest: helps you write better programs ======================================= +.. toctree:: + :hidden: + + getting-started + how-to/index + reference/index + explanation/index + example/index + +.. toctree:: + :caption: About the project + :hidden: + + changelog + contributing + backwards-compatibility + sponsor + tidelift + license + contact + +.. toctree:: + :caption: Useful links + :hidden: + + pytest @ PyPI + pytest @ GitHub + Issue Tracker + PDF Documentation + .. module:: pytest The ``pytest`` framework makes it easy to write small, readable tests, and can From ba2d750d35bd21f02aaf7526083bfd3d1e0e4435 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 09:45:28 -0300 Subject: [PATCH 0800/1271] build(deps): Bump django in /testing/plugins_integration (#12598) Bumps [django](https://github.com/django/django) from 5.0.6 to 5.0.7. - [Commits](https://github.com/django/django/compare/5.0.6...5.0.7) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index b3ced6e5c9d..12aa89f7644 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.4.0 -django==5.0.6 +django==5.0.7 pytest-asyncio==0.23.7 pytest-bdd==7.2.0 pytest-cov==5.0.0 From 423f71963c9a4b6a06d8322407d6cef05184c9a2 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 12 Jul 2024 19:50:44 +0200 Subject: [PATCH 0801/1271] Update contact channels (#12515) Follow-up to #12427 --- doc/en/contact.rst | 62 +++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/doc/en/contact.rst b/doc/en/contact.rst index 44957a0d4a8..ef9d1e8edca 100644 --- a/doc/en/contact.rst +++ b/doc/en/contact.rst @@ -3,45 +3,51 @@ .. _`contact`: Contact channels -=================================== +================ -- `pytest issue tracker`_ to report bugs or suggest features (for version - 2.0 and above). -- `pytest discussions`_ at github for general questions. -- `pytest discord server `_ - for pytest development visibility and general assistance. +Web +--- + +- `pytest issue tracker`_ to report bugs or suggest features. +- `pytest discussions`_ at GitHub for general questions. - `pytest on stackoverflow.com `_ - to post precise questions with the tag ``pytest``. New Questions will usually + to post precise questions with the tag ``pytest``. New questions will usually be seen by pytest users or developers and answered quickly. -- `Testing In Python`_: a mailing list for Python testing tools and discussion. - -- `pytest-dev at python.org (mailing list)`_ pytest specific announcements and discussions. - -- :doc:`contribution guide ` for help on submitting pull - requests to GitHub. +Chat +---- +- `pytest discord server `_ + for pytest development visibility and general assistance. - ``#pytest`` `on irc.libera.chat `_ IRC channel for random questions (using an IRC client, or `via webchat - `) -- ``#pytest`` `on Matrix https://matrix.to/#/#pytest:matrix.org>`. + `_) +- ``#pytest`` `on Matrix `_. +Mail +---- -.. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues -.. _`old issue tracker`: https://bitbucket.org/hpk42/py-trunk/issues/ - -.. _`pytest discussions`: https://github.com/pytest-dev/pytest/discussions - -.. _`get an account`: +- `Testing In Python`_: a mailing list for Python testing tools and discussion. +- `pytest-dev at python.org`_ a mailing list for pytest specific announcements and discussions. +- Mail to `core@pytest.org `_ for topics that cannot be + discussed in public. Mails sent there will be distributed among the members + in the pytest core team, who can also be contacted individually: -.. _tetamap: https://tetamap.wordpress.com/ + * Ronny Pfannschmidt (:user:`RonnyPfannschmidt`, `ronny@pytest.org `_) + * Florian Bruhin (:user:`The-Compiler`, `florian@pytest.org `_) + * Bruno Oliveira (:user:`nicoddemus`, `bruno@pytest.org `_) + * Ran Benita (:user:`bluetech`, `ran@pytest.org `_) + * Zac Hatfield-Dodds (:user:`Zac-HD`, `zac@pytest.org `_) -.. _`@pylibcommit`: https://twitter.com/pylibcommit +Other +----- +- The :doc:`contribution guide ` for help on submitting pull + requests to GitHub. +- Florian Bruhin (:user:`The-Compiler`) offers pytest professional teaching and + consulting via `Bruhin Software `_. +.. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues +.. _`pytest discussions`: https://github.com/pytest-dev/pytest/discussions .. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python -.. _FOAF: https://en.wikipedia.org/wiki/FOAF -.. _`py-dev`: -.. _`development mailing list`: -.. _`pytest-dev at python.org (mailing list)`: http://mail.python.org/mailman/listinfo/pytest-dev -.. _`pytest-commit at python.org (mailing list)`: http://mail.python.org/mailman/listinfo/pytest-commit +.. _`pytest-dev at python.org`: http://mail.python.org/mailman/listinfo/pytest-dev From c5f15e01206361c5ef38fd3c5e8216fcb6b27ff1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 14 Jul 2024 13:07:47 +0000 Subject: [PATCH 0802/1271] [automated] Update plugin list (#12607) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 106 +++++++++++++++++++------------ 1 file changed, 65 insertions(+), 41 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index c0020a2bfb7..7526b055943 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jul 03, 2024 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jul 10, 2024 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -143,7 +143,7 @@ This list contains 1484 plugins. :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 - :pypi:`pytest-bazel` A pytest runner with bazel support Jul 05, 2024 4 - Beta pytest + :pypi:`pytest-bazel` A pytest runner with bazel support Jul 12, 2024 4 - Beta pytest :pypi:`pytest-bdd` BDD for pytest Jun 04, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 @@ -153,7 +153,7 @@ This list contains 1484 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jul 04, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jul 08, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -307,7 +307,7 @@ This list contains 1484 plugins. :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A :pypi:`pytest-custom-exit-code` Exit pytest test session with custom exit code in different scenarios Aug 07, 2019 4 - Beta pytest (>=4.0.2) :pypi:`pytest-custom-nodeid` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 07, 2021 N/A N/A - :pypi:`pytest-custom-outputs` A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail. Also allows users to retrieve test results in fixtures. Jun 28, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-custom-outputs` A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail. Also allows users to retrieve test results in fixtures. Jul 10, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A :pypi:`pytest-cython` A plugin for testing Cython extension modules Apr 05, 2024 5 - Production/Stable pytest>=8 @@ -364,6 +364,7 @@ This list contains 1484 plugins. :pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all' :pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0) :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 11, 2023 4 - Beta pytest>=7.3.2 + :pypi:`pytest-dirty` Static import analysis for thrifty testing. Jul 11, 2024 3 - Alpha pytest>=8.2; extra == "dev" :pypi:`pytest-disable` pytest plugin to disable a test and skip it from testrun Sep 10, 2015 4 - Beta N/A :pypi:`pytest-disable-plugin` Disable plugins per test Feb 28, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-discord` A pytest plugin to notify test results to a Discord channel. May 11, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 @@ -420,6 +421,7 @@ This list contains 1484 plugins. :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) :pypi:`pytest-doctest-mkdocstrings` Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) Mar 02, 2024 N/A pytest :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Mar 10, 2024 5 - Production/Stable pytest >=4.6 + :pypi:`pytest-documentary` A simple pytest plugin to generate test documentation Jul 11, 2024 N/A pytest :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 Dec 14, 2023 N/A N/A :pypi:`pytest-dolphin` Some extra stuff that we use ininternally Nov 30, 2016 4 - Beta pytest (==3.0.4) @@ -577,6 +579,7 @@ This list contains 1484 plugins. :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Oct 29, 2023 4 - Beta pytest>=7.0.0 + :pypi:`pytest-freezeblaster` Wrap tests with fixtures in freeze_time Jul 10, 2024 N/A pytest>=6.2.5 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -596,7 +599,7 @@ This list contains 1484 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jul 02, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jul 08, 2024 N/A pytest>=3.6 :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 @@ -639,7 +642,7 @@ This list contains 1484 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jul 06, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 11, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -651,7 +654,7 @@ This list contains 1484 plugins. :pypi:`pytest-html` pytest plugin for generating HTML reports Nov 07, 2023 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-html-merger` Pytest HTML reports merging utility Nov 11, 2023 N/A N/A + :pypi:`pytest-html-merger` Pytest HTML reports merging utility Jul 12, 2024 N/A N/A :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Jan 17, 2024 5 - Production/Stable N/A :pypi:`pytest-html-profiling` Pytest plugin for generating HTML reports with per-test profiling and optionally call graph visualizations. Based on pytest-html by Dave Hunt. Feb 11, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A @@ -709,7 +712,7 @@ This list contains 1484 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Jul 05, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Jul 11, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -721,7 +724,7 @@ This list contains 1484 plugins. :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 30, 2024 3 - Alpha N/A - :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jun 06, 2024 N/A pytest>=7.2.0 + :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jul 09, 2024 N/A pytest>=7.2.0 :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Mar 27, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest @@ -803,7 +806,7 @@ This list contains 1484 plugins. :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A - :pypi:`pytest-mark-manage` 用例标签化管理 Jun 07, 2024 N/A pytest + :pypi:`pytest-mark-manage` 用例标签化管理 Jul 08, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Mar 15, 2024 5 - Production/Stable pytest @@ -1087,7 +1090,7 @@ This list contains 1484 plugins. :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Mar 14, 2024 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jun 27, 2024 N/A N/A - :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Dec 06, 2023 4 - Beta pytest>=3.5.0 + :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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. Jun 19, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest @@ -1164,7 +1167,7 @@ This list contains 1484 plugins. :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. May 02, 2024 4 - Beta pytest>=5 + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 09, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest @@ -1182,7 +1185,7 @@ This list contains 1484 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 06, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 08, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1192,7 +1195,7 @@ This list contains 1484 plugins. :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 Feb 01, 2024 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. Jul 06, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 08, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1270,8 +1273,8 @@ This list contains 1484 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 Jul 03, 2024 N/A pytest<8,>5.4.0 - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jun 14, 2024 N/A N/A + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jul 11, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jul 10, 2024 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 @@ -1302,7 +1305,7 @@ This list contains 1484 plugins. :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 Mar 07, 2024 4 - Beta pytest >=7.0 + :pypi:`pytest-subtests` unittest subTest() support and subtests fixture Jul 07, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Feb 01, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A @@ -1418,7 +1421,7 @@ This list contains 1484 plugins. :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A - :pypi:`pytest-twisted` A twisted plugin for pytest. Mar 19, 2024 5 - Production/Stable pytest >=2.3 + :pypi:`pytest-twisted` A twisted plugin for pytest. Jul 10, 2024 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 Feb 01, 2024 4 - Beta N/A @@ -1498,7 +1501,7 @@ This list contains 1484 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. Jul 03, 2024 4 - Beta pytest>=7.2.2 :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 02, 2024 N/A pytest>=7.4.0 + :pypi:`pytest-yaml-sanmu` pytest plugin for generating test cases by yaml Jul 12, 2024 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) @@ -1804,7 +1807,7 @@ This list contains 1484 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Jul 03, 2024, + *last release*: Jul 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2287,7 +2290,7 @@ This list contains 1484 plugins. A pytest plugin to repeat the entire test suite in batches. :pypi:`pytest-bazel` - *last release*: Jul 05, 2024, + *last release*: Jul 12, 2024, *status*: 4 - Beta, *requires*: pytest @@ -2357,7 +2360,7 @@ This list contains 1484 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jul 04, 2024, + *last release*: Jul 08, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3435,7 +3438,7 @@ This list contains 1484 plugins. Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report :pypi:`pytest-custom-outputs` - *last release*: Jun 28, 2024, + *last release*: Jul 10, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -3833,6 +3836,13 @@ This list contains 1484 plugins. pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing + :pypi:`pytest-dirty` + *last release*: Jul 11, 2024, + *status*: 3 - Alpha, + *requires*: pytest>=8.2; extra == "dev" + + Static import analysis for thrifty testing. + :pypi:`pytest-disable` *last release*: Sep 10, 2015, *status*: 4 - Beta, @@ -4225,6 +4235,13 @@ This list contains 1484 plugins. Pytest plugin with advanced doctest features. + :pypi:`pytest-documentary` + *last release*: Jul 11, 2024, + *status*: N/A, + *requires*: pytest + + A simple pytest plugin to generate test documentation + :pypi:`pytest-dogu-report` *last release*: Jul 07, 2023, *status*: N/A, @@ -5324,6 +5341,13 @@ This list contains 1484 plugins. Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications + :pypi:`pytest-freezeblaster` + *last release*: Jul 10, 2024, + *status*: N/A, + *requires*: pytest>=6.2.5 + + Wrap tests with fixtures in freeze_time + :pypi:`pytest-freezegun` *last release*: Jul 19, 2020, *status*: 4 - Beta, @@ -5458,7 +5482,7 @@ This list contains 1484 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jul 02, 2024, + *last release*: Jul 08, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5759,7 +5783,7 @@ This list contains 1484 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jul 06, 2024, + *last release*: Jul 11, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 @@ -5843,7 +5867,7 @@ This list contains 1484 plugins. optimized pytest plugin for generating HTML reports :pypi:`pytest-html-merger` - *last release*: Nov 11, 2023, + *last release*: Jul 12, 2024, *status*: N/A, *requires*: N/A @@ -6249,7 +6273,7 @@ This list contains 1484 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Jul 05, 2024, + *last release*: Jul 11, 2024, *status*: N/A, *requires*: pytest @@ -6333,7 +6357,7 @@ This list contains 1484 plugins. py.test JIRA integration plugin, using markers :pypi:`pytest-jira-xfail` - *last release*: Jun 06, 2024, + *last release*: Jul 09, 2024, *status*: N/A, *requires*: pytest>=7.2.0 @@ -6907,7 +6931,7 @@ This list contains 1484 plugins. UNKNOWN :pypi:`pytest-mark-manage` - *last release*: Jun 07, 2024, + *last release*: Jul 08, 2024, *status*: N/A, *requires*: pytest @@ -8895,7 +8919,7 @@ This list contains 1484 plugins. Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. :pypi:`pytest-recording` - *last release*: Dec 06, 2023, + *last release*: Jul 09, 2024, *status*: 4 - Beta, *requires*: pytest>=3.5.0 @@ -9434,7 +9458,7 @@ This list contains 1484 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: May 02, 2024, + *last release*: Jul 09, 2024, *status*: 4 - Beta, *requires*: pytest>=5 @@ -9560,7 +9584,7 @@ This list contains 1484 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jul 06, 2024, + *last release*: Jul 08, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9630,7 +9654,7 @@ This list contains 1484 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jul 06, 2024, + *last release*: Jul 08, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10176,14 +10200,14 @@ This list contains 1484 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jul 03, 2024, + *last release*: Jul 11, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Jun 14, 2024, + *last release*: Jul 10, 2024, *status*: N/A, *requires*: N/A @@ -10400,9 +10424,9 @@ This list contains 1484 plugins. A hack to explicitly set up and tear down fixtures. :pypi:`pytest-subtests` - *last release*: Mar 07, 2024, + *last release*: Jul 07, 2024, *status*: 4 - Beta, - *requires*: pytest >=7.0 + *requires*: pytest>=7.0 unittest subTest() support and subtests fixture @@ -11212,9 +11236,9 @@ This list contains 1484 plugins. :pypi:`pytest-twisted` - *last release*: Mar 19, 2024, + *last release*: Jul 10, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=2.3 + *requires*: pytest>=2.3 A twisted plugin for pytest. @@ -11772,7 +11796,7 @@ This list contains 1484 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Jul 02, 2024, + *last release*: Jul 12, 2024, *status*: N/A, *requires*: pytest>=7.4.0 From 711cee58b5d4a24a17f501f15d6b701bfa458726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 07:47:30 +0200 Subject: [PATCH 0803/1271] build(deps): Bump pytest-twisted in /testing/plugins_integration (#12609) Bumps [pytest-twisted](https://github.com/pytest-dev/pytest-twisted) from 1.14.1 to 1.14.2. - [Release notes](https://github.com/pytest-dev/pytest-twisted/releases) - [Commits](https://github.com/pytest-dev/pytest-twisted/compare/v1.14.1...v1.14.2) --- updated-dependencies: - dependency-name: pytest-twisted dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 12aa89f7644..4c1efcf32ed 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -10,6 +10,6 @@ pytest-mock==3.14.0 pytest-rerunfailures==14.0 pytest-sugar==1.0.0 pytest-trio==0.8.0 -pytest-twisted==1.14.1 +pytest-twisted==1.14.2 twisted==24.3.0 pytest-xvfb==3.0.0 From d9a2fd04635c57100f25e93d7d98317d824b2e69 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 23:00:01 +0000 Subject: [PATCH 0804/1271] [pre-commit.ci] pre-commit autoupdate (#12614) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.1 → v0.5.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.1...v0.5.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ce365ddbef2..419addd95be 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.1" + rev: "v0.5.2" hooks: - id: ruff args: ["--fix"] From 28b03b30aab8ed1ad86c2baba756d8486edd70d5 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 11 Jun 2024 15:11:43 +0200 Subject: [PATCH 0805/1271] [pylint/ruff] Activate PLR / PLC messages in ruff --- pyproject.toml | 42 ++++++++++++++++++++++++++++----------- src/_pytest/helpconfig.py | 1 - 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1eb4871bc21..f3eba4a08a8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,7 +102,9 @@ lint.select = [ "I", # isort "PGH004", # pygrep-hooks - Use specific rule codes when using noqa "PIE", # flake8-pie + "PLC", # pylint convention "PLE", # pylint error + "PLR", # pylint refactor "PLR1714", # Consider merging multiple comparisons "PLW", # pylint warning "PYI", # flake8-pyi @@ -139,6 +141,17 @@ lint.ignore = [ # what we're doing when we use type(..) is ... "E721", # Do not compare types, use `isinstance()` # pylint ignore + "PLC0105", # `TypeVar` name "E" does not reflect its covariance; + "PLC0414", # Import alias does not rename original package + "PLR0124", # Name compared with itself + "PLR0133", # Two constants compared in a comparison (lots of those in tests) + "PLR0402", # Use `from x.y import z` in lieu of alias + "PLR0911", # Too many return statements + "PLR0912", # Too many branches + "PLR0913", # Too many arguments in function definition + "PLR0915", # Too many statements + "PLR2004", # Magic value used in comparison + "PLR2044", # Line with empty comment "PLR5501", # Use `elif` instead of `else` then `if` "PLW0120", # remove the else and dedent its contents "PLW0603", # Using the global statement @@ -191,9 +204,9 @@ disable = [ "broad-exception-caught", "broad-exception-raised", "cell-var-from-loop", # B023 from ruff / flake8-bugbear - "comparison-of-constants", + "comparison-of-constants", # disabled in ruff (PLR0133) "comparison-with-callable", - "comparison-with-itself", + "comparison-with-itself", # PLR0124 from ruff "condition-evals-to-constant", "consider-using-dict-items", "consider-using-from-import", @@ -201,14 +214,17 @@ disable = [ "consider-using-in", "consider-using-ternary", "consider-using-with", + "consider-using-from-import", # not activated by default, PLR0402 disabled in ruff "cyclic-import", "disallowed-name", # foo / bar are used often in tests "duplicate-code", + "else-if-used", # not activated by default, PLR5501 disabled in ruff + "empty-comment", # not activated by default, PLR2044 disabled in ruff "eval-used", "exec-used", "expression-not-assigned", "fixme", - "global-statement", + "global-statement", # PLW0603 disabled in ruff "import-error", "import-outside-toplevel", "inconsistent-return-statements", @@ -218,6 +234,7 @@ disable = [ "invalid-str-returned", "keyword-arg-before-vararg", "line-too-long", + "magic-value-comparison", # not activated by default, PLR2004 disabled in ruff "method-hidden", "missing-docstring", "missing-timeout", @@ -232,14 +249,15 @@ disable = [ "no-self-argument", "not-an-iterable", "not-callable", - "pointless-exception-statement", - "pointless-statement", - "pointless-string-statement", + "pointless-exception-statement", # https://github.com/pytest-dev/pytest/pull/12379 + "pointless-statement", # https://github.com/pytest-dev/pytest/pull/12379 + "pointless-string-statement", # https://github.com/pytest-dev/pytest/pull/12379 "possibly-used-before-assignment", "protected-access", "raise-missing-from", "redefined-argument-from-local", "redefined-builtin", + "redefined-loop-name", # PLW2901 disabled in ruff "redefined-outer-name", "reimported", "simplifiable-condition", @@ -249,18 +267,18 @@ disable = [ "super-init-not-called", "too-few-public-methods", "too-many-ancestors", - "too-many-arguments", - "too-many-branches", + "too-many-arguments", # disabled in ruff + "too-many-branches", # disabled in ruff "too-many-function-args", "too-many-instance-attributes", "too-many-lines", "too-many-locals", "too-many-nested-blocks", "too-many-public-methods", - "too-many-return-statements", - "too-many-statements", + "too-many-return-statements", # disabled in ruff + "too-many-statements", # disabled in ruff "try-except-raise", - "typevar-name-incorrect-variance", + "typevar-name-incorrect-variance", # PLC0105 disabled in ruff "unbalanced-tuple-unpacking", "undefined-loop-variable", "undefined-variable", @@ -280,7 +298,7 @@ disable = [ "use-dict-literal", "use-implicit-booleaness-not-comparison", "use-implicit-booleaness-not-len", - "useless-else-on-loop", + "useless-else-on-loop", # PLC0414 disabled in ruff "useless-import-alias", "useless-return", "using-constant-test", diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 1433607a19b..1886d5c9342 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -238,7 +238,6 @@ def showhelp(config: Config) -> None: for warningreport in reporter.stats.get("warnings", []): tw.line("warning : " + warningreport.message, red=True) - return conftest_options = [("pytest_plugins", "list of plugin names to load")] From 6f0faec9e3121affb8d2f19f9b026caa373e56c5 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 16 Jul 2024 16:07:40 +0200 Subject: [PATCH 0806/1271] [ruff] Fix redefined argument 'exc' --- src/_pytest/_io/saferepr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py index 13b793f0a77..cee70e332f9 100644 --- a/src/_pytest/_io/saferepr.py +++ b/src/_pytest/_io/saferepr.py @@ -18,8 +18,8 @@ def _format_repr_exception(exc: BaseException, obj: object) -> str: exc_info = _try_repr_or_str(exc) except (KeyboardInterrupt, SystemExit): raise - except BaseException as exc: - exc_info = f"unpresentable exception ({_try_repr_or_str(exc)})" + except BaseException as inner_exc: + exc_info = f"unpresentable exception ({_try_repr_or_str(inner_exc)})" return ( f"<[{exc_info} raised in repr()] {type(obj).__name__} object at 0x{id(obj):x}>" ) From 80c0302af8014f44f3f0bac3fb4740a17331152c Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 16 Jul 2024 18:36:38 +0300 Subject: [PATCH 0807/1271] doc: mention `PYTEST_DISABLE_PLUGIN_AUTOLOAD` in writing_plugins.rst --- doc/en/how-to/writing_plugins.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/en/how-to/writing_plugins.rst b/doc/en/how-to/writing_plugins.rst index 14e5194ce63..1bba9644649 100644 --- a/doc/en/how-to/writing_plugins.rst +++ b/doc/en/how-to/writing_plugins.rst @@ -43,7 +43,8 @@ Plugin discovery order at tool startup and loading the specified plugin. This happens before normal command-line parsing. 4. by loading all plugins registered through installed third-party package - :ref:`entry points `. + :ref:`entry points `, unless the + :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD` environment variable is set. 5. by loading all plugins specified through the :envvar:`PYTEST_PLUGINS` environment variable. From d489247505a953885a156e61d4473497cbc167ea Mon Sep 17 00:00:00 2001 From: Nicolas Simonds <0xDEC0DE@users.noreply.github.com> Date: Wed, 17 Jul 2024 06:24:03 -0700 Subject: [PATCH 0808/1271] Fix caching of parameterized fixtures (#12600) The fix for Issue #6541 caused regression where cache hits became cache misses, unexpectedly. Fixes #6962 --------- Co-authored-by: Nicolas Simonds Co-authored-by: Bruno Oliveira Co-authored-by: Ran Benita --- AUTHORS | 1 + changelog/6962.bugfix.rst | 2 ++ src/_pytest/fixtures.py | 14 ++++++++++---- testing/python/fixtures.py | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 changelog/6962.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 8d31170560c..9b6cb6a9d23 100644 --- a/AUTHORS +++ b/AUTHORS @@ -306,6 +306,7 @@ Nicholas Devenish Nicholas Murphy Niclas Olofsson Nicolas Delaby +Nicolas Simonds Nico Vidal Nikolay Kondratyev Nipunn Koorapati diff --git a/changelog/6962.bugfix.rst b/changelog/6962.bugfix.rst new file mode 100644 index 00000000000..030b6e06392 --- /dev/null +++ b/changelog/6962.bugfix.rst @@ -0,0 +1,2 @@ +Parametrization parameters are now compared using `==` instead of `is` (`is` is still used as a fallback if the parameter does not support `==`). +This fixes use of parameters such as lists, which have a different `id` but compare equal, causing fixtures to be re-computed instead of being cached. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 0151a4d9c86..7d0b40b150a 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1053,12 +1053,18 @@ def execute(self, request: SubRequest) -> FixtureValue: requested_fixtures_that_should_finalize_us.append(fixturedef) # Check for (and return) cached value/exception. - my_cache_key = self.cache_key(request) if self.cached_result is not None: + request_cache_key = self.cache_key(request) cache_key = self.cached_result[1] - # note: comparison with `==` can fail (or be expensive) for e.g. - # numpy arrays (#6497). - if my_cache_key is cache_key: + try: + # Attempt to make a normal == check: this might fail for objects + # which do not implement the standard comparison (like numpy arrays -- #6497). + cache_hit = bool(request_cache_key == cache_key) + except (ValueError, RuntimeError): + # If the comparison raises, use 'is' as fallback. + cache_hit = request_cache_key is cache_key + + if cache_hit: if self.cached_result[2] is not None: exc, exc_tb = self.cached_result[2] raise exc.with_traceback(exc_tb) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 5c3a6a35b34..8d2646309a8 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1557,6 +1557,38 @@ def test_printer_2(self): result = pytester.runpytest() result.stdout.fnmatch_lines(["* 2 passed in *"]) + def test_parameterized_fixture_caching(self, pytester: Pytester) -> None: + """Regression test for #12600.""" + pytester.makepyfile( + """ + import pytest + from itertools import count + + CACHE_MISSES = count(0) + + def pytest_generate_tests(metafunc): + if "my_fixture" in metafunc.fixturenames: + # Use unique objects for parametrization (as opposed to small strings + # and small integers which are singletons). + metafunc.parametrize("my_fixture", [[1], [2]], indirect=True) + + @pytest.fixture(scope='session') + def my_fixture(request): + next(CACHE_MISSES) + + def test1(my_fixture): + pass + + def test2(my_fixture): + pass + + def teardown_module(): + assert next(CACHE_MISSES) == 2 + """ + ) + result = pytester.runpytest() + result.stdout.no_fnmatch_line("* ERROR at teardown *") + class TestFixtureManagerParseFactories: @pytest.fixture From 9eee45a7479cf5fa23b79057708a994a3b8d0eee Mon Sep 17 00:00:00 2001 From: SOUBHIK KUMAR MITRA Date: Mon, 1 Jul 2024 22:37:58 +0530 Subject: [PATCH 0809/1271] Bump PyPy runtime to v3.9 @ GHA PyPy 3.8 has a flaky bug in the garbage collector that is not going to be fixed there since that version is EoL, but newer versions have it addressed. The problem manifests itself in CI as follows: ```console TypeError: expected some sort of stmt, but got <_ast.Load object ...> ``` This patch makes use of the PyPy version that is still supported and contains a fix for the said bug. Ref: https://www.pypy.org/posts/2024/03/fixing-bug-incremental-gc.html Resolves #11771. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d78e0900fd9..9158d6bcc72 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -150,7 +150,7 @@ jobs: tox_env: "py313" use_coverage: true - name: "ubuntu-pypy3" - python: "pypy-3.8" + python: "pypy-3.9" os: ubuntu-latest tox_env: "pypy3-xdist" From d42b76daadb88d993ee74753766e22711a27395f Mon Sep 17 00:00:00 2001 From: SOUBHIK KUMAR MITRA Date: Fri, 19 Jul 2024 17:26:46 +0530 Subject: [PATCH 0810/1271] Adjust test_errors_in_xfail_skip_expressions for PyPy It appears that newer PyPy versions have a different syntax error marker offset. This patch stripps 7 whitespaces off of the marker line. --- testing/test_skipping.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 558e3d35c6a..d1a63b1d920 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -1140,8 +1140,8 @@ def test_func(): result = pytester.runpytest() markline = " ^" pypy_version_info = getattr(sys, "pypy_version_info", None) - if pypy_version_info is not None and pypy_version_info < (6,): - markline = markline[1:] + if pypy_version_info is not None: + markline = markline[7:] if sys.version_info >= (3, 10): expected = [ From ced7072bb4f7653ad2f1d0d33639d87e7bc5f358 Mon Sep 17 00:00:00 2001 From: SOUBHIK KUMAR MITRA Date: Thu, 4 Jul 2024 15:01:34 +0530 Subject: [PATCH 0811/1271] Add a change note for PR #11771 Co-authored-by: Sviatoslav Sydorenko --- changelog/11771.contrib.rst | 5 +++++ changelog/12557.contrib.rst | 1 + 2 files changed, 6 insertions(+) create mode 100644 changelog/11771.contrib.rst create mode 120000 changelog/12557.contrib.rst diff --git a/changelog/11771.contrib.rst b/changelog/11771.contrib.rst new file mode 100644 index 00000000000..a3c1ed1099e --- /dev/null +++ b/changelog/11771.contrib.rst @@ -0,0 +1,5 @@ +The PyPy runtime version has been updated to 3.9 from 3.8 that introduced +a flaky bug at the garbage collector which was not expected to fix there +as the V3.8 is EoL. + +-- by :user:`x612skm` diff --git a/changelog/12557.contrib.rst b/changelog/12557.contrib.rst new file mode 120000 index 00000000000..c036c519093 --- /dev/null +++ b/changelog/12557.contrib.rst @@ -0,0 +1 @@ +11771.contrib.rst \ No newline at end of file From 04bac8deaf1abd49e198cfd5cb66d8001b1de1ea Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sat, 20 Jul 2024 15:20:56 +0000 Subject: [PATCH 0812/1271] Cherry-pick 8.3.0, 8.3.1 release notes --- changelog/11706.bugfix.rst | 4 - changelog/11771.contrib.rst | 5 - changelog/11797.bugfix.rst | 1 - changelog/12153.doc.rst | 1 - changelog/12204.bugfix.rst | 11 -- changelog/12231.feature.rst | 11 -- changelog/12264.bugfix.rst | 1 - changelog/12275.bugfix.rst | 1 - changelog/12281.feature.rst | 8 - changelog/12328.bugfix.rst | 1 - changelog/12424.bugfix.rst | 1 - changelog/12467.improvement.rst | 3 - changelog/12469.doc.rst | 6 - changelog/12469.improvement.rst | 4 - changelog/12472.bugfix.rst | 1 - changelog/12493.contrib.rst | 13 -- changelog/12498.contrib.rst | 5 - changelog/12501.contrib.rst | 11 -- changelog/12502.contrib.rst | 7 - changelog/12505.bugfix.rst | 1 - changelog/12522.contrib.rst | 4 - changelog/12531.contrib.rst | 6 - changelog/12533.contrib.rst | 7 - changelog/12544.improvement.rst | 3 - changelog/12545.improvement.rst | 1 - changelog/12557.contrib.rst | 1 - changelog/12562.contrib.rst | 2 - changelog/12567.feature.rst | 7 - changelog/12577.doc.rst | 3 - changelog/12580.bugfix.rst | 1 - changelog/2871.improvement.rst | 1 - changelog/389.improvement.rst | 38 ---- changelog/6962.bugfix.rst | 2 - changelog/7166.bugfix.rst | 1 - changelog/7662.improvement.rst | 1 - doc/en/announce/index.rst | 2 + doc/en/announce/release-8.3.0.rst | 60 +++++++ doc/en/announce/release-8.3.1.rst | 19 ++ doc/en/builtin.rst | 34 ++-- doc/en/changelog.rst | 263 ++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 10 +- doc/en/example/pythoncollection.rst | 4 +- doc/en/example/reportingdemo.rst | 96 +++++----- doc/en/example/simple.rst | 25 --- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/output.rst | 8 - doc/en/reference/reference.rst | 199 ++++++++++----------- 48 files changed, 521 insertions(+), 377 deletions(-) delete mode 100644 changelog/11706.bugfix.rst delete mode 100644 changelog/11771.contrib.rst delete mode 100644 changelog/11797.bugfix.rst delete mode 100644 changelog/12153.doc.rst delete mode 100644 changelog/12204.bugfix.rst delete mode 100644 changelog/12231.feature.rst delete mode 120000 changelog/12264.bugfix.rst delete mode 100644 changelog/12275.bugfix.rst delete mode 100644 changelog/12281.feature.rst delete mode 100644 changelog/12328.bugfix.rst delete mode 100644 changelog/12424.bugfix.rst delete mode 100644 changelog/12467.improvement.rst delete mode 100644 changelog/12469.doc.rst delete mode 100644 changelog/12469.improvement.rst delete mode 100644 changelog/12472.bugfix.rst delete mode 100644 changelog/12493.contrib.rst delete mode 100644 changelog/12498.contrib.rst delete mode 100644 changelog/12501.contrib.rst delete mode 100644 changelog/12502.contrib.rst delete mode 100644 changelog/12505.bugfix.rst delete mode 100644 changelog/12522.contrib.rst delete mode 100644 changelog/12531.contrib.rst delete mode 100644 changelog/12533.contrib.rst delete mode 100644 changelog/12544.improvement.rst delete mode 120000 changelog/12545.improvement.rst delete mode 120000 changelog/12557.contrib.rst delete mode 100644 changelog/12562.contrib.rst delete mode 100644 changelog/12567.feature.rst delete mode 100644 changelog/12577.doc.rst delete mode 100644 changelog/12580.bugfix.rst delete mode 100644 changelog/2871.improvement.rst delete mode 100644 changelog/389.improvement.rst delete mode 100644 changelog/6962.bugfix.rst delete mode 100644 changelog/7166.bugfix.rst delete mode 100644 changelog/7662.improvement.rst create mode 100644 doc/en/announce/release-8.3.0.rst create mode 100644 doc/en/announce/release-8.3.1.rst diff --git a/changelog/11706.bugfix.rst b/changelog/11706.bugfix.rst deleted file mode 100644 index a86db5ef66a..00000000000 --- a/changelog/11706.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -Fix reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`. - -Originally added in pytest 8.0.0, but reverted in 8.0.2 due to a regression in pytest-xdist. -This regression was fixed in pytest-xdist 3.6.1. diff --git a/changelog/11771.contrib.rst b/changelog/11771.contrib.rst deleted file mode 100644 index a3c1ed1099e..00000000000 --- a/changelog/11771.contrib.rst +++ /dev/null @@ -1,5 +0,0 @@ -The PyPy runtime version has been updated to 3.9 from 3.8 that introduced -a flaky bug at the garbage collector which was not expected to fix there -as the V3.8 is EoL. - --- by :user:`x612skm` diff --git a/changelog/11797.bugfix.rst b/changelog/11797.bugfix.rst deleted file mode 100644 index 94b72da00fd..00000000000 --- a/changelog/11797.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`pytest.approx` now correctly handles :class:`Sequence `-like objects. diff --git a/changelog/12153.doc.rst b/changelog/12153.doc.rst deleted file mode 100644 index ac36becf9a7..00000000000 --- a/changelog/12153.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Documented using :envvar:`PYTEST_VERSION` to detect if code is running from within a pytest run. diff --git a/changelog/12204.bugfix.rst b/changelog/12204.bugfix.rst deleted file mode 100644 index 099ad70610a..00000000000 --- a/changelog/12204.bugfix.rst +++ /dev/null @@ -1,11 +0,0 @@ -Fixed a regression in pytest 8.0 where tracebacks get longer and longer when multiple -tests fail due to a shared higher-scope fixture which raised -- by :user:`bluetech`. - -Also fixed a similar regression in pytest 5.4 for collectors which raise during setup. - -The fix necessitated internal changes which may affect some plugins: - -* ``FixtureDef.cached_result[2]`` is now a tuple ``(exc, tb)`` - instead of ``exc``. -* ``SetupState.stack`` failures are now a tuple ``(exc, tb)`` - instead of ``exc``. diff --git a/changelog/12231.feature.rst b/changelog/12231.feature.rst deleted file mode 100644 index dad04bc20c1..00000000000 --- a/changelog/12231.feature.rst +++ /dev/null @@ -1,11 +0,0 @@ -Added `--xfail-tb` flag, which turns on traceback output for XFAIL results. - -* If the `--xfail-tb` flag is not sent, tracebacks for XFAIL results are NOT shown. -* The style of traceback for XFAIL is set with `--tb`, and can be `auto|long|short|line|native|no`. -* Note: Even if you have `--xfail-tb` set, you won't see them if `--tb=no`. - -Some history: - -With pytest 8.0, `-rx` or `-ra` would not only turn on summary reports for xfail, but also report the tracebacks for xfail results. This caused issues with some projects that utilize xfail, but don't want to see all of the xfail tracebacks. - -This change detaches xfail tracebacks from `-rx`, and now we turn on xfail tracebacks with `--xfail-tb`. With this, the default `-rx`/ `-ra` behavior is identical to pre-8.0 with respect to xfail tracebacks. While this is a behavior change, it brings default behavior back to pre-8.0.0 behavior, which ultimately was considered the better course of action. diff --git a/changelog/12264.bugfix.rst b/changelog/12264.bugfix.rst deleted file mode 120000 index e5704e6e819..00000000000 --- a/changelog/12264.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -12204.bugfix.rst \ No newline at end of file diff --git a/changelog/12275.bugfix.rst b/changelog/12275.bugfix.rst deleted file mode 100644 index 2d040a3a063..00000000000 --- a/changelog/12275.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix collection error upon encountering an :mod:`abstract ` class, including abstract `unittest.TestCase` subclasses. diff --git a/changelog/12281.feature.rst b/changelog/12281.feature.rst deleted file mode 100644 index c6e8e3b3098..00000000000 --- a/changelog/12281.feature.rst +++ /dev/null @@ -1,8 +0,0 @@ -Added support for keyword matching in marker expressions. - -Now tests can be selected by marker keyword arguments. -Supported values are :class:`int`, (unescaped) :class:`str`, :class:`bool` & :data:`None`. - -See :ref:`marker examples ` for more information. - --- by :user:`lovetheguitar` diff --git a/changelog/12328.bugfix.rst b/changelog/12328.bugfix.rst deleted file mode 100644 index f334425850b..00000000000 --- a/changelog/12328.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a regression in pytest 8.0.0 where package-scoped parameterized items were not correctly reordered to minimize setups/teardowns in some cases. diff --git a/changelog/12424.bugfix.rst b/changelog/12424.bugfix.rst deleted file mode 100644 index 7ad1126858b..00000000000 --- a/changelog/12424.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix crash with `assert testcase is not None` assertion failure when re-running unittest tests using plugins like pytest-rerunfailures. Regressed in 8.2.2. diff --git a/changelog/12467.improvement.rst b/changelog/12467.improvement.rst deleted file mode 100644 index b1e0581ed16..00000000000 --- a/changelog/12467.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Migrated all internal type-annotations to the python3.10+ style by using the `annotations` future import. - --- by :user:`RonnyPfannschmidt` diff --git a/changelog/12469.doc.rst b/changelog/12469.doc.rst deleted file mode 100644 index 2340315353c..00000000000 --- a/changelog/12469.doc.rst +++ /dev/null @@ -1,6 +0,0 @@ -The external plugin mentions in the documentation now avoid mentioning -:std:doc:`setuptools entry-points ` as the concept is -much more generic nowadays. Instead, the terminology of "external", -"installed", or "third-party" plugins (or packages) replaces that. - --- by :user:`webknjaz` diff --git a/changelog/12469.improvement.rst b/changelog/12469.improvement.rst deleted file mode 100644 index a90fb1e6610..00000000000 --- a/changelog/12469.improvement.rst +++ /dev/null @@ -1,4 +0,0 @@ -The console output now uses the "third-party plugins" terminology, -replacing the previously established but confusing and outdated -reference to :std:doc:`setuptools ` --- by :user:`webknjaz`. diff --git a/changelog/12472.bugfix.rst b/changelog/12472.bugfix.rst deleted file mode 100644 index f08e9d1f90b..00000000000 --- a/changelog/12472.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash when returning category ``"error"`` or ``"failed"`` with a custom test status from :hook:`pytest_report_teststatus` hook -- :user:`pbrezina`. diff --git a/changelog/12493.contrib.rst b/changelog/12493.contrib.rst deleted file mode 100644 index db3d045697e..00000000000 --- a/changelog/12493.contrib.rst +++ /dev/null @@ -1,13 +0,0 @@ -The change log draft preview integration has been refactored to use a -third party extension ``sphinxcontib-towncrier``. The previous in-repo -script was putting the change log preview file at -:file:`doc/en/_changelog_towncrier_draft.rst`. Said file is no longer -ignored in Git and might show up among untracked files in the -development environments of the contributors. To address that, the -contributors can run the following command that will clean it up: - -.. code-block:: console - - $ git clean -x -i -- doc/en/_changelog_towncrier_draft.rst - --- by :user:`webknjaz` diff --git a/changelog/12498.contrib.rst b/changelog/12498.contrib.rst deleted file mode 100644 index 436c6f0e9ed..00000000000 --- a/changelog/12498.contrib.rst +++ /dev/null @@ -1,5 +0,0 @@ -All the undocumented ``tox`` environments now have descriptions. -They can be listed in one's development environment by invoking -``tox -av`` in a terminal. - --- by :user:`webknjaz` diff --git a/changelog/12501.contrib.rst b/changelog/12501.contrib.rst deleted file mode 100644 index 6f434c287b3..00000000000 --- a/changelog/12501.contrib.rst +++ /dev/null @@ -1,11 +0,0 @@ -The changelog configuration has been updated to introduce more accurate -audience-tailored categories. Previously, there was a ``trivial`` -change log fragment type with an unclear and broad meaning. It was -removed and we now have ``contrib``, ``misc`` and ``packaging`` in -place of it. - -The new change note types target the readers who are downstream -packagers and project contributors. Additionally, the miscellaneous -section is kept for unspecified updates that do not fit anywhere else. - --- by :user:`webknjaz` diff --git a/changelog/12502.contrib.rst b/changelog/12502.contrib.rst deleted file mode 100644 index 940a2d7a120..00000000000 --- a/changelog/12502.contrib.rst +++ /dev/null @@ -1,7 +0,0 @@ -The UX of the GitHub automation making pull requests to update the -plugin list has been updated. Previously, the maintainers had to close -the automatically created pull requests and re-open them to trigger the -CI runs. From now on, they only need to click the `Ready for review` -button instead. - --- by :user:`webknjaz` diff --git a/changelog/12505.bugfix.rst b/changelog/12505.bugfix.rst deleted file mode 100644 index f55a8a17e4b..00000000000 --- a/changelog/12505.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Improve handling of invalid regex patterns in :func:`pytest.raises(match=r'...') ` by providing a clear error message. diff --git a/changelog/12522.contrib.rst b/changelog/12522.contrib.rst deleted file mode 100644 index dd994317165..00000000000 --- a/changelog/12522.contrib.rst +++ /dev/null @@ -1,4 +0,0 @@ -The ``:pull:`` RST role has been replaced with a shorter -``:pr:`` due to starting to use the implementation from -the third-party :pypi:`sphinx-issues` Sphinx extension --- by :user:`webknjaz`. diff --git a/changelog/12531.contrib.rst b/changelog/12531.contrib.rst deleted file mode 100644 index 12083fc320e..00000000000 --- a/changelog/12531.contrib.rst +++ /dev/null @@ -1,6 +0,0 @@ -The coverage reporting configuration has been updated to exclude -pytest's own tests marked as expected to fail from the coverage -report. This has an effect of reducing the influence of flaky -tests on the resulting number. - --- by :user:`webknjaz` diff --git a/changelog/12533.contrib.rst b/changelog/12533.contrib.rst deleted file mode 100644 index 3da7007a0fd..00000000000 --- a/changelog/12533.contrib.rst +++ /dev/null @@ -1,7 +0,0 @@ -The ``extlinks`` Sphinx extension is no longer enabled. The ``:bpo:`` -role it used to declare has been removed with that. BPO itself has -migrated to GitHub some years ago and it is possible to link the -respective issues by using their GitHub issue numbers and the -``:issue:`` role that the ``sphinx-issues`` extension implements. - --- by :user:`webknjaz` diff --git a/changelog/12544.improvement.rst b/changelog/12544.improvement.rst deleted file mode 100644 index 41125f5d939..00000000000 --- a/changelog/12544.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -The ``_in_venv()`` function now detects Python virtual environments by -checking for a :file:`pyvenv.cfg` file, ensuring reliable detection on -various platforms -- by :user:`zachsnickers`. diff --git a/changelog/12545.improvement.rst b/changelog/12545.improvement.rst deleted file mode 120000 index 41a1e6bfa49..00000000000 --- a/changelog/12545.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -12544.improvement.rst \ No newline at end of file diff --git a/changelog/12557.contrib.rst b/changelog/12557.contrib.rst deleted file mode 120000 index c036c519093..00000000000 --- a/changelog/12557.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -11771.contrib.rst \ No newline at end of file diff --git a/changelog/12562.contrib.rst b/changelog/12562.contrib.rst deleted file mode 100644 index 0d30495983a..00000000000 --- a/changelog/12562.contrib.rst +++ /dev/null @@ -1,2 +0,0 @@ -Possible typos in using the ``:user:`` RST role is now being linted -through the pre-commit tool integration -- by :user:`webknjaz`. diff --git a/changelog/12567.feature.rst b/changelog/12567.feature.rst deleted file mode 100644 index 3690d7aff68..00000000000 --- a/changelog/12567.feature.rst +++ /dev/null @@ -1,7 +0,0 @@ -Added ``--no-fold-skipped`` command line option - -If this option is set, then skipped tests in short summary are no longer grouped -by reason but all tests are printed individually with correct nodeid in the same -way as other statuses. - --- by :user:`pbrezina` diff --git a/changelog/12577.doc.rst b/changelog/12577.doc.rst deleted file mode 100644 index 0bd427e177d..00000000000 --- a/changelog/12577.doc.rst +++ /dev/null @@ -1,3 +0,0 @@ -`CI` and `BUILD_NUMBER` environment variables role is discribed in -the reference doc. They now also appears when doing `pytest -h` --- by :user:`MarcBresson`. diff --git a/changelog/12580.bugfix.rst b/changelog/12580.bugfix.rst deleted file mode 100644 index 9186ef1a4c9..00000000000 --- a/changelog/12580.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash when using the cache class on Windows and the cache directory was created concurrently. diff --git a/changelog/2871.improvement.rst b/changelog/2871.improvement.rst deleted file mode 100644 index 1ba399550c7..00000000000 --- a/changelog/2871.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Do not truncate arguments to functions in output when running with `-vvv`. diff --git a/changelog/389.improvement.rst b/changelog/389.improvement.rst deleted file mode 100644 index f8e2c19fde0..00000000000 --- a/changelog/389.improvement.rst +++ /dev/null @@ -1,38 +0,0 @@ -The readability of assertion introspection of bound methods has been enhanced --- by :user:`farbodahm`, :user:`webknjaz`, :user:`obestwalter`, :user:`flub` -and :user:`glyphack`. - -Earlier, it was like: - -.. code-block:: console - - =================================== FAILURES =================================== - _____________________________________ test _____________________________________ - - def test(): - > assert Help().fun() == 2 - E assert 1 == 2 - E + where 1 = >() - E + where > = .fun - E + where = Help() - - example.py:7: AssertionError - =========================== 1 failed in 0.03 seconds =========================== - - -And now it's like: - -.. code-block:: console - - =================================== FAILURES =================================== - _____________________________________ test _____________________________________ - - def test(): - > assert Help().fun() == 2 - E assert 1 == 2 - E + where 1 = fun() - E + where fun = .fun - E + where = Help() - - test_local.py:13: AssertionError - =========================== 1 failed in 0.03 seconds =========================== diff --git a/changelog/6962.bugfix.rst b/changelog/6962.bugfix.rst deleted file mode 100644 index 030b6e06392..00000000000 --- a/changelog/6962.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Parametrization parameters are now compared using `==` instead of `is` (`is` is still used as a fallback if the parameter does not support `==`). -This fixes use of parameters such as lists, which have a different `id` but compare equal, causing fixtures to be re-computed instead of being cached. diff --git a/changelog/7166.bugfix.rst b/changelog/7166.bugfix.rst deleted file mode 100644 index 98e6821f2ff..00000000000 --- a/changelog/7166.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed progress percentages (the ``[ 87%]`` at the edge of the screen) sometimes not aligning correctly when running with pytest-xdist ``-n``. diff --git a/changelog/7662.improvement.rst b/changelog/7662.improvement.rst deleted file mode 100644 index b6ae1ba7e4c..00000000000 --- a/changelog/7662.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added timezone information to the testsuite timestamp in the JUnit XML report. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index c65eb5f3613..429cb8249a1 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,8 @@ Release announcements :maxdepth: 2 + release-8.3.1 + release-8.3.0 release-8.2.2 release-8.2.1 release-8.2.0 diff --git a/doc/en/announce/release-8.3.0.rst b/doc/en/announce/release-8.3.0.rst new file mode 100644 index 00000000000..ec5cd3d0db9 --- /dev/null +++ b/doc/en/announce/release-8.3.0.rst @@ -0,0 +1,60 @@ +pytest-8.3.0 +======================================= + +The pytest team is proud to announce the 8.3.0 release! + +This release contains new features, improvements, and bug fixes, +the full list of changes is available in the changelog: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Anita Hammer +* Ben Brown +* Brian Okken +* Bruno Oliveira +* Cornelius Riemenschneider +* Farbod Ahmadian +* Florian Bruhin +* Hynek Schlawack +* James Frost +* Jason R. Coombs +* Jelle Zijlstra +* Josh Soref +* Marc Bresson +* Michael Vogt +* Nathan Goldbaum +* Nicolas Simonds +* Oliver Bestwalter +* Pavel Březina +* Pierre Sassoulas +* Pradyun Gedam +* Ran Benita +* Ronny Pfannschmidt +* SOUBHIK KUMAR MITRA +* Sam Jirovec +* Stavros Ntentos +* Sviatoslav Sydorenko +* Sviatoslav Sydorenko (Святослав Сидоренко) +* Tomasz Kłoczko +* Virendra Patil +* Yutian Li +* Zach Snicker +* dj +* holger krekel +* joseph-sentry +* lovetheguitar +* neutraljump + + +Happy testing, +The pytest Development Team diff --git a/doc/en/announce/release-8.3.1.rst b/doc/en/announce/release-8.3.1.rst new file mode 100644 index 00000000000..0fb9b40d9c7 --- /dev/null +++ b/doc/en/announce/release-8.3.1.rst @@ -0,0 +1,19 @@ +pytest-8.3.1 +======================================= + +pytest 8.3.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Ran Benita + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 8dfffb0828a..b4c0f91f8e5 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:560 + cache -- .../_pytest/cacheprovider.py:558 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1003 + capsysbinary -- .../_pytest/capture.py:1005 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -43,6 +43,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[bytes] `. Example: + .. code-block:: python def test_output(capsysbinary): @@ -50,7 +51,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1030 + capfd -- .../_pytest/capture.py:1033 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -60,6 +61,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[str] `. Example: + .. code-block:: python def test_system_echo(capfd): @@ -67,7 +69,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1057 + capfdbinary -- .../_pytest/capture.py:1061 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -77,6 +79,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[bytes] `. Example: + .. code-block:: python def test_system_echo(capfdbinary): @@ -84,7 +87,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - capsys -- .../_pytest/capture.py:976 + capsys -- .../_pytest/capture.py:977 Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsys.readouterr()`` method @@ -94,6 +97,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Returns an instance of :class:`CaptureFixture[str] `. Example: + .. code-block:: python def test_output(capsys): @@ -101,7 +105,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:738 + doctest_namespace [session scope] -- .../_pytest/doctest.py:740 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -115,7 +119,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1338 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1344 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -125,7 +129,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a if pytestconfig.getoption("verbose") > 0: ... - record_property -- .../_pytest/junitxml.py:284 + record_property -- .../_pytest/junitxml.py:280 Add extra properties to the calling test. User properties become part of the test report and are available to the @@ -139,13 +143,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a def test_function(record_property): record_property("example_key", 1) - record_xml_attribute -- .../_pytest/junitxml.py:307 + record_xml_attribute -- .../_pytest/junitxml.py:303 Add extra xml attributes to the tag for the calling test. The fixture is callable with ``name, value``. The value is automatically XML-encoded. - record_testsuite_property [session scope] -- .../_pytest/junitxml.py:345 + record_testsuite_property [session scope] -- .../_pytest/junitxml.py:341 Record a new ```` tag as child of the root ````. This is suitable to writing global information regarding the entire test @@ -170,10 +174,10 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a `pytest-xdist `__ plugin. See :issue:`7767` for details. - tmpdir_factory [session scope] -- .../_pytest/legacypath.py:303 + tmpdir_factory [session scope] -- .../_pytest/legacypath.py:298 Return a :class:`pytest.TempdirFactory` instance for the test session. - tmpdir -- .../_pytest/legacypath.py:310 + tmpdir -- .../_pytest/legacypath.py:305 Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. @@ -192,7 +196,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:602 + caplog -- .../_pytest/logging.py:600 Access and control log capturing. Captured logs are available through the following properties/methods:: @@ -203,7 +207,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a * caplog.record_tuples -> list of (logger_name, level, message) tuples * caplog.clear() -> clear captured records and formatted log output string - monkeypatch -- .../_pytest/monkeypatch.py:33 + monkeypatch -- .../_pytest/monkeypatch.py:31 A convenient fixture for monkey-patching. The fixture provides these methods to modify objects, dictionaries, or @@ -227,7 +231,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a To undo modifications done by the fixture in a contained scope, use :meth:`context() `. - recwarn -- .../_pytest/recwarn.py:32 + recwarn -- .../_pytest/recwarn.py:35 Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 8e3efd0479b..f6aefbd3b13 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,269 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.3.1 (2024-07-20) +========================= + +The 8.3.0 release failed to include the change notes and docs for the release. This patch release remedies this. There are no other changes. + + +pytest 8.3.0 (2024-07-20) +========================= + +New features +------------ + +- `#12231 `_: Added `--xfail-tb` flag, which turns on traceback output for XFAIL results. + + * If the `--xfail-tb` flag is not given, tracebacks for XFAIL results are NOT shown. + * The style of traceback for XFAIL is set with `--tb`, and can be `auto|long|short|line|native|no`. + * Note: Even if you have `--xfail-tb` set, you won't see them if `--tb=no`. + + Some history: + + With pytest 8.0, `-rx` or `-ra` would not only turn on summary reports for xfail, but also report the tracebacks for xfail results. This caused issues with some projects that utilize xfail, but don't want to see all of the xfail tracebacks. + + This change detaches xfail tracebacks from `-rx`, and now we turn on xfail tracebacks with `--xfail-tb`. With this, the default `-rx`/ `-ra` behavior is identical to pre-8.0 with respect to xfail tracebacks. While this is a behavior change, it brings default behavior back to pre-8.0.0 behavior, which ultimately was considered the better course of action. + + +- `#12281 `_: Added support for keyword matching in marker expressions. + + Now tests can be selected by marker keyword arguments. + Supported values are :class:`int`, (unescaped) :class:`str`, :class:`bool` & :data:`None`. + + See :ref:`marker examples ` for more information. + + -- by :user:`lovetheguitar` + + +- `#12567 `_: Added ``--no-fold-skipped`` command line option. + + If this option is set, then skipped tests in short summary are no longer grouped + by reason but all tests are printed individually with their nodeid in the same + way as other statuses. + + -- by :user:`pbrezina` + + + +Improvements in existing functionality +-------------------------------------- + +- `#12469 `_: The console output now uses the "third-party plugins" terminology, + replacing the previously established but confusing and outdated + reference to :std:doc:`setuptools ` + -- by :user:`webknjaz`. + + +- `#12544 `_, `#12545 `_: Python virtual environment detection was improved by + checking for a :file:`pyvenv.cfg` file, ensuring reliable detection on + various platforms -- by :user:`zachsnickers`. + + +- `#2871 `_: Do not truncate arguments to functions in output when running with `-vvv`. + + +- `#389 `_: The readability of assertion introspection of bound methods has been enhanced + -- by :user:`farbodahm`, :user:`webknjaz`, :user:`obestwalter`, :user:`flub` + and :user:`glyphack`. + + Earlier, it was like: + + .. code-block:: console + + =================================== FAILURES =================================== + _____________________________________ test _____________________________________ + + def test(): + > assert Help().fun() == 2 + E assert 1 == 2 + E + where 1 = >() + E + where > = .fun + E + where = Help() + + example.py:7: AssertionError + =========================== 1 failed in 0.03 seconds =========================== + + + And now it's like: + + .. code-block:: console + + =================================== FAILURES =================================== + _____________________________________ test _____________________________________ + + def test(): + > assert Help().fun() == 2 + E assert 1 == 2 + E + where 1 = fun() + E + where fun = .fun + E + where = Help() + + test_local.py:13: AssertionError + =========================== 1 failed in 0.03 seconds =========================== + + +- `#7662 `_: Added timezone information to the testsuite timestamp in the JUnit XML report. + + + +Bug fixes +--------- + +- `#11706 `_: Fixed reporting of teardown errors in higher-scoped fixtures when using `--maxfail` or `--stepwise`. + + Originally added in pytest 8.0.0, but reverted in 8.0.2 due to a regression in pytest-xdist. + This regression was fixed in pytest-xdist 3.6.1. + + +- `#11797 `_: :func:`pytest.approx` now correctly handles :class:`Sequence `-like objects. + + +- `#12204 `_, `#12264 `_: Fixed a regression in pytest 8.0 where tracebacks get longer and longer when multiple + tests fail due to a shared higher-scope fixture which raised -- by :user:`bluetech`. + + Also fixed a similar regression in pytest 5.4 for collectors which raise during setup. + + The fix necessitated internal changes which may affect some plugins: + + * ``FixtureDef.cached_result[2]`` is now a tuple ``(exc, tb)`` + instead of ``exc``. + * ``SetupState.stack`` failures are now a tuple ``(exc, tb)`` + instead of ``exc``. + + +- `#12275 `_: Fixed collection error upon encountering an :mod:`abstract ` class, including abstract `unittest.TestCase` subclasses. + + +- `#12328 `_: Fixed a regression in pytest 8.0.0 where package-scoped parameterized items were not correctly reordered to minimize setups/teardowns in some cases. + + +- `#12424 `_: Fixed crash with `assert testcase is not None` assertion failure when re-running unittest tests using plugins like pytest-rerunfailures. Regressed in 8.2.2. + + +- `#12472 `_: Fixed a crash when returning category ``"error"`` or ``"failed"`` with a custom test status from :hook:`pytest_report_teststatus` hook -- :user:`pbrezina`. + + +- `#12505 `_: Improved handling of invalid regex patterns in :func:`pytest.raises(match=r'...') ` by providing a clear error message. + + +- `#12580 `_: Fixed a crash when using the cache class on Windows and the cache directory was created concurrently. + + +- `#6962 `_: Parametrization parameters are now compared using `==` instead of `is` (`is` is still used as a fallback if the parameter does not support `==`). + This fixes use of parameters such as lists, which have a different `id` but compare equal, causing fixtures to be re-computed instead of being cached. + + +- `#7166 `_: Fixed progress percentages (the ``[ 87%]`` at the edge of the screen) sometimes not aligning correctly when running with pytest-xdist ``-n``. + + + +Improved documentation +---------------------- + +- `#12153 `_: Documented using :envvar:`PYTEST_VERSION` to detect if code is running from within a pytest run. + + +- `#12469 `_: The external plugin mentions in the documentation now avoid mentioning + :std:doc:`setuptools entry-points ` as the concept is + much more generic nowadays. Instead, the terminology of "external", + "installed", or "third-party" plugins (or packages) replaces that. + + -- by :user:`webknjaz` + + +- `#12577 `_: `CI` and `BUILD_NUMBER` environment variables role is discribed in + the reference doc. They now also appear when doing `pytest -h` + -- by :user:`MarcBresson`. + + + +Contributor-facing changes +-------------------------- + +- `#12467 `_: Migrated all internal type-annotations to the python3.10+ style by using the `annotations` future import. + + -- by :user:`RonnyPfannschmidt` + + +- `#11771 `_, `#12557 `_: The PyPy runtime version has been updated to 3.9 from 3.8 that introduced + a flaky bug at the garbage collector which was not expected to fix there + as the 3.8 is EoL. + + -- by :user:`x612skm` + + +- `#12493 `_: The change log draft preview integration has been refactored to use a + third party extension ``sphinxcontib-towncrier``. The previous in-repo + script was putting the change log preview file at + :file:`doc/en/_changelog_towncrier_draft.rst`. Said file is no longer + ignored in Git and might show up among untracked files in the + development environments of the contributors. To address that, the + contributors can run the following command that will clean it up: + + .. code-block:: console + + $ git clean -x -i -- doc/en/_changelog_towncrier_draft.rst + + -- by :user:`webknjaz` + + +- `#12498 `_: All the undocumented ``tox`` environments now have descriptions. + They can be listed in one's development environment by invoking + ``tox -av`` in a terminal. + + -- by :user:`webknjaz` + + +- `#12501 `_: The changelog configuration has been updated to introduce more accurate + audience-tailored categories. Previously, there was a ``trivial`` + change log fragment type with an unclear and broad meaning. It was + removed and we now have ``contrib``, ``misc`` and ``packaging`` in + place of it. + + The new change note types target the readers who are downstream + packagers and project contributors. Additionally, the miscellaneous + section is kept for unspecified updates that do not fit anywhere else. + + -- by :user:`webknjaz` + + +- `#12502 `_: The UX of the GitHub automation making pull requests to update the + plugin list has been updated. Previously, the maintainers had to close + the automatically created pull requests and re-open them to trigger the + CI runs. From now on, they only need to click the `Ready for review` + button instead. + + -- by :user:`webknjaz` + + +- `#12522 `_: The ``:pull:`` RST role has been replaced with a shorter + ``:pr:`` due to starting to use the implementation from + the third-party :pypi:`sphinx-issues` Sphinx extension + -- by :user:`webknjaz`. + + +- `#12531 `_: The coverage reporting configuration has been updated to exclude + pytest's own tests marked as expected to fail from the coverage + report. This has an effect of reducing the influence of flaky + tests on the resulting number. + + -- by :user:`webknjaz` + + +- `#12533 `_: The ``extlinks`` Sphinx extension is no longer enabled. The ``:bpo:`` + role it used to declare has been removed with that. BPO itself has + migrated to GitHub some years ago and it is possible to link the + respective issues by using their GitHub issue numbers and the + ``:issue:`` role that the ``sphinx-issues`` extension implements. + + -- by :user:`webknjaz` + + +- `#12562 `_: Possible typos in using the ``:user:`` RST role is now being linted + through the pre-commit tool integration -- by :user:`webknjaz`. + + pytest 8.2.2 (2024-06-04) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index d540bf08337..b5679ff6305 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + @@ -505,8 +505,8 @@ Running it results in some skips if we don't have all the python interpreters in . $ pytest -rs -q multipython.py ssssssssssss...ssssssssssss [100%] ========================= short test summary info ========================== - SKIPPED [12] multipython.py:65: 'python3.9' not found - SKIPPED [12] multipython.py:65: 'python3.11' not found + SKIPPED [12] multipython.py:67: 'python3.9' not found + SKIPPED [12] multipython.py:67: 'python3.11' not found 3 passed, 24 skipped in 0.12s Parametrization of optional implementations/imports diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 39b799ed934..9705ccf94f8 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 2c34cc2b00d..0da58d0490e 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -25,7 +25,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert param1 * 2 < param2 E assert (3 * 2) < 6 - failure_demo.py:19: AssertionError + failure_demo.py:21: AssertionError _________________________ TestFailing.test_simple __________________________ self = @@ -42,7 +42,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + where 42 = .f at 0xdeadbeef0002>() E + and 43 = .g at 0xdeadbeef0003>() - failure_demo.py:30: AssertionError + failure_demo.py:32: AssertionError ____________________ TestFailing.test_simple_multiline _____________________ self = @@ -50,7 +50,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_simple_multiline(self): > otherfunc_multi(42, 6 * 9) - failure_demo.py:33: + failure_demo.py:35: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ a = 42, b = 54 @@ -59,7 +59,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert a == b E assert 42 == 54 - failure_demo.py:14: AssertionError + failure_demo.py:16: AssertionError ___________________________ TestFailing.test_not ___________________________ self = @@ -72,7 +72,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E assert not 42 E + where 42 = .f at 0xdeadbeef0006>() - failure_demo.py:39: AssertionError + failure_demo.py:41: AssertionError _________________ TestSpecialisedExplanations.test_eq_text _________________ self = @@ -84,7 +84,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E - eggs E + spam - failure_demo.py:44: AssertionError + failure_demo.py:46: AssertionError _____________ TestSpecialisedExplanations.test_eq_similar_text _____________ self = @@ -98,7 +98,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + foo 1 bar E ? ^ - failure_demo.py:47: AssertionError + failure_demo.py:49: AssertionError ____________ TestSpecialisedExplanations.test_eq_multiline_text ____________ self = @@ -112,7 +112,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + spam E bar - failure_demo.py:50: AssertionError + failure_demo.py:52: AssertionError ______________ TestSpecialisedExplanations.test_eq_long_text _______________ self = @@ -130,7 +130,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + 1111111111a222222222 E ? ^ - failure_demo.py:55: AssertionError + failure_demo.py:57: AssertionError _________ TestSpecialisedExplanations.test_eq_long_text_multiline __________ self = @@ -150,7 +150,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E E ...Full output truncated (7 lines hidden), use '-vv' to show - failure_demo.py:60: AssertionError + failure_demo.py:62: AssertionError _________________ TestSpecialisedExplanations.test_eq_list _________________ self = @@ -162,7 +162,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E At index 2 diff: 2 != 3 E Use -v to get more diff - failure_demo.py:63: AssertionError + failure_demo.py:65: AssertionError ______________ TestSpecialisedExplanations.test_eq_list_long _______________ self = @@ -176,7 +176,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E At index 100 diff: 1 != 2 E Use -v to get more diff - failure_demo.py:68: AssertionError + failure_demo.py:70: AssertionError _________________ TestSpecialisedExplanations.test_eq_dict _________________ self = @@ -194,7 +194,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E {'d': 0} E Use -v to get more diff - failure_demo.py:71: AssertionError + failure_demo.py:73: AssertionError _________________ TestSpecialisedExplanations.test_eq_set __________________ self = @@ -212,7 +212,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E 21 E Use -v to get more diff - failure_demo.py:74: AssertionError + failure_demo.py:76: AssertionError _____________ TestSpecialisedExplanations.test_eq_longer_list ______________ self = @@ -224,7 +224,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E Right contains one more item: 3 E Use -v to get more diff - failure_demo.py:77: AssertionError + failure_demo.py:79: AssertionError _________________ TestSpecialisedExplanations.test_in_list _________________ self = @@ -233,7 +233,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert 1 in [0, 2, 3, 4, 5] E assert 1 in [0, 2, 3, 4, 5] - failure_demo.py:80: AssertionError + failure_demo.py:82: AssertionError __________ TestSpecialisedExplanations.test_not_in_text_multiline __________ self = @@ -252,7 +252,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E and a E tail - failure_demo.py:84: AssertionError + failure_demo.py:86: AssertionError ___________ TestSpecialisedExplanations.test_not_in_text_single ____________ self = @@ -266,7 +266,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E single foo line E ? +++ - failure_demo.py:88: AssertionError + failure_demo.py:90: AssertionError _________ TestSpecialisedExplanations.test_not_in_text_single_long _________ self = @@ -280,7 +280,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail E ? +++ - failure_demo.py:92: AssertionError + failure_demo.py:94: AssertionError ______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______ self = @@ -294,7 +294,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - failure_demo.py:96: AssertionError + failure_demo.py:98: AssertionError ______________ TestSpecialisedExplanations.test_eq_dataclass _______________ self = @@ -321,7 +321,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E - c E + b - failure_demo.py:108: AssertionError + failure_demo.py:110: AssertionError ________________ TestSpecialisedExplanations.test_eq_attrs _________________ self = @@ -348,7 +348,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E - c E + b - failure_demo.py:120: AssertionError + failure_demo.py:122: AssertionError ______________________________ test_attribute ______________________________ def test_attribute(): @@ -360,7 +360,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E assert 1 == 2 E + where 1 = .Foo object at 0xdeadbeef0018>.b - failure_demo.py:128: AssertionError + failure_demo.py:130: AssertionError _________________________ test_attribute_instance __________________________ def test_attribute_instance(): @@ -372,7 +372,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + where 1 = .Foo object at 0xdeadbeef0019>.b E + where .Foo object at 0xdeadbeef0019> = .Foo'>() - failure_demo.py:135: AssertionError + failure_demo.py:137: AssertionError __________________________ test_attribute_failure __________________________ def test_attribute_failure(): @@ -385,7 +385,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: i = Foo() > assert i.b == 2 - failure_demo.py:146: + failure_demo.py:148: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = .Foo object at 0xdeadbeef001a> @@ -394,7 +394,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > raise Exception("Failed to get attrib") E Exception: Failed to get attrib - failure_demo.py:141: Exception + failure_demo.py:143: Exception _________________________ test_attribute_multiple __________________________ def test_attribute_multiple(): @@ -411,7 +411,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + and 2 = .Bar object at 0xdeadbeef001c>.b E + where .Bar object at 0xdeadbeef001c> = .Bar'>() - failure_demo.py:156: AssertionError + failure_demo.py:158: AssertionError __________________________ TestRaises.test_raises __________________________ self = @@ -421,7 +421,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > raises(TypeError, int, s) E ValueError: invalid literal for int() with base 10: 'qwe' - failure_demo.py:166: ValueError + failure_demo.py:168: ValueError ______________________ TestRaises.test_raises_doesnt _______________________ self = @@ -430,7 +430,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > raises(OSError, int, "3") E Failed: DID NOT RAISE - failure_demo.py:169: Failed + failure_demo.py:171: Failed __________________________ TestRaises.test_raise ___________________________ self = @@ -439,7 +439,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > raise ValueError("demo error") E ValueError: demo error - failure_demo.py:172: ValueError + failure_demo.py:174: ValueError ________________________ TestRaises.test_tupleerror ________________________ self = @@ -448,7 +448,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > a, b = [1] # noqa: F841 E ValueError: not enough values to unpack (expected 2, got 1) - failure_demo.py:175: ValueError + failure_demo.py:177: ValueError ______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______ self = @@ -459,7 +459,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > a, b = items.pop() E TypeError: cannot unpack non-iterable int object - failure_demo.py:180: TypeError + failure_demo.py:182: TypeError --------------------------- Captured stdout call --------------------------- items is [1, 2, 3] ________________________ TestRaises.test_some_error ________________________ @@ -470,7 +470,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > if namenotexi: # noqa: F821 E NameError: name 'namenotexi' is not defined - failure_demo.py:183: NameError + failure_demo.py:185: NameError ____________________ test_dynamic_compile_shows_nicely _____________________ def test_dynamic_compile_shows_nicely(): @@ -486,7 +486,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: sys.modules[name] = module > module.foo() - failure_demo.py:202: + failure_demo.py:204: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ > ??? @@ -506,9 +506,9 @@ Here is a nice run of several failures and how ``pytest`` presents things: > somefunc(f(), g()) - failure_demo.py:213: + failure_demo.py:215: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - failure_demo.py:10: in somefunc + failure_demo.py:12: in somefunc otherfunc(x, y) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ @@ -518,7 +518,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert a == b E assert 44 == 43 - failure_demo.py:6: AssertionError + failure_demo.py:8: AssertionError ___________________ TestMoreErrors.test_z1_unpack_error ____________________ self = @@ -528,7 +528,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > a, b = items E ValueError: not enough values to unpack (expected 2, got 0) - failure_demo.py:217: ValueError + failure_demo.py:219: ValueError ____________________ TestMoreErrors.test_z2_type_error _____________________ self = @@ -538,7 +538,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > a, b = items E TypeError: cannot unpack non-iterable int object - failure_demo.py:221: TypeError + failure_demo.py:223: TypeError ______________________ TestMoreErrors.test_startswith ______________________ self = @@ -551,7 +551,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + where False = ('456') E + where = '123'.startswith - failure_demo.py:226: AssertionError + failure_demo.py:228: AssertionError __________________ TestMoreErrors.test_startswith_nested ___________________ self = @@ -570,7 +570,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + where '123' = .f at 0xdeadbeef0029>() E + and '456' = .g at 0xdeadbeef002a>() - failure_demo.py:235: AssertionError + failure_demo.py:237: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ self = @@ -581,7 +581,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + where False = isinstance(43, float) E + where 43 = globf(42) - failure_demo.py:238: AssertionError + failure_demo.py:240: AssertionError _______________________ TestMoreErrors.test_instance _______________________ self = @@ -592,7 +592,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E assert 42 != 42 E + where 42 = .x - failure_demo.py:242: AssertionError + failure_demo.py:244: AssertionError _______________________ TestMoreErrors.test_compare ________________________ self = @@ -602,7 +602,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E assert 11 < 5 E + where 11 = globf(10) - failure_demo.py:245: AssertionError + failure_demo.py:247: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ self = @@ -613,7 +613,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: > assert x == 0 E assert 1 == 0 - failure_demo.py:250: AssertionError + failure_demo.py:252: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ self = @@ -628,7 +628,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E assert 1 == 2 E + where 1 = .A'>.a - failure_demo.py:261: AssertionError + failure_demo.py:263: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ self = @@ -647,7 +647,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E assert 1 == 2 E + where 1 = .A'>.a - failure_demo.py:268: AssertionError + failure_demo.py:270: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ self = @@ -669,7 +669,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: E assert 1 == 2 E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a - failure_demo.py:281: AssertionError + failure_demo.py:283: AssertionError ========================= short test summary info ========================== FAILED failure_demo.py::test_generative[3-6] - assert (3 * 2) < 6 FAILED failure_demo.py::TestFailing::test_simple - assert 42 == 43 diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index d4ace3f0413..a5e2e78c397 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -645,31 +645,6 @@ If we run this: E assert 0 test_step.py:11: AssertionError - ================================ XFAILURES ================================= - ______________________ TestUserHandling.test_deletion ______________________ - - item = - - def pytest_runtest_setup(item): - if "incremental" in item.keywords: - # retrieve the class name of the test - cls_name = str(item.cls) - # check if a previous test has failed for this class - if cls_name in _test_failed_incremental: - # retrieve the index of the test (if parametrize is used in combination with incremental) - parametrize_index = ( - tuple(item.callspec.indices.values()) - if hasattr(item, "callspec") - else () - ) - # retrieve the name of the first test function to fail for this class name and index - test_name = _test_failed_incremental[cls_name].get(parametrize_index, None) - # if name found, test has failed for the combination of class name & test name - if test_name is not None: - > pytest.xfail(f"previous test failed ({test_name})") - E _pytest.outcomes.XFailed: previous test failed (test_modification) - - conftest.py:47: XFailed ========================= short test summary info ========================== XFAIL test_step.py::TestUserHandling::test_deletion - reason: previous test failed (test_modification) ================== 1 failed, 2 passed, 1 xfailed in 0.12s ================== diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 85bee729ba1..b519656a182 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.2.2 + pytest 8.3.1 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index ecd297867c5..5c66c348eca 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index 4994ad1af69..8b15f95f0fd 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -444,14 +444,6 @@ Example: E assert 0 test_example.py:14: AssertionError - ================================ XFAILURES ================================= - ________________________________ test_xfail ________________________________ - - def test_xfail(): - > pytest.xfail("xfailing this test") - E _pytest.outcomes.XFailed: xfailing this test - - test_example.py:26: XFailed ================================= XPASSES ================================== ========================= short test summary info ========================== SKIPPED [1] test_example.py:22: skipping this test diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index d1222728e13..099c8a00260 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1939,18 +1939,19 @@ All the command-line flags can be obtained by running ``pytest --help``:: general: -k EXPRESSION Only run tests which match the given substring expression. An expression is a Python evaluable - expression where all names are substring-matched against - test names and their parent classes. Example: -k - 'test_method or test_other' matches all test functions - and classes whose name contains 'test_method' or - 'test_other', while -k 'not test_method' matches those - that don't contain 'test_method' in their names. -k 'not - test_method and not test_other' will eliminate the - matches. Additionally keywords are matched to classes - and functions containing extra names in their - 'extra_keyword_matches' set, as well as functions which - have names assigned directly to them. The matching is - case-insensitive. + expression where all names are substring-matched + against test names and their parent classes. + Example: -k 'test_method or test_other' matches all + test functions and classes whose name contains + 'test_method' or 'test_other', while -k 'not + test_method' matches those that don't contain + 'test_method' in their names. -k 'not test_method + and not test_other' will eliminate the matches. + Additionally keywords are matched to classes and + functions containing extra names in their + 'extra_keyword_matches' set, as well as functions + which have names assigned directly to them. The + matching is case-insensitive. -m MARKEXPR Only run tests matching given mark expression. For example: -m 'mark1 and not mark2'. --markers show markers (builtin, plugin and per-project ones). @@ -1968,28 +1969,28 @@ All the command-line flags can be obtained by running ``pytest --help``:: --trace Immediately break when running each test --capture=method Per-test capturing method: one of fd|sys|no|tee-sys -s Shortcut for --capture=no - --runxfail Report the results of xfail tests as if they were not - marked - --lf, --last-failed Rerun only the tests that failed at the last run (or all - if none failed) - --ff, --failed-first Run all tests, but run the last failures first. This may - re-order tests and thus lead to repeated fixture + --runxfail Report the results of xfail tests as if they were + not marked + --lf, --last-failed Rerun only the tests that failed at the last run (or + all if none failed) + --ff, --failed-first Run all tests, but run the last failures first. This + may re-order tests and thus lead to repeated fixture setup/teardown. --nf, --new-first Run tests from new files first, then the rest of the tests sorted by file mtime --cache-show=[CACHESHOW] - Show cache contents, don't perform collection or tests. - Optional argument: glob (default: '*'). + Show cache contents, don't perform collection or + tests. Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run --lfnf={all,none}, --last-failed-no-failures={all,none} - With ``--lf``, determines whether to execute tests when - there are no previously (known) failures or when no - cached ``lastfailed`` data was found. ``all`` (the - default) runs the full test suite again. ``none`` just - emits a message about no known failures and exits - successfully. - --sw, --stepwise Exit on test failure and continue from last failing test - next time + With ``--lf``, determines whether to execute tests + when there are no previously (known) failures or + when no cached ``lastfailed`` data was found. + ``all`` (the default) runs the full test suite + again. ``none`` just emits a message about no known + failures and exits successfully. + --sw, --stepwise Exit on test failure and continue from last failing + test next time --sw-skip, --stepwise-skip Ignore the first failing test but stop on the next failing test. Implicitly enables --stepwise. @@ -2001,20 +2002,22 @@ All the command-line flags can be obtained by running ``pytest --help``:: -v, --verbose Increase verbosity --no-header Disable header --no-summary Disable summary + --no-fold-skipped Do not fold skipped tests in short summary. -q, --quiet Decrease verbosity --verbosity=VERBOSE Set verbosity. Default: 0. -r chars Show extra test summary info as specified by chars: (f)ailed, (E)rror, (s)kipped, (x)failed, (X)passed, (p)assed, (P)assed with output, (a)ll except passed - (p/P), or (A)ll. (w)arnings are enabled by default (see - --disable-warnings), 'N' can be used to reset the list. - (default: 'fE'). + (p/P), or (A)ll. (w)arnings are enabled by default + (see --disable-warnings), 'N' can be used to reset + the list. (default: 'fE'). --disable-warnings, --disable-pytest-warnings Disable warnings summary -l, --showlocals Show locals in tracebacks (disabled by default) - --no-showlocals Hide locals in tracebacks (negate --showlocals passed - through addopts) - --tb=style Traceback print mode (auto/long/short/line/native/no) + --no-showlocals Hide locals in tracebacks (negate --showlocals + passed through addopts) + --tb=style Traceback print mode + (auto/long/short/line/native/no) --xfail-tb Show tracebacks for xfail (as long as --tb != no) --show-capture={no,stdout,stderr,log,all} Controls how captured stdout/stderr/log is shown on @@ -2022,37 +2025,39 @@ All the command-line flags can be obtained by running ``pytest --help``:: --full-trace Don't cut any tracebacks (default is to cut) --color=color Color terminal output (yes/no/auto) --code-highlight={yes,no} - Whether code should be highlighted (only if --color is - also enabled). Default: yes. + Whether code should be highlighted (only if --color + is also enabled). Default: yes. --pastebin=mode Send failed|all info to bpaste.net pastebin service --junit-xml=path Create junit-xml style report file at given path --junit-prefix=str Prepend prefix to classnames in junit-xml output pytest-warnings: -W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGS - Set which warnings to report, see -W option of Python - itself + Set which warnings to report, see -W option of + Python itself --maxfail=num Exit after first num failures or errors --strict-config Any warnings encountered while parsing the `pytest` section of the configuration file raise errors - --strict-markers Markers not registered in the `markers` section of the - configuration file raise errors + --strict-markers Markers not registered in the `markers` section of + the configuration file raise errors --strict (Deprecated) alias to --strict-markers -c FILE, --config-file=FILE Load configuration from `FILE` instead of trying to locate one of the implicit configuration files. --continue-on-collection-errors Force test execution even if collection errors occur - --rootdir=ROOTDIR Define root directory for tests. Can be relative path: - 'root_dir', './root_dir', 'root_dir/another_dir/'; - absolute path: '/home/user/root_dir'; path with - variables: '$HOME/root_dir'. + --rootdir=ROOTDIR Define root directory for tests. Can be relative + path: 'root_dir', './root_dir', + 'root_dir/another_dir/'; absolute path: + '/home/user/root_dir'; path with variables: + '$HOME/root_dir'. collection: --collect-only, --co Only collect tests, don't execute them --pyargs Try to interpret all arguments as Python packages --ignore=path Ignore path during collection (multi-allowed) - --ignore-glob=path Ignore path pattern during collection (multi-allowed) + --ignore-glob=path Ignore path pattern during collection (multi- + allowed) --deselect=nodeid_prefix Deselect item (via node id prefix) during collection (multi-allowed) @@ -2062,8 +2067,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: --collect-in-virtualenv Don't ignore tests in a local virtualenv directory --import-mode={prepend,append,importlib} - Prepend/append to sys.path when importing test modules - and conftest files. Default: prepend. + Prepend/append to sys.path when importing test + modules and conftest files. Default: prepend. --doctest-modules Run doctests in all .py modules --doctest-report={none,cdiff,ndiff,udiff,only_first_failure} Choose another output format for diffs on doctest @@ -2076,37 +2081,38 @@ All the command-line flags can be obtained by running ``pytest --help``:: failure test session debugging and configuration: - --basetemp=dir Base temporary directory for this test run. (Warning: - this directory is removed if it exists.) - -V, --version Display pytest version and information about plugins. - When given twice, also display information about - plugins. + --basetemp=dir Base temporary directory for this test run. + (Warning: this directory is removed if it exists.) + -V, --version Display pytest version and information about + plugins. When given twice, also display information + about plugins. -h, --help Show help message and configuration info -p name Early-load given plugin module name or entry point - (multi-allowed). To avoid loading of plugins, use the - `no:` prefix, e.g. `no:doctest`. + (multi-allowed). To avoid loading of plugins, use + the `no:` prefix, e.g. `no:doctest`. --trace-config Trace considerations of conftest.py files --debug=[DEBUG_FILE_NAME] Store internal tracing debug information in this log - file. This file is opened with 'w' and truncated as a - result, care advised. Default: pytestdebug.log. + file. This file is opened with 'w' and truncated as + a result, care advised. Default: pytestdebug.log. -o OVERRIDE_INI, --override-ini=OVERRIDE_INI - Override ini option with "option=value" style, e.g. `-o - xfail_strict=True -o cache_dir=cache`. + Override ini option with "option=value" style, e.g. + `-o xfail_strict=True -o cache_dir=cache`. --assert=MODE Control assertion debugging tools. 'plain' performs no assertion debugging. - 'rewrite' (the default) rewrites assert statements in - test modules on import to provide assert expression - information. + 'rewrite' (the default) rewrites assert statements + in test modules on import to provide assert + expression information. --setup-only Only setup fixtures, do not execute tests --setup-show Show setup of fixtures while executing tests - --setup-plan Show what fixtures and tests would be executed but don't - execute anything + --setup-plan Show what fixtures and tests would be executed but + don't execute anything logging: - --log-level=LEVEL Level of messages to catch/display. Not set by default, - so it depends on the root/parent log handler's effective - level, where it is "WARNING" by default. + --log-level=LEVEL Level of messages to catch/display. Not set by + default, so it depends on the root/parent log + handler's effective level, where it is "WARNING" by + default. --log-format=LOG_FORMAT Log format used by the logging module --log-date-format=LOG_DATE_FORMAT @@ -2130,13 +2136,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: Auto-indent multiline messages passed to the logging module. Accepts true|on, false|off or an integer. --log-disable=LOGGER_DISABLE - Disable a logger by name. Can be passed multiple times. - - Custom options: - --lsof Run FD checks if lsof is available - --runpytest={inprocess,subprocess} - Run pytest sub runs in tests using an 'inprocess' or - 'subprocess' (python -m main) method + Disable a logger by name. Can be passed multiple + times. [pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg|pyproject.toml file found: @@ -2151,33 +2152,37 @@ All the command-line flags can be obtained by running ``pytest --help``:: warnings.filterwarnings. Processed after -W/--pythonwarnings. consider_namespace_packages (bool): - Consider namespace packages when resolving module names - during import - usefixtures (args): List of default fixtures to be used with this project + Consider namespace packages when resolving module + names during import + usefixtures (args): List of default fixtures to be used with this + project python_files (args): Glob-style file patterns for Python test module discovery python_classes (args): - Prefixes or glob names for Python test class discovery + Prefixes or glob names for Python test class + discovery python_functions (args): Prefixes or glob names for Python test function and method discovery disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool): - Disable string escape non-ASCII characters, might cause - unwanted side effects(use at your own risk) + Disable string escape non-ASCII characters, might + cause unwanted side effects(use at your own risk) console_output_style (string): - Console output: "classic", or with additional progress - information ("progress" (percentage) | "count" | - "progress-even-when-capture-no" (forces progress even - when capture=no) + Console output: "classic", or with additional + progress information ("progress" (percentage) | + "count" | "progress-even-when-capture-no" (forces + progress even when capture=no) verbosity_test_cases (string): Specify a verbosity level for test case execution, - overriding the main level. Higher levels will provide - more detailed information about each test case executed. - xfail_strict (bool): Default for the strict parameter of xfail markers when - not given explicitly (default: False) + overriding the main level. Higher levels will + provide more detailed information about each test + case executed. + xfail_strict (bool): Default for the strict parameter of xfail markers + when not given explicitly (default: False) tmp_path_retention_count (string): How many sessions should we keep the `tmp_path` - directories, according to `tmp_path_retention_policy`. + directories, according to + `tmp_path_retention_policy`. tmp_path_retention_policy (string): Controls which directories created by the `tmp_path` fixture are kept around, based on test outcome. @@ -2186,9 +2191,9 @@ All the command-line flags can be obtained by running ``pytest --help``:: Enables the pytest_assertion_pass hook. Make sure to delete any previously generated pyc cache files. verbosity_assertions (string): - Specify a verbosity level for assertions, overriding the - main level. Higher levels will provide more detailed - explanation when an assertion fails. + Specify a verbosity level for assertions, overriding + the main level. Higher levels will provide more + detailed explanation when an assertion fails. junit_suite_name (string): Test suite name for JUnit report junit_logging (string): @@ -2210,8 +2215,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: log_format (string): Default value for --log-format log_date_format (string): Default value for --log-date-format - log_cli (bool): Enable log display during test run (also known as "live - logging") + log_cli (bool): Enable log display during test run (also known as + "live logging") log_cli_level (string): Default value for --log-cli-level log_cli_format (string): @@ -2231,18 +2236,16 @@ All the command-line flags can be obtained by running ``pytest --help``:: Default value for --log-auto-indent pythonpath (paths): Add paths to sys.path faulthandler_timeout (string): - Dump the traceback of all threads if a test takes more - than TIMEOUT seconds to finish + Dump the traceback of all threads if a test takes + more than TIMEOUT seconds to finish addopts (args): Extra command line options minversion (string): Minimally required pytest version required_plugins (args): Plugins that must be present for pytest to run - pytester_example_dir (string): - Directory to take the pytester example files from Environment variables: CI When set (regardless of value), pytest knows it is running in a CI process and does not truncate summary info - BUILD_NUMBER equivalent to CI + BUILD_NUMBER Equivalent to CI PYTEST_ADDOPTS Extra command line options PYTEST_PLUGINS Comma-separated plugins to load during startup PYTEST_DISABLE_PLUGIN_AUTOLOAD Set to disable plugin auto-loading From 908c77185e12c77b1c001b41f5c81cea91e3e3c9 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 21 Jul 2024 00:22:46 +0000 Subject: [PATCH 0813/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 126 ++++++++++++++++++------------- 1 file changed, 75 insertions(+), 51 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 7526b055943..8bdce41627b 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7; extra == "pytest" - :pypi:`nuts` Network Unit Testing System May 28, 2024 N/A pytest<8,>=7 + :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Feb 10, 2024 N/A pytest (>=6) @@ -111,7 +111,7 @@ This list contains 1487 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio May 19, 2024 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Jul 17, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -143,7 +143,7 @@ This list contains 1487 plugins. :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 - :pypi:`pytest-bazel` A pytest runner with bazel support Jul 12, 2024 4 - Beta pytest + :pypi:`pytest-bazel` A pytest runner with bazel support Jul 20, 2024 4 - Beta pytest :pypi:`pytest-bdd` BDD for pytest Jun 04, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 @@ -153,7 +153,7 @@ This list contains 1487 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jul 08, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jul 19, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -176,7 +176,7 @@ This list contains 1487 plugins. :pypi:`pytest-board` Local continuous test runner with pytest and watchdog. Jan 20, 2019 N/A N/A :pypi:`pytest-boost-xml` Plugin for pytest to generate boost xml reports Nov 30, 2022 4 - Beta N/A :pypi:`pytest-bootstrap` Mar 04, 2022 N/A N/A - :pypi:`pytest-boto-mock` Thin-wrapper around the mock package for easier use with pytest Jun 05, 2024 5 - Production/Stable pytest>=8.2.0 + :pypi:`pytest-boto-mock` Thin-wrapper around the mock package for easier use with pytest Jul 16, 2024 5 - Production/Stable pytest>=8.2.0 :pypi:`pytest-bpdb` A py.test plug-in to enable drop to bpdb debugger on test failure. Jan 19, 2015 2 - Pre-Alpha N/A :pypi:`pytest-bq` BigQuery fixtures and fixture factories for Pytest. May 08, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-bravado` Pytest-bravado automatically generates from OpenAPI specification client fixtures. Feb 15, 2022 N/A N/A @@ -210,7 +210,7 @@ This list contains 1487 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` Pytest plugin for Celery Apr 11, 2024 4 - Beta N/A + :pypi:`pytest-celery` Pytest plugin for Celery Jul 17, 2024 4 - Beta N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -436,7 +436,7 @@ This list contains 1487 plugins. :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 18, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A - :pypi:`pytest-duration-insights` Jun 25, 2021 N/A N/A + :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Apr 22, 2022 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Mar 12, 2024 5 - Production/Stable pytest @@ -523,6 +523,7 @@ This list contains 1487 plugins. :pypi:`pytest-failed-screenshot` Test case fails,take a screenshot,save it,attach it to the allure Apr 21, 2021 N/A N/A :pypi:`pytest-failed-to-verify` A pytest plugin that helps better distinguishing real test failures from setup flakiness. Aug 08, 2019 5 - Production/Stable pytest (>=4.1.0) :pypi:`pytest-fail-slow` Fail tests that take too long to run Jun 01, 2024 N/A pytest>=7.0 + :pypi:`pytest-failure-tracker` A pytest plugin for tracking test failures over multiple runs Jul 17, 2024 N/A pytest>=6.0.0 :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A :pypi:`pytest-falcon-client` A package to prevent Dependency Confusion attacks against Yandex. Feb 21, 2024 N/A N/A @@ -557,7 +558,7 @@ This list contains 1487 plugins. :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest - :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Mar 18, 2022 4 - Beta pytest (>=7.0) + :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Jul 19, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jul 10, 2023 5 - Production/Stable pytest :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) @@ -642,12 +643,12 @@ This list contains 1487 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 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 Jul 11, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 20, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 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. Jul 05, 2024 N/A pytest + :pypi:`pytest-houdini` pytest plugin for testing code in Houdini. Jul 15, 2024 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) @@ -665,7 +666,7 @@ This list contains 1487 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 24, 2024 3 - Alpha N/A + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Jul 19, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest May 08, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-httpx` Send responses to httpx. Feb 21, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -683,6 +684,7 @@ This list contains 1487 plugins. :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. Jul 01, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-import-check` pytest plugin to check whether Python modules can be imported Jul 19, 2024 3 - Alpha pytest>=8.1 :pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A :pypi:`pytest-infinity` Jun 09, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-influxdb` Plugin for influxdb and pytest integration. Apr 20, 2021 N/A N/A @@ -725,7 +727,7 @@ This list contains 1487 plugins. :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 30, 2024 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jul 09, 2024 N/A pytest>=7.2.0 - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Mar 27, 2024 4 - Beta pytest>=6.2.4 + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Jul 19, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -762,7 +764,7 @@ This list contains 1487 plugins. :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Mar 16, 2024 N/A pytest (>=7) + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Jul 17, 2024 N/A pytest>=7 :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A @@ -796,6 +798,7 @@ This list contains 1487 plugins. :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logikal` Common testing environment Jun 27, 2024 5 - Production/Stable pytest==8.2.2 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A + :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Jul 19, 2024 4 - Beta N/A :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers May 22, 2024 3 - Alpha pytest @@ -1043,7 +1046,7 @@ This list contains 1487 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 Jun 12, 2024 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Jul 15, 2024 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) @@ -1136,7 +1139,7 @@ This list contains 1487 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 :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. May 23, 2024 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest May 17, 2024 N/A pytest~=4.6; python_version == "2.7" + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jul 16, 2024 N/A pytest~=7.0 :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 @@ -1185,7 +1188,7 @@ This list contains 1487 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 08, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 19, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1195,7 +1198,7 @@ This list contains 1487 plugins. :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 Feb 01, 2024 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. Jul 08, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 19, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1205,7 +1208,7 @@ This list contains 1487 plugins. :pypi:`pytest-server` test server exec cmd Jun 24, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Jun 17, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-servers` pytest servers Jul 19, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-service` May 11, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest @@ -1288,7 +1291,7 @@ This list contains 1487 plugins. :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-static` pytest-static Jun 20, 2024 1 - Planning pytest<8.0.0,>=7.4.3 - :pypi:`pytest-stats` Collects tests metadata for future analysis, easy to extend for any data store Jul 03, 2024 N/A pytest>=8.0.0 + :pypi:`pytest-stats` Collects tests metadata for future analysis, easy to extend for any data store Jul 18, 2024 N/A pytest>=8.0.0 :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A @@ -1305,7 +1308,7 @@ This list contains 1487 plugins. :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 Jul 07, 2024 4 - Beta pytest>=7.0 + :pypi:`pytest-subtests` unittest subTest() support and subtests fixture Jul 17, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Feb 01, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A @@ -1365,7 +1368,7 @@ This list contains 1487 plugins. :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Jul 01, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Jul 17, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) @@ -1501,7 +1504,7 @@ This list contains 1487 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. Jul 03, 2024 4 - Beta pytest>=7.2.2 :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 12, 2024 N/A pytest>=7.4.0 + :pypi:`pytest-yaml-sanmu` Pytest plugin for generating test cases with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Jul 20, 2024 N/A pytest~=8.2.2 :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) @@ -1541,7 +1544,7 @@ This list contains 1487 plugins. Test whether your code is logging correctly 🪵 :pypi:`nuts` - *last release*: May 28, 2024, + *last release*: Jul 19, 2024, *status*: N/A, *requires*: pytest<8,>=7 @@ -2066,7 +2069,7 @@ This list contains 1487 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: May 19, 2024, + *last release*: Jul 17, 2024, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 @@ -2290,7 +2293,7 @@ This list contains 1487 plugins. A pytest plugin to repeat the entire test suite in batches. :pypi:`pytest-bazel` - *last release*: Jul 12, 2024, + *last release*: Jul 20, 2024, *status*: 4 - Beta, *requires*: pytest @@ -2360,7 +2363,7 @@ This list contains 1487 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jul 08, 2024, + *last release*: Jul 19, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2521,7 +2524,7 @@ This list contains 1487 plugins. :pypi:`pytest-boto-mock` - *last release*: Jun 05, 2024, + *last release*: Jul 16, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=8.2.0 @@ -2759,7 +2762,7 @@ This list contains 1487 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Apr 11, 2024, + *last release*: Jul 17, 2024, *status*: 4 - Beta, *requires*: N/A @@ -4341,7 +4344,7 @@ This list contains 1487 plugins. A pytest plugin for dumping test results to json. :pypi:`pytest-duration-insights` - *last release*: Jun 25, 2021, + *last release*: Jul 15, 2024, *status*: N/A, *requires*: N/A @@ -4949,6 +4952,13 @@ This list contains 1487 plugins. Fail tests that take too long to run + :pypi:`pytest-failure-tracker` + *last release*: Jul 17, 2024, + *status*: N/A, + *requires*: pytest>=6.0.0 + + A pytest plugin for tracking test failures over multiple runs + :pypi:`pytest-faker` *last release*: Dec 19, 2016, *status*: 6 - Mature, @@ -5188,9 +5198,9 @@ This list contains 1487 plugins. A pytest plugin to assert type annotations at runtime. :pypi:`pytest-flake8` - *last release*: Mar 18, 2022, - *status*: 4 - Beta, - *requires*: pytest (>=7.0) + *last release*: Jul 19, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=7.0 pytest plugin to check FLAKE8 requirements @@ -5783,7 +5793,7 @@ This list contains 1487 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jul 11, 2024, + *last release*: Jul 20, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 @@ -5818,7 +5828,7 @@ This list contains 1487 plugins. A plugin that tracks test changes :pypi:`pytest-houdini` - *last release*: Jul 05, 2024, + *last release*: Jul 15, 2024, *status*: N/A, *requires*: pytest @@ -5944,7 +5954,7 @@ This list contains 1487 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest_httpserver` - *last release*: Feb 24, 2024, + *last release*: Jul 19, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -6069,6 +6079,13 @@ This list contains 1487 plugins. A pytest plugin for image snapshot management and comparison. + :pypi:`pytest-import-check` + *last release*: Jul 19, 2024, + *status*: 3 - Alpha, + *requires*: pytest>=8.1 + + pytest plugin to check whether Python modules can be imported + :pypi:`pytest-incremental` *last release*: Apr 24, 2021, *status*: 5 - Production/Stable, @@ -6364,7 +6381,7 @@ This list contains 1487 plugins. Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: Mar 27, 2024, + *last release*: Jul 19, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.4 @@ -6623,9 +6640,9 @@ This list contains 1487 plugins. It helps to use fixtures in pytest.mark.parametrize :pypi:`pytest-lazy-fixtures` - *last release*: Mar 16, 2024, + *last release*: Jul 17, 2024, *status*: N/A, - *requires*: pytest (>=7) + *requires*: pytest>=7 Allows you to use fixtures in @pytest.mark.parametrize. @@ -6860,6 +6877,13 @@ This list contains 1487 plugins. Package for creating a pytest test run reprot + :pypi:`pytest-logscanner` + *last release*: Jul 19, 2024, + *status*: 4 - Beta, + *requires*: N/A + + Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) + :pypi:`pytest-loguru` *last release*: Mar 20, 2024, *status*: 5 - Production/Stable, @@ -8590,7 +8614,7 @@ This list contains 1487 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Jun 12, 2024, + *last release*: Jul 15, 2024, *status*: N/A, *requires*: pytest @@ -9241,9 +9265,9 @@ This list contains 1487 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: May 17, 2024, + *last release*: Jul 16, 2024, *status*: N/A, - *requires*: pytest~=4.6; python_version == "2.7" + *requires*: pytest~=7.0 Resilient Circuits fixtures for PyTest @@ -9584,7 +9608,7 @@ This list contains 1487 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jul 08, 2024, + *last release*: Jul 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9654,7 +9678,7 @@ This list contains 1487 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jul 08, 2024, + *last release*: Jul 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9724,7 +9748,7 @@ This list contains 1487 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Jun 17, 2024, + *last release*: Jul 19, 2024, *status*: 3 - Alpha, *requires*: pytest>=6.2 @@ -10305,7 +10329,7 @@ This list contains 1487 plugins. pytest-static :pypi:`pytest-stats` - *last release*: Jul 03, 2024, + *last release*: Jul 18, 2024, *status*: N/A, *requires*: pytest>=8.0.0 @@ -10424,7 +10448,7 @@ This list contains 1487 plugins. A hack to explicitly set up and tear down fixtures. :pypi:`pytest-subtests` - *last release*: Jul 07, 2024, + *last release*: Jul 17, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0 @@ -10844,7 +10868,7 @@ This list contains 1487 plugins. A plugin that allows coll test data for use on Test Tracer :pypi:`pytest-test-tracer-for-pytest-bdd` - *last release*: Jul 01, 2024, + *last release*: Jul 17, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -11796,11 +11820,11 @@ This list contains 1487 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Jul 12, 2024, + *last release*: Jul 20, 2024, *status*: N/A, - *requires*: pytest>=7.4.0 + *requires*: pytest~=8.2.2 - pytest plugin for generating test cases by yaml + Pytest plugin for generating test cases with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. :pypi:`pytest-yamltree` *last release*: Mar 02, 2020, From 82b297cf22f62d9129a91d6413d86d0ed9c53505 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 21 Jul 2024 09:23:51 +0300 Subject: [PATCH 0814/1271] doc/changelog: update user tag --- doc/en/changelog.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index f6aefbd3b13..083d30abf86 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -55,6 +55,8 @@ New features This change detaches xfail tracebacks from `-rx`, and now we turn on xfail tracebacks with `--xfail-tb`. With this, the default `-rx`/ `-ra` behavior is identical to pre-8.0 with respect to xfail tracebacks. While this is a behavior change, it brings default behavior back to pre-8.0.0 behavior, which ultimately was considered the better course of action. + -- by :user:`okken` + - `#12281 `_: Added support for keyword matching in marker expressions. From 1590cfb7a5f89d18a137cd0fd217c9a026e22666 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 09:34:06 -0300 Subject: [PATCH 0815/1271] build(deps): Bump hynek/build-and-inspect-python-package (#12643) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.6.0 to 2.7.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.6.0...v2.7.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f5ea4d39764..3718d180f94 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.6.0 + uses: hynek/build-and-inspect-python-package@v2.7.0 with: attest-build-provenance-github: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9158d6bcc72..b2fb5131221 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.6.0 + uses: hynek/build-and-inspect-python-package@v2.7.0 build: needs: [package] From 643845feb76f99d7619655609e34e78b6a628b32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:08:16 -0300 Subject: [PATCH 0816/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#12644) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.7 to 0.23.8. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.7...v0.23.8) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 4c1efcf32ed..cdb3e7264a0 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.4.0 django==5.0.7 -pytest-asyncio==0.23.7 +pytest-asyncio==0.23.8 pytest-bdd==7.2.0 pytest-cov==5.0.0 pytest-django==4.8.0 From 51c40c4f4aaf6a17e1db3c0628b76a4773bdfdb6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 22:33:00 +0000 Subject: [PATCH 0817/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.2 → v0.5.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.2...v0.5.4) - [github.com/pre-commit/mirrors-mypy: v1.10.1 → v1.11.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.10.1...v1.11.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 419addd95be..79697cf1caa 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.2" + rev: "v0.5.4" hooks: - id: ruff args: ["--fix"] @@ -21,7 +21,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.1 + rev: v1.11.0 hooks: - id: mypy files: ^(src/|testing/|scripts/) From 69a4a71ef07097a511bf3ddd4385f9840112d492 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 23 Jul 2024 09:57:35 -0300 Subject: [PATCH 0818/1271] Adapt code after updating to mypy 1.11 --- src/_pytest/_io/pprint.py | 4 ++-- src/_pytest/capture.py | 1 + src/_pytest/faulthandler.py | 1 + testing/test_assertion.py | 2 +- testing/test_monkeypatch.py | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 7213be7ba9b..fc29989be0b 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -111,7 +111,7 @@ def _format( p(self, object, stream, indent, allowance, context, level + 1) context.remove(objid) elif ( - _dataclasses.is_dataclass(object) + _dataclasses.is_dataclass(object) # type:ignore[unreachable] and not isinstance(object, type) and object.__dataclass_params__.repr and @@ -119,7 +119,7 @@ def _format( hasattr(object.__repr__, "__wrapped__") and "__create_fn__" in object.__repr__.__wrapped__.__qualname__ ): - context.add(objid) + context.add(objid) # type:ignore[unreachable] self._pprint_dataclass( object, stream, indent, allowance, context, level + 1 ) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index c4dfcc27552..b9652843279 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -202,6 +202,7 @@ def write(self, s: str) -> int: class DontReadFromInput(TextIO): @property def encoding(self) -> str: + assert sys.__stdin__ is not None return sys.__stdin__.encoding def read(self, size: int = -1) -> str: diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index 07e60f03fc9..d16aea1eb88 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -64,6 +64,7 @@ def get_stderr_fileno() -> int: # pytest-xdist monkeypatches sys.stderr with an object that is not an actual file. # https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors # This is potentially dangerous, but the best we can do. + assert sys.__stderr__ is not None return sys.__stderr__.fileno() diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 69ca0f73ff2..31192df0f6f 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -823,7 +823,7 @@ def __setitem__(self, item, value): def __delitem__(self, item): pass - def insert(self, item, index): + def insert(self, index, value): pass expl = callequal(TestSequence([0, 1]), list([0, 2])) diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 079d8ff60ad..944d91f6e65 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -415,7 +415,7 @@ def test_context() -> None: with monkeypatch.context() as m: m.setattr(functools, "partial", 3) assert not inspect.isclass(functools.partial) - assert inspect.isclass(functools.partial) + assert inspect.isclass(functools.partial) # type:ignore[unreachable] def test_context_classmethod() -> None: From b3ddf7cddcb3616fda302d773443ca51d9b14fe9 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 23 Jul 2024 20:23:32 +0200 Subject: [PATCH 0819/1271] Revert "doc: Add changing RTD version to checklist (#9606)" This reverts commit 77a38a3b754e6a82332a1f7bd11bc684c345af28. --- RELEASING.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/RELEASING.rst b/RELEASING.rst index 08004a84c00..030a5c8652f 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -158,8 +158,6 @@ Both automatic and manual processes described above follow the same steps from t git tag MAJOR.{MINOR+1}.0.dev0 git push upstream MAJOR.{MINOR+1}.0.dev0 -#. For major and minor releases, change the default version in the `Read the Docs Settings `_ to the new branch. - #. Send an email announcement with the contents from:: doc/en/announce/release-.rst From d0f7884a1d11ac08a20af3ddf0a17bc4990c4784 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 23 Jul 2024 23:43:59 +0200 Subject: [PATCH 0820/1271] explicitly detect conda envs - fixes #12652 initially we accidentially detected conda environmnts by just testing too many files after steamlining we no longer detected conda environments now we explicitly detect conda environments and test for support --- changelog/12652.bugfix.rst | 4 ++++ src/_pytest/main.py | 13 +++++++++++-- testing/test_collection.py | 28 ++++++++++++++++++++-------- 3 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 changelog/12652.bugfix.rst diff --git a/changelog/12652.bugfix.rst b/changelog/12652.bugfix.rst new file mode 100644 index 00000000000..78398212ceb --- /dev/null +++ b/changelog/12652.bugfix.rst @@ -0,0 +1,4 @@ +Resolve the regression in conda environment detection by +explicitly expanding virtualenv detection to conda environents + +-- by :user:`RonnyPfannschmidt` diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 8ec26906003..0ec3377163e 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -370,9 +370,18 @@ def pytest_runtestloop(session: Session) -> bool: def _in_venv(path: Path) -> bool: """Attempt to detect if ``path`` is the root of a Virtual Environment by checking for the existence of the pyvenv.cfg file. - [https://peps.python.org/pep-0405/]""" + + [https://peps.python.org/pep-0405/] + + for regression protection we also check for conda environments that do not include pyenv.cfg yet + https://github.com/conda/conda/issues/13337 is the conda issue tracking adding pyenv.cfg + + """ try: - return path.joinpath("pyvenv.cfg").is_file() + return ( + path.joinpath("pyvenv.cfg").is_file() + or path.joinpath("conda-meta", "history").is_file() + ) except OSError: return False diff --git a/testing/test_collection.py b/testing/test_collection.py index f5822240335..aba8f8ea48d 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -3,6 +3,7 @@ import os from pathlib import Path +from pathlib import PurePath import pprint import shutil import sys @@ -152,8 +153,17 @@ def test_ignored_certain_directories(self, pytester: Pytester) -> None: assert "test_notfound" not in s assert "test_found" in s - def test_ignored_virtualenvs(self, pytester: Pytester) -> None: - ensure_file(pytester.path / "virtual" / "pyvenv.cfg") + known_environment_types = pytest.mark.parametrize( + "env_path", + [ + pytest.param(PurePath("pyvenv.cfg"), id="venv"), + pytest.param(PurePath("conda-meta", "history"), id="conda"), + ], + ) + + @known_environment_types + def test_ignored_virtualenvs(self, pytester: Pytester, env_path: PurePath) -> None: + ensure_file(pytester.path / "virtual" / env_path) testfile = ensure_file(pytester.path / "virtual" / "test_invenv.py") testfile.write_text("def test_hello(): pass", encoding="utf-8") @@ -167,11 +177,12 @@ def test_ignored_virtualenvs(self, pytester: Pytester) -> None: result = pytester.runpytest("virtual") assert "test_invenv" in result.stdout.str() + @known_environment_types def test_ignored_virtualenvs_norecursedirs_precedence( - self, pytester: Pytester + self, pytester: Pytester, env_path ) -> None: # norecursedirs takes priority - ensure_file(pytester.path / ".virtual" / "pyvenv.cfg") + ensure_file(pytester.path / ".virtual" / env_path) testfile = ensure_file(pytester.path / ".virtual" / "test_invenv.py") testfile.write_text("def test_hello(): pass", encoding="utf-8") result = pytester.runpytest("--collect-in-virtualenv") @@ -180,13 +191,14 @@ def test_ignored_virtualenvs_norecursedirs_precedence( result = pytester.runpytest("--collect-in-virtualenv", ".virtual") assert "test_invenv" in result.stdout.str() - def test__in_venv(self, pytester: Pytester) -> None: + @known_environment_types + def test__in_venv(self, pytester: Pytester, env_path: PurePath) -> None: """Directly test the virtual env detection function""" - # no pyvenv.cfg, not a virtualenv + # no env path, not a env base_path = pytester.mkdir("venv") assert _in_venv(base_path) is False - # with pyvenv.cfg, totally a virtualenv - base_path.joinpath("pyvenv.cfg").touch() + # with env path, totally a env + ensure_file(base_path.joinpath(env_path)) assert _in_venv(base_path) is True def test_custom_norecursedirs(self, pytester: Pytester) -> None: From fa915f6aa8e5c5aa223efd23b44248cf4e6e4582 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Wed, 24 Jul 2024 07:48:58 +0200 Subject: [PATCH 0821/1271] Apply suggestions from code review Co-authored-by: Bruno Oliveira --- changelog/12652.bugfix.rst | 3 +-- src/_pytest/main.py | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/changelog/12652.bugfix.rst b/changelog/12652.bugfix.rst index 78398212ceb..da7644df06d 100644 --- a/changelog/12652.bugfix.rst +++ b/changelog/12652.bugfix.rst @@ -1,4 +1,3 @@ -Resolve the regression in conda environment detection by -explicitly expanding virtualenv detection to conda environents +Resolve regression `conda` environments where no longer being automatically detected. -- by :user:`RonnyPfannschmidt` diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 0ec3377163e..226693805f7 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -373,8 +373,10 @@ def _in_venv(path: Path) -> bool: [https://peps.python.org/pep-0405/] - for regression protection we also check for conda environments that do not include pyenv.cfg yet - https://github.com/conda/conda/issues/13337 is the conda issue tracking adding pyenv.cfg + For regression protection we also check for conda environments that do not include pyenv.cfg yet -- + https://github.com/conda/conda/issues/13337 is the conda issue tracking adding pyenv.cfg. + + Checking for the `conda-meta/history` file per https://github.com/pytest-dev/pytest/issues/12652#issuecomment-2246336902. """ try: From 1f7c917f07716d861235770e0eeef642c0bddf33 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 05:51:11 +0000 Subject: [PATCH 0822/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 226693805f7..befc7ccce6e 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -373,9 +373,9 @@ def _in_venv(path: Path) -> bool: [https://peps.python.org/pep-0405/] - For regression protection we also check for conda environments that do not include pyenv.cfg yet -- + For regression protection we also check for conda environments that do not include pyenv.cfg yet -- https://github.com/conda/conda/issues/13337 is the conda issue tracking adding pyenv.cfg. - + Checking for the `conda-meta/history` file per https://github.com/pytest-dev/pytest/issues/12652#issuecomment-2246336902. """ From d0a904faa4acbada493a8b2961e50c57a823e0c4 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 28 Jul 2024 00:23:08 +0000 Subject: [PATCH 0823/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 128 +++++++++++++++++-------------- 1 file changed, 72 insertions(+), 56 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 8bdce41627b..4cec461b9eb 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jul 10, 2024 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jul 24, 2024 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -123,17 +123,18 @@ This list contains 1490 plugins. :pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A :pypi:`pytest-autocap` automatically capture test & fixture stdout/stderr to files May 15, 2022 N/A pytest (<7.2,>=7.1.2) :pypi:`pytest-autochecklog` automatically check condition and log all the checks Apr 25, 2015 4 - Beta N/A + :pypi:`pytest-auto-fixture` ... Jul 23, 2024 N/A pytest>=8 :pypi:`pytest-automation` pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. Apr 24, 2024 N/A pytest>=7.0.0 :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest - :pypi:`pytest-aux` templates/examples and aux for pytest Jul 05, 2024 N/A N/A + :pypi:`pytest-aux` templates/examples and aux for pytest Jul 26, 2024 N/A N/A :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 24, 2024 4 - Beta pytest :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A - :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Feb 02, 2024 N/A pytest (>=8.0.0,<9.0.0) + :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Jul 25, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest @@ -153,7 +154,7 @@ This list contains 1490 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jul 19, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jul 25, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -453,7 +454,7 @@ This list contains 1490 plugins. :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 15, 2024 5 - Production/Stable pytest >=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) - :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Apr 04, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jul 25, 2024 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. May 31, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. May 23, 2024 5 - Production/Stable N/A @@ -558,7 +559,7 @@ This list contains 1490 plugins. :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest - :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Jul 19, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Jul 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jul 10, 2023 5 - Production/Stable pytest :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) @@ -624,7 +625,7 @@ This list contains 1490 plugins. :pypi:`pytest-group-by-class` A Pytest plugin for running a subset of your tests by splitting them in to groups of classes. Jun 27, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-growl` Growl notifications for pytest results. Jan 13, 2014 5 - Production/Stable N/A :pypi:`pytest-grpc` pytest plugin for grpc May 01, 2020 N/A pytest (>=3.6.0) - :pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Feb 05, 2023 N/A N/A + :pypi:`pytest-grunnur` Py.Test plugin for Grunnur-based packages. Jul 26, 2024 N/A pytest>=6 :pypi:`pytest_gui_status` Show pytest status in gui Jan 23, 2016 N/A pytest :pypi:`pytest-hammertime` Display "🔨 " instead of "." for passed pytest tests. Jul 28, 2018 N/A pytest :pypi:`pytest-hardware-test-report` A simple plugin to use with pytest Apr 01, 2024 4 - Beta pytest<9.0.0,>=8.0.0 @@ -666,15 +667,15 @@ This list contains 1490 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Jul 19, 2024 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest May 08, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Jul 21, 2024 3 - Alpha N/A + :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 25, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-httpx` Send responses to httpx. Feb 21, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Apr 22, 2024 3 - Alpha pytest>=7.0.0 + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Jul 25, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A @@ -696,8 +697,8 @@ This list contains 1490 plugins. :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :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. Jul 05, 2024 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 05, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Jul 06, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Jul 24, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest @@ -714,7 +715,7 @@ This list contains 1490 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Jul 11, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Jul 23, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -738,7 +739,7 @@ This list contains 1490 plugins. :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-jtr` pytest plugin supporting json test report output Jun 04, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-jtr` pytest plugin supporting json test report output Jul 21, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest @@ -764,7 +765,7 @@ This list contains 1490 plugins. :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Jul 17, 2024 N/A pytest>=7 + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Jul 22, 2024 N/A pytest>=7 :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A @@ -825,7 +826,7 @@ This list contains 1490 plugins. :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Feb 15, 2024 N/A pytest (>=7.4.3) :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A - :pypi:`pytest-memray` A simple plugin to use with pytest Apr 18, 2024 N/A pytest>=7.2 + :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) @@ -1046,7 +1047,7 @@ This list contains 1490 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 Jul 15, 2024 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Jul 23, 2024 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) @@ -1127,6 +1128,7 @@ This list contains 1490 plugins. :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Mar 27, 2024 N/A pytest>=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A + :pypi:`pytest-req` pytest requests plugin Jul 26, 2024 N/A pytest<9.0.0,>=8.3.1 :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A @@ -1138,7 +1140,7 @@ This list contains 1490 plugins. :pypi:`pytest-rerunclassfailures` pytest rerun class failures plugin Apr 24, 2024 5 - Production/Stable pytest>=7.2 :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 :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. May 23, 2024 4 - Beta pytest + :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Jul 23, 2024 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jul 16, 2024 N/A pytest~=7.0 :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) @@ -1170,7 +1172,7 @@ This list contains 1490 plugins. :pypi:`pytest-rst` Test code from RST documents with pytest Jan 26, 2023 N/A N/A :pypi:`pytest-rt` pytest data collector plugin for Testgr May 05, 2022 N/A N/A :pypi:`pytest-rts` Coverage-based regression test selection (RTS) plugin for pytest May 17, 2021 N/A pytest - :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 09, 2024 4 - Beta pytest>=5 + :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 21, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest @@ -1188,7 +1190,7 @@ This list contains 1490 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 26, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1198,7 +1200,7 @@ This list contains 1490 plugins. :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 Feb 01, 2024 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. Jul 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jul 26, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1276,7 +1278,7 @@ This list contains 1490 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 Jul 11, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Jul 24, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jul 10, 2024 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 @@ -1300,13 +1302,13 @@ This list contains 1490 plugins. :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) - :pypi:`pytest-structlog` Structured logging assertions Jun 09, 2024 N/A pytest + :pypi:`pytest-structlog` Structured logging assertions Jul 25, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A :pypi:`pytest-stub` Stub packages, modules and attributes. Apr 28, 2020 5 - Production/Stable N/A :pypi:`pytest-stubprocess` Provide stub implementations for subprocesses in Python tests Sep 17, 2018 3 - Alpha pytest (>=3.5.0) :pypi:`pytest-study` A pytest plugin to organize long run tests (named studies) without interfering the regular tests Sep 26, 2017 3 - Alpha pytest (>=2.0) :pypi:`pytest-subinterpreter` Run pytest in a subinterpreter Nov 25, 2023 N/A pytest>=7.0.0 - :pypi:`pytest-subprocess` A plugin to fake subprocess for pytest Jan 28, 2023 5 - Production/Stable pytest (>=4.0.0) + :pypi:`pytest-subprocess` A plugin to fake subprocess for pytest Jul 24, 2024 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 Jul 17, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) @@ -1371,7 +1373,7 @@ This list contains 1490 plugins. :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Jul 17, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 - :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Aug 23, 2023 4 - Beta pytest (>=7.0.0) + :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 22, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-tf` Test your OpenTofu and Terraform config using a PyTest plugin May 29, 2024 N/A pytest<9.0.0,>=8.2.1 :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A @@ -1810,7 +1812,7 @@ This list contains 1490 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Jul 10, 2024, + *last release*: Jul 24, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2152,6 +2154,13 @@ This list contains 1490 plugins. automatically check condition and log all the checks + :pypi:`pytest-auto-fixture` + *last release*: Jul 23, 2024, + *status*: N/A, + *requires*: pytest>=8 + + ... + :pypi:`pytest-automation` *last release*: Apr 24, 2024, *status*: N/A, @@ -2181,7 +2190,7 @@ This list contains 1490 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: Jul 05, 2024, + *last release*: Jul 26, 2024, *status*: N/A, *requires*: N/A @@ -2223,9 +2232,9 @@ This list contains 1490 plugins. Protect your AWS credentials in unit tests :pypi:`pytest-aws-fixtures` - *last release*: Feb 02, 2024, + *last release*: Jul 25, 2024, *status*: N/A, - *requires*: pytest (>=8.0.0,<9.0.0) + *requires*: pytest<9.0.0,>=8.0.0 A series of fixtures to use in integration tests involving actual AWS services. @@ -2363,7 +2372,7 @@ This list contains 1490 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jul 19, 2024, + *last release*: Jul 25, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -4463,7 +4472,7 @@ This list contains 1490 plugins. An eliot plugin for pytest. :pypi:`pytest-elk-reporter` - *last release*: Apr 04, 2024, + *last release*: Jul 25, 2024, *status*: 4 - Beta, *requires*: pytest>=3.5.0 @@ -5198,7 +5207,7 @@ This list contains 1490 plugins. A pytest plugin to assert type annotations at runtime. :pypi:`pytest-flake8` - *last release*: Jul 19, 2024, + *last release*: Jul 21, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -5660,9 +5669,9 @@ This list contains 1490 plugins. pytest plugin for grpc :pypi:`pytest-grunnur` - *last release*: Feb 05, 2023, + *last release*: Jul 26, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest>=6 Py.Test plugin for Grunnur-based packages. @@ -5954,14 +5963,14 @@ This list contains 1490 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest_httpserver` - *last release*: Jul 19, 2024, + *last release*: Jul 21, 2024, *status*: 3 - Alpha, *requires*: N/A pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: May 08, 2024, + *last release*: Jul 25, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -6010,8 +6019,8 @@ This list contains 1490 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Apr 22, 2024, - *status*: 3 - Alpha, + *last release*: Jul 25, 2024, + *status*: 4 - Beta, *requires*: pytest>=7.0.0 A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite @@ -6164,14 +6173,14 @@ This list contains 1490 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Jul 05, 2024, + *last release*: Jul 22, 2024, *status*: 5 - Production/Stable, *requires*: N/A Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Jul 06, 2024, + *last release*: Jul 24, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6290,7 +6299,7 @@ This list contains 1490 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Jul 11, 2024, + *last release*: Jul 23, 2024, *status*: N/A, *requires*: pytest @@ -6458,7 +6467,7 @@ This list contains 1490 plugins. A pytest plugin to perform JSONSchema validations :pypi:`pytest-jtr` - *last release*: Jun 04, 2024, + *last release*: Jul 21, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -6640,7 +6649,7 @@ This list contains 1490 plugins. It helps to use fixtures in pytest.mark.parametrize :pypi:`pytest-lazy-fixtures` - *last release*: Jul 17, 2024, + *last release*: Jul 22, 2024, *status*: N/A, *requires*: pytest>=7 @@ -7067,7 +7076,7 @@ This list contains 1490 plugins. Estimates memory consumption of test functions :pypi:`pytest-memray` - *last release*: Apr 18, 2024, + *last release*: Jul 25, 2024, *status*: N/A, *requires*: pytest>=7.2 @@ -8614,7 +8623,7 @@ This list contains 1490 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Jul 15, 2024, + *last release*: Jul 23, 2024, *status*: N/A, *requires*: pytest @@ -9180,6 +9189,13 @@ This list contains 1490 plugins. Pytest Repo Structure + :pypi:`pytest-req` + *last release*: Jul 26, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.3.1 + + pytest requests plugin + :pypi:`pytest-reqs` *last release*: May 12, 2019, *status*: N/A, @@ -9258,7 +9274,7 @@ This list contains 1490 plugins. pytest plugin to re-run tests to eliminate flaky failures :pypi:`pytest-reserial` - *last release*: May 23, 2024, + *last release*: Jul 23, 2024, *status*: 4 - Beta, *requires*: pytest @@ -9482,7 +9498,7 @@ This list contains 1490 plugins. Coverage-based regression test selection (RTS) plugin for pytest :pypi:`pytest-ruff` - *last release*: Jul 09, 2024, + *last release*: Jul 21, 2024, *status*: 4 - Beta, *requires*: pytest>=5 @@ -9608,7 +9624,7 @@ This list contains 1490 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jul 19, 2024, + *last release*: Jul 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9678,7 +9694,7 @@ This list contains 1490 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jul 19, 2024, + *last release*: Jul 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10224,7 +10240,7 @@ This list contains 1490 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jul 11, 2024, + *last release*: Jul 24, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10392,7 +10408,7 @@ This list contains 1490 plugins. A Pytest plugin that allows you to loop tests for a user defined amount of time. :pypi:`pytest-structlog` - *last release*: Jun 09, 2024, + *last release*: Jul 25, 2024, *status*: N/A, *requires*: pytest @@ -10434,9 +10450,9 @@ This list contains 1490 plugins. Run pytest in a subinterpreter :pypi:`pytest-subprocess` - *last release*: Jan 28, 2023, + *last release*: Jul 24, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.0.0) + *requires*: pytest>=4.0.0 A plugin to fake subprocess for pytest @@ -10889,9 +10905,9 @@ This list contains 1490 plugins. Tesults plugin for pytest :pypi:`pytest-textual-snapshot` - *last release*: Aug 23, 2023, + *last release*: Jul 22, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.0.0) + *requires*: pytest>=8.0.0 Snapshot testing for Textual apps From 3594adc066ab33dcfcc1bce5276b29266613a83b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 05:52:48 +0200 Subject: [PATCH 0824/1271] build(deps): Bump hynek/build-and-inspect-python-package (#12666) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.7.0 to 2.8.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.7.0...v2.8.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3718d180f94..34a0b25c63c 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.7.0 + uses: hynek/build-and-inspect-python-package@v2.8.0 with: attest-build-provenance-github: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b2fb5131221..83a3d9cb33e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.7.0 + uses: hynek/build-and-inspect-python-package@v2.8.0 build: needs: [package] From 7ce3222764193feb581abfea58f8920b36e259de Mon Sep 17 00:00:00 2001 From: Stefaan Lippens Date: Mon, 29 Jul 2024 13:46:39 +0200 Subject: [PATCH 0825/1271] Make TerminalReporter public API and add to reference docs #6649 (#12661) Fixes #6649 --- changelog/6649.doc.rst | 1 + changelog/6649.misc.rst | 1 + doc/en/reference/reference.rst | 7 +++++++ src/_pytest/terminal.py | 2 +- src/pytest/__init__.py | 2 ++ 5 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 changelog/6649.doc.rst create mode 100644 changelog/6649.misc.rst diff --git a/changelog/6649.doc.rst b/changelog/6649.doc.rst new file mode 100644 index 00000000000..cf5bb781b87 --- /dev/null +++ b/changelog/6649.doc.rst @@ -0,0 +1 @@ +Added :class:`~pytest.TerminalReporter` to the :ref:`api-reference` documentation page. diff --git a/changelog/6649.misc.rst b/changelog/6649.misc.rst new file mode 100644 index 00000000000..cec8c3f4506 --- /dev/null +++ b/changelog/6649.misc.rst @@ -0,0 +1 @@ +Added :class:`~pytest.TerminalReporter` to the public pytest API, as it is part of the signature of the :hook:`pytest_terminal_summary` hook. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 099c8a00260..3a5063b6b58 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1013,6 +1013,13 @@ PytestPluginManager :inherited-members: :show-inheritance: +TerminalReporter +~~~~~~~~~~~~~~~~ + +.. autoclass:: pytest.TerminalReporter + :members: + :inherited-members: + TestReport ~~~~~~~~~~ diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 8c722124d04..cdda5a90ea1 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1340,7 +1340,7 @@ def build_summary_stats_line(self) -> tuple[list[tuple[str, dict[str, bool]]], s The summary stats line is the line shown at the end, "=== 12 passed, 2 errors in Xs===". This function builds a list of the "parts" that make up for the text in that line, in - the example above it would be: + the example above it would be:: [ ("12 passed", {"green": True}), diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 90abcdab036..92152b7c7b4 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -68,6 +68,7 @@ from _pytest.runner import CallInfo from _pytest.stash import Stash from _pytest.stash import StashKey +from _pytest.terminal import TerminalReporter from _pytest.terminal import TestShortLogReport from _pytest.tmpdir import TempPathFactory from _pytest.warning_types import PytestAssertRewriteWarning @@ -161,6 +162,7 @@ "version_tuple", "TempdirFactory", "TempPathFactory", + "TerminalReporter", "Testdir", "TestReport", "TestShortLogReport", From 8509fe8be58ea1c093b4b0ac89382bfdacea0083 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 07:25:50 +0200 Subject: [PATCH 0826/1271] [pre-commit.ci] pre-commit autoupdate (#12669) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.4 → v0.5.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.4...v0.5.5) - [github.com/asottile/pyupgrade: v3.16.0 → v3.17.0](https://github.com/asottile/pyupgrade/compare/v3.16.0...v3.17.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 79697cf1caa..aaa28d6b7c4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.4" + rev: "v0.5.5" hooks: - id: ruff args: ["--fix"] @@ -44,7 +44,7 @@ repos: # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version additional_dependencies: ["tox>=4.9"] - repo: https://github.com/asottile/pyupgrade - rev: v3.16.0 + rev: v3.17.0 hooks: - id: pyupgrade stages: [manual] From cd0dd3c9787a2bd1c5a91c911679b1c1e8531afc Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 31 Jul 2024 16:49:04 -0300 Subject: [PATCH 0827/1271] Pin towncrier due to incompatibility with sphinxcontrib-towncrier Pin `towncrier` until we find a solution to https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92. --- doc/en/broken-dep-constraints.txt | 6 ++++++ doc/en/requirements.txt | 1 + 2 files changed, 7 insertions(+) create mode 100644 doc/en/broken-dep-constraints.txt diff --git a/doc/en/broken-dep-constraints.txt b/doc/en/broken-dep-constraints.txt new file mode 100644 index 00000000000..f7c3211a9a0 --- /dev/null +++ b/doc/en/broken-dep-constraints.txt @@ -0,0 +1,6 @@ +# This file contains transitive dependencies that need to be pinned for some reason. +# Eventually this file will be empty, but in this case keep it around for future use. + +# Pin towncrier temporarily due to incompatibility with sphinxcontrib-towncrier: +# https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 +towncrier!=24.7.0,!=24.7.1 diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 0637c967b8a..42225057e2b 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -1,3 +1,4 @@ +-c broken-dep-constraints.txt pluggy>=1.5.0 pygments-pytest>=2.3.0 sphinx-removed-in>=0.2.0 From 303e5c51b9bfaa9d699f8852feaf70029ac5ecdc Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 31 Jul 2024 16:51:27 -0300 Subject: [PATCH 0828/1271] Remove explicit package dependency package was previously an explicit dependency because it was pinned in https://github.com/pytest-dev/pytest/pull/10578, however since then the pin has been removed, so the explicit dependency is no longer necessary. --- doc/en/requirements.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/en/requirements.txt b/doc/en/requirements.txt index 42225057e2b..ddcb7efb99b 100644 --- a/doc/en/requirements.txt +++ b/doc/en/requirements.txt @@ -5,10 +5,6 @@ sphinx-removed-in>=0.2.0 sphinx>=7 sphinxcontrib-trio sphinxcontrib-svg2pdfconverter -# Pin packaging because it no longer handles 'latest' version, which -# is the version that is assigned to the docs. -# See https://github.com/pytest-dev/pytest/pull/10578#issuecomment-1348249045. -packaging furo sphinxcontrib-towncrier sphinx-issues From c6c7ade7aa827329fb1531fbeff969c244dc2fec Mon Sep 17 00:00:00 2001 From: Rob Arrow Date: Thu, 1 Aug 2024 16:07:57 +0100 Subject: [PATCH 0829/1271] Remove quotes from example tmp_path_retention_policy Previously the docs contained an example for `tmp_path_retention_policy` which included quotes around the value. If the configuration was actually set with this value. The following error would be encountered `INTERNALERROR> ValueError: tmp_path_retention_policy must be either all, failed, none. Current input: "all".` This is because the value of the field was not being unwrapped from the quotes when parsed. This commit removes the quotes from the example so that if used in the configuration file, no error will occur. --- AUTHORS | 1 + changelog/12678.doc.rst | 1 + doc/en/reference/reference.rst | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/12678.doc.rst diff --git a/AUTHORS b/AUTHORS index 9b6cb6a9d23..8103a1d52a5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -351,6 +351,7 @@ Rafal Semik Raquel Alegre Ravi Chandra Reagan Lee +Rob Arrow Robert Holt Roberto Aldera Roberto Polli diff --git a/changelog/12678.doc.rst b/changelog/12678.doc.rst new file mode 100644 index 00000000000..9d79ec41007 --- /dev/null +++ b/changelog/12678.doc.rst @@ -0,0 +1 @@ +Remove erroneous quotes from `tmp_path_retention_policy` example in docs. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 3a5063b6b58..7ea5921f581 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1873,7 +1873,7 @@ passed multiple times. The expected format is ``name=value``. For example:: .. code-block:: ini [pytest] - tmp_path_retention_policy = "all" + tmp_path_retention_policy = all Default: ``all`` From 90d70465ef2a09415a2d6ee7211d8dbc1e0c8650 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Thu, 1 Aug 2024 23:41:31 +0200 Subject: [PATCH 0830/1271] Merge pull request #12660 from pytest-dev/release-8.3.2 (cherry picked from commit 7b62fef8e15b58eaf5a6c8a201feeb97592df0aa) --- changelog/12652.bugfix.rst | 3 --- doc/en/announce/index.rst | 1 + doc/en/announce/release-8.3.2.rst | 19 +++++++++++++++++++ doc/en/changelog.rst | 11 +++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 8 files changed, 38 insertions(+), 10 deletions(-) delete mode 100644 changelog/12652.bugfix.rst create mode 100644 doc/en/announce/release-8.3.2.rst diff --git a/changelog/12652.bugfix.rst b/changelog/12652.bugfix.rst deleted file mode 100644 index da7644df06d..00000000000 --- a/changelog/12652.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Resolve regression `conda` environments where no longer being automatically detected. - --- by :user:`RonnyPfannschmidt` diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 429cb8249a1..09311a1a1ab 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.3.2 release-8.3.1 release-8.3.0 release-8.2.2 diff --git a/doc/en/announce/release-8.3.2.rst b/doc/en/announce/release-8.3.2.rst new file mode 100644 index 00000000000..1e4a071692c --- /dev/null +++ b/doc/en/announce/release-8.3.2.rst @@ -0,0 +1,19 @@ +pytest-8.3.2 +======================================= + +pytest 8.3.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Ran Benita +* Ronny Pfannschmidt + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 083d30abf86..3178f82044d 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,17 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.3.2 (2024-07-24) +========================= + +Bug fixes +--------- + +- `#12652 `_: Resolve regression `conda` environments where no longer being automatically detected. + + -- by :user:`RonnyPfannschmidt` + + pytest 8.3.1 (2024-07-20) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index b5679ff6305..3e449b2eaa2 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 9705ccf94f8..5bd03035c14 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index b519656a182..050fd2d80ec 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.3.1 + pytest 8.3.2 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 5c66c348eca..f4d59ff93c0 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From 5a0158368798f466ac74c8e89aef40829cd86d5c Mon Sep 17 00:00:00 2001 From: fazeelghafoor <33656455+fazeelghafoor@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:26:50 -0400 Subject: [PATCH 0831/1271] Improve approx repr for better readability (#12665) Adjust `ApproxScalar.__repr__` to format tolerances in decimal form for smaller ranges. Closes #6985 --------- Co-authored-by: Bruno Oliveira Co-authored-by: Pierre Sassoulas --- changelog/6985.improvement.rst | 21 +++++++++++++++++++++ src/_pytest/python_api.py | 6 +++++- testing/python/approx.py | 16 +++++++++++----- 3 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 changelog/6985.improvement.rst diff --git a/changelog/6985.improvement.rst b/changelog/6985.improvement.rst new file mode 100644 index 00000000000..34ee8edc77d --- /dev/null +++ b/changelog/6985.improvement.rst @@ -0,0 +1,21 @@ +Improved :func:`pytest.approx` to enhance the readability of value ranges and tolerances between 0.001 and 1000. + * The `repr` method now provides clearer output for values within those ranges, making it easier to interpret the results. + * Previously, the output for those ranges of values and tolerances was displayed in scientific notation (e.g., `42 ± 1.0e+00`). The updated method now presents the tolerance as a decimal for better readability (e.g., `42 ± 1`). + + Example: + + **Previous Output:** + + .. code-block:: console + + >>> pytest.approx(42, abs=1) + 42 ± 1.0e+00 + + **Current Output:** + + .. code-block:: console + + >>> pytest.approx(42, abs=1) + 42 ± 1 + + -- by :user:`fazeelghafoor` diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 4174a55b589..d2107c2fc78 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -406,7 +406,11 @@ def __repr__(self) -> str: # If a sensible tolerance can't be calculated, self.tolerance will # raise a ValueError. In this case, display '???'. try: - vetted_tolerance = f"{self.tolerance:.1e}" + if 1e-3 <= self.tolerance < 1e3: + vetted_tolerance = f"{self.tolerance:n}" + else: + vetted_tolerance = f"{self.tolerance:.1e}" + if ( isinstance(self.expected, Complex) and self.expected.imag diff --git a/testing/python/approx.py b/testing/python/approx.py index 69743cdbe17..21932059cc6 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -92,6 +92,7 @@ def do_assert(lhs, rhs, expected_message, verbosity_level=0): SOME_FLOAT = r"[+-]?([0-9]*[.])?[0-9]+\s*" SOME_INT = r"[0-9]+\s*" +SOME_TOLERANCE = rf"({SOME_FLOAT}|[+-]?[0-9]+(\.[0-9]+)?[eE][+-]?[0-9]+\s*)" class TestApprox: @@ -103,7 +104,7 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): "", " comparison failed", f" Obtained: {SOME_FLOAT}", - f" Expected: {SOME_FLOAT} ± {SOME_FLOAT}", + f" Expected: {SOME_FLOAT} ± {SOME_TOLERANCE}", ], ) @@ -119,9 +120,9 @@ def test_error_messages_native_dtypes(self, assert_approx_raises_regex): r" comparison failed. Mismatched elements: 2 / 3:", rf" Max absolute difference: {SOME_FLOAT}", rf" Max relative difference: {SOME_FLOAT}", - r" Index \| Obtained\s+\| Expected ", - rf" a \| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}", - rf" c \| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_FLOAT}", + r" Index \| Obtained\s+\| Expected\s+", + rf" a \| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_TOLERANCE}", + rf" c \| {SOME_FLOAT} \| {SOME_FLOAT} ± {SOME_TOLERANCE}", ], ) @@ -334,6 +335,11 @@ def test_repr_string(self): "approx({'b': 2.0 ± 2.0e-06, 'a': 1.0 ± 1.0e-06})", ) + assert repr(approx(42, abs=1)) == "42 ± 1" + assert repr(approx(5, rel=0.01)) == "5 ± 0.05" + assert repr(approx(24000, abs=500)) == "24000 ± 500" + assert repr(approx(1500, abs=555)) == "1500 ± 555" + def test_repr_complex_numbers(self): assert repr(approx(inf + 1j)) == "(inf+1j)" assert repr(approx(1.0j, rel=inf)) == "1j ± inf" @@ -347,7 +353,7 @@ def test_repr_complex_numbers(self): assert repr(approx(3 + 4 * 1j)) == "(3+4j) ± 5.0e-06 ∠ ±180°" # absolute tolerance is not scaled - assert repr(approx(3.3 + 4.4 * 1j, abs=0.02)) == "(3.3+4.4j) ± 2.0e-02 ∠ ±180°" + assert repr(approx(3.3 + 4.4 * 1j, abs=0.02)) == "(3.3+4.4j) ± 0.02 ∠ ±180°" @pytest.mark.parametrize( "value, expected_repr_string", From 69b7b83763a0086aa37e0b603e2b12e9be239010 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 4 Aug 2024 00:22:52 +0000 Subject: [PATCH 0832/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 146 ++++++++++++++++--------------- 1 file changed, 77 insertions(+), 69 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 4cec461b9eb..c031c6371c9 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.2) :pypi:`pytest-ai1899` pytest plugin for connecting to ai1899 smart system stack Mar 13, 2024 5 - Production/Stable N/A - :pypi:`pytest-aio` Pytest plugin for testing async python code Apr 08, 2024 5 - Production/Stable pytest + :pypi:`pytest-aio` Pytest plugin for testing async python code Jul 31, 2024 5 - Production/Stable pytest :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A :pypi:`pytest-aiogram` May 06, 2023 N/A N/A :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Sep 06, 2023 4 - Beta pytest >=6.1.0 @@ -60,7 +60,7 @@ This list contains 1492 plugins. :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Mar 04, 2024 N/A pytest (>=6.0) + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 29, 2024 N/A pytest>=6.0 :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -78,7 +78,7 @@ This list contains 1492 plugins. :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A - :pypi:`pytest-antilru` Bust functools.lru_cache when running pytest to avoid test pollution Jul 05, 2022 5 - Production/Stable pytest + :pypi:`pytest-antilru` Bust functools.lru_cache when running pytest to avoid test pollution Jul 28, 2024 5 - Production/Stable pytest>=7; python_version >= "3.10" :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 Jan 18, 2024 N/A pytest :pypi:`pytest-aoc` Downloads puzzle inputs for Advent of Code and synthesizes PyTest fixtures Dec 02, 2023 5 - Production/Stable pytest ; extra == 'test' @@ -111,7 +111,7 @@ This list contains 1492 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Jul 17, 2024 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Jul 30, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -123,18 +123,18 @@ This list contains 1492 plugins. :pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A :pypi:`pytest-autocap` automatically capture test & fixture stdout/stderr to files May 15, 2022 N/A pytest (<7.2,>=7.1.2) :pypi:`pytest-autochecklog` automatically check condition and log all the checks Apr 25, 2015 4 - Beta N/A - :pypi:`pytest-auto-fixture` ... Jul 23, 2024 N/A pytest>=8 + :pypi:`pytest-autofixture` simplify pytest fixtures Aug 01, 2024 N/A pytest>=8 :pypi:`pytest-automation` pytest plugin for building a test suite, using YAML files to extend pytest parameterize functionality. Apr 24, 2024 N/A pytest>=7.0.0 :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest - :pypi:`pytest-aux` templates/examples and aux for pytest Jul 26, 2024 N/A N/A + :pypi:`pytest-aux` templates/examples and aux for pytest Aug 02, 2024 N/A N/A :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 24, 2024 4 - Beta pytest :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A - :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Jul 25, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Jul 30, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest @@ -154,7 +154,7 @@ This list contains 1492 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jul 25, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 01, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -243,14 +243,14 @@ This list contains 1492 plugins. :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Jun 17, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Jun 27, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Jul 30, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest May 31, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Aug 01, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 @@ -289,7 +289,7 @@ This list contains 1492 plugins. :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Jun 04, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Jul 28, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 @@ -329,7 +329,7 @@ This list contains 1492 plugins. :pypi:`pytest-datafixtures` Data fixtures for pytest made simple Dec 05, 2020 5 - Production/Stable N/A :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A - :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Feb 15, 2024 5 - Production/Stable pytest + :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jul 31, 2024 5 - Production/Stable pytest :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A :pypi:`pytest-data-suites` Class-based pytest parametrization Apr 06, 2024 N/A pytest<9.0,>=6.0 :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) @@ -430,6 +430,7 @@ This list contains 1492 plugins. :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) :pypi:`pytest-dot-only-pkcopley` A Pytest marker for only running a single test Oct 27, 2023 N/A N/A + :pypi:`pytest-dpg` pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications. Aug 01, 2024 N/A N/A :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A @@ -456,14 +457,14 @@ This list contains 1492 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 Jul 25, 2024 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. May 31, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. May 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. May 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. May 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. May 23, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. May 31, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. May 31, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. May 23, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jul 31, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jul 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jul 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jul 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jul 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jul 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jul 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jul 31, 2024 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) @@ -534,7 +535,7 @@ This list contains 1492 plugins. :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) - :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. May 30, 2024 N/A N/A + :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Jul 31, 2024 N/A N/A :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A :pypi:`pytest-file` Pytest File Mar 18, 2024 1 - Planning N/A @@ -580,7 +581,7 @@ This list contains 1492 plugins. :pypi:`pytest-forks` Fork helper for pytest Mar 05, 2024 N/A N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A - :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Oct 29, 2023 4 - Beta pytest>=7.0.0 + :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Jul 30, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-freezeblaster` Wrap tests with fixtures in freeze_time Jul 10, 2024 N/A pytest>=6.2.5 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 @@ -642,9 +643,9 @@ This list contains 1492 plugins. :pypi:`pytest-historic` Custom report to display pytest historical execution records Apr 08, 2020 N/A pytest :pypi:`pytest-historic-hook` Custom listener to store execution results into MYSQL DB, which is used for pytest-historic report Apr 08, 2020 N/A pytest :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) - :pypi:`pytest-home` Home directory fixtures Oct 09, 2023 5 - Production/Stable pytest + :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Jul 20, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jul 31, 2024 3 - Alpha pytest==8.2.0 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -710,12 +711,12 @@ This list contains 1492 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. Feb 09, 2024 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Jul 30, 2024 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 5 - Production/Stable pytest<7.2.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Jul 23, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Aug 02, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -813,7 +814,7 @@ This list contains 1492 plugins. :pypi:`pytest-mark-manage` 用例标签化管理 Jul 08, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A - :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Mar 15, 2024 5 - Production/Stable pytest + :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Aug 01, 2024 5 - Production/Stable pytest :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -867,10 +868,10 @@ This list contains 1492 plugins. :pypi:`pytest-motor` A pytest plugin for motor, the non-blocking MongoDB driver. Jul 21, 2021 3 - Alpha pytest :pypi:`pytest-mp` A test batcher for multiprocessed Pytest runs May 23, 2018 4 - Beta pytest :pypi:`pytest-mpi` pytest plugin to collect information from tests Jan 08, 2022 3 - Alpha pytest - :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Apr 13, 2023 3 - Alpha pytest + :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Jul 29, 2024 3 - Alpha pytest :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Feb 14, 2024 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT May 08, 2024 4 - Beta pytest<9; extra == "test" + :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Jul 29, 2024 4 - Beta pytest<9; extra == "test" :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A @@ -1190,7 +1191,7 @@ This list contains 1492 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jul 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 03, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1200,7 +1201,7 @@ This list contains 1492 plugins. :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 Feb 01, 2024 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. Jul 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 03, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1370,7 +1371,7 @@ This list contains 1492 plugins. :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Jul 17, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Jul 29, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 22, 2024 4 - Beta pytest>=8.0.0 @@ -1644,7 +1645,7 @@ This list contains 1492 plugins. pytest plugin for connecting to ai1899 smart system stack :pypi:`pytest-aio` - *last release*: Apr 08, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -1714,9 +1715,9 @@ This list contains 1492 plugins. :pypi:`pytest-alembic` - *last release*: Mar 04, 2024, + *last release*: Jul 29, 2024, *status*: N/A, - *requires*: pytest (>=6.0) + *requires*: pytest>=6.0 A pytest plugin for verifying alembic migrations. @@ -1840,9 +1841,9 @@ This list contains 1492 plugins. A pytest plugin for running unit tests within an ansible collection :pypi:`pytest-antilru` - *last release*: Jul 05, 2022, + *last release*: Jul 28, 2024, *status*: 5 - Production/Stable, - *requires*: pytest + *requires*: pytest>=7; python_version >= "3.10" Bust functools.lru_cache when running pytest to avoid test pollution @@ -2071,7 +2072,7 @@ This list contains 1492 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jul 17, 2024, + *last release*: Jul 30, 2024, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 @@ -2154,12 +2155,12 @@ This list contains 1492 plugins. automatically check condition and log all the checks - :pypi:`pytest-auto-fixture` - *last release*: Jul 23, 2024, + :pypi:`pytest-autofixture` + *last release*: Aug 01, 2024, *status*: N/A, *requires*: pytest>=8 - ... + simplify pytest fixtures :pypi:`pytest-automation` *last release*: Apr 24, 2024, @@ -2190,7 +2191,7 @@ This list contains 1492 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: Jul 26, 2024, + *last release*: Aug 02, 2024, *status*: N/A, *requires*: N/A @@ -2232,7 +2233,7 @@ This list contains 1492 plugins. Protect your AWS credentials in unit tests :pypi:`pytest-aws-fixtures` - *last release*: Jul 25, 2024, + *last release*: Jul 30, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -2372,7 +2373,7 @@ This list contains 1492 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jul 25, 2024, + *last release*: Aug 01, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2995,7 +2996,7 @@ This list contains 1492 plugins. A cleanup plugin for pytest :pypi:`pytest-clerk` - *last release*: Jun 27, 2024, + *last release*: Jul 30, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -3044,7 +3045,7 @@ This list contains 1492 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: May 31, 2024, + *last release*: Aug 01, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3317,7 +3318,7 @@ This list contains 1492 plugins. Coverage dynamic context support for PyTest, including sub-processes :pypi:`pytest-coveragemarkers` - *last release*: Jun 04, 2024, + *last release*: Jul 28, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -3597,7 +3598,7 @@ This list contains 1492 plugins. A pytest plugin for managing an archive of test data. :pypi:`pytest-datarecorder` - *last release*: Feb 15, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -4303,6 +4304,13 @@ This list contains 1492 plugins. A Pytest marker for only running a single test + :pypi:`pytest-dpg` + *last release*: Aug 01, 2024, + *status*: N/A, + *requires*: N/A + + pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications. + :pypi:`pytest-draw` *last release*: Mar 21, 2023, *status*: 3 - Alpha, @@ -4486,56 +4494,56 @@ This list contains 1492 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: May 31, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: May 23, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: May 23, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: May 23, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: May 23, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: May 31, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: May 31, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: May 23, 2024, + *last release*: Jul 31, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5032,7 +5040,7 @@ This list contains 1492 plugins. py.test plugin that activates the fault handler module for tests (dummy package) :pypi:`pytest-fauna` - *last release*: May 30, 2024, + *last release*: Jul 31, 2024, *status*: N/A, *requires*: N/A @@ -5354,7 +5362,7 @@ This list contains 1492 plugins. A pytest plugin to shim pytest commandline options for fowards compatibility :pypi:`pytest-frappe` - *last release*: Oct 29, 2023, + *last release*: Jul 30, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -5788,7 +5796,7 @@ This list contains 1492 plugins. Pytest plugin to keep a history of your pytest runs :pypi:`pytest-home` - *last release*: Oct 09, 2023, + *last release*: Jul 28, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -5802,7 +5810,7 @@ This list contains 1492 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jul 20, 2024, + *last release*: Jul 31, 2024, *status*: 3 - Alpha, *requires*: pytest==8.2.0 @@ -6264,7 +6272,7 @@ This list contains 1492 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Feb 09, 2024, + *last release*: Jul 30, 2024, *status*: 4 - Beta, *requires*: pytest @@ -6299,7 +6307,7 @@ This list contains 1492 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Jul 23, 2024, + *last release*: Aug 02, 2024, *status*: N/A, *requires*: pytest @@ -6985,7 +6993,7 @@ This list contains 1492 plugins. UNKNOWN :pypi:`pytest-matcher` - *last release*: Mar 15, 2024, + *last release*: Aug 01, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -7363,7 +7371,7 @@ This list contains 1492 plugins. pytest plugin to collect information from tests :pypi:`pytest-mpiexec` - *last release*: Apr 13, 2023, + *last release*: Jul 29, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -7384,7 +7392,7 @@ This list contains 1492 plugins. low-startup-overhead, scalable, distributed-testing pytest plugin :pypi:`pytest-mqtt` - *last release*: May 08, 2024, + *last release*: Jul 29, 2024, *status*: 4 - Beta, *requires*: pytest<9; extra == "test" @@ -9624,7 +9632,7 @@ This list contains 1492 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jul 26, 2024, + *last release*: Aug 03, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9694,7 +9702,7 @@ This list contains 1492 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jul 26, 2024, + *last release*: Aug 03, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10884,7 +10892,7 @@ This list contains 1492 plugins. A plugin that allows coll test data for use on Test Tracer :pypi:`pytest-test-tracer-for-pytest-bdd` - *last release*: Jul 17, 2024, + *last release*: Jul 29, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 From bc1e17e90c5324797b4ebc5fd229d2662ad15e6e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 5 Aug 2024 10:40:42 -0300 Subject: [PATCH 0833/1271] Obey verbosity level when printing 'msg' part of assertions (#12662) Seems like we just missed that case when more fine-grained verbosity levels were added. Fixes #6682, #12307 --- changelog/6682.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 2 +- testing/test_assertrewrite.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 changelog/6682.bugfix.rst diff --git a/changelog/6682.bugfix.rst b/changelog/6682.bugfix.rst new file mode 100644 index 00000000000..7f756cbd9c2 --- /dev/null +++ b/changelog/6682.bugfix.rst @@ -0,0 +1 @@ +Fixed bug where the verbosity levels where not being respected when printing the "msg" part of failed assertion (as in ``assert condition, msg``). diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index bfcbcbd3f8d..f7ff4f6f7a2 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -451,7 +451,7 @@ def _format_assertmsg(obj: object) -> str: # However in either case we want to preserve the newline. replaces = [("\n", "\n~"), ("%", "%%")] if not isinstance(obj, str): - obj = saferepr(obj) + obj = saferepr(obj, _get_maxsize_for_saferepr(util._config)) replaces.append(("\\n", "\n~")) for r1, r2 in replaces: diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 5ee40ee6568..11688acb6f5 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -341,6 +341,34 @@ def test_assertion_messages_bytes(self, pytester: Pytester) -> None: assert result.ret == 1 result.stdout.fnmatch_lines(["*AssertionError: b'ohai!'", "*assert False"]) + def test_assertion_message_verbosity(self, pytester: Pytester) -> None: + """ + Obey verbosity levels when printing the "message" part of assertions, when they are + non-strings (#6682). + """ + pytester.makepyfile( + """ + class LongRepr: + + def __repr__(self): + return "A" * 500 + + def test_assertion_verbosity(): + assert False, LongRepr() + """ + ) + # Normal verbosity: assertion message gets abbreviated. + result = pytester.runpytest() + assert result.ret == 1 + result.stdout.re_match_lines( + [r".*AssertionError: A+\.\.\.A+$", ".*assert False"] + ) + + # High-verbosity: do not abbreviate the assertion message. + result = pytester.runpytest("-vv") + assert result.ret == 1 + result.stdout.re_match_lines([r".*AssertionError: A+$", ".*assert False"]) + def test_boolop(self) -> None: def f1() -> None: f = g = False From 2b99703acace3194a7e28c05a097d06d29949aa9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 6 Aug 2024 07:44:13 -0300 Subject: [PATCH 0834/1271] Add merge/squash guidelines to CONTRIBUTING.rst (#12672) As discussed in https://github.com/pytest-dev/pytest/discussions/12633. --- CONTRIBUTING.rst | 55 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 12e2b18bb52..6e96fd24c40 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -380,6 +380,57 @@ pull requests from other contributors yourself after having reviewed them. +Merge/squash guidelines +----------------------- + +When a PR is approved and ready to be integrated to the ``main`` branch, one has the option to *merge* the commits unchanged, or *squash* all the commits into a single commit. + +Here are some guidelines on how to proceed, based on examples of a single PR commit history: + +1. Miscellaneous commits: + + * ``Implement X`` + * ``Fix test_a`` + * ``Add myself to AUTHORS`` + * ``fixup! Fix test_a`` + * ``Update tests/test_integration.py`` + * ``Merge origin/main into PR branch`` + * ``Update tests/test_integration.py`` + + In this case, prefer to use the **Squash** merge strategy: the commit history is a bit messy (not in a derogatory way, often one just commits changes because they know the changes will eventually be squashed together), so squashing everything into a single commit is best. You must clean up the commit message, making sure it contains useful details. + +2. Separate commits related to the same topic: + + * ``Implement X`` + * ``Add myself to AUTHORS`` + * ``Update CHANGELOG for X`` + + In this case, prefer to use the **Squash** merge strategy: while the commit history is not "messy" as in the example above, the individual commits do not bring much value overall, specially when looking at the changes a few months/years down the line. + +3. Separate commits, each with their own topic (refactorings, renames, etc), but still have a larger topic/purpose. + + * ``Refactor class X in preparation for feature Y`` + * ``Remove unused method`` + * ``Implement feature Y`` + + In this case, prefer to use the **Merge** strategy: each commit is valuable on its own, even if they serve a common topic overall. Looking at the history later, it is useful to have the removal of the unused method separately on its own commit, along with more information (such as how it became unused in the first place). + +4. Separate commits, each with their own topic, but without a larger topic/purpose other than improve the code base (using more modern techniques, improve typing, removing clutter, etc). + + * ``Improve internal names in X`` + * ``Add type annotations to Y`` + * ``Remove unnecessary dict access`` + * ``Remove unreachable code due to EOL Python`` + + In this case, prefer to use the **Merge** strategy: each commit is valuable on its own, and the information on each is valuable in the long term. + + +As mentioned, those are overall guidelines, not rules cast in stone. This topic was discussed in `#12633 `_. + + +*Backport PRs* (as those created automatically from a ``backport`` label) should always be **squashed**, as they preserve the original PR author. + + Backporting bug fixes for the next patch release ------------------------------------------------ @@ -438,6 +489,8 @@ above? All the above are not rules, but merely some guidelines/suggestions on what we should expect about backports. +Backports should be **squashed** (rather than **merged**), as doing so preserves the original PR author correctly. + Handling stale issues/PRs ------------------------- @@ -485,7 +538,7 @@ When closing a Pull Request, it needs to be acknowledging the time, effort, and -Closing Issues +Closing issues -------------- When a pull request is submitted to fix an issue, add text like ``closes #XYZW`` to the PR description and/or commits (where ``XYZW`` is the issue number). See the `GitHub docs `_ for more information. From 85760bff2776989b365167c7aeb35c86308ab76b Mon Sep 17 00:00:00 2001 From: Daniel Miller Date: Tue, 6 Aug 2024 06:47:27 -0400 Subject: [PATCH 0835/1271] Apply pythonpath option as early as possible (#12536) This allows plugins loaded via '-p' to benefit from the new PYTHONPATH, making the option useful in more cases and less surprising. For this to work it was required for the functionality to be part of Config rather than a separate plugin, which is unfortunate but in the end considered a small price to pay. Fix #11118. --------- Co-authored-by: Bruno Oliveira --- changelog/11118.improvement.rst | 3 +++ doc/en/reference/reference.rst | 5 ----- src/_pytest/config/__init__.py | 17 ++++++++++++++++- src/_pytest/python_path.py | 26 -------------------------- testing/test_config.py | 1 - testing/test_python_path.py | 33 +++++++++++++++++++++++++-------- 6 files changed, 44 insertions(+), 41 deletions(-) create mode 100644 changelog/11118.improvement.rst delete mode 100644 src/_pytest/python_path.py diff --git a/changelog/11118.improvement.rst b/changelog/11118.improvement.rst new file mode 100644 index 00000000000..4760dbe9d64 --- /dev/null +++ b/changelog/11118.improvement.rst @@ -0,0 +1,3 @@ +Now :confval:`pythonpath` configures `$PYTHONPATH` earlier than before during the initialization process, which now also affects plugins loaded via the `-p` command-line option. + +-- by :user:`millerdev` diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 7ea5921f581..c1f94957d9c 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1796,11 +1796,6 @@ passed multiple times. The expected format is ``name=value``. For example:: [pytest] pythonpath = src1 src2 - .. note:: - - ``pythonpath`` does not affect some imports that happen very early, - most notably plugins loaded using the ``-p`` command line option. - .. confval:: required_plugins diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 0c1850df503..fbb5fb6fdea 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -268,7 +268,6 @@ def directory_arg(path: str, optname: str) -> str: "warnings", "logging", "reports", - "python_path", "unraisableexception", "threadexception", "faulthandler", @@ -1245,6 +1244,9 @@ def _initini(self, args: Sequence[str]) -> None: self._parser.extra_info["inifile"] = str(self.inipath) self._parser.addini("addopts", "Extra command line options", "args") self._parser.addini("minversion", "Minimally required pytest version") + self._parser.addini( + "pythonpath", type="paths", help="Add paths to sys.path", default=[] + ) self._parser.addini( "required_plugins", "Plugins that must be present for pytest to run", @@ -1294,6 +1296,18 @@ def _mark_plugins_for_rewrite(self, hook) -> None: for name in _iter_rewritable_modules(package_files): hook.mark_rewrite(name) + def _configure_python_path(self) -> None: + # `pythonpath = a b` will set `sys.path` to `[a, b, x, y, z, ...]` + for path in reversed(self.getini("pythonpath")): + sys.path.insert(0, str(path)) + self.add_cleanup(self._unconfigure_python_path) + + def _unconfigure_python_path(self) -> None: + for path in self.getini("pythonpath"): + path_str = str(path) + if path_str in sys.path: + sys.path.remove(path_str) + def _validate_args(self, args: list[str], via: str) -> list[str]: """Validate known args.""" self._parser._config_source_hint = via # type: ignore @@ -1370,6 +1384,7 @@ def _preparse(self, args: list[str], addopts: bool = True) -> None: ) self._checkversion() self._consider_importhook(args) + self._configure_python_path() self.pluginmanager.consider_preparse(args, exclude_only=False) if not os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD"): # Don't autoload from distribution package entry point. Only diff --git a/src/_pytest/python_path.py b/src/_pytest/python_path.py deleted file mode 100644 index 6e33c8a39f2..00000000000 --- a/src/_pytest/python_path.py +++ /dev/null @@ -1,26 +0,0 @@ -from __future__ import annotations - -import sys - -import pytest -from pytest import Config -from pytest import Parser - - -def pytest_addoption(parser: Parser) -> None: - parser.addini("pythonpath", type="paths", help="Add paths to sys.path", default=[]) - - -@pytest.hookimpl(tryfirst=True) -def pytest_load_initial_conftests(early_config: Config) -> None: - # `pythonpath = a b` will set `sys.path` to `[a, b, x, y, z, ...]` - for path in reversed(early_config.getini("pythonpath")): - sys.path.insert(0, str(path)) - - -@pytest.hookimpl(trylast=True) -def pytest_unconfigure(config: Config) -> None: - for path in config.getini("pythonpath"): - path_str = str(path) - if path_str in sys.path: - sys.path.remove(path_str) diff --git a/testing/test_config.py b/testing/test_config.py index 232839399e2..aa3e4147927 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1409,7 +1409,6 @@ def pytest_load_initial_conftests(self): ("_pytest.config", "nonwrapper"), (m.__module__, "nonwrapper"), ("_pytest.legacypath", "nonwrapper"), - ("_pytest.python_path", "nonwrapper"), ("_pytest.capture", "wrapper"), ("_pytest.warnings", "wrapper"), ] diff --git a/testing/test_python_path.py b/testing/test_python_path.py index 1db02252d22..d12ef96115f 100644 --- a/testing/test_python_path.py +++ b/testing/test_python_path.py @@ -3,7 +3,6 @@ import sys from textwrap import dedent -from typing import Generator from _pytest.pytester import Pytester import pytest @@ -62,6 +61,27 @@ def test_two_dirs(pytester: Pytester, file_structure) -> None: result.assert_outcomes(passed=2) +def test_local_plugin(pytester: Pytester, file_structure) -> None: + """`pythonpath` kicks early enough to load plugins via -p (#11118).""" + localplugin_py = pytester.path / "sub" / "localplugin.py" + content = dedent( + """ + def pytest_load_initial_conftests(): + print("local plugin load") + + def pytest_unconfigure(): + print("local plugin unconfig") + """ + ) + localplugin_py.write_text(content, encoding="utf-8") + + pytester.makeini("[pytest]\npythonpath=sub\n") + result = pytester.runpytest("-plocalplugin", "-s", "test_foo.py") + result.stdout.fnmatch_lines(["local plugin load", "local plugin unconfig"]) + assert result.ret == 0 + result.assert_outcomes(passed=1) + + def test_module_not_found(pytester: Pytester, file_structure) -> None: """Without the pythonpath setting, the module should not be found.""" pytester.makefile(".ini", pytest="[pytest]\n") @@ -95,16 +115,13 @@ def test_clean_up(pytester: Pytester) -> None: after: list[str] | None = None class Plugin: - @pytest.hookimpl(wrapper=True, tryfirst=True) - def pytest_unconfigure(self) -> Generator[None, None, None]: - nonlocal before, after + @pytest.hookimpl(tryfirst=True) + def pytest_unconfigure(self) -> None: + nonlocal before before = sys.path.copy() - try: - return (yield) - finally: - after = sys.path.copy() result = pytester.runpytest_inprocess(plugins=[Plugin()]) + after = sys.path.copy() assert result.ret == 0 assert before is not None From a01dca5321c899dd01f01c6ff698af87d86b9fd3 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 6 Aug 2024 14:01:38 -0300 Subject: [PATCH 0836/1271] Add Pierre to official contacts (#12694) As part of onboarding Pierre to the core team. Also add contacts in alphabetical order --- doc/en/contact.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/en/contact.rst b/doc/en/contact.rst index ef9d1e8edca..d650a7efbab 100644 --- a/doc/en/contact.rst +++ b/doc/en/contact.rst @@ -33,10 +33,11 @@ Mail discussed in public. Mails sent there will be distributed among the members in the pytest core team, who can also be contacted individually: - * Ronny Pfannschmidt (:user:`RonnyPfannschmidt`, `ronny@pytest.org `_) - * Florian Bruhin (:user:`The-Compiler`, `florian@pytest.org `_) * Bruno Oliveira (:user:`nicoddemus`, `bruno@pytest.org `_) + * Florian Bruhin (:user:`The-Compiler`, `florian@pytest.org `_) + * Pierre Sassoulas (:user:`Pierre-Sassoulas`, `pierre@pytest.org `_) * Ran Benita (:user:`bluetech`, `ran@pytest.org `_) + * Ronny Pfannschmidt (:user:`RonnyPfannschmidt`, `ronny@pytest.org `_) * Zac Hatfield-Dodds (:user:`Zac-HD`, `zac@pytest.org `_) Other From 4aa43d5521c011e3612031c46abc1ad9133beff4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 23:10:25 +0000 Subject: [PATCH 0837/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.5 → v0.5.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.5...v0.5.6) - [github.com/pre-commit/mirrors-mypy: v1.11.0 → v1.11.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.11.0...v1.11.1) - [github.com/tox-dev/pyproject-fmt: 2.1.4 → 2.2.1](https://github.com/tox-dev/pyproject-fmt/compare/2.1.4...2.2.1) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aaa28d6b7c4..5348fdde93d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.5" + rev: "v0.5.6" hooks: - id: ruff args: ["--fix"] @@ -21,7 +21,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.0 + rev: v1.11.1 hooks: - id: mypy files: ^(src/|testing/|scripts/) @@ -38,7 +38,7 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "2.1.4" + rev: "2.2.1" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version From 127544b9b6c761348f5b90053fae72dbccadfed2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 7 Aug 2024 08:42:58 -0300 Subject: [PATCH 0838/1271] Replace types-pkg-resources by types-setuptools According to https://pypi.org/project/types-pkg-resources/#history, that package has been supplanted by `types-setuptools`. --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5348fdde93d..f27c46f3a54 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: - pluggy>=1.5.0 - packaging - tomli - - types-pkg_resources + - types-setuptools - types-tabulate # for mypy running on python>=3.11 since exceptiongroup is only a dependency # on <3.11 From ef9b8f9d748b6f50eab5d43e32d93008f7880899 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:33:50 +0200 Subject: [PATCH 0839/1271] build(deps): Bump django in /testing/plugins_integration (#12698) Bumps [django](https://github.com/django/django) from 5.0.7 to 5.0.8. - [Commits](https://github.com/django/django/compare/5.0.7...5.0.8) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index cdb3e7264a0..512c20c6450 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.4.0 -django==5.0.7 +django==5.0.8 pytest-asyncio==0.23.8 pytest-bdd==7.2.0 pytest-cov==5.0.0 From 49eafce55bf31c1993db9f411bc2d669804d5bb3 Mon Sep 17 00:00:00 2001 From: Eugene Mwangi Date: Fri, 9 Aug 2024 18:23:03 +0300 Subject: [PATCH 0840/1271] docs: Revise `cache_dir` option section (#12701) Update the description for the `cache_dir` configuration options section to improve semantics and clarity for an unclear sentence in the file `reference.rst`. --- doc/en/reference/reference.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index c1f94957d9c..f7dfb3ffa71 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1294,10 +1294,10 @@ passed multiple times. The expected format is ``name=value``. For example:: .. confval:: cache_dir - Sets a directory where stores content of cache plugin. Default directory is + Sets the directory where the cache plugin's content is stored. Default directory is ``.pytest_cache`` which is created in :ref:`rootdir `. Directory may be relative or absolute path. If setting relative path, then directory is created - relative to :ref:`rootdir `. Additionally path may contain environment + relative to :ref:`rootdir `. Additionally, a path may contain environment variables, that will be expanded. For more information about cache plugin please refer to :ref:`cache_provider`. From cb98538e9c2ba3c65baf07432229d97fd5a29657 Mon Sep 17 00:00:00 2001 From: Reagan Lee <96998476+reaganjlee@users.noreply.github.com> Date: Fri, 9 Aug 2024 08:26:34 -0700 Subject: [PATCH 0841/1271] Fix `errisinstance` typing (#12700) Fixes #12667 --- changelog/12667.bugfix.rst | 1 + src/_pytest/_code/code.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/12667.bugfix.rst diff --git a/changelog/12667.bugfix.rst b/changelog/12667.bugfix.rst new file mode 100644 index 00000000000..eceee86cb53 --- /dev/null +++ b/changelog/12667.bugfix.rst @@ -0,0 +1 @@ +Fixed a regression where type change in `ExceptionInfo.errisinstance` caused `mypy` to fail. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index e7452825756..8fac39ea298 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -56,7 +56,7 @@ TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] -EXCEPTION_OR_MORE = Union[Type[Exception], Tuple[Type[Exception], ...]] +EXCEPTION_OR_MORE = Union[Type[BaseException], Tuple[Type[BaseException], ...]] class Code: From 6a3ac51ee2350d5072fdd082040e7cfa22331fc0 Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Sun, 11 Aug 2024 08:06:32 +0330 Subject: [PATCH 0842/1271] Revert the unintended change in tests reordering from #11220 (#12542) In #11220, an unintended change in reordering was introduced by changing the way indices were assigned to direct params. This PR reverts that change and reduces #11220 changes to just refactors. After this PR we could safely decide on the solutions discussed in #12008, i.e. #12082 or the one initially introduced in #11220 . Fixes #12008 Co-authored-by: Bruno Oliveira Co-authored-by: Bruno Oliveira --- changelog/12008.bugfix.rst | 1 + src/_pytest/python.py | 10 ++++++++++ testing/example_scripts/issue_519.py | 4 ++-- testing/python/metafunc.py | 6 +++--- 4 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 changelog/12008.bugfix.rst diff --git a/changelog/12008.bugfix.rst b/changelog/12008.bugfix.rst new file mode 100644 index 00000000000..b9680b89236 --- /dev/null +++ b/changelog/12008.bugfix.rst @@ -0,0 +1 @@ +In :pr:`11220`, an unintended change in reordering was introduced by changing the way indices were assigned to direct params. More specifically, before that change, the indices of direct params to metafunc's callspecs were assigned after all parametrizations took place. Now, that change is reverted. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 9182ce7dfe9..094113bd1b4 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -464,6 +464,7 @@ def _genfunctions(self, name: str, funcobj) -> Iterator[Function]: if not metafunc._calls: yield Function.from_parent(self, name=name, fixtureinfo=fixtureinfo) else: + metafunc._recompute_direct_params_indices() # Direct parametrizations taking place in module/class-specific # `metafunc.parametrize` calls may have shadowed some fixtures, so make sure # we update what the function really needs a.k.a its fixture closure. Note that @@ -1131,6 +1132,8 @@ def __init__( # Result of parametrize(). self._calls: list[CallSpec2] = [] + self._params_directness: dict[str, Literal["indirect", "direct"]] = {} + def parametrize( self, argnames: str | Sequence[str], @@ -1273,6 +1276,7 @@ def parametrize( name2pseudofixturedef_key, default ) arg_directness = self._resolve_args_directness(argnames, indirect) + self._params_directness.update(arg_directness) for argname in argnames: if arg_directness[argname] == "indirect": continue @@ -1445,6 +1449,12 @@ def _validate_if_using_arg_names( pytrace=False, ) + def _recompute_direct_params_indices(self) -> None: + for argname, param_type in self._params_directness.items(): + if param_type == "direct": + for i, callspec in enumerate(self._calls): + callspec.indices[argname] = i + def _find_parametrized_scope( argnames: Sequence[str], diff --git a/testing/example_scripts/issue_519.py b/testing/example_scripts/issue_519.py index 138c07e95be..da5f5ad6aa9 100644 --- a/testing/example_scripts/issue_519.py +++ b/testing/example_scripts/issue_519.py @@ -23,13 +23,13 @@ def checked_order(): assert order == [ ("issue_519.py", "fix1", "arg1v1"), ("test_one[arg1v1-arg2v1]", "fix2", "arg2v1"), - ("test_one[arg1v1-arg2v2]", "fix2", "arg2v2"), ("test_two[arg1v1-arg2v1]", "fix2", "arg2v1"), + ("test_one[arg1v1-arg2v2]", "fix2", "arg2v2"), ("test_two[arg1v1-arg2v2]", "fix2", "arg2v2"), ("issue_519.py", "fix1", "arg1v2"), ("test_one[arg1v2-arg2v1]", "fix2", "arg2v1"), - ("test_one[arg1v2-arg2v2]", "fix2", "arg2v2"), ("test_two[arg1v2-arg2v1]", "fix2", "arg2v1"), + ("test_one[arg1v2-arg2v2]", "fix2", "arg2v2"), ("test_two[arg1v2-arg2v2]", "fix2", "arg2v2"), ] diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 2dd85607e71..be224d9e20b 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1005,14 +1005,14 @@ def test3(arg1): result.stdout.re_match_lines( [ r" ", - r" ", r" ", + r" ", + r" ", r" ", + r" ", r" ", - r" ", r" ", r" ", - r" ", r" ", ] ) From ccd1f95602c0730046afc0e6dcf8ff3cbcb499a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 06:26:15 +0200 Subject: [PATCH 0843/1271] build(deps): Bump twisted in /testing/plugins_integration (#12711) Bumps [twisted](https://github.com/twisted/twisted) from 24.3.0 to 24.7.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-24.3.0...twisted-24.7.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 512c20c6450..edab9c4261d 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -11,5 +11,5 @@ pytest-rerunfailures==14.0 pytest-sugar==1.0.0 pytest-trio==0.8.0 pytest-twisted==1.14.2 -twisted==24.3.0 +twisted==24.7.0 pytest-xvfb==3.0.0 From 9446f024df846eefb8f2213d2854f7ec5552822a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 06:26:55 +0200 Subject: [PATCH 0844/1271] build(deps): Bump django in /testing/plugins_integration (#12710) Bumps [django](https://github.com/django/django) from 5.0.8 to 5.1. - [Commits](https://github.com/django/django/compare/5.0.8...5.1) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index edab9c4261d..bd554c6307d 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.4.0 -django==5.0.8 +django==5.1 pytest-asyncio==0.23.8 pytest-bdd==7.2.0 pytest-cov==5.0.0 From 38ad84bafd18d15ceff1960d636c693560337844 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 11:29:43 +0000 Subject: [PATCH 0845/1271] [automated] Update plugin list (#12709) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 184 ++++++++++++++++++------------- 1 file changed, 108 insertions(+), 76 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index c031c6371c9..6aea0dd86c0 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -148,12 +148,12 @@ This list contains 1493 plugins. :pypi:`pytest-bdd` BDD for pytest Jun 04, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 - :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports May 20, 2024 N/A pytest >=7.1.3 + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 04, 2024 N/A pytest>=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest - :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Jan 25, 2024 N/A pytest + :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 01, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A @@ -169,7 +169,7 @@ This list contains 1493 plugins. :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) :pypi:`pytest-blame` A pytest plugin helps developers to debug by providing useful commits history. May 04, 2019 N/A pytest (>=4.4.0) - :pypi:`pytest-blender` Blender Pytest plugin. Aug 10, 2023 N/A pytest ; extra == 'dev' + :pypi:`pytest-blender` Blender Pytest plugin. Aug 02, 2024 N/A pytest :pypi:`pytest-blink1` Pytest plugin to emit notifications via the Blink(1) RGB LED Jan 07, 2018 4 - Beta N/A :pypi:`pytest-blockage` Disable network requests during a test run. Dec 21, 2021 N/A pytest :pypi:`pytest-blocker` pytest plugin to mark a test as blocker and skip all other tests Sep 07, 2015 4 - Beta N/A @@ -250,7 +250,7 @@ This list contains 1493 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Aug 01, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Aug 09, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 @@ -317,7 +317,7 @@ This list contains 1493 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Jul 02, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Aug 07, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -430,7 +430,7 @@ This list contains 1493 plugins. :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) :pypi:`pytest-dot-only-pkcopley` A Pytest marker for only running a single test Oct 27, 2023 N/A N/A - :pypi:`pytest-dpg` pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications. Aug 01, 2024 N/A N/A + :pypi:`pytest-dpg` pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications Aug 07, 2024 N/A N/A :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A @@ -457,14 +457,14 @@ This list contains 1493 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 Jul 25, 2024 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. Jul 31, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jul 31, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jul 31, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jul 31, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jul 31, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jul 31, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jul 31, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jul 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Aug 09, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Aug 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Aug 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Aug 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Aug 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Aug 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Aug 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Aug 09, 2024 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) @@ -493,7 +493,7 @@ This list contains 1493 plugins. :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 02, 2024 4 - Beta pytest>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-saas` Jun 07, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -633,7 +633,7 @@ This list contains 1493 plugins. :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Mar 16, 2024 5 - Production/Stable N/A :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Feb 07, 2024 4 - Beta pytest (>=8.0.0,<9.0.0) - :pypi:`pytest-helm-templates` Pytest fixtures for unit testing the output of helm templates May 08, 2024 N/A pytest~=7.4.0; extra == "dev" + :pypi:`pytest-helm-templates` Pytest fixtures for unit testing the output of helm templates Aug 07, 2024 N/A pytest~=7.4.0; extra == "dev" :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest :pypi:`pytest-helpers-namespace` Pytest Helpers Namespace Plugin Dec 29, 2021 5 - Production/Stable pytest (>=6.0.0) @@ -645,7 +645,7 @@ This list contains 1493 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Jul 31, 2024 3 - Alpha pytest==8.2.0 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 08, 2024 3 - Alpha pytest==8.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -711,7 +711,7 @@ This list contains 1493 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. Jul 30, 2024 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Aug 09, 2024 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 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 @@ -745,6 +745,7 @@ This list contains 1493 plugins. :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest + :pypi:`pytest-kairos` Pytest plugin with random number generation, reproducibility, and test repetition Aug 08, 2024 5 - Production/Stable pytest>=5.0.0 :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-keep-together` Pytest plugin to customize test ordering by running all 'related' tests together Dec 07, 2022 5 - Production/Stable pytest :pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0) @@ -798,7 +799,7 @@ This list contains 1493 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Jun 27, 2024 5 - Production/Stable pytest==8.2.2 + :pypi:`pytest-logikal` Common testing environment Aug 08, 2024 5 - Production/Stable pytest==8.3.2 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Jul 19, 2024 4 - Beta N/A :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" @@ -814,6 +815,7 @@ This list contains 1493 plugins. :pypi:`pytest-mark-manage` 用例标签化管理 Jul 08, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A + :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Aug 06, 2024 N/A N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Aug 01, 2024 5 - Production/Stable pytest :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A @@ -835,7 +837,7 @@ This list contains 1493 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 Feb 12, 2024 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 Jul 02, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Aug 02, 2024 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) @@ -874,7 +876,7 @@ This list contains 1493 plugins. :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Jul 29, 2024 4 - Beta pytest<9; extra == "test" :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest - :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Dec 07, 2022 N/A N/A + :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Aug 05, 2024 N/A N/A :pypi:`pytest-multithreading-allure` pytest_multithreading_allure Nov 25, 2022 N/A N/A :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) @@ -889,6 +891,7 @@ This list contains 1493 plugins. :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) :pypi:`pytest-neos` Pytest plugin for neos Jun 11, 2024 1 - Planning N/A + :pypi:`pytest-netconf` A pytest plugin that provides a mock NETCONF (RFC6241/RFC6242) server for local testing. Aug 08, 2024 N/A N/A :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jul 05, 2024 N/A pytest<7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest @@ -900,8 +903,8 @@ This list contains 1493 plugins. :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jul 01, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A - :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Apr 11, 2024 N/A N/A - :pypi:`pytest-nocustom` Run all tests without custom markers Apr 11, 2024 5 - Production/Stable N/A + :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Aug 05, 2024 N/A N/A + :pypi:`pytest-nocustom` Run all tests without custom markers Aug 05, 2024 5 - Production/Stable N/A :pypi:`pytest-node-dependency` pytest plugin for controlling execution flow Apr 10, 2024 5 - Production/Stable N/A :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) @@ -954,6 +957,7 @@ This list contains 1493 plugins. :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest :pypi:`pytest_param_files` Create pytest parametrize decorators from external files. Jul 29, 2023 N/A pytest + :pypi:`pytest-params` Simplified pytest test case parameters. Aug 05, 2024 N/A pytest>=7.0.0 :pypi:`pytest-param-scope` pytest parametrize scope fixture workaround Oct 18, 2023 N/A pytest :pypi:`pytest-parawtf` Finally spell paramete?ri[sz]e correctly Dec 03, 2018 4 - Beta pytest (>=3.6.0) :pypi:`pytest-pass` Check out https://github.com/elilutsky/pytest-pass Dec 04, 2019 N/A N/A @@ -1119,7 +1123,7 @@ This list contains 1493 plugins. :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest - :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Jun 28, 2024 4 - Beta N/A + :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Aug 08, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) @@ -1191,7 +1195,7 @@ This list contains 1493 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 03, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 07, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1201,7 +1205,7 @@ This list contains 1493 plugins. :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 Feb 01, 2024 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. Aug 03, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 07, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1212,7 +1216,7 @@ This list contains 1493 plugins. :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A :pypi:`pytest-servers` pytest servers Jul 19, 2024 3 - Alpha pytest>=6.2 - :pypi:`pytest-service` May 11, 2024 5 - Production/Stable pytest>=6.0.0 + :pypi:`pytest-service` Aug 06, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest :pypi:`pytest-session-fixture-globalize` py.test plugin to make session fixtures behave as if written in conftest, even if it is written in some modules May 15, 2018 4 - Beta N/A @@ -1267,7 +1271,7 @@ This list contains 1493 plugins. :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest :pypi:`pytest-spawner` py.test plugin to spawn process and communicate with them. Jul 31, 2015 4 - Beta N/A - :pypi:`pytest-spec` Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. May 04, 2021 N/A N/A + :pypi:`pytest-spec` Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. Aug 04, 2024 N/A pytest; extra == "test" :pypi:`pytest-spec2md` Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. Apr 10, 2024 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 Apr 13, 2024 4 - Beta pytest>=8.1.1 @@ -1279,7 +1283,7 @@ This list contains 1493 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 Jul 24, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Aug 07, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jul 10, 2024 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 @@ -1293,7 +1297,7 @@ This list contains 1493 plugins. :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A - :pypi:`pytest-static` pytest-static Jun 20, 2024 1 - Planning pytest<8.0.0,>=7.4.3 + :pypi:`pytest-static` pytest-static Aug 09, 2024 1 - Planning pytest<8.0.0,>=7.4.3 :pypi:`pytest-stats` Collects tests metadata for future analysis, easy to extend for any data store Jul 18, 2024 N/A pytest>=8.0.0 :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest @@ -1496,8 +1500,8 @@ This list contains 1493 plugins. :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A - :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Apr 23, 2024 N/A pytest~=7.0 - :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Oct 30, 2017 3 - Alpha pytest + :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Aug 07, 2024 N/A pytest~=8.2.2 + :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Aug 07, 2024 3 - Alpha pytest :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. May 19, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) @@ -1507,7 +1511,7 @@ This list contains 1493 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. Jul 03, 2024 4 - Beta pytest>=7.2.2 :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 with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Jul 20, 2024 N/A pytest~=8.2.2 + :pypi:`pytest-yaml-sanmu` Pytest plugin for generating test cases with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Aug 03, 2024 N/A pytest~=8.2.2 :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) @@ -2191,7 +2195,7 @@ This list contains 1493 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: Aug 02, 2024, + *last release*: Aug 06, 2024, *status*: N/A, *requires*: N/A @@ -2331,9 +2335,9 @@ This list contains 1493 plugins. BDD for pytest :pypi:`pytest-bdd-report` - *last release*: May 20, 2024, + *last release*: Aug 04, 2024, *status*: N/A, - *requires*: pytest >=7.1.3 + *requires*: pytest>=7.1.3 A pytest-bdd plugin for generating useful and informative BDD test reports @@ -2366,7 +2370,7 @@ This list contains 1493 plugins. A pytest plugin that reports test results to the BeakerLib framework :pypi:`pytest-beartype` - *last release*: Jan 25, 2024, + *last release*: Aug 08, 2024, *status*: N/A, *requires*: pytest @@ -2478,9 +2482,9 @@ This list contains 1493 plugins. A pytest plugin helps developers to debug by providing useful commits history. :pypi:`pytest-blender` - *last release*: Aug 10, 2023, + *last release*: Aug 02, 2024, *status*: N/A, - *requires*: pytest ; extra == 'dev' + *requires*: pytest Blender Pytest plugin. @@ -3045,7 +3049,7 @@ This list contains 1493 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Aug 01, 2024, + *last release*: Aug 09, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3514,7 +3518,7 @@ This list contains 1493 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Jul 02, 2024, + *last release*: Aug 07, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4305,11 +4309,11 @@ This list contains 1493 plugins. A Pytest marker for only running a single test :pypi:`pytest-dpg` - *last release*: Aug 01, 2024, + *last release*: Aug 07, 2024, *status*: N/A, *requires*: N/A - pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications. + pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications :pypi:`pytest-draw` *last release*: Mar 21, 2023, @@ -4494,56 +4498,56 @@ This list contains 1493 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jul 31, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jul 31, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jul 31, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jul 31, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Jul 31, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jul 31, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jul 31, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Jul 31, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4746,7 +4750,7 @@ This list contains 1493 plugins. :pypi:`pytest-exasol-saas` - *last release*: Jun 07, 2024, + *last release*: Aug 06, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -5726,7 +5730,7 @@ This list contains 1493 plugins. A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. :pypi:`pytest-helm-templates` - *last release*: May 08, 2024, + *last release*: Aug 07, 2024, *status*: N/A, *requires*: pytest~=7.4.0; extra == "dev" @@ -5810,9 +5814,9 @@ This list contains 1493 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jul 31, 2024, + *last release*: Aug 08, 2024, *status*: 3 - Alpha, - *requires*: pytest==8.2.0 + *requires*: pytest==8.3.1 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -6272,7 +6276,7 @@ This list contains 1493 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Jul 30, 2024, + *last release*: Aug 09, 2024, *status*: 4 - Beta, *requires*: pytest @@ -6509,6 +6513,13 @@ This list contains 1493 plugins. A plugin to send pytest events to Kafka + :pypi:`pytest-kairos` + *last release*: Aug 08, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=5.0.0 + + Pytest plugin with random number generation, reproducibility, and test repetition + :pypi:`pytest-kasima` *last release*: Jan 26, 2023, *status*: 5 - Production/Stable, @@ -6881,9 +6892,9 @@ This list contains 1493 plugins. :pypi:`pytest-logikal` - *last release*: Jun 27, 2024, + *last release*: Aug 08, 2024, *status*: 5 - Production/Stable, - *requires*: pytest==8.2.2 + *requires*: pytest==8.3.2 Common testing environment @@ -6992,6 +7003,13 @@ This list contains 1493 plugins. UNKNOWN + :pypi:`pytest-mask-secrets` + *last release*: Aug 06, 2024, + *status*: N/A, + *requires*: N/A + + Pytest plugin to hide sensitive data in test reports + :pypi:`pytest-matcher` *last release*: Aug 01, 2024, *status*: 5 - Production/Stable, @@ -7140,7 +7158,7 @@ This list contains 1493 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Jul 02, 2024, + *last release*: Aug 02, 2024, *status*: N/A, *requires*: pytest @@ -7413,7 +7431,7 @@ This list contains 1493 plugins. Multi-process logs handling and other helpers for pytest :pypi:`pytest-multithreading` - *last release*: Dec 07, 2022, + *last release*: Aug 05, 2024, *status*: N/A, *requires*: N/A @@ -7517,6 +7535,13 @@ This list contains 1493 plugins. Pytest plugin for neos + :pypi:`pytest-netconf` + *last release*: Aug 08, 2024, + *status*: N/A, + *requires*: N/A + + A pytest plugin that provides a mock NETCONF (RFC6241/RFC6242) server for local testing. + :pypi:`pytest-netdut` *last release*: Jul 05, 2024, *status*: N/A, @@ -7595,14 +7620,14 @@ This list contains 1493 plugins. A small snippet for nicer PyTest's Parametrize :pypi:`pytest_nlcov` - *last release*: Apr 11, 2024, + *last release*: Aug 05, 2024, *status*: N/A, *requires*: N/A Pytest plugin to get the coverage of the new lines (based on git diff) only :pypi:`pytest-nocustom` - *last release*: Apr 11, 2024, + *last release*: Aug 05, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -7972,6 +7997,13 @@ This list contains 1493 plugins. Create pytest parametrize decorators from external files. + :pypi:`pytest-params` + *last release*: Aug 05, 2024, + *status*: N/A, + *requires*: pytest>=7.0.0 + + Simplified pytest test case parameters. + :pypi:`pytest-param-scope` *last release*: Oct 18, 2023, *status*: N/A, @@ -9128,7 +9160,7 @@ This list contains 1493 plugins. Generate Pytest reports with templates :pypi:`pytest-reporter-html1` - *last release*: Jun 28, 2024, + *last release*: Aug 08, 2024, *status*: 4 - Beta, *requires*: N/A @@ -9632,7 +9664,7 @@ This list contains 1493 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Aug 03, 2024, + *last release*: Aug 07, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9702,7 +9734,7 @@ This list contains 1493 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Aug 03, 2024, + *last release*: Aug 07, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9779,7 +9811,7 @@ This list contains 1493 plugins. pytest servers :pypi:`pytest-service` - *last release*: May 11, 2024, + *last release*: Aug 06, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.0.0 @@ -10164,9 +10196,9 @@ This list contains 1493 plugins. py.test plugin to spawn process and communicate with them. :pypi:`pytest-spec` - *last release*: May 04, 2021, + *last release*: Aug 04, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest; extra == "test" Library pytest-spec is a pytest plugin to display test execution output like a SPECIFICATION. @@ -10248,7 +10280,7 @@ This list contains 1493 plugins. :pypi:`pytest-splunk-addon` - *last release*: Jul 24, 2024, + *last release*: Aug 07, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10346,7 +10378,7 @@ This list contains 1493 plugins. A package to prevent Dependency Confusion attacks against Yandex. :pypi:`pytest-static` - *last release*: Jun 20, 2024, + *last release*: Aug 09, 2024, *status*: 1 - Planning, *requires*: pytest<8.0.0,>=7.4.3 @@ -11767,14 +11799,14 @@ This list contains 1493 plugins. Extended logging for test and decorators :pypi:`pytest-xlsx` - *last release*: Apr 23, 2024, + *last release*: Aug 07, 2024, *status*: N/A, - *requires*: pytest~=7.0 + *requires*: pytest~=8.2.2 pytest plugin for generating test cases by xlsx(excel) :pypi:`pytest-xpara` - *last release*: Oct 30, 2017, + *last release*: Aug 07, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -11844,7 +11876,7 @@ This list contains 1493 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Jul 20, 2024, + *last release*: Aug 03, 2024, *status*: N/A, *requires*: pytest~=8.2.2 From b08b41cefb5e83271a055bf6a22c79d52a06a8c3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 21:53:50 +0200 Subject: [PATCH 0846/1271] [pre-commit.ci] pre-commit autoupdate (#12712) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.6 → v0.5.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.6...v0.5.7) * Apply pyupgrade latest changes Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 2 +- src/_pytest/cacheprovider.py | 6 ++---- src/_pytest/capture.py | 22 +++++++++++----------- src/_pytest/doctest.py | 2 +- src/_pytest/logging.py | 22 ++++++++++------------ src/_pytest/monkeypatch.py | 4 ++-- src/_pytest/pytester.py | 4 ++-- src/_pytest/python.py | 8 ++++---- src/_pytest/recwarn.py | 2 +- src/_pytest/skipping.py | 2 +- src/_pytest/terminal.py | 4 ++-- src/_pytest/threadexception.py | 8 ++++---- src/_pytest/tmpdir.py | 2 +- src/_pytest/unittest.py | 4 ++-- src/_pytest/unraisableexception.py | 8 ++++---- src/_pytest/warnings.py | 8 ++++---- testing/conftest.py | 2 +- testing/io/test_terminalwriter.py | 4 +--- testing/test_assertrewrite.py | 2 +- testing/test_cacheprovider.py | 2 +- testing/test_capture.py | 2 +- testing/test_conftest.py | 4 +--- testing/test_monkeypatch.py | 2 +- testing/test_pathlib.py | 2 +- 24 files changed, 60 insertions(+), 68 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f27c46f3a54..0e36d1e6137 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.6" + rev: "v0.5.7" hooks: - id: ruff args: ["--fix"] diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 20bb262e05d..7190810570e 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -369,7 +369,7 @@ def pytest_collectreport(self, report: CollectReport) -> None: @hookimpl(wrapper=True, tryfirst=True) def pytest_collection_modifyitems( self, config: Config, items: list[nodes.Item] - ) -> Generator[None, None, None]: + ) -> Generator[None]: res = yield if not self.active: @@ -439,9 +439,7 @@ def __init__(self, config: Config) -> None: self.cached_nodeids = set(config.cache.get("cache/nodeids", [])) @hookimpl(wrapper=True, tryfirst=True) - def pytest_collection_modifyitems( - self, items: list[nodes.Item] - ) -> Generator[None, None, None]: + def pytest_collection_modifyitems(self, items: list[nodes.Item]) -> Generator[None]: res = yield if self.active: diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index b9652843279..506c0b3d287 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -135,7 +135,7 @@ def _reopen_stdio(f, mode): @hookimpl(wrapper=True) -def pytest_load_initial_conftests(early_config: Config) -> Generator[None, None, None]: +def pytest_load_initial_conftests(early_config: Config) -> Generator[None]: ns = early_config.known_args_namespace if ns.capture == "fd": _windowsconsoleio_workaround(sys.stdout) @@ -818,7 +818,7 @@ def resume_fixture(self) -> None: # Helper context managers @contextlib.contextmanager - def global_and_fixture_disabled(self) -> Generator[None, None, None]: + def global_and_fixture_disabled(self) -> Generator[None]: """Context manager to temporarily disable global and current fixture capturing.""" do_fixture = self._capture_fixture and self._capture_fixture._is_started() if do_fixture: @@ -835,7 +835,7 @@ def global_and_fixture_disabled(self) -> Generator[None, None, None]: self.resume_fixture() @contextlib.contextmanager - def item_capture(self, when: str, item: Item) -> Generator[None, None, None]: + def item_capture(self, when: str, item: Item) -> Generator[None]: self.resume_global_capture() self.activate_fixture() try: @@ -870,17 +870,17 @@ def pytest_make_collect_report( return rep @hookimpl(wrapper=True) - def pytest_runtest_setup(self, item: Item) -> Generator[None, None, None]: + def pytest_runtest_setup(self, item: Item) -> Generator[None]: with self.item_capture("setup", item): return (yield) @hookimpl(wrapper=True) - def pytest_runtest_call(self, item: Item) -> Generator[None, None, None]: + def pytest_runtest_call(self, item: Item) -> Generator[None]: with self.item_capture("call", item): return (yield) @hookimpl(wrapper=True) - def pytest_runtest_teardown(self, item: Item) -> Generator[None, None, None]: + def pytest_runtest_teardown(self, item: Item) -> Generator[None]: with self.item_capture("teardown", item): return (yield) @@ -962,7 +962,7 @@ def _is_started(self) -> bool: return False @contextlib.contextmanager - def disabled(self) -> Generator[None, None, None]: + def disabled(self) -> Generator[None]: """Temporarily disable capturing while inside the ``with`` block.""" capmanager: CaptureManager = self.request.config.pluginmanager.getplugin( "capturemanager" @@ -975,7 +975,7 @@ def disabled(self) -> Generator[None, None, None]: @fixture -def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]: +def capsys(request: SubRequest) -> Generator[CaptureFixture[str]]: r"""Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsys.readouterr()`` method @@ -1003,7 +1003,7 @@ def test_output(capsys): @fixture -def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, None]: +def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes]]: r"""Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -1031,7 +1031,7 @@ def test_output(capsysbinary): @fixture -def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]: +def capfd(request: SubRequest) -> Generator[CaptureFixture[str]]: r"""Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -1059,7 +1059,7 @@ def test_system_echo(capfd): @fixture -def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, None]: +def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes]]: r"""Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index cb46d9a3bb5..675f4322328 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -467,7 +467,7 @@ def _is_mocked(obj: object) -> bool: @contextmanager -def _patch_unwrap_mock_aware() -> Generator[None, None, None]: +def _patch_unwrap_mock_aware() -> Generator[None]: """Context manager which replaces ``inspect.unwrap`` with a version that's aware of mock objects and doesn't recurse into them.""" real_unwrap = inspect.unwrap diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 44af8ff2041..9f3417e9af2 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -554,9 +554,7 @@ def set_level(self, level: int | str, logger: str | None = None) -> None: self._initial_disabled_logging_level = initial_disabled_logging_level @contextmanager - def at_level( - self, level: int | str, logger: str | None = None - ) -> Generator[None, None, None]: + def at_level(self, level: int | str, logger: str | None = None) -> Generator[None]: """Context manager that sets the level for capturing of logs. After the end of the 'with' statement the level is restored to its original value. @@ -580,7 +578,7 @@ def at_level( logging.disable(original_disable_level) @contextmanager - def filtering(self, filter_: logging.Filter) -> Generator[None, None, None]: + def filtering(self, filter_: logging.Filter) -> Generator[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. @@ -597,7 +595,7 @@ def filtering(self, filter_: logging.Filter) -> Generator[None, None, None]: @fixture -def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture, None, None]: +def caplog(request: FixtureRequest) -> Generator[LogCaptureFixture]: """Access and control log capturing. Captured logs are available through the following properties/methods:: @@ -776,7 +774,7 @@ def _log_cli_enabled(self) -> bool: return True @hookimpl(wrapper=True, tryfirst=True) - def pytest_sessionstart(self) -> Generator[None, None, None]: + def pytest_sessionstart(self) -> Generator[None]: self.log_cli_handler.set_when("sessionstart") with catching_logs(self.log_cli_handler, level=self.log_cli_level): @@ -784,7 +782,7 @@ def pytest_sessionstart(self) -> Generator[None, None, None]: return (yield) @hookimpl(wrapper=True, tryfirst=True) - def pytest_collection(self) -> Generator[None, None, None]: + def pytest_collection(self) -> Generator[None]: self.log_cli_handler.set_when("collection") with catching_logs(self.log_cli_handler, level=self.log_cli_level): @@ -813,7 +811,7 @@ def pytest_runtest_logstart(self) -> None: def pytest_runtest_logreport(self) -> None: self.log_cli_handler.set_when("logreport") - def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None, None, None]: + def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None]: """Implement the internals of the pytest_runtest_xxx() hooks.""" with catching_logs( self.caplog_handler, @@ -834,7 +832,7 @@ def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None, None, Non item.add_report_section(when, "log", log) @hookimpl(wrapper=True) - def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]: + def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None]: self.log_cli_handler.set_when("setup") empty: dict[str, list[logging.LogRecord]] = {} @@ -842,13 +840,13 @@ def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None, None, None]: yield from self._runtest_for(item, "setup") @hookimpl(wrapper=True) - def pytest_runtest_call(self, item: nodes.Item) -> Generator[None, None, None]: + def pytest_runtest_call(self, item: nodes.Item) -> Generator[None]: self.log_cli_handler.set_when("call") yield from self._runtest_for(item, "call") @hookimpl(wrapper=True) - def pytest_runtest_teardown(self, item: nodes.Item) -> Generator[None, None, None]: + def pytest_runtest_teardown(self, item: nodes.Item) -> Generator[None]: self.log_cli_handler.set_when("teardown") try: @@ -862,7 +860,7 @@ def pytest_runtest_logfinish(self) -> None: self.log_cli_handler.set_when("finish") @hookimpl(wrapper=True, tryfirst=True) - def pytest_sessionfinish(self) -> Generator[None, None, None]: + def pytest_sessionfinish(self) -> Generator[None]: self.log_cli_handler.set_when("sessionfinish") with catching_logs(self.log_cli_handler, level=self.log_cli_level): diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index 75b019a3be6..46eb1724e35 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -28,7 +28,7 @@ @fixture -def monkeypatch() -> Generator[MonkeyPatch, None, None]: +def monkeypatch() -> Generator[MonkeyPatch]: """A convenient fixture for monkey-patching. The fixture provides these methods to modify objects, dictionaries, or @@ -135,7 +135,7 @@ def __init__(self) -> None: @classmethod @contextmanager - def context(cls) -> Generator[MonkeyPatch, None, None]: + def context(cls) -> Generator[MonkeyPatch]: """Context manager that returns a new :class:`MonkeyPatch` object which undoes any patching done inside the ``with`` block upon exit. diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 5c6ce5e889f..3f7520ee4ad 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -491,7 +491,7 @@ def pytester( @fixture -def _sys_snapshot() -> Generator[None, None, None]: +def _sys_snapshot() -> Generator[None]: snappaths = SysPathsSnapshot() snapmods = SysModulesSnapshot() yield @@ -500,7 +500,7 @@ def _sys_snapshot() -> Generator[None, None, None]: @fixture -def _config_for_test() -> Generator[Config, None, None]: +def _config_for_test() -> Generator[Config]: from _pytest.config import get_config config = get_config() diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 094113bd1b4..3a8c77fd2f0 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -569,7 +569,7 @@ def _register_setup_module_fixture(self) -> None: if setup_module is None and teardown_module is None: return - def xunit_setup_module_fixture(request) -> Generator[None, None, None]: + def xunit_setup_module_fixture(request) -> Generator[None]: module = request.module if setup_module is not None: _call_with_optional_argument(setup_module, module) @@ -600,7 +600,7 @@ def _register_setup_function_fixture(self) -> None: if setup_function is None and teardown_function is None: return - def xunit_setup_function_fixture(request) -> Generator[None, None, None]: + def xunit_setup_function_fixture(request) -> Generator[None]: if request.instance is not None: # in this case we are bound to an instance, so we need to let # setup_method handle this @@ -781,7 +781,7 @@ def _register_setup_class_fixture(self) -> None: if setup_class is None and teardown_class is None: return - def xunit_setup_class_fixture(request) -> Generator[None, None, None]: + def xunit_setup_class_fixture(request) -> Generator[None]: cls = request.cls if setup_class is not None: func = getimfunc(setup_class) @@ -814,7 +814,7 @@ def _register_setup_method_fixture(self) -> None: if setup_method is None and teardown_method is None: return - def xunit_setup_method_fixture(request) -> Generator[None, None, None]: + def xunit_setup_method_fixture(request) -> Generator[None]: instance = request.instance method = request.function if setup_method is not None: diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 3fc00d94736..85d8de84abb 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -32,7 +32,7 @@ @fixture -def recwarn() -> Generator[WarningsRecorder, None, None]: +def recwarn() -> Generator[WarningsRecorder]: """Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 08fcb283eb2..9818be2ab03 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -245,7 +245,7 @@ def pytest_runtest_setup(item: Item) -> None: @hookimpl(wrapper=True) -def pytest_runtest_call(item: Item) -> Generator[None, None, None]: +def pytest_runtest_call(item: Item) -> Generator[None]: xfailed = item.stash.get(xfailed_key, None) if xfailed is None: item.stash[xfailed_key] = xfailed = evaluate_xfail_marks(item) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index cdda5a90ea1..55ef1ea8eee 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -889,7 +889,7 @@ def _printcollecteditems(self, items: Sequence[Item]) -> None: @hookimpl(wrapper=True) def pytest_sessionfinish( self, session: Session, exitstatus: int | ExitCode - ) -> Generator[None, None, None]: + ) -> Generator[None]: result = yield self._tw.line("") summary_exit_codes = ( @@ -914,7 +914,7 @@ def pytest_sessionfinish( return result @hookimpl(wrapper=True) - def pytest_terminal_summary(self) -> Generator[None, None, None]: + def pytest_terminal_summary(self) -> Generator[None]: self.summary_errors() self.summary_failures() self.summary_xfailures() diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index d78c32c852f..c1ed80387aa 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -62,7 +62,7 @@ def __exit__( del self.args -def thread_exception_runtest_hook() -> Generator[None, None, None]: +def thread_exception_runtest_hook() -> Generator[None]: with catch_threading_exception() as cm: try: yield @@ -83,15 +83,15 @@ def thread_exception_runtest_hook() -> Generator[None, None, None]: @pytest.hookimpl(wrapper=True, trylast=True) -def pytest_runtest_setup() -> Generator[None, None, None]: +def pytest_runtest_setup() -> Generator[None]: yield from thread_exception_runtest_hook() @pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_call() -> Generator[None, None, None]: +def pytest_runtest_call() -> Generator[None]: yield from thread_exception_runtest_hook() @pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_teardown() -> Generator[None, None, None]: +def pytest_runtest_teardown() -> Generator[None]: yield from thread_exception_runtest_hook() diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 91109ea69ef..de0cbcfeb1c 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -256,7 +256,7 @@ def _mk_tmp(request: FixtureRequest, factory: TempPathFactory) -> Path: @fixture def tmp_path( request: FixtureRequest, tmp_path_factory: TempPathFactory -) -> Generator[Path, None, None]: +) -> Generator[Path]: """Return a temporary directory path object which is unique to each test function invocation, created as a sub directory of the base temporary directory. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index aefea1333d9..8cecd4f9339 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -137,7 +137,7 @@ def process_teardown_exceptions() -> None: def unittest_setup_class_fixture( request: FixtureRequest, - ) -> Generator[None, None, None]: + ) -> Generator[None]: cls = request.cls if _is_skipped(cls): reason = cls.__unittest_skip_why__ @@ -178,7 +178,7 @@ def _register_unittest_setup_method_fixture(self, cls: type) -> None: def unittest_setup_method_fixture( request: FixtureRequest, - ) -> Generator[None, None, None]: + ) -> Generator[None]: self = request.instance if _is_skipped(self): reason = self.__unittest_skip_why__ diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index c191703a3de..77a2de20041 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -64,7 +64,7 @@ def __exit__( del self.unraisable -def unraisable_exception_runtest_hook() -> Generator[None, None, None]: +def unraisable_exception_runtest_hook() -> Generator[None]: with catch_unraisable_exception() as cm: try: yield @@ -86,15 +86,15 @@ def unraisable_exception_runtest_hook() -> Generator[None, None, None]: @pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_setup() -> Generator[None, None, None]: +def pytest_runtest_setup() -> Generator[None]: yield from unraisable_exception_runtest_hook() @pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_call() -> Generator[None, None, None]: +def pytest_runtest_call() -> Generator[None]: yield from unraisable_exception_runtest_hook() @pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_teardown() -> Generator[None, None, None]: +def pytest_runtest_teardown() -> Generator[None]: yield from unraisable_exception_runtest_hook() diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index 5c59e55c5db..eeb4772649d 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -30,7 +30,7 @@ def catch_warnings_for_item( ihook, when: Literal["config", "collect", "runtest"], item: Item | None, -) -> Generator[None, None, None]: +) -> Generator[None]: """Context manager that catches warnings generated in the contained execution block. ``item`` can be None if we are not in the context of an item execution. @@ -124,7 +124,7 @@ def pytest_collection(session: Session) -> Generator[None, object, object]: @pytest.hookimpl(wrapper=True) def pytest_terminal_summary( terminalreporter: TerminalReporter, -) -> Generator[None, None, None]: +) -> Generator[None]: config = terminalreporter.config with catch_warnings_for_item( config=config, ihook=config.hook, when="config", item=None @@ -133,7 +133,7 @@ def pytest_terminal_summary( @pytest.hookimpl(wrapper=True) -def pytest_sessionfinish(session: Session) -> Generator[None, None, None]: +def pytest_sessionfinish(session: Session) -> Generator[None]: config = session.config with catch_warnings_for_item( config=config, ihook=config.hook, when="config", item=None @@ -144,7 +144,7 @@ def pytest_sessionfinish(session: Session) -> Generator[None, None, None]: @pytest.hookimpl(wrapper=True) def pytest_load_initial_conftests( early_config: Config, -) -> Generator[None, None, None]: +) -> Generator[None]: with catch_warnings_for_item( config=early_config, ihook=early_config.hook, when="config", item=None ): diff --git a/testing/conftest.py b/testing/conftest.py index 24e5d183094..046bb77a109 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -46,7 +46,7 @@ def reset_colors(monkeypatch: pytest.MonkeyPatch) -> None: @pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_collection_modifyitems(items) -> Generator[None, None, None]: +def pytest_collection_modifyitems(items) -> Generator[None]: """Prefer faster tests. Use a hook wrapper to do this in the beginning, so e.g. --ff still works diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index 043c2d1d904..92cde240a11 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -67,9 +67,7 @@ def test_terminalwriter_not_unicode() -> None: class TestTerminalWriter: @pytest.fixture(params=["path", "stringio"]) - def tw( - self, request, tmp_path: Path - ) -> Generator[terminalwriter.TerminalWriter, None, None]: + def tw(self, request, tmp_path: Path) -> Generator[terminalwriter.TerminalWriter]: if request.param == "path": p = tmp_path.joinpath("tmpfile") f = open(str(p), "w+", encoding="utf8") diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 11688acb6f5..73c11a1a9d8 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1660,7 +1660,7 @@ class TestEarlyRewriteBailout: @pytest.fixture def hook( self, pytestconfig, monkeypatch, pytester: Pytester - ) -> Generator[AssertionRewritingHook, None, None]: + ) -> Generator[AssertionRewritingHook]: """Returns a patched AssertionRewritingHook instance so we can configure its initial paths and track if PathFinder.find_spec has been called. """ diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 72b4265cf75..94bc55d3047 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -69,7 +69,7 @@ def test_cache_writefail_cachefile_silent(self, pytester: Pytester) -> None: cache.set("test/broken", []) @pytest.fixture - def unwritable_cache_dir(self, pytester: Pytester) -> Generator[Path, None, None]: + def unwritable_cache_dir(self, pytester: Pytester) -> Generator[Path]: cache_dir = pytester.path.joinpath(".pytest_cache") cache_dir.mkdir() mode = cache_dir.stat().st_mode diff --git a/testing/test_capture.py b/testing/test_capture.py index fe6bd7d14fa..328de740e8a 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -939,7 +939,7 @@ def test_captureresult() -> None: @pytest.fixture -def tmpfile(pytester: Pytester) -> Generator[BinaryIO, None, None]: +def tmpfile(pytester: Pytester) -> Generator[BinaryIO]: f = pytester.makepyfile("").open("wb+") yield f if not f.closed: diff --git a/testing/test_conftest.py b/testing/test_conftest.py index d51846f2f5f..ea60c1909c2 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -44,9 +44,7 @@ def conftest_setinitial( @pytest.mark.usefixtures("_sys_snapshot") class TestConftestValueAccessGlobal: @pytest.fixture(scope="module", params=["global", "inpackage"]) - def basedir( - self, request, tmp_path_factory: TempPathFactory - ) -> Generator[Path, None, None]: + def basedir(self, request, tmp_path_factory: TempPathFactory) -> Generator[Path]: tmp_path = tmp_path_factory.mktemp("basedir", numbered=True) tmp_path.joinpath("adir/b").mkdir(parents=True) tmp_path.joinpath("adir/conftest.py").write_text( diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 944d91f6e65..7c62d90f2b9 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -14,7 +14,7 @@ @pytest.fixture -def mp() -> Generator[MonkeyPatch, None, None]: +def mp() -> Generator[MonkeyPatch]: cwd = os.getcwd() sys_path = list(sys.path) yield MonkeyPatch() diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 81aba25f78f..377c30ca900 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -125,7 +125,7 @@ class TestImportPath: """ @pytest.fixture(scope="session") - def path1(self, tmp_path_factory: TempPathFactory) -> Generator[Path, None, None]: + def path1(self, tmp_path_factory: TempPathFactory) -> Generator[Path]: path = tmp_path_factory.mktemp("path") self.setuptestfs(path) yield path From 7cb7cfc704ddcbece7b65fbdc6deccff6cc51b62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 18 Aug 2024 01:53:14 +0000 Subject: [PATCH 0847/1271] [automated] Update plugin list (#12720) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 206 ++++++++++++++++++------------- 1 file changed, 119 insertions(+), 87 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6aea0dd86c0..43fa0be55a8 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jul 24, 2024 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Aug 16, 2024 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -111,7 +111,7 @@ This list contains 1497 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Jul 30, 2024 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Aug 09, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -154,7 +154,7 @@ This list contains 1497 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 01, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 17, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -211,7 +211,7 @@ This list contains 1497 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` Pytest plugin for Celery Jul 17, 2024 4 - Beta N/A + :pypi:`pytest-celery` Pytest plugin for Celery Aug 12, 2024 4 - Beta N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -243,14 +243,14 @@ This list contains 1497 plugins. :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Jun 17, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Jul 30, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Aug 15, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Aug 09, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Aug 16, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 @@ -289,7 +289,7 @@ This list contains 1497 plugins. :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Jul 28, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Aug 14, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 @@ -399,21 +399,21 @@ This list contains 1497 plugins. :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Feb 02, 2024 N/A pytest <9.0,>=4.0 - :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Feb 16, 2022 4 - Beta pytest + :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) :pypi:`pytest-docker-compose-v2` Manages Docker containers during your integration tests Feb 28, 2024 4 - Beta pytest<8,>=7.2.2 :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) :pypi:`pytest-docker-fixtures` pytest docker fixtures Apr 03, 2024 3 - Alpha N/A - :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Feb 09, 2022 4 - Beta pytest - :pypi:`pytest-docker-haproxy-fixtures` Pytest fixtures for testing with haproxy. Feb 09, 2022 4 - Beta pytest + :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Aug 12, 2024 4 - Beta pytest + :pypi:`pytest-docker-haproxy-fixtures` Pytest fixtures for testing with haproxy. Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-pexpect` pytest plugin for writing functional tests with pexpect and docker Jan 14, 2019 N/A pytest :pypi:`pytest-docker-postgresql` A simple plugin to use with pytest Sep 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-docker-py` Easy to use, simple to extend, pytest plugin that minimally leverages docker-py. Nov 27, 2018 N/A pytest (==4.0.0) - :pypi:`pytest-docker-registry-fixtures` Pytest fixtures for testing with docker registries. Apr 08, 2022 4 - Beta pytest + :pypi:`pytest-docker-registry-fixtures` Pytest fixtures for testing with docker registries. Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-service` pytest plugin to start docker container Jan 03, 2024 3 - Alpha pytest (>=7.1.3) - :pypi:`pytest-docker-squid-fixtures` Pytest fixtures for testing with squid. Feb 09, 2022 4 - Beta pytest + :pypi:`pytest-docker-squid-fixtures` Pytest fixtures for testing with squid. Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-tools` Docker integration tests for pytest Feb 17, 2022 4 - Beta pytest (>=6.0.1) :pypi:`pytest-docs` Documentation tool for pytest Nov 11, 2018 4 - Beta pytest (>=3.5.0) :pypi:`pytest-docstyle` pytest plugin to run pydocstyle Mar 23, 2020 3 - Alpha N/A @@ -430,7 +430,7 @@ This list contains 1497 plugins. :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) :pypi:`pytest-dot-only-pkcopley` A Pytest marker for only running a single test Oct 27, 2023 N/A N/A - :pypi:`pytest-dpg` pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications Aug 07, 2024 N/A N/A + :pypi:`pytest-dpg` pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications Aug 13, 2024 N/A N/A :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A @@ -457,14 +457,14 @@ This list contains 1497 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 Jul 25, 2024 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. Aug 09, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Aug 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Aug 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Aug 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Aug 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Aug 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Aug 09, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Aug 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Aug 16, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Aug 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Aug 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Aug 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Aug 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Aug 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Aug 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Aug 16, 2024 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) @@ -491,9 +491,11 @@ This list contains 1497 plugins. :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Apr 22, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Jul 02, 2024 4 - Beta pytest>=7 + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Aug 13, 2024 4 - Beta pytest>=7 + :pypi:`pytest-exasol-backend` Aug 14, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-slc` Aug 15, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -558,7 +560,7 @@ This list contains 1497 plugins. :pypi:`pytest-fixture-remover` A LibCST codemod to remove pytest fixtures applied via the usefixtures decorator, as well as its parametrizations. Feb 14, 2024 5 - Production/Stable N/A :pypi:`pytest-fixture-rtttg` Warn or fail on fixture name clash Feb 23, 2022 N/A pytest (>=7.0.1,<8.0.0) :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A - :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 18, 2020 6 - Mature pytest + :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 15, 2024 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Jul 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jul 10, 2023 5 - Production/Stable pytest @@ -571,7 +573,7 @@ This list contains 1497 plugins. :pypi:`pytest-flask-sqlalchemy` A pytest plugin for preserving test isolation in Flask-SQlAlchemy using database transactions. Apr 30, 2022 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flask-sqlalchemy-transactions` Run tests in transactions using pytest, Flask, and SQLalchemy. Aug 02, 2018 4 - Beta pytest (>=3.2.1) :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest - :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Jun 05, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Aug 14, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) :pypi:`pytest-fly` pytest observer Apr 14, 2024 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest @@ -593,7 +595,7 @@ This list contains 1497 plugins. :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A :pypi:`pytest-fzf` fzf-based test selector for pytest Jul 03, 2024 4 - Beta pytest>=6.0.0 :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A - :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Apr 12, 2022 N/A pytest (>=6.0.0) + :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Aug 12, 2024 N/A pytest>=7.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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 @@ -604,7 +606,7 @@ This list contains 1497 plugins. :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. Jul 08, 2024 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest - :pypi:`pytest-gitconfig` Provide a gitconfig sandbox for testing Oct 15, 2023 4 - Beta pytest>=7.1.2 + :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 4 - Beta pytest>=7.1.2 :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-diff` Pytest plugin that allows the user to select the tests affected by a range of git commits Apr 02, 2024 N/A N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest @@ -645,7 +647,7 @@ This list contains 1497 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Aug 08, 2024 3 - Alpha pytest==8.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 17, 2024 3 - Alpha pytest==8.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -668,8 +670,8 @@ This list contains 1497 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Jul 21, 2024 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Jul 25, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A + :pypi:`pytest-httptesting` http_testing framework on top of pytest Aug 10, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-httpx` Send responses to httpx. Feb 21, 2024 5 - Production/Stable pytest <9,>=7 :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest @@ -699,7 +701,7 @@ This list contains 1497 plugins. :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. Jul 05, 2024 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Jul 24, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Aug 12, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest @@ -743,7 +745,7 @@ This list contains 1497 plugins. :pypi:`pytest-jtr` pytest plugin supporting json test report output Jul 21, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest - :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Jun 14, 2023 N/A pytest + :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Aug 14, 2024 N/A pytest :pypi:`pytest-kafkavents` A plugin to send pytest events to Kafka Sep 08, 2021 4 - Beta pytest :pypi:`pytest-kairos` Pytest plugin with random number generation, reproducibility, and test repetition Aug 08, 2024 5 - Production/Stable pytest>=5.0.0 :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) @@ -812,11 +814,12 @@ This list contains 1497 plugins. :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A - :pypi:`pytest-mark-manage` 用例标签化管理 Jul 08, 2024 N/A pytest + :pypi:`pytest-mark-manage` 用例标签化管理 Aug 15, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Aug 06, 2024 N/A N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Aug 01, 2024 5 - Production/Stable pytest + :pypi:`pytest-matchers` Matchers for pytest Aug 16, 2024 N/A N/A :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -976,7 +979,7 @@ This list contains 1497 plugins. :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-performancetotal` A performance plugin for pytest Mar 19, 2024 4 - Beta N/A :pypi:`pytest-persistence` Pytest tool for persistent objects May 23, 2024 N/A N/A - :pypi:`pytest-pexpect` Pytest pexpect plugin. Mar 27, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) @@ -1019,7 +1022,7 @@ This list contains 1497 plugins. :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 11, 2024 5 - Production/Stable pytest >=6.2 + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Aug 14, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-powerpack` Mar 17, 2024 N/A pytest (>=8.1.1,<9.0.0) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) @@ -1101,6 +1104,7 @@ This list contains 1497 plugins. :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jun 27, 2024 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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-record-video` 用例执行过程中录制视频 Aug 15, 2024 N/A N/A :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Jun 19, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A @@ -1195,7 +1199,7 @@ This list contains 1497 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 07, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 13, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1205,7 +1209,7 @@ This list contains 1497 plugins. :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 Feb 01, 2024 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. Aug 07, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 13, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1215,7 +1219,7 @@ This list contains 1497 plugins. :pypi:`pytest-server` test server exec cmd Jun 24, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Jul 19, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-servers` pytest servers Aug 15, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-service` Aug 06, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest @@ -1237,7 +1241,7 @@ This list contains 1497 plugins. :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest :pypi:`pytest-single-file-logging` Allow for multiple processes to log to a single file May 05, 2016 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-skip-markers` Pytest Salt Plugin Jan 04, 2024 5 - Production/Stable pytest >=7.1.0 + :pypi:`pytest-skip-markers` Pytest Salt Plugin Aug 09, 2024 5 - Production/Stable pytest>=7.1.0 :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 @@ -1283,12 +1287,12 @@ This list contains 1497 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 Aug 07, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Aug 14, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jul 10, 2024 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 - :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock May 21, 2024 3 - Alpha pytest>=7.0.0 + :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Aug 10, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 19, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) @@ -1511,7 +1515,7 @@ This list contains 1497 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. Jul 03, 2024 4 - Beta pytest>=7.2.2 :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 with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Aug 03, 2024 N/A pytest~=8.2.2 + :pypi:`pytest-yaml-sanmu` Pytest plugin for generating test cases with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Aug 16, 2024 N/A pytest~=8.2.2 :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) @@ -1817,7 +1821,7 @@ This list contains 1497 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Jul 24, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2076,7 +2080,7 @@ This list contains 1497 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jul 30, 2024, + *last release*: Aug 09, 2024, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 @@ -2377,7 +2381,7 @@ This list contains 1497 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Aug 01, 2024, + *last release*: Aug 17, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2776,7 +2780,7 @@ This list contains 1497 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Jul 17, 2024, + *last release*: Aug 12, 2024, *status*: 4 - Beta, *requires*: N/A @@ -3000,7 +3004,7 @@ This list contains 1497 plugins. A cleanup plugin for pytest :pypi:`pytest-clerk` - *last release*: Jul 30, 2024, + *last release*: Aug 15, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -3049,7 +3053,7 @@ This list contains 1497 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3322,7 +3326,7 @@ This list contains 1497 plugins. Coverage dynamic context support for PyTest, including sub-processes :pypi:`pytest-coveragemarkers` - *last release*: Jul 28, 2024, + *last release*: Aug 14, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -4092,7 +4096,7 @@ This list contains 1497 plugins. Simple pytest fixtures for Docker and Docker Compose based tests :pypi:`pytest-docker-apache-fixtures` - *last release*: Feb 16, 2022, + *last release*: Aug 12, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4141,14 +4145,14 @@ This list contains 1497 plugins. pytest docker fixtures :pypi:`pytest-docker-git-fixtures` - *last release*: Feb 09, 2022, + *last release*: Aug 12, 2024, *status*: 4 - Beta, *requires*: pytest Pytest fixtures for testing with git scm. :pypi:`pytest-docker-haproxy-fixtures` - *last release*: Feb 09, 2022, + *last release*: Aug 12, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4176,7 +4180,7 @@ This list contains 1497 plugins. Easy to use, simple to extend, pytest plugin that minimally leverages docker-py. :pypi:`pytest-docker-registry-fixtures` - *last release*: Apr 08, 2022, + *last release*: Aug 12, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4190,7 +4194,7 @@ This list contains 1497 plugins. pytest plugin to start docker container :pypi:`pytest-docker-squid-fixtures` - *last release*: Feb 09, 2022, + *last release*: Aug 12, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4309,7 +4313,7 @@ This list contains 1497 plugins. A Pytest marker for only running a single test :pypi:`pytest-dpg` - *last release*: Aug 07, 2024, + *last release*: Aug 13, 2024, *status*: N/A, *requires*: N/A @@ -4498,56 +4502,56 @@ This list contains 1497 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Aug 09, 2024, + *last release*: Aug 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4736,12 +4740,19 @@ This list contains 1497 plugins. Parse queries in Lucene and Elasticsearch syntaxes :pypi:`pytest-examples` - *last release*: Jul 02, 2024, + *last release*: Aug 13, 2024, *status*: 4 - Beta, *requires*: pytest>=7 Pytest plugin for testing examples in docstrings and markdown files. + :pypi:`pytest-exasol-backend` + *last release*: Aug 14, 2024, + *status*: N/A, + *requires*: pytest<9,>=7 + + + :pypi:`pytest-exasol-itde` *last release*: Jul 01, 2024, *status*: N/A, @@ -4756,6 +4767,13 @@ This list contains 1497 plugins. + :pypi:`pytest-exasol-slc` + *last release*: Aug 15, 2024, + *status*: N/A, + *requires*: pytest<9,>=7 + + + :pypi:`pytest-excel` *last release*: Jun 18, 2024, *status*: 5 - Production/Stable, @@ -5205,7 +5223,7 @@ This list contains 1497 plugins. Common fixtures for pytest :pypi:`pytest-fixture-tools` - *last release*: Aug 18, 2020, + *last release*: Aug 15, 2024, *status*: 6 - Mature, *requires*: pytest @@ -5296,7 +5314,7 @@ This list contains 1497 plugins. :pypi:`pytest-fluent` - *last release*: Jun 05, 2024, + *last release*: Aug 14, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -5450,9 +5468,9 @@ This list contains 1497 plugins. pytest plugin for apps written with Google's AppEngine :pypi:`pytest-gather-fixtures` - *last release*: Apr 12, 2022, + *last release*: Aug 12, 2024, *status*: N/A, - *requires*: pytest (>=6.0.0) + *requires*: pytest>=7.0.0 set up asynchronous pytest fixtures concurrently @@ -5527,11 +5545,11 @@ This list contains 1497 plugins. Git repository fixture for py.test :pypi:`pytest-gitconfig` - *last release*: Oct 15, 2023, + *last release*: Aug 11, 2024, *status*: 4 - Beta, *requires*: pytest>=7.1.2 - Provide a gitconfig sandbox for testing + Provide a Git config sandbox for testing :pypi:`pytest-gitcov` *last release*: Jan 11, 2020, @@ -5814,7 +5832,7 @@ This list contains 1497 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Aug 08, 2024, + *last release*: Aug 17, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.1 @@ -5975,14 +5993,14 @@ This list contains 1497 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest_httpserver` - *last release*: Jul 21, 2024, + *last release*: Aug 11, 2024, *status*: 3 - Alpha, *requires*: N/A pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: Jul 25, 2024, + *last release*: Aug 10, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -6192,7 +6210,7 @@ This list contains 1497 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Jul 24, 2024, + *last release*: Aug 12, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6500,7 +6518,7 @@ This list contains 1497 plugins. A reusable JupyterHub pytest plugin :pypi:`pytest-kafka` - *last release*: Jun 14, 2023, + *last release*: Aug 14, 2024, *status*: N/A, *requires*: pytest @@ -6983,7 +7001,7 @@ This list contains 1497 plugins. UNKNOWN :pypi:`pytest-mark-manage` - *last release*: Jul 08, 2024, + *last release*: Aug 15, 2024, *status*: N/A, *requires*: pytest @@ -7017,6 +7035,13 @@ This list contains 1497 plugins. Easy way to match captured \`pytest\` output against expectations stored in files + :pypi:`pytest-matchers` + *last release*: Aug 16, 2024, + *status*: N/A, + *requires*: N/A + + Matchers for pytest + :pypi:`pytest-match-skip` *last release*: May 15, 2019, *status*: 4 - Beta, @@ -8131,7 +8156,7 @@ This list contains 1497 plugins. Pytest tool for persistent objects :pypi:`pytest-pexpect` - *last release*: Mar 27, 2024, + *last release*: Aug 13, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -8432,9 +8457,9 @@ This list contains 1497 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: Mar 11, 2024, + *last release*: Aug 14, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6.2 + *requires*: pytest>=6.2 Postgresql fixtures and fixture factories for Pytest. @@ -9005,6 +9030,13 @@ This list contains 1497 plugins. Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal + :pypi:`pytest-record-video` + *last release*: Aug 15, 2024, + *status*: N/A, + *requires*: N/A + + 用例执行过程中录制视频 + :pypi:`pytest-redis` *last release*: Jun 19, 2024, *status*: 5 - Production/Stable, @@ -9664,7 +9696,7 @@ This list contains 1497 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Aug 07, 2024, + *last release*: Aug 13, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9734,7 +9766,7 @@ This list contains 1497 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Aug 07, 2024, + *last release*: Aug 13, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9804,7 +9836,7 @@ This list contains 1497 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Jul 19, 2024, + *last release*: Aug 15, 2024, *status*: 3 - Alpha, *requires*: pytest>=6.2 @@ -9958,9 +9990,9 @@ This list contains 1497 plugins. Allow for multiple processes to log to a single file :pypi:`pytest-skip-markers` - *last release*: Jan 04, 2024, + *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.1.0 + *requires*: pytest>=7.1.0 Pytest Salt Plugin @@ -10280,7 +10312,7 @@ This list contains 1497 plugins. :pypi:`pytest-splunk-addon` - *last release*: Aug 07, 2024, + *last release*: Aug 14, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10315,7 +10347,7 @@ This list contains 1497 plugins. pytest plugin with sqlalchemy related fixtures :pypi:`pytest-sqlalchemy-mock` - *last release*: May 21, 2024, + *last release*: Aug 10, 2024, *status*: 3 - Alpha, *requires*: pytest>=7.0.0 @@ -11876,7 +11908,7 @@ This list contains 1497 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Aug 03, 2024, + *last release*: Aug 16, 2024, *status*: N/A, *requires*: pytest~=8.2.2 From 33db65c112e5d76e89dd45024e272df214d2ea9c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 21:06:03 -0300 Subject: [PATCH 0848/1271] [pre-commit.ci] pre-commit autoupdate (#12725) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.5.7 → v0.6.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.5.7...v0.6.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0e36d1e6137..a841a4a9a0f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.5.7" + rev: "v0.6.1" hooks: - id: ruff args: ["--fix"] From 51845fc70dba0fba27387e21e2db39d583892dec Mon Sep 17 00:00:00 2001 From: Stefaan Lippens Date: Thu, 22 Aug 2024 17:55:35 +0200 Subject: [PATCH 0849/1271] docs: clarify `pytest_deselected`/`pytest_collection_modifyitems` usage (#12729) Closes #12663 --- changelog/12663.doc.rst | 1 + src/_pytest/hookspec.py | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 changelog/12663.doc.rst diff --git a/changelog/12663.doc.rst b/changelog/12663.doc.rst new file mode 100644 index 00000000000..e665bc67a10 --- /dev/null +++ b/changelog/12663.doc.rst @@ -0,0 +1 @@ +Clarify that the `pytest_deselected` hook should be called from `pytest_collection_modifyitems` hook implementations when items are deselected. diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 99614899994..0a41b0aca47 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -274,6 +274,11 @@ def pytest_collection_modifyitems( """Called after collection has been performed. May filter or re-order the items in-place. + When items are deselected (filtered out from ``items``), + the hook :hook:`pytest_deselected` must be called explicitly + with the deselected items to properly notify other plugins, + e.g. with ``config.hook.pytest_deselected(deselected_items)``. + :param session: The pytest session object. :param config: The pytest config object. :param items: List of item objects. @@ -454,6 +459,12 @@ def pytest_collectreport(report: CollectReport) -> None: def pytest_deselected(items: Sequence[Item]) -> None: """Called for deselected test items, e.g. by keyword. + Note that this hook has two integration aspects for plugins: + + - it can be *implemented* to be notified of deselected items + - it must be *called* from :hook:`pytest_collection_modifyitems` + implementations when items are deselected (to properly notify other plugins). + May be called multiple times. :param items: From 05c43afae25b8ee7da3f69978802ce0f5e562e4e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:32:54 +0200 Subject: [PATCH 0850/1271] [pre-commit.ci] pre-commit autoupdate (#12741) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.1 → v0.6.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.1...v0.6.2) - [github.com/pre-commit/mirrors-mypy: v1.11.1 → v1.11.2](https://github.com/pre-commit/mirrors-mypy/compare/v1.11.1...v1.11.2) * Fix sphinx with a more robust fix Until https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 is resolved. Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 4 ++-- doc/en/broken-dep-constraints.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a841a4a9a0f..938b0bf407b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.1" + rev: "v0.6.2" hooks: - id: ruff args: ["--fix"] @@ -21,7 +21,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.1 + rev: v1.11.2 hooks: - id: mypy files: ^(src/|testing/|scripts/) diff --git a/doc/en/broken-dep-constraints.txt b/doc/en/broken-dep-constraints.txt index f7c3211a9a0..3a8d2c34b5a 100644 --- a/doc/en/broken-dep-constraints.txt +++ b/doc/en/broken-dep-constraints.txt @@ -3,4 +3,4 @@ # Pin towncrier temporarily due to incompatibility with sphinxcontrib-towncrier: # https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 -towncrier!=24.7.0,!=24.7.1 +towncrier<24.7 From 8a834a26e932ef00acc9a354ded4efd675597429 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:32:46 +0000 Subject: [PATCH 0851/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#12739) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.23.8 to 0.24.0. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.23.8...v0.24.0) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index bd554c6307d..c48b55c0ae2 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.4.0 django==5.1 -pytest-asyncio==0.23.8 +pytest-asyncio==0.24.0 pytest-bdd==7.2.0 pytest-cov==5.0.0 pytest-django==4.8.0 From e2483991561dfd7adbad9d78d7ba9585acd1547c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Brigitta=20Sip=C5=91cz?= Date: Wed, 28 Aug 2024 14:30:47 -0700 Subject: [PATCH 0852/1271] MAINT: adding back Python 3.13 classifier (#12743) * adding max_supported_python to pyproject-fmt config --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index f3eba4a08a8..ccd349fcdc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ classifiers = [ "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing", "Topic :: Utilities", @@ -313,6 +314,7 @@ ignore = "W009" [tool.pyproject-fmt] indent = 4 +max_supported_python = "3.13" [tool.pytest.ini_options] minversion = "2.0" From ab259a36e3359659e4568358fb0e9d43b10be5de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 Aug 2024 21:34:09 +0000 Subject: [PATCH 0853/1271] [automated] Update plugin list (#12738) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 210 +++++++++++++++++-------------- 1 file changed, 113 insertions(+), 97 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 43fa0be55a8..d425454ea87 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.0.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Aug 22, 2024 4 - Beta pytest<9,>=8.2 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -154,7 +154,7 @@ This list contains 1501 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 17, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 22, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -256,7 +256,7 @@ This list contains 1501 plugins. :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A - :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Nov 29, 2022 4 - Beta pytest (>=4.6.0) + :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Aug 21, 2024 4 - Beta pytest>=4.6.0 :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A @@ -293,7 +293,6 @@ This list contains 1501 plugins. :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 - :pypi:`pytest-cppython` A pytest plugin that imports CPPython testing types Mar 14, 2024 N/A N/A :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -317,7 +316,7 @@ This list contains 1501 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Aug 07, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Aug 20, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -333,7 +332,7 @@ This list contains 1501 plugins. :pypi:`pytest-dataset` Plugin for loading different datasets for pytest by prefix from json or yaml files Sep 01, 2023 5 - Production/Stable N/A :pypi:`pytest-data-suites` Class-based pytest parametrization Apr 06, 2024 N/A pytest<9.0,>=6.0 :pypi:`pytest-datatest` A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). Oct 15, 2020 4 - Beta pytest (>=3.3) - :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Dec 04, 2019 N/A N/A + :pypi:`pytest-db` Session scope fixture "db" for mysql query or change Aug 22, 2024 N/A pytest :pypi:`pytest-dbfixtures` Databases fixtures plugin for py.test. Dec 07, 2016 4 - Beta N/A :pypi:`pytest-db-plugin` Nov 27, 2021 N/A pytest (>=5.0) :pypi:`pytest-dbt` Unit test dbt models with standard python tooling Jun 08, 2023 2 - Pre-Alpha pytest (>=7.0.0,<8.0.0) @@ -453,18 +452,19 @@ This list contains 1501 plugins. :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Jun 09, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 15, 2024 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-elasticsearch-test` Elasticsearch fixtures and fixture factories for Pytest. Aug 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jul 25, 2024 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. Aug 16, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Aug 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Aug 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Aug 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Aug 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Aug 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Aug 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Aug 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Aug 19, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Aug 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Aug 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Aug 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Aug 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Aug 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Aug 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Aug 19, 2024 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) @@ -492,7 +492,7 @@ This list contains 1501 plugins. :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Apr 22, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Aug 13, 2024 4 - Beta pytest>=7 - :pypi:`pytest-exasol-backend` Aug 14, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-backend` Aug 23, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-slc` Aug 15, 2024 N/A pytest<9,>=7 @@ -595,7 +595,7 @@ This list contains 1501 plugins. :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A :pypi:`pytest-fzf` fzf-based test selector for pytest Jul 03, 2024 4 - Beta pytest>=6.0.0 :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A - :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Aug 12, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Aug 18, 2024 N/A pytest>=7.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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 @@ -657,7 +657,7 @@ This list contains 1501 plugins. :pypi:`pytest-hoverfly-wrapper` Integrates the Hoverfly HTTP proxy into Pytest Feb 27, 2023 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-hpfeeds` Helpers for testing hpfeeds in your python project Feb 28, 2023 4 - Beta pytest (>=6.2.4,<7.0.0) :pypi:`pytest-html` pytest plugin for generating HTML reports Nov 07, 2023 5 - Production/Stable pytest>=7.0.0 - :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 01, 2023 5 - Production/Stable N/A + :pypi:`pytest-html-cn` pytest plugin for generating HTML reports Aug 19, 2024 5 - Production/Stable pytest!=6.0.0,>=5.0 :pypi:`pytest-html-lee` optimized pytest plugin for generating HTML reports Jun 30, 2020 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-html-merger` Pytest HTML reports merging utility Jul 12, 2024 N/A N/A :pypi:`pytest-html-object-storage` Pytest report plugin for send HTML report on object-storage Jan 17, 2024 5 - Production/Stable N/A @@ -665,7 +665,7 @@ This list contains 1501 plugins. :pypi:`pytest-html-reporter` Generates a static html report based on pytest framework Feb 13, 2022 N/A N/A :pypi:`pytest-html-report-merger` May 22, 2024 N/A N/A :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A - :pypi:`pytest-http` Fixture "http" for http requests Dec 05, 2019 N/A N/A + :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A @@ -699,9 +699,9 @@ This list contains 1501 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :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. Jul 05, 2024 5 - Production/Stable pytest + :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Aug 19, 2024 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 22, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Aug 12, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Aug 20, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest @@ -718,11 +718,12 @@ This list contains 1501 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Aug 02, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Aug 21, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A + :pypi:`pytest-iteration` Add iteration mark for tests Aug 22, 2024 N/A pytest :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A :pypi:`pytest_jar_yuan` A allure and pytest used package Dec 12, 2022 N/A N/A :pypi:`pytest-jasmine` Run jasmine tests from your pytest test suite Nov 04, 2017 1 - Planning N/A @@ -736,7 +737,7 @@ This list contains 1501 plugins. :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-json` Generate JSON test reports Jan 18, 2016 4 - Beta N/A - :pypi:`pytest-json-ctrf` Pytest plugin to generate json report in CTRF (Common Test Report Format) Jun 15, 2024 N/A pytest>6.0.0 + :pypi:`pytest-json-ctrf` Pytest plugin to generate json report in CTRF (Common Test Report Format) Aug 17, 2024 N/A pytest>6.0.0 :pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Mar 14, 2023 4 - Beta N/A :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) @@ -789,7 +790,7 @@ This list contains 1501 plugins. :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 May 19, 2024 5 - Production/Stable pytest - :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 12, 2023 4 - Beta N/A + :pypi:`pytest-localserver` pytest plugin to test server connections locally. Aug 17, 2024 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lock` pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. Feb 03, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-lockable` lockable resource plugin for pytest Jan 24, 2024 5 - Production/Stable pytest @@ -819,7 +820,7 @@ This list contains 1501 plugins. :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Aug 06, 2024 N/A N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Aug 01, 2024 5 - Production/Stable pytest - :pypi:`pytest-matchers` Matchers for pytest Aug 16, 2024 N/A N/A + :pypi:`pytest-matchers` Matchers for pytest Aug 24, 2024 N/A pytest<9.0,>=7.0 :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -940,14 +941,14 @@ This list contains 1501 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 Apr 02, 2024 4 - Beta pytest>=5.0; python_version < "3.10" + :pypi:`pytest-order` pytest plugin to run your tests in a specific order Aug 22, 2024 5 - Production/Stable 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 :pypi:`pytest-ot` A pytest plugin for instrumenting test runs via OpenTelemetry Mar 21, 2024 N/A pytest; extra == "dev" :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Mar 18, 2024 N/A pytest==8.1.1 :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A - :pypi:`pytest-owner` Add owner mark for tests Apr 25, 2022 N/A N/A + :pypi:`pytest-owner` Add owner mark for tests Aug 19, 2024 N/A pytest :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A :pypi:`pytest-pahrametahrize` Parametrize your tests with a Boston accent. Nov 24, 2021 4 - Beta pytest (>=6.0,<7.0) :pypi:`pytest-parallel` a pytest plugin for parallel and concurrent testing Oct 10, 2021 3 - Alpha pytest (>=3.0.0) @@ -978,7 +979,7 @@ This list contains 1501 plugins. :pypi:`pytest-perf` Run performance tests against the mainline code. May 20, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) :pypi:`pytest-performancetotal` A performance plugin for pytest Mar 19, 2024 4 - Beta N/A - :pypi:`pytest-persistence` Pytest tool for persistent objects May 23, 2024 N/A N/A + :pypi:`pytest-persistence` Pytest tool for persistent objects Aug 21, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) @@ -1019,7 +1020,6 @@ This list contains 1501 plugins. :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pook` Pytest plugin for pook Feb 15, 2024 4 - Beta pytest :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest - :pypi:`pytest-porringer` Jan 18, 2024 N/A pytest>=7.4.4 :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Aug 14, 2024 5 - Production/Stable pytest>=6.2 @@ -1030,7 +1030,7 @@ This list contains 1501 plugins. :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Aug 25, 2023 5 - Production/Stable pytest>=7.4 - :pypi:`pytest-priority` pytest plugin for add priority for tests Jul 23, 2023 N/A N/A + :pypi:`pytest-priority` pytest plugin for add priority for tests Aug 19, 2024 N/A pytest :pypi:`pytest-proceed` Apr 10, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest @@ -1064,7 +1064,7 @@ This list contains 1501 plugins. :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report May 05, 2024 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Jan 26, 2024 4 - Beta pytest >=7.0.0 - :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Jan 02, 2024 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Aug 17, 2024 N/A pytest<9.0.0,>=8.3.2 :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) :pypi:`pytest-pythonhashseed` Pytest plugin to set PYTHONHASHSEED env var. Feb 25, 2024 4 - Beta pytest>=3.0.0 @@ -1100,7 +1100,7 @@ This list contains 1501 plugins. :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jun 07, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A - :pypi:`pytest-reana` Pytest fixtures for REANA. Mar 14, 2024 3 - Alpha N/A + :pypi:`pytest-reana` Pytest fixtures for REANA. Aug 21, 2024 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jun 27, 2024 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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 @@ -1174,7 +1174,7 @@ This list contains 1501 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Jul 01, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 21, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1205,6 +1205,7 @@ This list contains 1501 plugins. :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 Feb 16, 2024 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-scrutinize` Scrutinize your pytest test suites for slow fixtures, tests and more. Aug 19, 2024 4 - Beta pytest>=6 :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 Feb 01, 2024 5 - Production/Stable pytest>=6.0.0 @@ -1304,6 +1305,7 @@ This list contains 1501 plugins. :pypi:`pytest-static` pytest-static Aug 09, 2024 1 - Planning pytest<8.0.0,>=7.4.3 :pypi:`pytest-stats` Collects tests metadata for future analysis, easy to extend for any data store Jul 18, 2024 N/A pytest>=8.0.0 :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) + :pypi:`pytest-status` Add status mark for tests Aug 22, 2024 N/A pytest :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A @@ -1327,7 +1329,6 @@ This list contains 1501 plugins. :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A - :pypi:`pytest-synodic` Synodic Pytest utilities Mar 09, 2024 N/A pytest>=8.0.2 :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A :pypi:`pytest_tagging` a pytest plugin to tag tests Apr 08, 2024 N/A pytest<8.0.0,>=7.1.3 @@ -1379,7 +1380,7 @@ This list contains 1501 plugins. :pypi:`pytest-testslide` TestSlide fixture for pytest Jan 07, 2021 5 - Production/Stable pytest (~=6.2) :pypi:`pytest-test-this` Plugin for py.test to run relevant tests, based on naively checking if a test contains a reference to the symbol you supply Sep 15, 2019 2 - Pre-Alpha pytest (>=2.3) :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Jul 29, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Aug 20, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 22, 2024 4 - Beta pytest>=8.0.0 @@ -1530,6 +1531,7 @@ This list contains 1501 plugins. :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) + :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Aug 20, 2024 N/A pytest :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) @@ -2080,9 +2082,9 @@ This list contains 1501 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Aug 09, 2024, + *last release*: Aug 22, 2024, *status*: 4 - Beta, - *requires*: pytest<9,>=7.0.0 + *requires*: pytest<9,>=8.2 Pytest support for asyncio @@ -2381,7 +2383,7 @@ This list contains 1501 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Aug 17, 2024, + *last release*: Aug 22, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3095,9 +3097,9 @@ This list contains 1501 plugins. pytest plugin to add source code sanity checks (pep8 and friends) :pypi:`pytest-codecov` - *last release*: Nov 29, 2022, + *last release*: Aug 21, 2024, *status*: 4 - Beta, - *requires*: pytest (>=4.6.0) + *requires*: pytest>=4.6.0 Pytest plugin for uploading pytest-cov results to codecov.io @@ -3353,13 +3355,6 @@ This list contains 1501 plugins. Use pytest's runner to discover and execute C++ tests - :pypi:`pytest-cppython` - *last release*: Mar 14, 2024, - *status*: N/A, - *requires*: N/A - - A pytest plugin that imports CPPython testing types - :pypi:`pytest-cqase` *last release*: Aug 22, 2022, *status*: N/A, @@ -3522,7 +3517,7 @@ This list contains 1501 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Aug 07, 2024, + *last release*: Aug 20, 2024, *status*: 4 - Beta, *requires*: pytest @@ -3634,9 +3629,9 @@ This list contains 1501 plugins. A pytest plugin for test driven data-wrangling (this is the development version of datatest's pytest integration). :pypi:`pytest-db` - *last release*: Dec 04, 2019, + *last release*: Aug 22, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest Session scope fixture "db" for mysql query or change @@ -4473,6 +4468,13 @@ This list contains 1501 plugins. Elasticsearch fixtures and fixture factories for Pytest. + :pypi:`pytest-elasticsearch-test` + *last release*: Aug 21, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=7.0 + + Elasticsearch fixtures and fixture factories for Pytest. + :pypi:`pytest-elements` *last release*: Jan 13, 2021, *status*: N/A, @@ -4502,56 +4504,56 @@ This list contains 1501 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Aug 16, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Aug 16, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Aug 16, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Aug 16, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Aug 16, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Aug 16, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Aug 16, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Aug 16, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4747,7 +4749,7 @@ This list contains 1501 plugins. Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-exasol-backend` - *last release*: Aug 14, 2024, + *last release*: Aug 23, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -5468,7 +5470,7 @@ This list contains 1501 plugins. pytest plugin for apps written with Google's AppEngine :pypi:`pytest-gather-fixtures` - *last release*: Aug 12, 2024, + *last release*: Aug 18, 2024, *status*: N/A, *requires*: pytest>=7.0.0 @@ -5902,9 +5904,9 @@ This list contains 1501 plugins. pytest plugin for generating HTML reports :pypi:`pytest-html-cn` - *last release*: Aug 01, 2023, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest!=6.0.0,>=5.0 pytest plugin for generating HTML reports @@ -5958,9 +5960,9 @@ This list contains 1501 plugins. pytest plugin for generating HTML reports :pypi:`pytest-http` - *last release*: Dec 05, 2019, + *last release*: Aug 22, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest Fixture "http" for http requests @@ -6196,7 +6198,7 @@ This list contains 1501 plugins. A pytest plugin for writing inline tests. :pypi:`pytest-inmanta` - *last release*: Jul 05, 2024, + *last release*: Aug 19, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -6210,7 +6212,7 @@ This list contains 1501 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Aug 12, 2024, + *last release*: Aug 20, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6329,7 +6331,7 @@ This list contains 1501 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Aug 02, 2024, + *last release*: Aug 21, 2024, *status*: N/A, *requires*: pytest @@ -6363,6 +6365,13 @@ This list contains 1501 plugins. Nicer list and iterable assertion messages for pytest + :pypi:`pytest-iteration` + *last release*: Aug 22, 2024, + *status*: N/A, + *requires*: pytest + + Add iteration mark for tests + :pypi:`pytest-iters` *last release*: May 24, 2022, *status*: N/A, @@ -6455,7 +6464,7 @@ This list contains 1501 plugins. Generate JSON test reports :pypi:`pytest-json-ctrf` - *last release*: Jun 15, 2024, + *last release*: Aug 17, 2024, *status*: N/A, *requires*: pytest>6.0.0 @@ -6826,7 +6835,7 @@ This list contains 1501 plugins. A PyTest plugin which provides an FTP fixture for your tests :pypi:`pytest-localserver` - *last release*: Oct 12, 2023, + *last release*: Aug 17, 2024, *status*: 4 - Beta, *requires*: N/A @@ -7036,9 +7045,9 @@ This list contains 1501 plugins. Easy way to match captured \`pytest\` output against expectations stored in files :pypi:`pytest-matchers` - *last release*: Aug 16, 2024, + *last release*: Aug 24, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest<9.0,>=7.0 Matchers for pytest @@ -7883,8 +7892,8 @@ This list contains 1501 plugins. A pytest plugin for orchestrating tests :pypi:`pytest-order` - *last release*: Apr 02, 2024, - *status*: 4 - Beta, + *last release*: Aug 22, 2024, + *status*: 5 - Production/Stable, *requires*: pytest>=5.0; python_version < "3.10" pytest plugin to run your tests in a specific order @@ -7932,9 +7941,9 @@ This list contains 1501 plugins. Pytest mark to override a value of an environment variable. :pypi:`pytest-owner` - *last release*: Apr 25, 2022, + *last release*: Aug 19, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest Add owner mark for tests @@ -8149,7 +8158,7 @@ This list contains 1501 plugins. A performance plugin for pytest :pypi:`pytest-persistence` - *last release*: May 23, 2024, + *last release*: Aug 21, 2024, *status*: N/A, *requires*: N/A @@ -8435,13 +8444,6 @@ This list contains 1501 plugins. A pytest plugin to help with testing pop projects - :pypi:`pytest-porringer` - *last release*: Jan 18, 2024, - *status*: N/A, - *requires*: pytest>=7.4.4 - - - :pypi:`pytest-portion` *last release*: Jan 28, 2021, *status*: 4 - Beta, @@ -8513,9 +8515,9 @@ This list contains 1501 plugins. pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) :pypi:`pytest-priority` - *last release*: Jul 23, 2023, + *last release*: Aug 19, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest pytest plugin for add priority for tests @@ -8751,9 +8753,9 @@ This list contains 1501 plugins. Pytest plugin for type checking code with Pyright :pypi:`pytest-pyspec` - *last release*: Jan 02, 2024, + *last release*: Aug 17, 2024, *status*: N/A, - *requires*: pytest (>=7.2.1,<8.0.0) + *requires*: pytest<9.0.0,>=8.3.2 A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". @@ -9003,7 +9005,7 @@ This list contains 1501 plugins. Test your README.md file :pypi:`pytest-reana` - *last release*: Mar 14, 2024, + *last release*: Aug 21, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -9521,7 +9523,7 @@ This list contains 1501 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Jul 01, 2024, + *last release*: Aug 21, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9737,6 +9739,13 @@ This list contains 1501 plugins. Saves a screenshot when a test case from a pytest execution fails + :pypi:`pytest-scrutinize` + *last release*: Aug 19, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6 + + Scrutinize your pytest test suites for slow fixtures, tests and more. + :pypi:`pytest-securestore` *last release*: Nov 08, 2021, *status*: 4 - Beta, @@ -10430,6 +10439,13 @@ This list contains 1501 plugins. pytest plugin for reporting to graphite + :pypi:`pytest-status` + *last release*: Aug 22, 2024, + *status*: N/A, + *requires*: pytest + + Add status mark for tests + :pypi:`pytest-stepfunctions` *last release*: May 08, 2021, *status*: 4 - Beta, @@ -10591,13 +10607,6 @@ This list contains 1501 plugins. pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. - :pypi:`pytest-synodic` - *last release*: Mar 09, 2024, - *status*: N/A, - *requires*: pytest>=8.0.2 - - Synodic Pytest utilities - :pypi:`pytest-system-statistics` *last release*: Feb 16, 2022, *status*: 5 - Production/Stable, @@ -10956,7 +10965,7 @@ This list contains 1501 plugins. A plugin that allows coll test data for use on Test Tracer :pypi:`pytest-test-tracer-for-pytest-bdd` - *last release*: Jul 29, 2024, + *last release*: Aug 20, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -12012,6 +12021,13 @@ This list contains 1501 plugins. Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. + :pypi:`pytest-zephyr-scale-integration` + *last release*: Aug 20, 2024, + *status*: N/A, + *requires*: pytest + + A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest + :pypi:`pytest-zest` *last release*: Nov 17, 2022, *status*: N/A, From c947145fbb4aeec810a259b19f70fcb52fd53ad4 Mon Sep 17 00:00:00 2001 From: Avasam Date: Thu, 29 Aug 2024 07:54:47 -0400 Subject: [PATCH 0854/1271] Replaced `typing.Self` with `typing_extensions.Self` (#12744) Fix incorrect Self import from typing instead of typing_extensions. --------- Co-authored-by: Bruno Oliveira --- changelog/12744.bugfix.rst | 1 + src/_pytest/doctest.py | 3 ++- src/_pytest/nodes.py | 2 +- src/_pytest/python.py | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 changelog/12744.bugfix.rst diff --git a/changelog/12744.bugfix.rst b/changelog/12744.bugfix.rst new file mode 100644 index 00000000000..7814b59c180 --- /dev/null +++ b/changelog/12744.bugfix.rst @@ -0,0 +1 @@ +Fixed typing compatibility with Python 3.9 or less -- replaced `typing.Self` with `typing_extensions.Self` -- by :user:`Avasam` diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 675f4322328..384dea976ad 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -44,7 +44,8 @@ if TYPE_CHECKING: import doctest - from typing import Self + + from typing_extensions import Self DOCTEST_REPORT_CHOICE_NONE = "none" DOCTEST_REPORT_CHOICE_CDIFF = "cdiff" diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index bbde2664b90..cc678695848 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -43,7 +43,7 @@ if TYPE_CHECKING: - from typing import Self + from typing_extensions import Self # Imported here due to circular import. from _pytest.main import Session diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 3a8c77fd2f0..6507c299225 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -78,7 +78,7 @@ if TYPE_CHECKING: - from typing import Self + from typing_extensions import Self def pytest_addoption(parser: Parser) -> None: From 419bc7a7c39d21af8a2b7cf29928ee93b7e02b19 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 29 Aug 2024 17:51:54 -0300 Subject: [PATCH 0855/1271] Use oldest supported Python in mypy pre-commit checks (#12747) Follow up to #12744, this ensures type checking works at the oldest Python version supported by pytest. --- .pre-commit-config.yaml | 1 + src/_pytest/main.py | 2 +- src/_pytest/runner.py | 4 ++-- testing/test_runner.py | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 938b0bf407b..8c7fde3f2c4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -26,6 +26,7 @@ repos: - id: mypy files: ^(src/|testing/|scripts/) args: [] + language_version: "3.8" additional_dependencies: - iniconfig>=1.1.0 - attrs>=19.2.0 diff --git a/src/_pytest/main.py b/src/_pytest/main.py index befc7ccce6e..e5534e98d69 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -49,7 +49,7 @@ if TYPE_CHECKING: - from typing import Self + from typing_extensions import Self from _pytest.fixtures import FixtureManager diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 716c4948f4a..d0e1cdc7faa 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -167,7 +167,7 @@ def pytest_runtest_call(item: Item) -> None: del sys.last_value del sys.last_traceback if sys.version_info >= (3, 12, 0): - del sys.last_exc + del sys.last_exc # type:ignore[attr-defined] except AttributeError: pass try: @@ -177,7 +177,7 @@ def pytest_runtest_call(item: Item) -> None: sys.last_type = type(e) sys.last_value = e if sys.version_info >= (3, 12, 0): - sys.last_exc = e + sys.last_exc = e # type:ignore[attr-defined] assert e.__traceback__ is not None # Skip *this* frame sys.last_traceback = e.__traceback__.tb_next diff --git a/testing/test_runner.py b/testing/test_runner.py index 1b59ff78633..0d9facdcd71 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -1030,7 +1030,7 @@ def runtest(self): assert sys.last_type is IndexError assert isinstance(sys.last_value, IndexError) if sys.version_info >= (3, 12, 0): - assert isinstance(sys.last_exc, IndexError) + assert isinstance(sys.last_exc, IndexError) # type:ignore[attr-defined] assert sys.last_value.args[0] == "TEST" assert sys.last_traceback From 9a444d113658be6ccb8dc9f57ed118a1ef17c94c Mon Sep 17 00:00:00 2001 From: dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com> Date: Fri, 30 Aug 2024 22:37:18 +0800 Subject: [PATCH 0856/1271] Fix assertion rewriting with importlib mode (#12716) Fixes #12659 --- AUTHORS | 1 + changelog/12659.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 10 +++++++++ src/_pytest/pathlib.py | 4 +++- testing/test_pathlib.py | 36 ++++++++++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 changelog/12659.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 8103a1d52a5..db993353689 100644 --- a/AUTHORS +++ b/AUTHORS @@ -412,6 +412,7 @@ Ted Xiao Terje Runde Thomas Grainger Thomas Hisch +Tianyu Dongfang Tim Hoffmann Tim Strazny TJ Bruno diff --git a/changelog/12659.bugfix.rst b/changelog/12659.bugfix.rst new file mode 100644 index 00000000000..297381b9602 --- /dev/null +++ b/changelog/12659.bugfix.rst @@ -0,0 +1 @@ +Fixed the issue of not displaying assertion failure differences when using the parameter ``--import-mode=importlib`` in pytest>=8.1. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index f7ff4f6f7a2..a7a92c0f1fe 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -101,6 +101,16 @@ def find_spec( # Type ignored because mypy is confused about the `self` binding here. spec = self._find_spec(name, path) # type: ignore + + if spec is None and path is not None: + # With --import-mode=importlib, PathFinder cannot find spec without modifying `sys.path`, + # causing inability to assert rewriting (#12659). + # At this point, try using the file path to find the module spec. + for _path_str in path: + spec = importlib.util.spec_from_file_location(name, _path_str) + if spec is not None: + break + if ( # the import machinery could not find a file to import spec is None diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index e4dc4eddc9c..81e52ea729d 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -621,7 +621,9 @@ def _import_module_using_spec( # Checking with sys.meta_path first in case one of its hooks can import this module, # such as our own assertion-rewrite hook. for meta_importer in sys.meta_path: - spec = meta_importer.find_spec(module_name, [str(module_location)]) + spec = meta_importer.find_spec( + module_name, [str(module_location), str(module_path)] + ) if spec_matches_module_path(spec, module_path): break else: diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 377c30ca900..7c0a0e03d76 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1372,6 +1372,42 @@ def test_resolve_pkg_root_and_module_name_ns_multiple_levels( ) assert mod is mod2 + def test_ns_multiple_levels_import_rewrite_assertions( + self, + tmp_path: Path, + monkeypatch: MonkeyPatch, + pytester: Pytester, + ) -> None: + """Check assert rewriting with `--import-mode=importlib` (#12659).""" + self.setup_directories(tmp_path, monkeypatch, pytester) + code = dedent(""" + def test(): + assert "four lights" == "five lights" + """) + + # A case is in a subdirectory with an `__init__.py` file. + test_py = tmp_path / "src/dist2/com/company/calc/algo/test_demo.py" + test_py.write_text(code, encoding="UTF-8") + + pkg_root, module_name = resolve_pkg_root_and_module_name( + test_py, consider_namespace_packages=True + ) + assert (pkg_root, module_name) == ( + tmp_path / "src/dist2", + "com.company.calc.algo.test_demo", + ) + + result = pytester.runpytest("--import-mode=importlib", test_py) + + result.stdout.fnmatch_lines( + [ + "E AssertionError: assert 'four lights' == 'five lights'", + "E *", + "E - five lights*", + "E + four lights", + ] + ) + @pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"]) def test_incorrect_namespace_package( self, From 4604387ae444a4f3478243f6d12f40b0cc48e121 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 11:05:13 -0300 Subject: [PATCH 0857/1271] [automated] Update plugin list (#12759) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 172 ++++++++++++++++++++++--------- 1 file changed, 122 insertions(+), 50 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index d425454ea87..992dc3d2be7 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 - :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 04, 2024 N/A pytest>=7.1.3 + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 26, 2024 N/A pytest>=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 22, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 30, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -220,7 +220,7 @@ This list contains 1503 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Jan 18, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Aug 28, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-checkdocs` check the README when running tests Apr 30, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -242,7 +242,7 @@ This list contains 1503 plugins. :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Jun 17, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A - :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Mar 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Aug 26, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Aug 15, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) @@ -252,6 +252,7 @@ This list contains 1503 plugins. :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cmake` Provide CMake module for Pytest Aug 16, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) + :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Aug 31, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest @@ -429,6 +430,7 @@ This list contains 1503 plugins. :pypi:`pytest-doorstop` A pytest plugin for adding test results into doorstop items. Jun 09, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-dotenv` A py.test plugin that parses environment files before running tests Jun 16, 2020 4 - Beta pytest (>=5.0.0) :pypi:`pytest-dot-only-pkcopley` A Pytest marker for only running a single test Oct 27, 2023 N/A N/A + :pypi:`pytest-dparam` A more readable alternative to @pytest.mark.parametrize. Aug 27, 2024 6 - Mature pytest :pypi:`pytest-dpg` pytest-dpg is a pytest plugin for testing Dear PyGui (DPG) applications Aug 13, 2024 N/A N/A :pypi:`pytest-draw` Pytest plugin for randomly selecting a specific number of tests Mar 21, 2023 3 - Alpha pytest :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) @@ -468,7 +470,7 @@ This list contains 1503 plugins. :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) - :pypi:`pytest-enabler` Enable installed pytest plugins Mar 21, 2024 5 - Production/Stable pytest>=6; extra == "testing" + :pypi:`pytest-enabler` Enable installed pytest plugins Aug 29, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "test" :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest @@ -495,7 +497,7 @@ This list contains 1503 plugins. :pypi:`pytest-exasol-backend` Aug 23, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-slc` Aug 15, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-slc` Aug 29, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -614,6 +616,7 @@ This list contains 1503 plugins. :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A + :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Aug 30, 2024 N/A N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Apr 03, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 @@ -647,7 +650,7 @@ This list contains 1503 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Aug 17, 2024 3 - Alpha pytest==8.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Aug 31, 2024 3 - Alpha pytest==8.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -718,7 +721,7 @@ This list contains 1503 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Aug 21, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Aug 30, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -802,12 +805,12 @@ This list contains 1503 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Aug 08, 2024 5 - Production/Stable pytest==8.3.2 + :pypi:`pytest-logikal` Common testing environment Aug 30, 2024 5 - Production/Stable pytest==8.3.2 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Jul 19, 2024 4 - Beta N/A :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest - :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers May 22, 2024 3 - Alpha pytest + :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Aug 28, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) @@ -820,7 +823,7 @@ This list contains 1503 plugins. :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Aug 06, 2024 N/A N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Aug 01, 2024 5 - Production/Stable pytest - :pypi:`pytest-matchers` Matchers for pytest Aug 24, 2024 N/A pytest<9.0,>=7.0 + :pypi:`pytest-matchers` Matchers for pytest Aug 26, 2024 N/A pytest<9.0,>=7.0 :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -830,7 +833,7 @@ This list contains 1503 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. May 18, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 - :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Feb 15, 2024 N/A pytest (>=7.4.3) + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Aug 27, 2024 N/A pytest>=7.4.3 :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 @@ -845,8 +848,9 @@ This list contains 1503 plugins. :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions May 26, 2024 N/A pytest>=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Aug 27, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-missing-modules` Pytest plugin to easily fake missing modules Aug 26, 2024 N/A pytest>=8.3.2 :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests May 28, 2024 N/A pytest>=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) @@ -1051,6 +1055,7 @@ This list contains 1503 plugins. :pypi:`pytest-py125` Dec 03, 2022 N/A N/A :pypi:`pytest-pycharm` Plugin for py.test to enter PyCharm debugger on uncaught exceptions Aug 13, 2020 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-pycodestyle` pytest plugin to run pycodestyle Oct 28, 2022 3 - Alpha N/A + :pypi:`pytest-pydantic-schema-sync` Pytest plugin to synchronise Pydantic model schemas with JSONSchema files Aug 29, 2024 N/A pytest>=6 :pypi:`pytest-pydev` py.test plugin to connect to a remote debug server with PyDev or PyCharm. Nov 15, 2017 3 - Alpha N/A :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A :pypi:`pytest-pylint` pytest plugin to check source code with pylint Oct 06, 2023 5 - Production/Stable pytest >=7.0 @@ -1073,7 +1078,7 @@ This list contains 1503 plugins. :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 - :pypi:`pytest-qanova` A pytest plugin to collect test information May 26, 2024 3 - Alpha pytest + :pypi:`pytest-qanova` A pytest plugin to collect test information Aug 26, 2024 3 - Alpha pytest :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 30, 2024 4 - Beta pytest<9.0.0,>=7.2.2 :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) @@ -1115,6 +1120,7 @@ This list contains 1503 plugins. :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Feb 26, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A + :pypi:`pytest-relative-path` Handle relative path in pytest options or ini configs Aug 30, 2024 N/A pytest :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Mar 29, 2024 5 - Production/Stable pytest>=7 :pypi:`pytest-remfiles` Pytest plugin to create a temporary directory with remote files Jul 01, 2019 5 - Production/Stable N/A :pypi:`pytest-remotedata` Pytest plugin for controlling remote data access. Sep 26, 2023 5 - Production/Stable pytest >=4.6 @@ -1199,7 +1205,7 @@ This list contains 1503 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 13, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 30, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1210,7 +1216,7 @@ This list contains 1503 plugins. :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 Feb 01, 2024 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. Aug 13, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Aug 30, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1229,10 +1235,11 @@ This list contains 1503 plugins. :pypi:`pytest-setupinfo` Displaying setup info during pytest command run Jan 23, 2023 N/A N/A :pypi:`pytest-sftpserver` py.test plugin to locally test sftp server connections. Sep 16, 2019 4 - Beta N/A :pypi:`pytest-shard` Dec 11, 2020 4 - Beta pytest + :pypi:`pytest-shared-session-scope` Aug 28, 2024 N/A pytest>=7 :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A - :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Feb 23, 2024 5 - Production/Stable pytest >=7.4.0 + :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Aug 26, 2024 5 - Production/Stable pytest>=7.4.0 :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) @@ -1288,7 +1295,7 @@ This list contains 1503 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 Aug 14, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Aug 28, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jul 10, 2024 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 @@ -1331,7 +1338,7 @@ This list contains 1503 plugins. :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A - :pypi:`pytest_tagging` a pytest plugin to tag tests Apr 08, 2024 N/A pytest<8.0.0,>=7.1.3 + :pypi:`pytest_tagging` a pytest plugin to tag tests Aug 31, 2024 N/A pytest<8.0.0,>=7.1.3 :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) @@ -1350,6 +1357,7 @@ This list contains 1503 plugins. :pypi:`pytest-terraform-fixture` generate terraform resources to use with pytest Nov 14, 2018 4 - Beta N/A :pypi:`pytest-testbook` A plugin to run tests written in Jupyter notebook Dec 11, 2016 3 - Alpha N/A :pypi:`pytest-testconfig` Test configuration plugin for pytest. Jan 11, 2020 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-testdata` Get and load testdata in pytest projects Aug 30, 2024 N/A pytest :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) @@ -1391,7 +1399,7 @@ This list contains 1503 plugins. :pypi:`pytest-thread` Jul 07, 2023 N/A N/A :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-time` Jun 24, 2023 3 - Alpha pytest + :pypi:`pytest-time` Aug 28, 2024 3 - Alpha pytest :pypi:`pytest-timeassert-ethan` execution duration Dec 25, 2023 N/A pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A :pypi:`pytest-timeout` pytest plugin to abort hanging tests Mar 07, 2024 5 - Production/Stable pytest >=7.0.0 @@ -1400,7 +1408,7 @@ This list contains 1503 plugins. :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Mar 27, 2024 N/A N/A :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Jan 04, 2024 5 - Production/Stable pytest - :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Jun 26, 2023 4 - Beta pytest (>=3.8.0) + :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Aug 29, 2024 4 - Beta pytest>=3.8.0 :pypi:`pytest-tipsi-django` Better fixtures for django Feb 05, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Feb 04, 2024 5 - Production/Stable pytest>=3.3.0 :pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0) @@ -1441,6 +1449,7 @@ This list contains 1503 plugins. :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 Feb 01, 2024 4 - Beta N/A :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Aug 15, 2023 4 - Beta N/A + :pypi:`pytest-typing-runner` Pytest plugin to make it easier to run and check python code against static type checkers Aug 29, 2024 N/A pytest==8.2.2; extra == "tests" :pypi:`pytest-tytest` Typhoon HIL plugin for pytest May 25, 2020 4 - Beta pytest (>=5.4.2) :pypi:`pytest-ubersmith` Easily mock calls to ubersmith at the \`requests\` level. Apr 13, 2015 N/A N/A :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest @@ -1481,7 +1490,7 @@ This list contains 1503 plugins. :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-wake` Mar 20, 2024 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A - :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Apr 01, 2024 4 - Beta N/A + :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Aug 28, 2024 4 - Beta N/A :pypi:`pytest_wdb` Trace pytest tests with wdb to halt on error with --wdb. Jul 04, 2016 N/A N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest @@ -2341,7 +2350,7 @@ This list contains 1503 plugins. BDD for pytest :pypi:`pytest-bdd-report` - *last release*: Aug 04, 2024, + *last release*: Aug 26, 2024, *status*: N/A, *requires*: pytest>=7.1.3 @@ -2383,7 +2392,7 @@ This list contains 1503 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Aug 22, 2024, + *last release*: Aug 30, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2845,8 +2854,8 @@ This list contains 1503 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Jan 18, 2024, - *status*: N/A, + *last release*: Aug 28, 2024, + *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 A pytest plugin that allows multiple failures per test. @@ -2999,7 +3008,7 @@ This list contains 1503 plugins. Automated, comprehensive and well-organised pytest test cases. :pypi:`pytest-cleanuptotal` - *last release*: Mar 19, 2024, + *last release*: Aug 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -3068,6 +3077,13 @@ This list contains 1503 plugins. Execute CMake Presets via pytest + :pypi:`pytest-cmdline-add-args` + *last release*: Aug 31, 2024, + *status*: N/A, + *requires*: N/A + + Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. + :pypi:`pytest-cobra` *last release*: Jun 29, 2019, *status*: 3 - Alpha, @@ -4307,6 +4323,13 @@ This list contains 1503 plugins. A Pytest marker for only running a single test + :pypi:`pytest-dparam` + *last release*: Aug 27, 2024, + *status*: 6 - Mature, + *requires*: pytest + + A more readable alternative to @pytest.mark.parametrize. + :pypi:`pytest-dpg` *last release*: Aug 13, 2024, *status*: N/A, @@ -4581,9 +4604,9 @@ This list contains 1503 plugins. Pytest plugin to represent test output with emoji support :pypi:`pytest-enabler` - *last release*: Mar 21, 2024, + *last release*: Aug 29, 2024, *status*: 5 - Production/Stable, - *requires*: pytest>=6; extra == "testing" + *requires*: pytest!=8.1.*,>=6; extra == "test" Enable installed pytest plugins @@ -4770,7 +4793,7 @@ This list contains 1503 plugins. :pypi:`pytest-exasol-slc` - *last release*: Aug 15, 2024, + *last release*: Aug 29, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -5602,6 +5625,13 @@ This list contains 1503 plugins. py.test plugin to ignore the same files as git + :pypi:`pytest-gitlab` + *last release*: Aug 30, 2024, + *status*: N/A, + *requires*: N/A + + Pytest Plugin for Gitlab + :pypi:`pytest-gitlabci-parallelized` *last release*: Mar 08, 2023, *status*: N/A, @@ -5834,7 +5864,7 @@ This list contains 1503 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Aug 17, 2024, + *last release*: Aug 31, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.1 @@ -6331,7 +6361,7 @@ This list contains 1503 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Aug 21, 2024, + *last release*: Aug 30, 2024, *status*: N/A, *requires*: pytest @@ -6919,7 +6949,7 @@ This list contains 1503 plugins. :pypi:`pytest-logikal` - *last release*: Aug 08, 2024, + *last release*: Aug 30, 2024, *status*: 5 - Production/Stable, *requires*: pytest==8.3.2 @@ -6954,7 +6984,7 @@ This list contains 1503 plugins. pytest plugin for looping tests :pypi:`pytest-lsp` - *last release*: May 22, 2024, + *last release*: Aug 28, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -7045,7 +7075,7 @@ This list contains 1503 plugins. Easy way to match captured \`pytest\` output against expectations stored in files :pypi:`pytest-matchers` - *last release*: Aug 24, 2024, + *last release*: Aug 26, 2024, *status*: N/A, *requires*: pytest<9.0,>=7.0 @@ -7115,9 +7145,9 @@ This list contains 1503 plugins. A pytest plugin to generate test outcomes reports with markdown table format. :pypi:`pytest-meilisearch` - *last release*: Feb 15, 2024, + *last release*: Aug 27, 2024, *status*: N/A, - *requires*: pytest (>=7.4.3) + *requires*: pytest>=7.4.3 Pytest helpers for testing projects using Meilisearch @@ -7220,7 +7250,7 @@ This list contains 1503 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: May 26, 2024, + *last release*: Aug 27, 2024, *status*: N/A, *requires*: pytest>=5.0.0 @@ -7233,6 +7263,13 @@ This list contains 1503 plugins. Pytest plugin that creates missing fixtures + :pypi:`pytest-missing-modules` + *last release*: Aug 26, 2024, + *status*: N/A, + *requires*: pytest>=8.3.2 + + Pytest plugin to easily fake missing modules + :pypi:`pytest-mitmproxy` *last release*: May 28, 2024, *status*: N/A, @@ -8661,6 +8698,13 @@ This list contains 1503 plugins. pytest plugin to run pycodestyle + :pypi:`pytest-pydantic-schema-sync` + *last release*: Aug 29, 2024, + *status*: N/A, + *requires*: pytest>=6 + + Pytest plugin to synchronise Pydantic model schemas with JSONSchema files + :pypi:`pytest-pydev` *last release*: Nov 15, 2017, *status*: 3 - Alpha, @@ -8816,7 +8860,7 @@ This list contains 1503 plugins. Pytest-pyvista package :pypi:`pytest-qanova` - *last release*: May 26, 2024, + *last release*: Aug 26, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -9109,6 +9153,13 @@ This list contains 1503 plugins. a pytest plugin that sorts tests using "before" and "after" markers + :pypi:`pytest-relative-path` + *last release*: Aug 30, 2024, + *status*: N/A, + *requires*: pytest + + Handle relative path in pytest options or ini configs + :pypi:`pytest-relaxed` *last release*: Mar 29, 2024, *status*: 5 - Production/Stable, @@ -9698,7 +9749,7 @@ This list contains 1503 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Aug 13, 2024, + *last release*: Aug 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9775,7 +9826,7 @@ This list contains 1503 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Aug 13, 2024, + *last release*: Aug 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9907,6 +9958,13 @@ This list contains 1503 plugins. + :pypi:`pytest-shared-session-scope` + *last release*: Aug 28, 2024, + *status*: N/A, + *requires*: pytest>=7 + + + :pypi:`pytest-share-hdf` *last release*: Sep 21, 2022, *status*: 4 - Beta, @@ -9929,9 +9987,9 @@ This list contains 1503 plugins. A pytest plugin to help with testing shell scripts / black box commands :pypi:`pytest-shell-utilities` - *last release*: Feb 23, 2024, + *last release*: Aug 26, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.4.0 + *requires*: pytest>=7.4.0 Pytest plugin to simplify running shell commands against the system @@ -10321,7 +10379,7 @@ This list contains 1503 plugins. :pypi:`pytest-splunk-addon` - *last release*: Aug 14, 2024, + *last release*: Aug 28, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10622,7 +10680,7 @@ This list contains 1503 plugins. Pyst - Pytest System-Test Plugin :pypi:`pytest_tagging` - *last release*: Apr 08, 2024, + *last release*: Aug 31, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.3 @@ -10754,6 +10812,13 @@ This list contains 1503 plugins. Test configuration plugin for pytest. + :pypi:`pytest-testdata` + *last release*: Aug 30, 2024, + *status*: N/A, + *requires*: pytest + + Get and load testdata in pytest projects + :pypi:`pytest-testdirectory` *last release*: May 02, 2023, *status*: 5 - Production/Stable, @@ -11042,7 +11107,7 @@ This list contains 1503 plugins. Ticking on tests :pypi:`pytest-time` - *last release*: Jun 24, 2023, + *last release*: Aug 28, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -11105,9 +11170,9 @@ This list contains 1503 plugins. The companion pytest plugin for tiny-api-client :pypi:`pytest-tinybird` - *last release*: Jun 26, 2023, + *last release*: Aug 29, 2024, *status*: 4 - Beta, - *requires*: pytest (>=3.8.0) + *requires*: pytest>=3.8.0 A pytest plugin to report test results to tinybird @@ -11391,6 +11456,13 @@ This list contains 1503 plugins. Typhoon HIL plugin for pytest + :pypi:`pytest-typing-runner` + *last release*: Aug 29, 2024, + *status*: N/A, + *requires*: pytest==8.2.2; extra == "tests" + + Pytest plugin to make it easier to run and check python code against static type checkers + :pypi:`pytest-tytest` *last release*: May 25, 2020, *status*: 4 - Beta, @@ -11672,7 +11744,7 @@ This list contains 1503 plugins. Local continuous test runner with pytest and watchdog. :pypi:`pytest-watcher` - *last release*: Apr 01, 2024, + *last release*: Aug 28, 2024, *status*: 4 - Beta, *requires*: N/A From 4f60c781be6351ec4e0015c1f1a547ba650b3726 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 03:53:52 +0000 Subject: [PATCH 0858/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.9.0 to 1.10.0 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 34a0b25c63c..02e7c6c0217 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.9.0 + uses: pypa/gh-action-pypi-publish@v1.10.0 - name: Push tag run: | From f8d3e4102fe72fba1bb4ef922121d3856bd80473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sviatoslav=20Sydorenko=20=28=D0=A1=D0=B2=D1=8F=D1=82=D0=BE?= =?UTF-8?q?=D1=81=D0=BB=D0=B0=D0=B2=20=D0=A1=D0=B8=D0=B4=D0=BE=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=29?= Date: Tue, 3 Sep 2024 00:13:38 +0200 Subject: [PATCH 0859/1271] Opt into uploading PEP 740 digital publish attestations to PyPI --- .github/workflows/deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 02e7c6c0217..abbdead2ca9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -55,6 +55,8 @@ jobs: - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@v1.10.0 + with: + attestations: true - name: Push tag run: | From 7928dade67fdd6851efade25f3462ff6f0ad2d49 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 21:26:21 -0300 Subject: [PATCH 0860/1271] [pre-commit.ci] pre-commit autoupdate (#12767) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.2 → v0.6.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.2...v0.6.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8c7fde3f2c4..612188c4ff5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.2" + rev: "v0.6.3" hooks: - id: ruff args: ["--fix"] From c6a0ef175a802efd01115454e8d18d0711ca350d Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 3 Sep 2024 22:03:46 +0200 Subject: [PATCH 0861/1271] doc: Remove past training (#12772) --- doc/en/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 95044e8a544..8b34d589643 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,6 @@ .. sidebar:: **Next Open Trainings and Events** - - `pytest: Professionelles Testen (nicht nur) für Python `_, at `CH Open Workshoptage `_, **September 2nd 2024**, HSLU Rotkreuz (CH) - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Leipzig (DE) / Remote Also see :doc:`previous talks and blogposts ` From 09e386e3e0df5a58ef9ab4f8e43f55c650633be7 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Tue, 3 Sep 2024 22:26:49 +0200 Subject: [PATCH 0862/1271] Fix typos and introduce codespell pre-commit hook (#12769) --- .pre-commit-config.yaml | 7 +++++++ AUTHORS | 1 + CONTRIBUTING.rst | 2 +- changelog/12769.misc.rst | 1 + doc/en/announce/release-2.3.0.rst | 4 ++-- doc/en/changelog.rst | 8 ++++---- doc/en/deprecations.rst | 2 +- doc/en/explanation/fixtures.rst | 2 +- doc/en/funcarg_compare.rst | 6 +++--- doc/en/how-to/fixtures.rst | 2 +- doc/en/how-to/unittest.rst | 2 +- pyproject.toml | 5 +++++ src/_pytest/config/__init__.py | 2 +- src/_pytest/debugging.py | 2 +- testing/python/fixtures.py | 2 +- testing/test_config.py | 2 +- 16 files changed, 32 insertions(+), 18 deletions(-) create mode 100644 changelog/12769.misc.rst diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 612188c4ff5..dfeca73648b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,6 +16,13 @@ repos: hooks: - id: blacken-docs additional_dependencies: [black==24.1.1] +- repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + args: ["--toml=pyproject.toml"] + additional_dependencies: + - tomli - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: diff --git a/AUTHORS b/AUTHORS index db993353689..8bc8ad5cbde 100644 --- a/AUTHORS +++ b/AUTHORS @@ -85,6 +85,7 @@ Chris NeJame Chris Rose Chris Wheeler Christian Boelsen +Christian Clauss Christian Fetzer Christian Neumüller Christian Theunert diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 6e96fd24c40..d615e5fb113 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -543,4 +543,4 @@ Closing issues When a pull request is submitted to fix an issue, add text like ``closes #XYZW`` to the PR description and/or commits (where ``XYZW`` is the issue number). See the `GitHub docs `_ for more information. -When an issue is due to user error (e.g. misunderstanding of a functionality), please politely explain to the user why the issue raised is really a non-issue and ask them to close the issue if they have no further questions. If the original requestor is unresponsive, the issue will be handled as described in the section `Handling stale issues/PRs`_ above. +When an issue is due to user error (e.g. misunderstanding of a functionality), please politely explain to the user why the issue raised is really a non-issue and ask them to close the issue if they have no further questions. If the original requester is unresponsive, the issue will be handled as described in the section `Handling stale issues/PRs`_ above. diff --git a/changelog/12769.misc.rst b/changelog/12769.misc.rst new file mode 100644 index 00000000000..aae4d137a0d --- /dev/null +++ b/changelog/12769.misc.rst @@ -0,0 +1 @@ +Fix typos discovered by codespell and add codespell to pre-commit hooks. diff --git a/doc/en/announce/release-2.3.0.rst b/doc/en/announce/release-2.3.0.rst index 6905b77b923..c405073ef40 100644 --- a/doc/en/announce/release-2.3.0.rst +++ b/doc/en/announce/release-2.3.0.rst @@ -6,10 +6,10 @@ and parametrized testing in Python. It is now easier, more efficient and more predictable to re-run the same tests with different fixture instances. Also, you can directly declare the caching "scope" of fixtures so that dependent tests throughout your whole test suite can -re-use database or other expensive fixture objects with ease. Lastly, +reuse database or other expensive fixture objects with ease. Lastly, it's possible for fixture functions (formerly known as funcarg factories) to use other fixtures, allowing for a completely modular and -re-usable fixture design. +reusable fixture design. For detailed info and tutorial-style examples, see: diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 3178f82044d..9da6f487f8d 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -215,7 +215,7 @@ Improved documentation -- by :user:`webknjaz` -- `#12577 `_: `CI` and `BUILD_NUMBER` environment variables role is discribed in +- `#12577 `_: `CI` and `BUILD_NUMBER` environment variables role is described in the reference doc. They now also appear when doing `pytest -h` -- by :user:`MarcBresson`. @@ -319,7 +319,7 @@ Bug Fixes - `#12367 `_: Fix a regression in pytest 8.2.0 where unittest class instances (a fresh one is created for each test) were not released promptly on test teardown but only on session teardown. -- `#12381 `_: Fix possible "Directory not empty" crashes arising from concurent cache dir (``.pytest_cache``) creation. Regressed in pytest 8.2.0. +- `#12381 `_: Fix possible "Directory not empty" crashes arising from concurrent cache dir (``.pytest_cache``) creation. Regressed in pytest 8.2.0. @@ -330,7 +330,7 @@ Improved Documentation - `#12356 `_: Added a subsection to the documentation for debugging flaky tests to mention - lack of thread safety in pytest as a possible source of flakyness. + lack of thread safety in pytest as a possible source of flakiness. - `#12363 `_: The documentation webpages now links to a canonical version to reduce outdated documentation in search engine results. @@ -676,7 +676,7 @@ Bug Fixes This bug was introduced in pytest 8.0.0rc1. -- `#9765 `_, `#11816 `_: Fixed a frustrating bug that afflicted some users with the only error being ``assert mod not in mods``. The issue was caused by the fact that ``str(Path(mod))`` and ``mod.__file__`` don't necessarily produce the same string, and was being erroneously used interchangably in some places in the code. +- `#9765 `_, `#11816 `_: Fixed a frustrating bug that afflicted some users with the only error being ``assert mod not in mods``. The issue was caused by the fact that ``str(Path(mod))`` and ``mod.__file__`` don't necessarily produce the same string, and was being erroneously used interchangeably in some places in the code. This fix also broke the internal API of ``PytestPluginManager.consider_conftest`` by introducing a new parameter -- we mention this in case it is being used by external code, even if marked as *private*. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index bf6268a4980..153d5195476 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -43,7 +43,7 @@ If the import attempt raises :class:`ModuleNotFoundError` (the usual case), then warning is emitted. This way, the usual cases will keep working the same way, while unexpected errors will now issue a warning, with -users being able to supress the warning by passing ``exc_type=ImportError`` explicitly. +users being able to suppress the warning by passing ``exc_type=ImportError`` explicitly. In ``9.0``, the warning will turn into an error, and in ``9.1`` :func:`pytest.importorskip` will only capture :class:`ModuleNotFoundError` by default and no warnings will be issued anymore -- but users can still capture diff --git a/doc/en/explanation/fixtures.rst b/doc/en/explanation/fixtures.rst index 0bb3bf49fb0..53d4796c825 100644 --- a/doc/en/explanation/fixtures.rst +++ b/doc/en/explanation/fixtures.rst @@ -75,7 +75,7 @@ style of setup/teardown functions: * fixture management scales from simple unit to complex functional testing, allowing to parametrize fixtures and tests according - to configuration and component options, or to re-use fixtures + to configuration and component options, or to reuse fixtures across function, class, module or whole test session scopes. * teardown logic can be easily, and safely managed, no matter how many fixtures diff --git a/doc/en/funcarg_compare.rst b/doc/en/funcarg_compare.rst index 8b900d30f20..bc5e7d3c515 100644 --- a/doc/en/funcarg_compare.rst +++ b/doc/en/funcarg_compare.rst @@ -16,7 +16,7 @@ Shortcomings of the previous ``pytest_funcarg__`` mechanism The pre pytest-2.3 funcarg mechanism calls a factory each time a funcarg for a test function is required. If a factory wants to -re-use a resource across different scopes, it often used +reuse a resource across different scopes, it often used the ``request.cached_setup()`` helper to manage caching of resources. Here is a basic example how we could implement a per-session Database object: @@ -107,7 +107,7 @@ the tests requiring "db" will run twice as well. The "mysql" and "pg" values will also be used for reporting the test-invocation variants. This new way of parametrizing funcarg factories should in many cases -allow to re-use already written factories because effectively +allow to reuse already written factories because effectively ``request.param`` was already used when test functions/classes were parametrized via :py:func:`metafunc.parametrize(indirect=True) ` calls. @@ -164,7 +164,7 @@ hook which are often used to setup global resources. This suffers from several problems: 1. in distributed testing the managing process would setup test resources - that are never needed because it only co-ordinates the test run + that are never needed because it only coordinates the test run activities of the worker processes. 2. if you only perform a collection (with "--collect-only") diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index f4d59ff93c0..d60635c4fea 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1487,7 +1487,7 @@ Modularity: using fixtures from a fixture function In addition to using fixtures in test functions, fixture functions can use other fixtures themselves. This contributes to a modular design -of your fixtures and allows re-use of framework-specific fixtures across +of your fixtures and allows reuse of framework-specific fixtures across many projects. As a simple example, we can extend the previous example and instantiate an object ``app`` where we stick the already defined ``smtp_connection`` resource into it: diff --git a/doc/en/how-to/unittest.rst b/doc/en/how-to/unittest.rst index 508aebde016..62e32b6d28f 100644 --- a/doc/en/how-to/unittest.rst +++ b/doc/en/how-to/unittest.rst @@ -109,7 +109,7 @@ achieves this by receiving a special ``request`` object which gives access to :ref:`the requesting test context ` such as the ``cls`` attribute, denoting the class from which the fixture is used. This architecture de-couples fixture writing from actual test -code and allows re-use of the fixture by a minimal reference, the fixture +code and allows reuse of the fixture by a minimal reference, the fixture name. So let's write an actual ``unittest.TestCase`` class using our fixture definition: diff --git a/pyproject.toml b/pyproject.toml index ccd349fcdc7..2fd11df1bf4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -307,6 +307,11 @@ disable = [ "wrong-import-position", # handled by isort / ruff ] +[tool.codespell] +ignore-words-list = "afile,asser,assertio,feld,hove,ned,noes,notin,paramete,parth,socio-economic,tesults,varius,wil" +skip = "*/plugin_list.rst" +write-changes = true + [tool.check-wheel-contents] # check-wheel-contents is executed by the build-and-inspect-python-package action. # W009: Wheel contains multiple toplevel library entries diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index fbb5fb6fdea..2299e90fdc4 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -360,7 +360,7 @@ def _get_legacy_hook_marks( opt_names: tuple[str, ...], ) -> dict[str, bool]: if TYPE_CHECKING: - # abuse typeguard from importlib to avoid massive method type union thats lacking a alias + # abuse typeguard from importlib to avoid massive method type union that's lacking an alias assert inspect.isroutine(method) known_marks: set[str] = {m.name for m in getattr(method, "pytestmark", [])} must_warn: list[str] = [] diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 3e1463fff26..2dfe321e968 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -332,7 +332,7 @@ def maybe_wrap_pytest_function_for_tracing(pyfuncitem) -> None: def _enter_pdb( node: Node, excinfo: ExceptionInfo[BaseException], rep: BaseReport ) -> BaseReport: - # XXX we re-use the TerminalReporter's terminalwriter + # XXX we reuse the TerminalReporter's terminalwriter # because this seems to avoid some encoding related troubles # for not completely clear reasons. tw = node.config.pluginmanager.getplugin("terminalreporter")._tw diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 8d2646309a8..46f0a762cbb 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -4338,7 +4338,7 @@ def test_func(self, f2, f1, m2): assert request.fixturenames == "s1 p1 m1 m2 c1 f2 f1".split() def test_parametrized_package_scope_reordering(self, pytester: Pytester) -> None: - """A paramaterized package-scoped fixture correctly reorders items to + """A parameterized package-scoped fixture correctly reorders items to minimize setups & teardowns. Regression test for #12328. diff --git a/testing/test_config.py b/testing/test_config.py index aa3e4147927..3f5f884ef7a 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -917,7 +917,7 @@ def pytest_addoption(parser): # default for string is "" value = config.getini("string1") assert value == "" - # should return None if None is explicity set as default value + # should return None if None is explicitly set as default value # irrespective of the type argument value = config.getini("none_1") assert value is None From 72c682ff9773ad2690711105a100423ebf7c7c15 Mon Sep 17 00:00:00 2001 From: GTowers1 <130098608+GTowers1@users.noreply.github.com> Date: Thu, 5 Sep 2024 04:04:12 -0700 Subject: [PATCH 0863/1271] Streamline checks for verbose option (#12706) Instead of calling `Config.option.verbose`, call the new `Config.get_verbosity` function to determine the verbosity level. This enables pytest to run correctly with the terminal plugin disabled. Fix #9422 --- changelog/9422.bugfix.rst | 3 +++ doc/en/example/simple.rst | 2 +- src/_pytest/cacheprovider.py | 2 +- src/_pytest/config/__init__.py | 2 +- src/_pytest/fixtures.py | 6 +++--- src/_pytest/logging.py | 2 +- src/_pytest/nodes.py | 4 ++-- src/_pytest/python.py | 2 +- src/_pytest/runner.py | 2 +- src/_pytest/stepwise.py | 2 +- testing/acceptance_test.py | 7 +++++++ 11 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 changelog/9422.bugfix.rst diff --git a/changelog/9422.bugfix.rst b/changelog/9422.bugfix.rst new file mode 100644 index 00000000000..38196340fd5 --- /dev/null +++ b/changelog/9422.bugfix.rst @@ -0,0 +1,3 @@ +Fix bug where disabling the terminal plugin via ``-p no:terminal`` would cause crashes related to missing the ``verbose`` option. + +-- by :user:`GTowers1` diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index a5e2e78c397..a14c34c19c3 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -460,7 +460,7 @@ display more information if applicable: def pytest_report_header(config): - if config.getoption("verbose") > 0: + if config.get_verbosity() > 0: return ["info1: did you know that ...", "did you?"] which will add info only when run with "--v": diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 7190810570e..1b236efdc9b 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -347,7 +347,7 @@ def get_last_failed_paths(self) -> set[Path]: return {x for x in result if x.exists()} def pytest_report_collectionfinish(self) -> str | None: - if self.active and self.config.getoption("verbose") >= 0: + if self.active and self.config.get_verbosity() >= 0: return f"run-last-failure: {self._report_status}" return None diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 2299e90fdc4..29e5a58c4ac 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1759,7 +1759,7 @@ def get_verbosity(self, verbosity_type: str | None = None) -> int: print(config.get_verbosity()) # 1 print(config.get_verbosity(Config.VERBOSITY_ASSERTIONS)) # 2 """ - global_level = self.option.verbose + global_level = self.getoption("verbose", default=0) assert isinstance(global_level, int) if verbosity_type is None: return global_level diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 7d0b40b150a..aaa92c63725 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1348,7 +1348,7 @@ def pytestconfig(request: FixtureRequest) -> Config: Example:: def test_foo(pytestconfig): - if pytestconfig.getoption("verbose") > 0: + if pytestconfig.get_verbosity() > 0: ... """ @@ -1807,7 +1807,7 @@ def _show_fixtures_per_test(config: Config, session: Session) -> None: session.perform_collect() invocation_dir = config.invocation_params.dir tw = _pytest.config.create_terminal_writer(config) - verbose = config.getvalue("verbose") + verbose = config.get_verbosity() def get_best_relpath(func) -> str: loc = getlocation(func, invocation_dir) @@ -1866,7 +1866,7 @@ def _showfixtures_main(config: Config, session: Session) -> None: session.perform_collect() invocation_dir = config.invocation_params.dir tw = _pytest.config.create_terminal_writer(config) - verbose = config.getvalue("verbose") + verbose = config.get_verbosity() fm = session._fixturemanager diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 9f3417e9af2..08c826ff6d4 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -794,7 +794,7 @@ def pytest_runtestloop(self, session: Session) -> Generator[None, object, object if session.config.option.collectonly: return (yield) - if self._log_cli_enabled() and self._config.getoption("verbose") < 1: + if self._log_cli_enabled() and self._config.get_verbosity() < 1: # The verbose flag is needed to avoid messy test progress output. self._config.option.verbose = 1 diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index cc678695848..51bc5174628 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -435,12 +435,12 @@ def _repr_failure_py( else: style = "long" - if self.config.getoption("verbose", 0) > 1: + if self.config.get_verbosity() > 1: truncate_locals = False else: truncate_locals = True - truncate_args = False if self.config.getoption("verbose", 0) > 2 else True + truncate_args = False if self.config.get_verbosity() > 2 else True # excinfo.getrepr() formats paths relative to the CWD if `abspath` is False. # It is possible for a fixture/test to change the CWD while this code runs, which diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 6507c299225..9c54dd20f80 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -513,7 +513,7 @@ def importtestmodule( ) from e except ImportError as e: exc_info = ExceptionInfo.from_current() - if config.getoption("verbose") < 2: + if config.get_verbosity() < 2: exc_info.traceback = exc_info.traceback.filter(filter_traceback) exc_repr = ( exc_info.getrepr(style="short") diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index d0e1cdc7faa..0b60301bf5f 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -71,7 +71,7 @@ def pytest_addoption(parser: Parser) -> None: def pytest_terminal_summary(terminalreporter: TerminalReporter) -> None: durations = terminalreporter.config.option.durations durations_min = terminalreporter.config.option.durations_min - verbose = terminalreporter.config.getvalue("verbose") + verbose = terminalreporter.config.get_verbosity() if durations is None: return tr = terminalreporter diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index bd906ce63c1..c7860808c35 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -113,7 +113,7 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: self.lastfailed = None def pytest_report_collectionfinish(self) -> str | None: - if self.config.getoption("verbose") >= 0 and self.report_status: + if self.config.get_verbosity() >= 0 and self.report_status: return f"stepwise: {self.report_status}" return None diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 01d911e8ca4..64a07ba8554 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1486,3 +1486,10 @@ def my_fixture(self, request): raise AssertionError( f"pytest command failed:\n{exc.stdout=!s}\n{exc.stderr=!s}" ) from exc + + +def test_no_terminal_plugin(pytester: Pytester) -> None: + """Smoke test to ensure pytest can execute without the terminal plugin (#9422).""" + pytester.makepyfile("def test(): assert 1 == 2") + result = pytester.runpytest("-pno:terminal", "-s") + assert result.ret == ExitCode.TESTS_FAILED From 9bde63f2baaf4b9a66a340b6389c059da757c3dc Mon Sep 17 00:00:00 2001 From: Stephen McDowell Date: Fri, 6 Sep 2024 18:00:11 -0400 Subject: [PATCH 0864/1271] [doc] Fix minor typo in example/parametrize.rst A space is needed for ``ZeroDivisionError`` to render as teletype. --- doc/en/example/parametrize.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 3e449b2eaa2..b175510da6a 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -686,5 +686,5 @@ For example: assert (6 / example_input) == e In the example above, the first three test cases should run without any -exceptions, while the fourth should raise a``ZeroDivisionError`` exception, +exceptions, while the fourth should raise a ``ZeroDivisionError`` exception, which is expected by pytest. From 3cc88d980166e0741f69c00bd7acbb0a245dcaec Mon Sep 17 00:00:00 2001 From: Ashley Whetter Date: Sat, 7 Sep 2024 08:11:17 -0700 Subject: [PATCH 0865/1271] Exception chains can be navigated when dropped into Pdb in Python 3.13+ (#12708) Closes #12707 --- AUTHORS | 1 + changelog/12707.improvement.rst | 1 + src/_pytest/debugging.py | 34 ++++++++++++++++++++--------- testing/test_debugging.py | 38 ++++++++++++++++++++++++++++++++- 4 files changed, 63 insertions(+), 11 deletions(-) create mode 100644 changelog/12707.improvement.rst diff --git a/AUTHORS b/AUTHORS index 8bc8ad5cbde..6da8cbfef80 100644 --- a/AUTHORS +++ b/AUTHORS @@ -51,6 +51,7 @@ Aron Coyle Aron Curzon Arthur Richard Ashish Kurmi +Ashley Whetter Aviral Verma Aviv Palivoda Babak Keyvani diff --git a/changelog/12707.improvement.rst b/changelog/12707.improvement.rst new file mode 100644 index 00000000000..4684b6561c8 --- /dev/null +++ b/changelog/12707.improvement.rst @@ -0,0 +1 @@ +Exception chains can be navigated when dropped into Pdb in Python 3.13+. diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 2dfe321e968..763606cd60e 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -292,8 +292,8 @@ def pytest_exception_interact( _enter_pdb(node, call.excinfo, report) def pytest_internalerror(self, excinfo: ExceptionInfo[BaseException]) -> None: - tb = _postmortem_traceback(excinfo) - post_mortem(tb) + exc_or_tb = _postmortem_exc_or_tb(excinfo) + post_mortem(exc_or_tb) class PdbTrace: @@ -354,32 +354,46 @@ def _enter_pdb( tw.sep(">", "traceback") rep.toterminal(tw) tw.sep(">", "entering PDB") - tb = _postmortem_traceback(excinfo) + tb_or_exc = _postmortem_exc_or_tb(excinfo) rep._pdbshown = True # type: ignore[attr-defined] - post_mortem(tb) + post_mortem(tb_or_exc) return rep -def _postmortem_traceback(excinfo: ExceptionInfo[BaseException]) -> types.TracebackType: +def _postmortem_exc_or_tb( + excinfo: ExceptionInfo[BaseException], +) -> types.TracebackType | BaseException: from doctest import UnexpectedException + get_exc = sys.version_info >= (3, 13) if isinstance(excinfo.value, UnexpectedException): # A doctest.UnexpectedException is not useful for post_mortem. # Use the underlying exception instead: - return excinfo.value.exc_info[2] + underlying_exc = excinfo.value + if get_exc: + return underlying_exc.exc_info[1] + + return underlying_exc.exc_info[2] elif isinstance(excinfo.value, ConftestImportFailure): # A config.ConftestImportFailure is not useful for post_mortem. # Use the underlying exception instead: - assert excinfo.value.cause.__traceback__ is not None - return excinfo.value.cause.__traceback__ + cause = excinfo.value.cause + if get_exc: + return cause + + assert cause.__traceback__ is not None + return cause.__traceback__ else: assert excinfo._excinfo is not None + if get_exc: + return excinfo._excinfo[1] + return excinfo._excinfo[2] -def post_mortem(t: types.TracebackType) -> None: +def post_mortem(tb_or_exc: types.TracebackType | BaseException) -> None: p = pytestPDB._init_pdb("post_mortem") p.reset() - p.interaction(None, t) + p.interaction(None, tb_or_exc) if p.quitting: outcomes.exit("Quitting debugger") diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 37032f92354..d86c9018b80 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -103,7 +103,10 @@ def test_func(): ) assert rep.failed assert len(pdblist) == 1 - tb = _pytest._code.Traceback(pdblist[0][0]) + if sys.version_info < (3, 13): + tb = _pytest._code.Traceback(pdblist[0][0]) + else: + tb = _pytest._code.Traceback(pdblist[0][0].__traceback__) assert tb[-1].name == "test_func" def test_pdb_on_xfail(self, pytester: Pytester, pdblist) -> None: @@ -921,6 +924,39 @@ def test_foo(): child.expect("custom set_trace>") self.flush(child) + @pytest.mark.skipif( + sys.version_info < (3, 13), + reason="Navigating exception chains was introduced in 3.13", + ) + def test_pdb_exception_chain_navigation(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( + """ + def inner_raise(): + is_inner = True + raise RuntimeError("Woops") + + def outer_raise(): + is_inner = False + try: + inner_raise() + except RuntimeError: + raise RuntimeError("Woopsie") + + def test_1(): + outer_raise() + assert True + """ + ) + child = pytester.spawn_pytest(f"--pdb {p1}") + child.expect("Pdb") + child.sendline("is_inner") + child.expect_exact("False") + child.sendline("exceptions 0") + child.sendline("is_inner") + child.expect_exact("True") + child.sendeof() + self.flush(child) + class TestDebuggingBreakpoints: @pytest.mark.parametrize("arg", ["--pdb", ""]) From de56e7c832f0ba3bf12d976dd552f8dd0b233377 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 8 Sep 2024 11:53:43 +0000 Subject: [PATCH 0866/1271] [automated] Update plugin list (#12786) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 128 ++++++++++++++++--------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 992dc3d2be7..ffca5c08380 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) - :pypi:`pytest-bdd-ng` BDD for pytest Dec 31, 2023 4 - Beta pytest >=5.0 + :pypi:`pytest-bdd-ng` BDD for pytest Sep 01, 2024 4 - Beta pytest>=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 26, 2024 N/A pytest>=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Aug 30, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Sep 05, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -240,7 +240,7 @@ This list contains 1512 plugins. :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) - :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Jun 17, 2024 N/A pytest + :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Aug 26, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Aug 15, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -252,7 +252,7 @@ This list contains 1512 plugins. :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cmake` Provide CMake module for Pytest Aug 16, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Aug 31, 2024 N/A N/A + :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest @@ -340,7 +340,7 @@ This list contains 1512 plugins. :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-dbt-core` Pytest extension for dbt. Jun 04, 2024 N/A pytest>=6.2.5; extra == "test" - :pypi:`pytest-dbt-postgres` Pytest tooling to unittest DBT & Postgres models Jan 02, 2024 N/A pytest (>=7.4.3,<8.0.0) + :pypi:`pytest-dbt-postgres` Pytest tooling to unittest DBT & Postgres models Sep 03, 2024 N/A pytest<9.0.0,>=8.3.2 :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-dc` Manages Docker containers during your integration tests Aug 16, 2023 5 - Production/Stable pytest >=3.3 @@ -373,7 +373,7 @@ This list contains 1512 plugins. :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. Jun 09, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-ditto-pandas` pytest-ditto plugin for pandas snapshots. May 29, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-ditto-pyarrow` pytest-ditto plugin for pyarrow tables. Jun 09, 2024 4 - Beta pytest>=3.5.0 - :pypi:`pytest-django` A Django plugin for pytest. Jan 30, 2024 5 - Production/Stable pytest >=7.0.0 + :pypi:`pytest-django` A Django plugin for pytest. Sep 02, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A @@ -593,6 +593,7 @@ This list contains 1512 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Sep 06, 2024 N/A pytest :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 Jul 03, 2024 4 - Beta pytest>=6.0.0 @@ -616,7 +617,7 @@ This list contains 1512 plugins. :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A - :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Aug 30, 2024 N/A N/A + :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Sep 06, 2024 N/A N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Apr 03, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 @@ -650,7 +651,7 @@ This list contains 1512 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Aug 31, 2024 3 - Alpha pytest==8.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Sep 07, 2024 3 - Alpha pytest==8.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -755,7 +756,7 @@ This list contains 1512 plugins. :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-keep-together` Pytest plugin to customize test ordering by running all 'related' tests together Dec 07, 2022 5 - Production/Stable pytest :pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Oct 01, 2023 N/A pytest (>=7.1) + :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Sep 05, 2024 N/A pytest>=8.0.2 :pypi:`pytest-kind` Kubernetes test support with KIND for pytest Nov 30, 2022 5 - Production/Stable N/A :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A @@ -780,7 +781,7 @@ This list contains 1512 plugins. :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 - :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Dec 22, 2023 4 - Beta N/A + :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Sep 05, 2024 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest @@ -810,7 +811,7 @@ This list contains 1512 plugins. :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Jul 19, 2024 4 - Beta N/A :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest - :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Aug 28, 2024 3 - Alpha pytest + :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Sep 04, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) @@ -850,7 +851,7 @@ This list contains 1512 plugins. :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Aug 27, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-missing-modules` Pytest plugin to easily fake missing modules Aug 26, 2024 N/A pytest>=8.3.2 + :pypi:`pytest-missing-modules` Pytest plugin to easily fake missing modules Sep 03, 2024 N/A pytest>=8.3.2 :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests May 28, 2024 N/A pytest>=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) @@ -940,7 +941,7 @@ This list contains 1512 plugins. :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Jun 05, 2024 3 - Alpha pytest>=4.6 :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Oct 01, 2023 N/A pytest - :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Jun 02, 2022 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Sep 05, 2024 5 - Production/Stable pytest>=5.0 :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest :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) @@ -1026,7 +1027,7 @@ This list contains 1512 plugins. :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Aug 14, 2024 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Sep 05, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-powerpack` Mar 17, 2024 N/A pytest (>=8.1.1,<9.0.0) :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) @@ -1078,7 +1079,7 @@ This list contains 1512 plugins. :pypi:`pytest-pytorch` pytest plugin for a better developer experience when working with the PyTorch test suite May 25, 2021 4 - Beta pytest :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 - :pypi:`pytest-qanova` A pytest plugin to collect test information Aug 26, 2024 3 - Alpha pytest + :pypi:`pytest-qanova` A pytest plugin to collect test information Sep 05, 2024 3 - Alpha pytest :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 30, 2024 4 - Beta pytest<9.0.0,>=7.2.2 :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) @@ -1105,7 +1106,7 @@ This list contains 1512 plugins. :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jun 07, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A - :pypi:`pytest-reana` Pytest fixtures for REANA. Aug 21, 2024 3 - Alpha N/A + :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jun 27, 2024 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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 @@ -1129,7 +1130,7 @@ This list contains 1512 plugins. :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest :pypi:`pytest_repeater` py.test plugin for repeating single test multiple times. Feb 09, 2018 1 - Planning N/A - :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Jan 11, 2024 5 - Production/Stable pytest + :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Sep 03, 2024 5 - Production/Stable pytest :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest @@ -1143,7 +1144,7 @@ This list contains 1512 plugins. :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Mar 27, 2024 N/A pytest>=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A - :pypi:`pytest-req` pytest requests plugin Jul 26, 2024 N/A pytest<9.0.0,>=8.3.1 + :pypi:`pytest-req` pytest requests plugin Aug 31, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.2 :pypi:`pytest-reqs` pytest plugin to check pinned requirements May 12, 2019 N/A pytest (>=2.4.2) :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A @@ -1205,7 +1206,7 @@ This list contains 1512 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Aug 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 05, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1216,11 +1217,11 @@ This list contains 1512 plugins. :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 Feb 01, 2024 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. Aug 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 05, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 - :pypi:`pytest-send-email` Send pytest execution result email Dec 04, 2019 N/A N/A + :pypi:`pytest-send-email` Send pytest execution result email Sep 02, 2024 N/A pytest :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Apr 25, 2024 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server` test server exec cmd Jun 24, 2024 N/A N/A @@ -1235,7 +1236,7 @@ This list contains 1512 plugins. :pypi:`pytest-setupinfo` Displaying setup info during pytest command run Jan 23, 2023 N/A N/A :pypi:`pytest-sftpserver` py.test plugin to locally test sftp server connections. Sep 16, 2019 4 - Beta N/A :pypi:`pytest-shard` Dec 11, 2020 4 - Beta pytest - :pypi:`pytest-shared-session-scope` Aug 28, 2024 N/A pytest>=7 + :pypi:`pytest-shared-session-scope` Sep 05, 2024 N/A pytest>=7 :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A @@ -1295,7 +1296,7 @@ This list contains 1512 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 Aug 28, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Sep 04, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jul 10, 2024 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 @@ -1318,7 +1319,7 @@ This list contains 1512 plugins. :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A :pypi:`pytest-stf` pytest plugin for openSTF Mar 25, 2024 N/A pytest>=5.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A - :pypi:`pytest-store` Pytest plugin to store values from test runs Nov 16, 2023 3 - Alpha pytest (>=7.0.0) + :pypi:`pytest-store` Pytest plugin to store values from test runs Sep 04, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-structlog` Structured logging assertions Jul 25, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A @@ -1540,7 +1541,7 @@ This list contains 1512 plugins. :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) - :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Aug 20, 2024 N/A pytest + :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Sep 04, 2024 N/A pytest :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) @@ -2343,9 +2344,9 @@ This list contains 1512 plugins. pytest plugin to display BDD info in HTML test report :pypi:`pytest-bdd-ng` - *last release*: Dec 31, 2023, + *last release*: Sep 01, 2024, *status*: 4 - Beta, - *requires*: pytest >=5.0 + *requires*: pytest>=5.0 BDD for pytest @@ -2392,7 +2393,7 @@ This list contains 1512 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Aug 30, 2024, + *last release*: Sep 05, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2994,7 +2995,7 @@ This list contains 1512 plugins. Easy quality control for CLDF datasets using pytest :pypi:`pytest-cleanslate` - *last release*: Jun 17, 2024, + *last release*: Sep 04, 2024, *status*: N/A, *requires*: pytest @@ -3078,7 +3079,7 @@ This list contains 1512 plugins. Execute CMake Presets via pytest :pypi:`pytest-cmdline-add-args` - *last release*: Aug 31, 2024, + *last release*: Sep 01, 2024, *status*: N/A, *requires*: N/A @@ -3694,9 +3695,9 @@ This list contains 1512 plugins. Pytest extension for dbt. :pypi:`pytest-dbt-postgres` - *last release*: Jan 02, 2024, + *last release*: Sep 03, 2024, *status*: N/A, - *requires*: pytest (>=7.4.3,<8.0.0) + *requires*: pytest<9.0.0,>=8.3.2 Pytest tooling to unittest DBT & Postgres models @@ -3925,9 +3926,9 @@ This list contains 1512 plugins. pytest-ditto plugin for pyarrow tables. :pypi:`pytest-django` - *last release*: Jan 30, 2024, + *last release*: Sep 02, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.0.0 + *requires*: pytest>=7.0.0 A Django plugin for pytest. @@ -5464,6 +5465,13 @@ This list contains 1512 plugins. An alternative way to parametrize test cases. + :pypi:`pytest-fv` + *last release*: Sep 06, 2024, + *status*: N/A, + *requires*: pytest + + pytest extensions to support running functional-verification jobs + :pypi:`pytest-fxa` *last release*: Aug 28, 2018, *status*: 5 - Production/Stable, @@ -5626,7 +5634,7 @@ This list contains 1512 plugins. py.test plugin to ignore the same files as git :pypi:`pytest-gitlab` - *last release*: Aug 30, 2024, + *last release*: Sep 06, 2024, *status*: N/A, *requires*: N/A @@ -5864,7 +5872,7 @@ This list contains 1512 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Aug 31, 2024, + *last release*: Sep 07, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.1 @@ -6599,9 +6607,9 @@ This list contains 1512 plugins. :pypi:`pytest-keyring` - *last release*: Oct 01, 2023, + *last release*: Sep 05, 2024, *status*: N/A, - *requires*: pytest (>=7.1) + *requires*: pytest>=8.0.2 A Pytest plugin to access the system's keyring to provide credentials for tests @@ -6774,7 +6782,7 @@ This list contains 1512 plugins. A python-libfaketime plugin for pytest :pypi:`pytest-libiio` - *last release*: Dec 22, 2023, + *last release*: Sep 05, 2024, *status*: 4 - Beta, *requires*: N/A @@ -6984,7 +6992,7 @@ This list contains 1512 plugins. pytest plugin for looping tests :pypi:`pytest-lsp` - *last release*: Aug 28, 2024, + *last release*: Sep 04, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -7264,7 +7272,7 @@ This list contains 1512 plugins. Pytest plugin that creates missing fixtures :pypi:`pytest-missing-modules` - *last release*: Aug 26, 2024, + *last release*: Sep 03, 2024, *status*: N/A, *requires*: pytest>=8.3.2 @@ -7894,9 +7902,9 @@ This list contains 1512 plugins. A pytest plugin for instrumenting test runs via OpenTelemetry :pypi:`pytest-opentmi` - *last release*: Jun 02, 2022, + *last release*: Sep 05, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=5.0) + *requires*: pytest>=5.0 pytest plugin for publish results to opentmi @@ -8496,7 +8504,7 @@ This list contains 1512 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: Aug 14, 2024, + *last release*: Sep 05, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.2 @@ -8860,7 +8868,7 @@ This list contains 1512 plugins. Pytest-pyvista package :pypi:`pytest-qanova` - *last release*: Aug 26, 2024, + *last release*: Sep 05, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -9049,7 +9057,7 @@ This list contains 1512 plugins. Test your README.md file :pypi:`pytest-reana` - *last release*: Aug 21, 2024, + *last release*: Sep 04, 2024, *status*: 3 - Alpha, *requires*: N/A @@ -9217,7 +9225,7 @@ This list contains 1512 plugins. py.test plugin for repeating single test multiple times. :pypi:`pytest-replay` - *last release*: Jan 11, 2024, + *last release*: Sep 03, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -9315,9 +9323,9 @@ This list contains 1512 plugins. Pytest Repo Structure :pypi:`pytest-req` - *last release*: Jul 26, 2024, - *status*: N/A, - *requires*: pytest<9.0.0,>=8.3.1 + *last release*: Aug 31, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest<9.0.0,>=8.3.2 pytest requests plugin @@ -9749,7 +9757,7 @@ This list contains 1512 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Aug 30, 2024, + *last release*: Sep 05, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9826,7 +9834,7 @@ This list contains 1512 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Aug 30, 2024, + *last release*: Sep 05, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9854,9 +9862,9 @@ This list contains 1512 plugins. A pytest plugin for selfie snapshot testing. :pypi:`pytest-send-email` - *last release*: Dec 04, 2019, + *last release*: Sep 02, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest Send pytest execution result email @@ -9959,7 +9967,7 @@ This list contains 1512 plugins. :pypi:`pytest-shared-session-scope` - *last release*: Aug 28, 2024, + *last release*: Sep 05, 2024, *status*: N/A, *requires*: pytest>=7 @@ -10379,7 +10387,7 @@ This list contains 1512 plugins. :pypi:`pytest-splunk-addon` - *last release*: Aug 28, 2024, + *last release*: Sep 04, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10540,9 +10548,9 @@ This list contains 1512 plugins. A plugin to pytest stoq :pypi:`pytest-store` - *last release*: Nov 16, 2023, + *last release*: Sep 04, 2024, *status*: 3 - Alpha, - *requires*: pytest (>=7.0.0) + *requires*: pytest>=7.0.0 Pytest plugin to store values from test runs @@ -12094,7 +12102,7 @@ This list contains 1512 plugins. Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. :pypi:`pytest-zephyr-scale-integration` - *last release*: Aug 20, 2024, + *last release*: Sep 04, 2024, *status*: N/A, *requires*: pytest From d35b802805b210c6d5281864d663f53c6a72f153 Mon Sep 17 00:00:00 2001 From: Nauman Ahmed <90570675+nauman897@users.noreply.github.com> Date: Sun, 8 Sep 2024 19:32:23 +0500 Subject: [PATCH 0867/1271] Fix issue with slashes being turned into backslashes on Windows (#12760) Fix #12745 --- AUTHORS | 1 + changelog/12745.bugfix.rst | 1 + src/_pytest/config/__init__.py | 8 ++++++-- testing/test_terminal.py | 35 ++++++++++++++++++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 changelog/12745.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 6da8cbfef80..374e6ad9bcc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -301,6 +301,7 @@ mrbean-bremen Nathan Goldbaum Nathaniel Compton Nathaniel Waisbrot +Nauman Ahmed Ned Batchelder Neil Martin Neven Mundar diff --git a/changelog/12745.bugfix.rst b/changelog/12745.bugfix.rst new file mode 100644 index 00000000000..420be931ce9 --- /dev/null +++ b/changelog/12745.bugfix.rst @@ -0,0 +1 @@ +Fixed an issue with backslashes being incorrectly converted in nodeid paths on Windows, ensuring consistent path handling across environments. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 29e5a58c4ac..c53661dbeb5 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1178,8 +1178,12 @@ def notify_exception( def cwd_relative_nodeid(self, nodeid: str) -> str: # nodeid's are relative to the rootpath, compute relative to cwd. if self.invocation_params.dir != self.rootpath: - fullpath = self.rootpath / nodeid - nodeid = bestrelpath(self.invocation_params.dir, fullpath) + base_path_part, *nodeid_part = nodeid.split("::") + # Only process path part + fullpath = self.rootpath / base_path_part + relative_path = bestrelpath(self.invocation_params.dir, fullpath) + + nodeid = "::".join([relative_path, *nodeid_part]) return nodeid @classmethod diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 11ad623fb6b..14c152d6123 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -3067,3 +3067,38 @@ def test_pass(): "*= 1 xpassed in * =*", ] ) + + +class TestNodeIDHandling: + def test_nodeid_handling_windows_paths(self, pytester: Pytester, tmp_path) -> None: + """Test the correct handling of Windows-style paths with backslashes.""" + pytester.makeini("[pytest]") # Change `config.rootpath` + + test_path = pytester.path / "tests" / "test_foo.py" + test_path.parent.mkdir() + os.chdir(test_path.parent) # Change `config.invocation_params.dir` + + test_path.write_text( + textwrap.dedent( + """ + import pytest + + @pytest.mark.parametrize("a", ["x/y", "C:/path", "\\\\", "C:\\\\path", "a::b/"]) + def test_x(a): + assert False + """ + ), + encoding="utf-8", + ) + + result = pytester.runpytest("-v") + + result.stdout.re_match_lines( + [ + r".*test_foo.py::test_x\[x/y\] .*FAILED.*", + r".*test_foo.py::test_x\[C:/path\] .*FAILED.*", + r".*test_foo.py::test_x\[\\\\\] .*FAILED.*", + r".*test_foo.py::test_x\[C:\\\\path\] .*FAILED.*", + r".*test_foo.py::test_x\[a::b/\] .*FAILED.*", + ] + ) From c6a529032231ccddd3040e8ab1a5a756eb9ea4a0 Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Sun, 8 Sep 2024 10:45:05 -0400 Subject: [PATCH 0868/1271] Do not discover properties when iterating fixtures (#12781) Resolves #12446 --- changelog/12446.bugfix.rst | 1 + src/_pytest/fixtures.py | 16 +++++++++++++--- testing/python/collect.py | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 changelog/12446.bugfix.rst diff --git a/changelog/12446.bugfix.rst b/changelog/12446.bugfix.rst new file mode 100644 index 00000000000..2f591c48eed --- /dev/null +++ b/changelog/12446.bugfix.rst @@ -0,0 +1 @@ +Avoid calling ``@property`` (and other instance descriptors) during fixture discovery -- by :user:`asottile` diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index aaa92c63725..6b882fa3515 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -53,6 +53,7 @@ from _pytest.compat import NOTSET from _pytest.compat import NotSetType from _pytest.compat import safe_getattr +from _pytest.compat import safe_isclass from _pytest.config import _PluggyPlugin from _pytest.config import Config from _pytest.config import ExitCode @@ -1724,17 +1725,26 @@ def parsefactories( if holderobj in self._holderobjseen: return + # Avoid accessing `@property` (and other descriptors) when iterating fixtures. + if not safe_isclass(holderobj) and not isinstance(holderobj, types.ModuleType): + holderobj_tp: object = type(holderobj) + else: + holderobj_tp = holderobj + self._holderobjseen.add(holderobj) for name in dir(holderobj): # The attribute can be an arbitrary descriptor, so the attribute - # access below can raise. safe_getatt() ignores such exceptions. - obj = safe_getattr(holderobj, name, None) - marker = getfixturemarker(obj) + # access below can raise. safe_getattr() ignores such exceptions. + obj_ub = safe_getattr(holderobj_tp, name, None) + marker = getfixturemarker(obj_ub) if not isinstance(marker, FixtureFunctionMarker): # Magic globals with __getattr__ might have got us a wrong # fixture attribute. continue + # OK we know it is a fixture -- now safe to look up on the _instance_. + obj = getattr(holderobj, name) + if marker.name: name = marker.name diff --git a/testing/python/collect.py b/testing/python/collect.py index 06386611279..530f1c340ff 100644 --- a/testing/python/collect.py +++ b/testing/python/collect.py @@ -263,6 +263,43 @@ def prop(self): result = pytester.runpytest() assert result.ret == ExitCode.NO_TESTS_COLLECTED + def test_does_not_discover_properties(self, pytester: Pytester) -> None: + """Regression test for #12446.""" + pytester.makepyfile( + """\ + class TestCase: + @property + def oops(self): + raise SystemExit('do not call me!') + """ + ) + result = pytester.runpytest() + assert result.ret == ExitCode.NO_TESTS_COLLECTED + + def test_does_not_discover_instance_descriptors(self, pytester: Pytester) -> None: + """Regression test for #12446.""" + pytester.makepyfile( + """\ + # not `@property`, but it acts like one + # this should cover the case of things like `@cached_property` / etc. + class MyProperty: + def __init__(self, func): + self._func = func + def __get__(self, inst, owner): + if inst is None: + return self + else: + return self._func.__get__(inst, owner)() + + class TestCase: + @MyProperty + def oops(self): + raise SystemExit('do not call me!') + """ + ) + result = pytester.runpytest() + assert result.ret == ExitCode.NO_TESTS_COLLECTED + def test_abstract_class_is_not_collected(self, pytester: Pytester) -> None: """Regression test for #12275 (non-unittest version).""" pytester.makepyfile( From 0b75b3ae66a030da0fb931878fccfd72de58ee9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 08:59:27 -0300 Subject: [PATCH 0869/1271] build(deps): Bump pytest-django in /testing/plugins_integration (#12792) Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.8.0 to 4.9.0. - [Release notes](https://github.com/pytest-dev/pytest-django/releases) - [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.8.0...v4.9.0) --- updated-dependencies: - dependency-name: pytest-django dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index c48b55c0ae2..aa5e0fb6caa 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -3,7 +3,7 @@ django==5.1 pytest-asyncio==0.24.0 pytest-bdd==7.2.0 pytest-cov==5.0.0 -pytest-django==4.8.0 +pytest-django==4.9.0 pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.14.0 From 39bd14ad1679e45583ab1ee35f152c35e3239226 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 08:59:38 -0300 Subject: [PATCH 0870/1271] build(deps): Bump django in /testing/plugins_integration (#12793) Bumps [django](https://github.com/django/django) from 5.1 to 5.1.1. - [Commits](https://github.com/django/django/compare/5.1...5.1.1) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index aa5e0fb6caa..70fac9e1f1c 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.4.0 -django==5.1 +django==5.1.1 pytest-asyncio==0.24.0 pytest-bdd==7.2.0 pytest-cov==5.0.0 From 63a5e11514501f8bd3ff50d88a09c33a7a5de0c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 09:04:10 -0300 Subject: [PATCH 0871/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.10.0 to 1.10.1 (#12790) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.10.0 to 1.10.1. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.10.0...v1.10.1) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index abbdead2ca9..1299c4c57c3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.10.0 + uses: pypa/gh-action-pypi-publish@v1.10.1 with: attestations: true From 7316b42df28ddf8de0038e5d6df1811408730dbd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 09:05:39 -0300 Subject: [PATCH 0872/1271] build(deps): Bump peter-evans/create-pull-request from 6.1.0 to 7.0.1 (#12791) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 6.1.0 to 7.0.1. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/c5a7806660adbe173f04e3e038b0ccdcd758773c...8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index ade8452afd5..2f1fb14ea70 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -47,7 +47,7 @@ jobs: - name: Create Pull Request id: pr - uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c + uses: peter-evans/create-pull-request@8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From e8504ed49be73e516ee1559a250daec659e96b9d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 9 Sep 2024 18:28:15 -0300 Subject: [PATCH 0873/1271] Include co-authors in release announcement (#12795) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As noted in #12789, the `release.py` script did not consider `Co-authored-by` fields, and since we introduced the new backport bot, this problem became more apparent due to how the backport commit and PR are generated. Previously, the list of authors produced by the script in the #12789 branch was: ``` * Avasam * Bruno Oliveira * Ronny Pfannschmidt * Sviatoslav Sydorenko (Святослав Сидоренко) ``` With this script: ``` * Anthony Sottile * Avasam * Bruno Oliveira * Christian Clauss * Eugene Mwangi * Florian Bruhin * GTowers1 * Nauman Ahmed * Pierre Sassoulas * Reagan Lee * Ronny Pfannschmidt * Stefaan Lippens * Sviatoslav Sydorenko (Святослав Сидоренко) * dongfangtianyu ``` --- scripts/release.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/scripts/release.py b/scripts/release.py index 545919cd60b..aef5d6d5f73 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -6,6 +6,7 @@ import argparse import os from pathlib import Path +import re from subprocess import call from subprocess import check_call from subprocess import check_output @@ -16,17 +17,27 @@ def announce(version: str, template_name: str, doc_version: str) -> None: """Generates a new release announcement entry in the docs.""" - # Get our list of authors + # Get our list of authors and co-authors. stdout = check_output(["git", "describe", "--abbrev=0", "--tags"], encoding="UTF-8") last_version = stdout.strip() + rev_range = f"{last_version}..HEAD" - stdout = check_output( - ["git", "log", f"{last_version}..HEAD", "--format=%aN"], encoding="UTF-8" + authors = check_output( + ["git", "log", rev_range, "--format=%aN"], encoding="UTF-8" + ).splitlines() + + co_authors_output = check_output( + ["git", "log", rev_range, "--format=%(trailers:key=Co-authored-by) "], + encoding="UTF-8", ) + co_authors: list[str] = [] + for co_author_line in co_authors_output.splitlines(): + if m := re.search(r"Co-authored-by: (.+?)<", co_author_line): + co_authors.append(m.group(1).strip()) contributors = { name - for name in stdout.splitlines() + for name in authors + co_authors if not name.endswith("[bot]") and name != "pytest bot" } From 3905a74b09ab4faded2a0aff7c4147fbb5b1a1e7 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 10 Sep 2024 07:53:09 -0300 Subject: [PATCH 0874/1271] Merge pull request #12798 from pytest-dev/release-8.3.3 Prepare release 8.3.3 (cherry picked from commit 03d8fb79aa3731f8c46f582bde8d590dbb278aba) --- changelog/12446.bugfix.rst | 1 - changelog/12659.bugfix.rst | 1 - changelog/12663.doc.rst | 1 - changelog/12667.bugfix.rst | 1 - changelog/12678.doc.rst | 1 - changelog/12744.bugfix.rst | 1 - changelog/12745.bugfix.rst | 1 - changelog/12769.misc.rst | 1 - changelog/6682.bugfix.rst | 1 - changelog/9422.bugfix.rst | 3 -- doc/en/announce/index.rst | 1 + doc/en/announce/release-8.3.3.rst | 31 +++++++++++++++++++ doc/en/builtin.rst | 18 +++++------ doc/en/changelog.rst | 46 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 ++-- doc/en/example/pythoncollection.rst | 4 +-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 18 files changed, 94 insertions(+), 28 deletions(-) delete mode 100644 changelog/12446.bugfix.rst delete mode 100644 changelog/12659.bugfix.rst delete mode 100644 changelog/12663.doc.rst delete mode 100644 changelog/12667.bugfix.rst delete mode 100644 changelog/12678.doc.rst delete mode 100644 changelog/12744.bugfix.rst delete mode 100644 changelog/12745.bugfix.rst delete mode 100644 changelog/12769.misc.rst delete mode 100644 changelog/6682.bugfix.rst delete mode 100644 changelog/9422.bugfix.rst create mode 100644 doc/en/announce/release-8.3.3.rst diff --git a/changelog/12446.bugfix.rst b/changelog/12446.bugfix.rst deleted file mode 100644 index 2f591c48eed..00000000000 --- a/changelog/12446.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Avoid calling ``@property`` (and other instance descriptors) during fixture discovery -- by :user:`asottile` diff --git a/changelog/12659.bugfix.rst b/changelog/12659.bugfix.rst deleted file mode 100644 index 297381b9602..00000000000 --- a/changelog/12659.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed the issue of not displaying assertion failure differences when using the parameter ``--import-mode=importlib`` in pytest>=8.1. diff --git a/changelog/12663.doc.rst b/changelog/12663.doc.rst deleted file mode 100644 index e665bc67a10..00000000000 --- a/changelog/12663.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Clarify that the `pytest_deselected` hook should be called from `pytest_collection_modifyitems` hook implementations when items are deselected. diff --git a/changelog/12667.bugfix.rst b/changelog/12667.bugfix.rst deleted file mode 100644 index eceee86cb53..00000000000 --- a/changelog/12667.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a regression where type change in `ExceptionInfo.errisinstance` caused `mypy` to fail. diff --git a/changelog/12678.doc.rst b/changelog/12678.doc.rst deleted file mode 100644 index 9d79ec41007..00000000000 --- a/changelog/12678.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Remove erroneous quotes from `tmp_path_retention_policy` example in docs. diff --git a/changelog/12744.bugfix.rst b/changelog/12744.bugfix.rst deleted file mode 100644 index 7814b59c180..00000000000 --- a/changelog/12744.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed typing compatibility with Python 3.9 or less -- replaced `typing.Self` with `typing_extensions.Self` -- by :user:`Avasam` diff --git a/changelog/12745.bugfix.rst b/changelog/12745.bugfix.rst deleted file mode 100644 index 420be931ce9..00000000000 --- a/changelog/12745.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed an issue with backslashes being incorrectly converted in nodeid paths on Windows, ensuring consistent path handling across environments. diff --git a/changelog/12769.misc.rst b/changelog/12769.misc.rst deleted file mode 100644 index aae4d137a0d..00000000000 --- a/changelog/12769.misc.rst +++ /dev/null @@ -1 +0,0 @@ -Fix typos discovered by codespell and add codespell to pre-commit hooks. diff --git a/changelog/6682.bugfix.rst b/changelog/6682.bugfix.rst deleted file mode 100644 index 7f756cbd9c2..00000000000 --- a/changelog/6682.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed bug where the verbosity levels where not being respected when printing the "msg" part of failed assertion (as in ``assert condition, msg``). diff --git a/changelog/9422.bugfix.rst b/changelog/9422.bugfix.rst deleted file mode 100644 index 38196340fd5..00000000000 --- a/changelog/9422.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix bug where disabling the terminal plugin via ``-p no:terminal`` would cause crashes related to missing the ``verbose`` option. - --- by :user:`GTowers1` diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 09311a1a1ab..61e4a772beb 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.3.3 release-8.3.2 release-8.3.1 release-8.3.0 diff --git a/doc/en/announce/release-8.3.3.rst b/doc/en/announce/release-8.3.3.rst new file mode 100644 index 00000000000..5e3eb36b921 --- /dev/null +++ b/doc/en/announce/release-8.3.3.rst @@ -0,0 +1,31 @@ +pytest-8.3.3 +======================================= + +pytest 8.3.3 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Anthony Sottile +* Avasam +* Bruno Oliveira +* Christian Clauss +* Eugene Mwangi +* Florian Bruhin +* GTowers1 +* Nauman Ahmed +* Pierre Sassoulas +* Reagan Lee +* Ronny Pfannschmidt +* Stefaan Lippens +* Sviatoslav Sydorenko (Святослав Сидоренко) +* dongfangtianyu + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index b4c0f91f8e5..9b406a6a512 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:558 + cache -- .../_pytest/cacheprovider.py:556 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1005 + capsysbinary -- .../_pytest/capture.py:1006 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -51,7 +51,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1033 + capfd -- .../_pytest/capture.py:1034 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -69,7 +69,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1061 + capfdbinary -- .../_pytest/capture.py:1062 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -87,7 +87,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - capsys -- .../_pytest/capture.py:977 + capsys -- .../_pytest/capture.py:978 Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsys.readouterr()`` method @@ -105,7 +105,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsys.readouterr() assert captured.out == "hello\n" - doctest_namespace [session scope] -- .../_pytest/doctest.py:740 + doctest_namespace [session scope] -- .../_pytest/doctest.py:741 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -119,14 +119,14 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1344 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1345 Session-scoped fixture that returns the session's :class:`pytest.Config` object. Example:: def test_foo(pytestconfig): - if pytestconfig.getoption("verbose") > 0: + if pytestconfig.get_verbosity() > 0: ... record_property -- .../_pytest/junitxml.py:280 @@ -196,7 +196,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:600 + caplog -- .../_pytest/logging.py:598 Access and control log capturing. Captured logs are available through the following properties/methods:: diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 9da6f487f8d..9f30c86be3a 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,52 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.3.3 (2024-09-09) +========================= + +Bug fixes +--------- + +- `#12446 `_: Avoid calling ``@property`` (and other instance descriptors) during fixture discovery -- by :user:`asottile` + + +- `#12659 `_: Fixed the issue of not displaying assertion failure differences when using the parameter ``--import-mode=importlib`` in pytest>=8.1. + + +- `#12667 `_: Fixed a regression where type change in `ExceptionInfo.errisinstance` caused `mypy` to fail. + + +- `#12744 `_: Fixed typing compatibility with Python 3.9 or less -- replaced `typing.Self` with `typing_extensions.Self` -- by :user:`Avasam` + + +- `#12745 `_: Fixed an issue with backslashes being incorrectly converted in nodeid paths on Windows, ensuring consistent path handling across environments. + + +- `#6682 `_: Fixed bug where the verbosity levels where not being respected when printing the "msg" part of failed assertion (as in ``assert condition, msg``). + + +- `#9422 `_: Fix bug where disabling the terminal plugin via ``-p no:terminal`` would cause crashes related to missing the ``verbose`` option. + + -- by :user:`GTowers1` + + + +Improved documentation +---------------------- + +- `#12663 `_: Clarify that the `pytest_deselected` hook should be called from `pytest_collection_modifyitems` hook implementations when items are deselected. + + +- `#12678 `_: Remove erroneous quotes from `tmp_path_retention_policy` example in docs. + + + +Miscellaneous internal changes +------------------------------ + +- `#12769 `_: Fix typos discovered by codespell and add codespell to pre-commit hooks. + + pytest 8.3.2 (2024-07-24) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index b175510da6a..fa43308d045 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 5bd03035c14..42a603f114c 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 050fd2d80ec..faf81154c48 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.3.2 + pytest 8.3.3 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index d60635c4fea..4f6e8cbee06 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From 222457d7d9898681bc3e035e8a65133503d13e04 Mon Sep 17 00:00:00 2001 From: sven <42868792+FreerGit@users.noreply.github.com> Date: Thu, 12 Sep 2024 19:33:16 +0200 Subject: [PATCH 0875/1271] Add `discover_imports` in conf - Allows a user to define whether or not pytest should treat imported (but not in testpaths) as test classes. - Imagine a class is called TestFoo defined in src/ dir, when discover_imports is disabled, TestFoo is not treated as a test class. --- AUTHORS | 1 + changelog/12749.feature.rst | 3 ++ src/_pytest/main.py | 5 ++ src/_pytest/python.py | 6 +++ testing/test_discover_imports.py | 88 ++++++++++++++++++++++++++++++++ 5 files changed, 103 insertions(+) create mode 100644 changelog/12749.feature.rst create mode 100644 testing/test_discover_imports.py diff --git a/AUTHORS b/AUTHORS index 374e6ad9bcc..b1dd40dbd4c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -400,6 +400,7 @@ Stefanie Molin Stefano Taschini Steffen Allner Stephan Obermann +Sven Sven-Hendrik Haase Sviatoslav Sydorenko Sylvain Marié diff --git a/changelog/12749.feature.rst b/changelog/12749.feature.rst new file mode 100644 index 00000000000..138a5bc7914 --- /dev/null +++ b/changelog/12749.feature.rst @@ -0,0 +1,3 @@ +Add :confval:`discover_imports`, when disabled (default) will make sure to not consider classes which are imported by a test file and starts with Test. + +-- by :user:`FreerGit` \ No newline at end of file diff --git a/src/_pytest/main.py b/src/_pytest/main.py index e5534e98d69..4887d336b2d 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -78,6 +78,11 @@ def pytest_addoption(parser: Parser) -> None: type="args", default=[], ) + parser.addini( + "discover_imports", + "Whether to discover tests in imported modules outside `testpaths`", + default=False, + ) group = parser.getgroup("general", "Running and selection options") group._addoption( "-x", diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 9c54dd20f80..9467b26fd02 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -741,6 +741,12 @@ def newinstance(self): return self.obj() def collect(self) -> Iterable[nodes.Item | nodes.Collector]: + if self.config.getini("discover_imports") == ("false" or False): + paths = self.config.getini("testpaths") + class_file = inspect.getfile(self.obj) + if not any(string in class_file for string in paths): + return [] + if not safe_getattr(self.obj, "__test__", True): return [] if hasinit(self.obj): diff --git a/testing/test_discover_imports.py b/testing/test_discover_imports.py new file mode 100644 index 00000000000..829b614ed46 --- /dev/null +++ b/testing/test_discover_imports.py @@ -0,0 +1,88 @@ +import pytest +import textwrap + +def test_discover_imports_enabled(pytester): + src_dir = pytester.mkdir("src") + tests_dir = pytester.mkdir("tests") + pytester.makeini(""" + [pytest] + testpaths = "tests" + discover_imports = true + """) + + src_file = src_dir / "foo.py" + + src_file.write_text(textwrap.dedent("""\ + class TestClass(object): + def __init__(self): + super().__init__() + + def test_foobar(self): + return true + """ + ), encoding="utf-8") + + test_file = tests_dir / "foo_test.py" + test_file.write_text(textwrap.dedent("""\ + import sys + import os + + current_file = os.path.abspath(__file__) + current_dir = os.path.dirname(current_file) + parent_dir = os.path.abspath(os.path.join(current_dir, '..')) + sys.path.append(parent_dir) + + from src.foo import TestClass + + class TestDomain: + def test_testament(self): + testament = TestClass() + pass + """), encoding="utf-8") + + result = pytester.runpytest() + result.assert_outcomes(errors=1) + +def test_discover_imports_disabled(pytester): + + src_dir = pytester.mkdir("src") + tests_dir = pytester.mkdir("tests") + pytester.makeini(""" + [pytest] + testpaths = "tests" + discover_imports = false + """) + + src_file = src_dir / "foo.py" + + src_file.write_text(textwrap.dedent("""\ + class Testament(object): + def __init__(self): + super().__init__() + self.collections = ["stamp", "coin"] + + def personal_property(self): + return [f"my {x} collection" for x in self.collections] + """ + ), encoding="utf-8") + + test_file = tests_dir / "foo_test.py" + test_file.write_text(textwrap.dedent("""\ + import sys + import os + + current_file = os.path.abspath(__file__) + current_dir = os.path.dirname(current_file) + parent_dir = os.path.abspath(os.path.join(current_dir, '..')) + sys.path.append(parent_dir) + + from src.foo import Testament + + class TestDomain: + def test_testament(self): + testament = Testament() + assert testament.personal_property() + """), encoding="utf-8") + + result = pytester.runpytest() + result.assert_outcomes(passed=1) \ No newline at end of file From fa3b6310c8202e820cd0195960d14d10a1f99303 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:38:20 +0000 Subject: [PATCH 0876/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- changelog/12749.feature.rst | 2 +- testing/test_discover_imports.py | 38 +++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/changelog/12749.feature.rst b/changelog/12749.feature.rst index 138a5bc7914..a6fb8bf9e62 100644 --- a/changelog/12749.feature.rst +++ b/changelog/12749.feature.rst @@ -1,3 +1,3 @@ Add :confval:`discover_imports`, when disabled (default) will make sure to not consider classes which are imported by a test file and starts with Test. --- by :user:`FreerGit` \ No newline at end of file +-- by :user:`FreerGit` diff --git a/testing/test_discover_imports.py b/testing/test_discover_imports.py index 829b614ed46..cdb55916ba6 100644 --- a/testing/test_discover_imports.py +++ b/testing/test_discover_imports.py @@ -1,6 +1,8 @@ -import pytest +from __future__ import annotations + import textwrap + def test_discover_imports_enabled(pytester): src_dir = pytester.mkdir("src") tests_dir = pytester.mkdir("tests") @@ -12,18 +14,21 @@ def test_discover_imports_enabled(pytester): src_file = src_dir / "foo.py" - src_file.write_text(textwrap.dedent("""\ + src_file.write_text( + textwrap.dedent("""\ class TestClass(object): def __init__(self): super().__init__() def test_foobar(self): return true - """ - ), encoding="utf-8") + """), + encoding="utf-8", + ) test_file = tests_dir / "foo_test.py" - test_file.write_text(textwrap.dedent("""\ + test_file.write_text( + textwrap.dedent("""\ import sys import os @@ -38,13 +43,15 @@ class TestDomain: def test_testament(self): testament = TestClass() pass - """), encoding="utf-8") + """), + encoding="utf-8", + ) result = pytester.runpytest() result.assert_outcomes(errors=1) + def test_discover_imports_disabled(pytester): - src_dir = pytester.mkdir("src") tests_dir = pytester.mkdir("tests") pytester.makeini(""" @@ -55,7 +62,8 @@ def test_discover_imports_disabled(pytester): src_file = src_dir / "foo.py" - src_file.write_text(textwrap.dedent("""\ + src_file.write_text( + textwrap.dedent("""\ class Testament(object): def __init__(self): super().__init__() @@ -63,11 +71,13 @@ def __init__(self): def personal_property(self): return [f"my {x} collection" for x in self.collections] - """ - ), encoding="utf-8") + """), + encoding="utf-8", + ) test_file = tests_dir / "foo_test.py" - test_file.write_text(textwrap.dedent("""\ + test_file.write_text( + textwrap.dedent("""\ import sys import os @@ -82,7 +92,9 @@ class TestDomain: def test_testament(self): testament = Testament() assert testament.personal_property() - """), encoding="utf-8") + """), + encoding="utf-8", + ) result = pytester.runpytest() - result.assert_outcomes(passed=1) \ No newline at end of file + result.assert_outcomes(passed=1) From 26cb6ccebdbfb5e505407917ee8db53a2a47c5c6 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 15 Sep 2024 00:25:17 +0000 Subject: [PATCH 0877/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 150 +++++++++++++++++-------------- 1 file changed, 83 insertions(+), 67 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index ffca5c08380..23e95e27730 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A - :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Feb 10, 2024 N/A pytest (>=6) + :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Sep 09, 2024 N/A pytest>=7 :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Nov 08, 2023 N/A pytest >=5.4.0 :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) @@ -74,7 +74,7 @@ This list contains 1513 plugins. :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Aug 16, 2024 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Sep 11, 2024 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -154,7 +154,7 @@ This list contains 1513 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Sep 05, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Sep 13, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -175,6 +175,7 @@ This list contains 1513 plugins. :pypi:`pytest-blocker` pytest plugin to mark a test as blocker and skip all other tests Sep 07, 2015 4 - Beta N/A :pypi:`pytest-blue` A pytest plugin that adds a \`blue\` fixture for printing stuff in blue. Sep 05, 2022 N/A N/A :pypi:`pytest-board` Local continuous test runner with pytest and watchdog. Jan 20, 2019 N/A N/A + :pypi:`pytest-boilerplate` The pytest plugin for your Django Boilerplate. Sep 12, 2024 5 - Production/Stable pytest>=4.0.0 :pypi:`pytest-boost-xml` Plugin for pytest to generate boost xml reports Nov 30, 2022 4 - Beta N/A :pypi:`pytest-bootstrap` Mar 04, 2022 N/A N/A :pypi:`pytest-boto-mock` Thin-wrapper around the mock package for easier use with pytest Jul 16, 2024 5 - Production/Stable pytest>=8.2.0 @@ -242,7 +243,7 @@ This list contains 1513 plugins. :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A - :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Aug 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 14, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Aug 15, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) @@ -317,7 +318,7 @@ This list contains 1513 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Aug 20, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Sep 07, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -440,7 +441,7 @@ This list contains 1513 plugins. :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A - :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Apr 22, 2022 5 - Production/Stable pytest (>=4.6) + :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Sep 11, 2024 5 - Production/Stable pytest>=4.6 :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Mar 12, 2024 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A @@ -470,14 +471,14 @@ This list contains 1513 plugins. :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) - :pypi:`pytest-enabler` Enable installed pytest plugins Aug 29, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "test" + :pypi:`pytest-enabler` Enable installed pytest plugins Sep 12, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "test" :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest :pypi:`pytest_energy_reporter` An energy estimation reporter for pytest Mar 28, 2024 3 - Alpha pytest<9.0.0,>=8.1.1 :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. Nov 28, 2023 5 - Production/Stable pytest>=7.4.3 + :pypi:`pytest-env` pytest plugin that allows you to add environment variables. Sep 07, 2024 5 - Production/Stable pytest>=8.3.2 :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-environment` Pytest Environment Mar 17, 2024 1 - Planning N/A @@ -593,7 +594,7 @@ This list contains 1513 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Sep 06, 2024 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Sep 11, 2024 N/A pytest :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 Jul 03, 2024 4 - Beta pytest>=6.0.0 @@ -619,7 +620,7 @@ This list contains 1513 plugins. :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Sep 06, 2024 N/A N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A - :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Apr 03, 2024 N/A pytest>=8.1.1 + :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Sep 09, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 :pypi:`pytest-git-selector` Utility to select tests that have had its dependencies modified (as identified by git diff) Nov 17, 2022 N/A N/A :pypi:`pytest-glamor-allure` Extends allure-pytest functionality Apr 30, 2024 4 - Beta pytest<=8.2.0 @@ -761,7 +762,7 @@ This list contains 1513 plugins. :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A :pypi:`pytest-konira` Run Konira DSL tests with py.test Oct 09, 2011 N/A N/A - :pypi:`pytest-kookit` Your simple but kooky integration testing with pytest May 16, 2024 N/A N/A + :pypi:`pytest-kookit` Your simple but kooky integration testing with pytest Sep 10, 2024 N/A N/A :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) @@ -852,7 +853,7 @@ This list contains 1513 plugins. :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Aug 27, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-missing-modules` Pytest plugin to easily fake missing modules Sep 03, 2024 N/A pytest>=8.3.2 - :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests May 28, 2024 N/A pytest>=7.0 + :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Sep 12, 2024 N/A pytest>=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Mar 21, 2024 5 - Production/Stable pytest>=6.2.5 @@ -899,7 +900,7 @@ This list contains 1513 plugins. :pypi:`pytest-ndb` pytest notebook debugger Apr 28, 2024 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) - :pypi:`pytest-neos` Pytest plugin for neos Jun 11, 2024 1 - Planning N/A + :pypi:`pytest-neos` Pytest plugin for neos Sep 10, 2024 5 - Production/Stable pytest<8.0,>=7.2; extra == "dev" :pypi:`pytest-netconf` A pytest plugin that provides a mock NETCONF (RFC6241/RFC6242) server for local testing. Aug 08, 2024 N/A N/A :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jul 05, 2024 N/A pytest<7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A @@ -909,7 +910,7 @@ This list contains 1513 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Jul 01, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Sep 06, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Aug 05, 2024 N/A N/A @@ -1002,7 +1003,7 @@ This list contains 1513 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Jul 03, 2024 N/A N/A + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Sep 06, 2024 N/A pytest<9.0.0,>=6.2.4 :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright May 24, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1014,7 +1015,7 @@ This list contains 1513 plugins. :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Mar 26, 2024 5 - Production/Stable pytest>=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A - :pypi:`pytest-pogo` Pytest plugin for pogo-migrate May 22, 2024 1 - Planning pytest<9,>=7 + :pypi:`pytest-pogo` Pytest plugin for pogo-migrate Sep 09, 2024 4 - Beta pytest<9,>=7 :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A :pypi:`pytest-pokie` Pokie plugin for pytest Oct 19, 2023 5 - Production/Stable N/A :pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A @@ -1034,7 +1035,7 @@ This list contains 1513 plugins. :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A - :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Aug 25, 2023 5 - Production/Stable pytest>=7.4 + :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Sep 08, 2024 5 - Production/Stable pytest>=8.3.2 :pypi:`pytest-priority` pytest plugin for add priority for tests Aug 19, 2024 N/A pytest :pypi:`pytest-proceed` Apr 10, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) @@ -1141,7 +1142,7 @@ This list contains 1513 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Mar 27, 2024 N/A pytest>=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Sep 06, 2024 N/A pytest>=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A :pypi:`pytest-req` pytest requests plugin Aug 31, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.2 @@ -1181,7 +1182,7 @@ This list contains 1513 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Aug 21, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 10, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1206,7 +1207,7 @@ This list contains 1513 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 05, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 12, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1217,14 +1218,14 @@ This list contains 1513 plugins. :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 Feb 01, 2024 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. Sep 05, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 12, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-send-email` Send pytest execution result email Sep 02, 2024 N/A pytest :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Apr 25, 2024 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A - :pypi:`pytest-server` test server exec cmd Jun 24, 2024 N/A N/A + :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A :pypi:`pytest-servers` pytest servers Aug 15, 2024 3 - Alpha pytest>=6.2 @@ -1236,7 +1237,7 @@ This list contains 1513 plugins. :pypi:`pytest-setupinfo` Displaying setup info during pytest command run Jan 23, 2023 N/A N/A :pypi:`pytest-sftpserver` py.test plugin to locally test sftp server connections. Sep 16, 2019 4 - Beta N/A :pypi:`pytest-shard` Dec 11, 2020 4 - Beta pytest - :pypi:`pytest-shared-session-scope` Sep 05, 2024 N/A pytest>=7 + :pypi:`pytest-shared-session-scope` Pytest session-scoped fixture that works with xdist Sep 08, 2024 N/A pytest>=7 :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A @@ -1340,7 +1341,7 @@ This list contains 1513 plugins. :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A :pypi:`pytest_tagging` a pytest plugin to tag tests Aug 31, 2024 N/A pytest<8.0.0,>=7.1.3 - :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Feb 15, 2023 N/A N/A + :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Sep 07, 2024 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Jul 15, 2023 5 - Production/Stable pytest (>=3.0) @@ -1391,7 +1392,7 @@ This list contains 1513 plugins. :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Aug 20, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 - :pypi:`pytest-tesults` Tesults plugin for pytest Feb 15, 2024 5 - Production/Stable pytest >=3.5.0 + :pypi:`pytest-tesults` Tesults plugin for pytest Sep 09, 2024 5 - Production/Stable pytest>=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 22, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-tf` Test your OpenTofu and Terraform config using a PyTest plugin May 29, 2024 N/A pytest<9.0.0,>=8.2.1 @@ -1445,12 +1446,12 @@ This list contains 1513 plugins. :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A - :pypi:`pytest-twisted` A twisted plugin for pytest. Jul 10, 2024 5 - Production/Stable pytest>=2.3 + :pypi:`pytest-twisted` A twisted plugin for pytest. Sep 10, 2024 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 Feb 01, 2024 4 - Beta N/A :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Aug 15, 2023 4 - Beta N/A - :pypi:`pytest-typing-runner` Pytest plugin to make it easier to run and check python code against static type checkers Aug 29, 2024 N/A pytest==8.2.2; extra == "tests" + :pypi:`pytest-typing-runner` Pytest plugin to make it easier to run and check python code against static type checkers Sep 09, 2024 N/A pytest==8.2.2; extra == "tests" :pypi:`pytest-tytest` Typhoon HIL plugin for pytest May 25, 2020 4 - Beta pytest (>=5.4.2) :pypi:`pytest-ubersmith` Easily mock calls to ubersmith at the \`requests\` level. Apr 13, 2015 N/A N/A :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest @@ -1492,6 +1493,7 @@ This list contains 1513 plugins. :pypi:`pytest-wake` Mar 20, 2024 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Aug 28, 2024 4 - Beta N/A + :pypi:`pytest-watch-plugin` Placeholder for internal package Sep 12, 2024 N/A N/A :pypi:`pytest_wdb` Trace pytest tests with wdb to halt on error with --wdb. Jul 04, 2016 N/A N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest @@ -1541,7 +1543,7 @@ This list contains 1513 plugins. :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) - :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Sep 04, 2024 N/A pytest + :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Sep 11, 2024 N/A pytest :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) @@ -1588,9 +1590,9 @@ This list contains 1513 plugins. A contextmanager pytest fixture for handling multiple mock abstracts :pypi:`pytest-accept` - *last release*: Feb 10, 2024, + *last release*: Sep 09, 2024, *status*: N/A, - *requires*: pytest (>=6) + *requires*: pytest>=7 A pytest-plugin for updating doctest outputs @@ -1833,7 +1835,7 @@ This list contains 1513 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. :pypi:`pytest-ansible` - *last release*: Aug 16, 2024, + *last release*: Sep 11, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2393,7 +2395,7 @@ This list contains 1513 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Sep 05, 2024, + *last release*: Sep 13, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2539,6 +2541,13 @@ This list contains 1513 plugins. Local continuous test runner with pytest and watchdog. + :pypi:`pytest-boilerplate` + *last release*: Sep 12, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=4.0.0 + + The pytest plugin for your Django Boilerplate. + :pypi:`pytest-boost-xml` *last release*: Nov 30, 2022, *status*: 4 - Beta, @@ -3009,7 +3018,7 @@ This list contains 1513 plugins. Automated, comprehensive and well-organised pytest test cases. :pypi:`pytest-cleanuptotal` - *last release*: Aug 26, 2024, + *last release*: Sep 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -3534,7 +3543,7 @@ This list contains 1513 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Aug 20, 2024, + *last release*: Sep 07, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4395,9 +4404,9 @@ This list contains 1513 plugins. :pypi:`pytest-durations` - *last release*: Apr 22, 2022, + *last release*: Sep 11, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.6) + *requires*: pytest>=4.6 Pytest plugin reporting fixtures and test functions execution time. @@ -4605,7 +4614,7 @@ This list contains 1513 plugins. Pytest plugin to represent test output with emoji support :pypi:`pytest-enabler` - *last release*: Aug 29, 2024, + *last release*: Sep 12, 2024, *status*: 5 - Production/Stable, *requires*: pytest!=8.1.*,>=6; extra == "test" @@ -4654,9 +4663,9 @@ This list contains 1513 plugins. Improvements for pytest (rejected upstream) :pypi:`pytest-env` - *last release*: Nov 28, 2023, + *last release*: Sep 07, 2024, *status*: 5 - Production/Stable, - *requires*: pytest>=7.4.3 + *requires*: pytest>=8.3.2 pytest plugin that allows you to add environment variables. @@ -5466,7 +5475,7 @@ This list contains 1513 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Sep 06, 2024, + *last release*: Sep 11, 2024, *status*: N/A, *requires*: pytest @@ -5648,7 +5657,7 @@ This list contains 1513 plugins. Parallelize pytest across GitLab CI workers. :pypi:`pytest-gitlab-code-quality` - *last release*: Apr 03, 2024, + *last release*: Sep 09, 2024, *status*: N/A, *requires*: pytest>=8.1.1 @@ -6642,7 +6651,7 @@ This list contains 1513 plugins. Run Konira DSL tests with py.test :pypi:`pytest-kookit` - *last release*: May 16, 2024, + *last release*: Sep 10, 2024, *status*: N/A, *requires*: N/A @@ -7279,7 +7288,7 @@ This list contains 1513 plugins. Pytest plugin to easily fake missing modules :pypi:`pytest-mitmproxy` - *last release*: May 28, 2024, + *last release*: Sep 12, 2024, *status*: N/A, *requires*: pytest>=7.0 @@ -7608,9 +7617,9 @@ This list contains 1513 plugins. pytest-neo is a plugin for pytest that shows tests like screen of Matrix. :pypi:`pytest-neos` - *last release*: Jun 11, 2024, - *status*: 1 - Planning, - *requires*: N/A + *last release*: Sep 10, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest<8.0,>=7.2; extra == "dev" Pytest plugin for neos @@ -7678,7 +7687,7 @@ This list contains 1513 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Jul 01, 2024, + *last release*: Sep 06, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -8329,9 +8338,9 @@ This list contains 1513 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Jul 03, 2024, + *last release*: Sep 06, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest<9.0.0,>=6.2.4 A pytest wrapper with fixtures for Playwright to automate web browsers @@ -8413,8 +8422,8 @@ This list contains 1513 plugins. :pypi:`pytest-pogo` - *last release*: May 22, 2024, - *status*: 1 - Planning, + *last release*: Sep 09, 2024, + *status*: 4 - Beta, *requires*: pytest<9,>=7 Pytest plugin for pogo-migrate @@ -8553,9 +8562,9 @@ This list contains 1513 plugins. Minitest-style test colors :pypi:`pytest-print` - *last release*: Aug 25, 2023, + *last release*: Sep 08, 2024, *status*: 5 - Production/Stable, - *requires*: pytest>=7.4 + *requires*: pytest>=8.3.2 pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) @@ -9302,7 +9311,7 @@ This list contains 1513 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Mar 27, 2024, + *last release*: Sep 06, 2024, *status*: N/A, *requires*: pytest>=3.8.0 @@ -9582,7 +9591,7 @@ This list contains 1513 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Aug 21, 2024, + *last release*: Sep 10, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9757,7 +9766,7 @@ This list contains 1513 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Sep 05, 2024, + *last release*: Sep 12, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9834,7 +9843,7 @@ This list contains 1513 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Sep 05, 2024, + *last release*: Sep 12, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9883,7 +9892,7 @@ This list contains 1513 plugins. Pytest plugin for sequencing markers for execution of tests :pypi:`pytest-server` - *last release*: Jun 24, 2024, + *last release*: Sep 09, 2024, *status*: N/A, *requires*: N/A @@ -9967,11 +9976,11 @@ This list contains 1513 plugins. :pypi:`pytest-shared-session-scope` - *last release*: Sep 05, 2024, + *last release*: Sep 08, 2024, *status*: N/A, *requires*: pytest>=7 - + Pytest session-scoped fixture that works with xdist :pypi:`pytest-share-hdf` *last release*: Sep 21, 2022, @@ -10695,7 +10704,7 @@ This list contains 1513 plugins. a pytest plugin to tag tests :pypi:`pytest-takeltest` - *last release*: Feb 15, 2023, + *last release*: Sep 07, 2024, *status*: N/A, *requires*: N/A @@ -11052,9 +11061,9 @@ This list contains 1513 plugins. :pypi:`pytest-tesults` - *last release*: Feb 15, 2024, + *last release*: Sep 09, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=3.5.0 + *requires*: pytest>=3.5.0 Tesults plugin for pytest @@ -11430,7 +11439,7 @@ This list contains 1513 plugins. :pypi:`pytest-twisted` - *last release*: Jul 10, 2024, + *last release*: Sep 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=2.3 @@ -11465,7 +11474,7 @@ This list contains 1513 plugins. Typhoon HIL plugin for pytest :pypi:`pytest-typing-runner` - *last release*: Aug 29, 2024, + *last release*: Sep 09, 2024, *status*: N/A, *requires*: pytest==8.2.2; extra == "tests" @@ -11758,6 +11767,13 @@ This list contains 1513 plugins. Automatically rerun your tests on file modifications + :pypi:`pytest-watch-plugin` + *last release*: Sep 12, 2024, + *status*: N/A, + *requires*: N/A + + Placeholder for internal package + :pypi:`pytest_wdb` *last release*: Jul 04, 2016, *status*: N/A, @@ -12102,7 +12118,7 @@ This list contains 1513 plugins. Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. :pypi:`pytest-zephyr-scale-integration` - *last release*: Sep 04, 2024, + *last release*: Sep 11, 2024, *status*: N/A, *requires*: pytest From c22b012ba86ad91e4578e9826c4987e77463f390 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:43:57 +0200 Subject: [PATCH 0878/1271] build(deps): Bump hynek/build-and-inspect-python-package (#12822) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.8.0 to 2.9.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.8.0...v2.9.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1299c4c57c3..cb053552ccd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.8.0 + uses: hynek/build-and-inspect-python-package@v2.9.0 with: attest-build-provenance-github: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 83a3d9cb33e..8e66f5eae5c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.8.0 + uses: hynek/build-and-inspect-python-package@v2.9.0 build: needs: [package] From e7e3f5067754294392ed646c294a81d8f3db217b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 08:01:42 +0000 Subject: [PATCH 0879/1271] build(deps): Bump peter-evans/create-pull-request from 7.0.1 to 7.0.2 (#12821) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.1 to 7.0.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20...d121e62763d8cc35b5fb1710e887d6e69a52d3a4) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 2f1fb14ea70..3029436ce79 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -47,7 +47,7 @@ jobs: - name: Create Pull Request id: pr - uses: peter-evans/create-pull-request@8867c4aba1b742c39f8d0ba35429c2dfa4b6cb20 + uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From d32dee15372ae0090575ebfad559bdecaf0cf3ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 13:10:41 +0200 Subject: [PATCH 0880/1271] build(deps): Bump pytest-twisted in /testing/plugins_integration (#12820) Bumps [pytest-twisted](https://github.com/pytest-dev/pytest-twisted) from 1.14.2 to 1.14.3. - [Release notes](https://github.com/pytest-dev/pytest-twisted/releases) - [Commits](https://github.com/pytest-dev/pytest-twisted/compare/v1.14.2...v1.14.3) --- updated-dependencies: - dependency-name: pytest-twisted dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 70fac9e1f1c..379b4ffa5e8 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -10,6 +10,6 @@ pytest-mock==3.14.0 pytest-rerunfailures==14.0 pytest-sugar==1.0.0 pytest-trio==0.8.0 -pytest-twisted==1.14.2 +pytest-twisted==1.14.3 twisted==24.7.0 pytest-xvfb==3.0.0 From c22a0cf8f5d8667960c6ce9556e77376e2077a76 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:36:45 +0000 Subject: [PATCH 0881/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.3 → v0.6.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.3...v0.6.5) - [github.com/tox-dev/pyproject-fmt: 2.2.1 → 2.2.3](https://github.com/tox-dev/pyproject-fmt/compare/2.2.1...2.2.3) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dfeca73648b..b6f2a16424a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.3" + rev: "v0.6.5" hooks: - id: ruff args: ["--fix"] @@ -46,7 +46,7 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "2.2.1" + rev: "2.2.3" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version From 50044f61446837dc3e2c4b56d7ad516d52808838 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 16 Sep 2024 20:17:09 -0300 Subject: [PATCH 0882/1271] Ignore ruff error about EncodingWarning not defined in Python<3.10 We have a runtime guard right above it, so it is OK to ignore it. --- testing/_py/test_local.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 4a95e2d0cd9..21fbfb3e3ad 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -19,7 +19,7 @@ def ignore_encoding_warning(): with warnings.catch_warnings(): if sys.version_info > (3, 10): - warnings.simplefilter("ignore", EncodingWarning) + warnings.simplefilter("ignore", EncodingWarning) # noqa: F821 yield From 4508d0b2d465eb02c97dc526c0bc8119e2b162f5 Mon Sep 17 00:00:00 2001 From: Serge Smertin <259697+nfx@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:59:54 +0200 Subject: [PATCH 0883/1271] Added Databricks fixture plugin for PyTest (#12826) Adding it as a `ADDITIONAL_PROJECTS`, because our naming conventions can't fit `pytest-` as a prefix. https://github.com/databrickslabs/pytester https://pypi.org/project/databricks-labs-pytester/ --- scripts/update-plugin-list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 75df0ddba40..556004d9e98 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -66,6 +66,7 @@ "logot", "nuts", "flask_fixture", + "databricks-labs-pytester", } From d924a63871df8542a6accbeb973e857a3b40eb85 Mon Sep 17 00:00:00 2001 From: Pavel Zhukov <48322035+zhukoff-pavel@users.noreply.github.com> Date: Sat, 21 Sep 2024 16:00:56 +0300 Subject: [PATCH 0884/1271] Implement truncation thresholds config options (#12766) Fixes #12765 Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/12765.feature.rst | 3 ++ doc/en/how-to/output.rst | 22 ++++++++++++ doc/en/reference/reference.rst | 40 +++++++++++++++++++++ src/_pytest/assertion/__init__.py | 12 +++++++ src/_pytest/assertion/truncate.py | 58 ++++++++++++++++++++---------- testing/test_assertion.py | 60 +++++++++++++++++++++++++++++++ 7 files changed, 177 insertions(+), 19 deletions(-) create mode 100644 changelog/12765.feature.rst diff --git a/AUTHORS b/AUTHORS index 374e6ad9bcc..1ee868448d4 100644 --- a/AUTHORS +++ b/AUTHORS @@ -328,6 +328,7 @@ Paul Müller Paul Reece Pauli Virtanen Pavel Karateev +Pavel Zhukov Paweł Adamczak Pedro Algarvio Petter Strandmark diff --git a/changelog/12765.feature.rst b/changelog/12765.feature.rst new file mode 100644 index 00000000000..193c75621f7 --- /dev/null +++ b/changelog/12765.feature.rst @@ -0,0 +1,3 @@ +Thresholds to trigger snippet truncation can now be set with :confval:`truncation_limit_lines` and :confval:`truncation_limit_chars`. + +See :ref:`truncation-params` for more information. diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index 8b15f95f0fd..d53dd4b8ec7 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -549,6 +549,28 @@ captured output: By default, parametrized variants of skipped tests are grouped together if they share the same skip reason. You can use ``--no-fold-skipped`` to print each skipped test separately. + +.. _truncation-params: + +Modifying truncation limits +-------------------------------------------------- + +.. versionadded: 8.4 + +Default truncation limits are 8 lines or 640 characters, whichever comes first. +To set custom truncation limits you can use following ``pytest.ini`` file options: + +.. code-block:: ini + + [pytest] + truncation_limit_lines = 10 + truncation_limit_chars = 90 + +That will cause pytest to truncate the assertions to 10 lines or 90 characters, whichever comes first. + +Setting both :confval:`truncation_limit_lines` and :confval:`truncation_limit_chars` to ``0`` will disable the truncation. +However, setting only one of those values will disable one truncation mode, but will leave the other one intact. + Creating resultlog format files -------------------------------------------------- diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index f7dfb3ffa71..73398ac811e 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1873,6 +1873,46 @@ passed multiple times. The expected format is ``name=value``. For example:: Default: ``all`` +.. confval:: truncation_limit_chars + + Controls maximum number of characters to truncate assertion message contents. + + Setting value to ``0`` disables the character limit for truncation. + + .. code-block:: ini + + [pytest] + truncation_limit_chars = 640 + + pytest truncates the assert messages to a certain limit by default to prevent comparison with large data to overload the console output. + + Default: ``640`` + + .. note:: + + If pytest detects it is :ref:`running on CI `, truncation is disabled automatically. + + +.. confval:: truncation_limit_lines + + Controls maximum number of linesto truncate assertion message contents. + + Setting value to ``0`` disables the lines limit for truncation. + + .. code-block:: ini + + [pytest] + truncation_limit_lines = 8 + + pytest truncates the assert messages to a certain limit by default to prevent comparison with large data to overload the console output. + + Default: ``8`` + + .. note:: + + If pytest detects it is :ref:`running on CI `, truncation is disabled automatically. + + .. confval:: usefixtures List of fixtures that will be applied to all test functions; this is semantically the same to apply diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index f2f1d029b4c..cbdf9fa0298 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -45,6 +45,18 @@ def pytest_addoption(parser: Parser) -> None: help="Enables the pytest_assertion_pass hook. " "Make sure to delete any previously generated pyc cache files.", ) + + parser.addini( + "truncation_limit_lines", + default=None, + help="Set threshold of LINES after which truncation will take effect", + ) + parser.addini( + "truncation_limit_chars", + default=None, + help=("Set threshold of CHARS after which truncation will take effect"), + ) + Config._add_verbosity_ini( parser, Config.VERBOSITY_ASSERTIONS, diff --git a/src/_pytest/assertion/truncate.py b/src/_pytest/assertion/truncate.py index b67f02ccaf8..4854a62ba6b 100644 --- a/src/_pytest/assertion/truncate.py +++ b/src/_pytest/assertion/truncate.py @@ -12,41 +12,54 @@ DEFAULT_MAX_LINES = 8 -DEFAULT_MAX_CHARS = 8 * 80 +DEFAULT_MAX_CHARS = DEFAULT_MAX_LINES * 80 USAGE_MSG = "use '-vv' to show" -def truncate_if_required( - explanation: list[str], item: Item, max_length: int | None = None -) -> list[str]: +def truncate_if_required(explanation: list[str], item: Item) -> list[str]: """Truncate this assertion explanation if the given test item is eligible.""" - if _should_truncate_item(item): - return _truncate_explanation(explanation) + should_truncate, max_lines, max_chars = _get_truncation_parameters(item) + if should_truncate: + return _truncate_explanation( + explanation, + max_lines=max_lines, + max_chars=max_chars, + ) return explanation -def _should_truncate_item(item: Item) -> bool: - """Whether or not this test item is eligible for truncation.""" +def _get_truncation_parameters(item: Item) -> tuple[bool, int, int]: + """Return the truncation parameters related to the given item, as (should truncate, max lines, max chars).""" + # We do not need to truncate if one of conditions is met: + # 1. Verbosity level is 2 or more; + # 2. Test is being run in CI environment; + # 3. Both truncation_limit_lines and truncation_limit_chars + # .ini parameters are set to 0 explicitly. + max_lines = item.config.getini("truncation_limit_lines") + max_lines = int(max_lines if max_lines is not None else DEFAULT_MAX_LINES) + + max_chars = item.config.getini("truncation_limit_chars") + max_chars = int(max_chars if max_chars is not None else DEFAULT_MAX_CHARS) + verbose = item.config.get_verbosity(Config.VERBOSITY_ASSERTIONS) - return verbose < 2 and not util.running_on_ci() + + should_truncate = verbose < 2 and not util.running_on_ci() + should_truncate = should_truncate and (max_lines > 0 or max_chars > 0) + + return should_truncate, max_lines, max_chars def _truncate_explanation( input_lines: list[str], - max_lines: int | None = None, - max_chars: int | None = None, + max_lines: int, + max_chars: int, ) -> list[str]: """Truncate given list of strings that makes up the assertion explanation. - Truncates to either 8 lines, or 640 characters - whichever the input reaches + Truncates to either max_lines, or max_chars - whichever the input reaches first, taking the truncation explanation into account. The remaining lines will be replaced by a usage message. """ - if max_lines is None: - max_lines = DEFAULT_MAX_LINES - if max_chars is None: - max_chars = DEFAULT_MAX_CHARS - # Check if truncation required input_char_count = len("".join(input_lines)) # The length of the truncation explanation depends on the number of lines @@ -71,16 +84,23 @@ def _truncate_explanation( ): return input_lines # Truncate first to max_lines, and then truncate to max_chars if necessary - truncated_explanation = input_lines[:max_lines] + if max_lines > 0: + truncated_explanation = input_lines[:max_lines] + else: + truncated_explanation = input_lines truncated_char = True # We reevaluate the need to truncate chars following removal of some lines - if len("".join(truncated_explanation)) > tolerable_max_chars: + if len("".join(truncated_explanation)) > tolerable_max_chars and max_chars > 0: truncated_explanation = _truncate_by_char_count( truncated_explanation, max_chars ) else: truncated_char = False + if truncated_explanation == input_lines: + # No truncation happened, so we do not need to add any explanations + return truncated_explanation + truncated_line_count = len(input_lines) - len(truncated_explanation) if truncated_explanation[-1]: # Add ellipsis and take into account part-truncated final line diff --git a/testing/test_assertion.py b/testing/test_assertion.py index 31192df0f6f..b10ca1c91f4 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1435,6 +1435,66 @@ def test_many_lines(): result = pytester.runpytest() result.stdout.fnmatch_lines(["* 6*"]) + @pytest.mark.parametrize( + ["truncation_lines", "truncation_chars", "expected_lines_hidden"], + ( + (3, None, 3), + (4, None, 0), + (0, None, 0), + (None, 8, 6), + (None, 9, 0), + (None, 0, 0), + (0, 0, 0), + (0, 1000, 0), + (1000, 0, 0), + ), + ) + def test_truncation_with_ini( + self, + monkeypatch, + pytester: Pytester, + truncation_lines: int | None, + truncation_chars: int | None, + expected_lines_hidden: int, + ) -> None: + pytester.makepyfile( + """\ + string_a = "123456789\\n23456789\\n3" + string_b = "123456789\\n23456789\\n4" + + def test(): + assert string_a == string_b + """ + ) + + # This test produces 6 lines of diff output or 79 characters + # So the effect should be when threshold is < 4 lines (considering 2 additional lines for explanation) + # Or < 9 characters (considering 70 additional characters for explanation) + + monkeypatch.delenv("CI", raising=False) + + ini = "[pytest]\n" + if truncation_lines is not None: + ini += f"truncation_limit_lines = {truncation_lines}\n" + if truncation_chars is not None: + ini += f"truncation_limit_chars = {truncation_chars}\n" + pytester.makeini(ini) + + result = pytester.runpytest() + + if expected_lines_hidden != 0: + result.stdout.fnmatch_lines( + [f"*truncated ({expected_lines_hidden} lines hidden)*"] + ) + else: + result.stdout.no_fnmatch_line("*truncated*") + result.stdout.fnmatch_lines( + [ + "*- 4*", + "*+ 3*", + ] + ) + def test_python25_compile_issue257(pytester: Pytester) -> None: pytester.makepyfile( From 2a22a696e7fa32c50672f057030ede2a1a9ddae4 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Sat, 21 Sep 2024 22:10:33 +0100 Subject: [PATCH 0885/1271] Remove missing msg parameter from docs --- doc/en/reference/reference.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 73398ac811e..3bb03cc0386 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -54,7 +54,7 @@ pytest.fail **Tutorial**: :ref:`skipping` -.. autofunction:: pytest.fail(reason, [pytrace=True, msg=None]) +.. autofunction:: pytest.fail(reason, [pytrace=True]) .. class:: pytest.fail.Exception @@ -63,7 +63,7 @@ pytest.fail pytest.skip ~~~~~~~~~~~ -.. autofunction:: pytest.skip(reason, [allow_module_level=False, msg=None]) +.. autofunction:: pytest.skip(reason, [allow_module_level=False]) .. class:: pytest.skip.Exception @@ -88,7 +88,7 @@ pytest.xfail pytest.exit ~~~~~~~~~~~ -.. autofunction:: pytest.exit(reason, [returncode=None, msg=None]) +.. autofunction:: pytest.exit(reason, [returncode=None]) .. class:: pytest.exit.Exception From 16fa1ee5e2a72e4dea3276d069e805d5d7abf5b9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 22 Sep 2024 08:44:47 +0000 Subject: [PATCH 0886/1271] [automated] Update plugin list (#12831) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 154 ++++++++++++++++++++----------- 1 file changed, 101 insertions(+), 53 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 23e95e27730..53028c576da 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,13 +27,14 @@ please refer to `the update script =8.3 :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 @@ -70,6 +71,7 @@ This list contains 1515 plugins. :pypi:`pytest-allure-intersection` Oct 27, 2022 N/A pytest (<5) :pypi:`pytest-allure-spec-coverage` The pytest plugin aimed to display test coverage of the specs(requirements) in Allure Oct 26, 2021 N/A pytest :pypi:`pytest-alphamoon` Static code checks used at Alphamoon Dec 30, 2021 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-amaranth-sim` Fixture to automate running Amaranth simulations Sep 21, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-analyzer` this plugin allows to analyze tests in pytest project, collect test metadata and sync it with testomat.io TCM system Feb 21, 2024 N/A pytest <8.0.0,>=7.3.1 :pypi:`pytest-android` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Feb 21, 2019 3 - Alpha pytest :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) @@ -154,7 +156,7 @@ This list contains 1515 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Sep 13, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Sep 18, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -212,7 +214,7 @@ This list contains 1515 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-celery` Pytest plugin for Celery Aug 12, 2024 4 - Beta N/A + :pypi:`pytest-celery` Pytest plugin for Celery Sep 20, 2024 4 - Beta N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -262,7 +264,7 @@ This list contains 1515 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Mar 19, 2024 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Sep 20, 2024 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -294,7 +296,7 @@ This list contains 1515 plugins. :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Aug 14, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A - :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Nov 01, 2023 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Sep 18, 2024 5 - Production/Stable pytest :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) @@ -478,7 +480,7 @@ This list contains 1515 plugins. :pypi:`pytest_energy_reporter` An energy estimation reporter for pytest Mar 28, 2024 3 - Alpha pytest<9.0.0,>=8.1.1 :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. Sep 07, 2024 5 - Production/Stable pytest>=8.3.2 + :pypi:`pytest-env` pytest plugin that allows you to add environment variables. Sep 17, 2024 5 - Production/Stable pytest>=8.3.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-environment` Pytest Environment Mar 17, 2024 1 - Planning N/A @@ -492,10 +494,11 @@ This list contains 1515 plugins. :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' - :pypi:`pytest-evm` The testing package containing tools to test Web3-based projects Apr 22, 2024 4 - Beta pytest<9.0.0,>=8.1.1 + :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 15, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Aug 13, 2024 4 - Beta pytest>=7 - :pypi:`pytest-exasol-backend` Aug 23, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-backend` Sep 18, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-extension` Sep 18, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-slc` Aug 29, 2024 N/A pytest<9,>=7 @@ -512,7 +515,7 @@ This list contains 1515 plugins. :pypi:`pytest-expect-test` A fixture to support expect tests in pytest Apr 10, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-experiments` A pytest plugin to help developers of research-oriented software projects keep track of the results of their numerical experiments. Dec 13, 2021 4 - Beta pytest (>=6.2.5,<7.0.0) :pypi:`pytest-explicit` A Pytest plugin to ignore certain marked tests by default Jun 15, 2021 5 - Production/Stable pytest - :pypi:`pytest-exploratory` Interactive console for pytest. Aug 18, 2023 N/A pytest (>=6.2) + :pypi:`pytest-exploratory` Interactive console for pytest. Sep 18, 2024 N/A pytest>=6.2 :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A :pypi:`pytest-ext` pytest plugin for automation test Mar 31, 2024 N/A pytest>=5.3 :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' @@ -618,7 +621,7 @@ This list contains 1515 plugins. :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A - :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Sep 06, 2024 N/A N/A + :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Sep 18, 2024 N/A N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Sep 09, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 @@ -652,7 +655,7 @@ This list contains 1515 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Sep 07, 2024 3 - Alpha pytest==8.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Sep 17, 2024 3 - Alpha pytest==8.3.1 :pypi:`pytest-honey` A simple plugin to use with pytest Jan 07, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-honors` Report on tests that honor constraints, and guard against regressions Mar 06, 2020 4 - Beta N/A :pypi:`pytest-hot-reloading` Apr 18, 2024 N/A N/A @@ -671,13 +674,13 @@ This list contains 1515 plugins. :pypi:`pytest-html-report-merger` May 22, 2024 N/A N/A :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest - :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin May 08, 2023 5 - Production/Stable pytest ; extra == 'test' + :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Sep 18, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Aug 10, 2024 N/A pytest<9.0.0,>=8.2.0 - :pypi:`pytest-httpx` Send responses to httpx. Feb 21, 2024 5 - Production/Stable pytest <9,>=7 + :pypi:`pytest-httpx` Send responses to httpx. Sep 20, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -718,13 +721,14 @@ This list contains 1515 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. Aug 09, 2024 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Sep 18, 2024 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 5 - Production/Stable pytest<7.2.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipywidgets` Aug 30, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest + :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Sep 18, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A @@ -846,7 +850,7 @@ This list contains 1515 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 Feb 12, 2024 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 Aug 02, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Sep 19, 2024 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) @@ -862,7 +866,7 @@ This list contains 1515 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Jun 20, 2024 N/A pytest>=1.0 + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Sep 17, 2024 N/A pytest>=1.0 :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -931,7 +935,7 @@ This list contains 1515 plugins. :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-odoo` py.test plugin to run Odoo tests Jul 06, 2023 4 - Beta pytest (>=7.2.0) + :pypi:`pytest-odoo` py.test plugin to run Odoo tests Sep 20, 2024 4 - Beta pytest<8.0.0,>=7.2.0 :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) @@ -963,6 +967,7 @@ This list contains 1515 plugins. :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A + :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Sep 16, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest @@ -1035,7 +1040,7 @@ This list contains 1515 plugins. :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A - :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Sep 08, 2024 5 - Production/Stable pytest>=8.3.2 + :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Sep 17, 2024 5 - Production/Stable pytest>=8.3.2 :pypi:`pytest-priority` pytest plugin for add priority for tests Aug 19, 2024 N/A pytest :pypi:`pytest-proceed` Apr 10, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) @@ -1207,7 +1212,7 @@ This list contains 1515 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 12, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 16, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1218,7 +1223,7 @@ This list contains 1515 plugins. :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 Feb 01, 2024 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. Sep 12, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 16, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1228,7 +1233,7 @@ This list contains 1515 plugins. :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Aug 15, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-servers` pytest servers Sep 17, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-service` Aug 06, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest @@ -1237,7 +1242,7 @@ This list contains 1515 plugins. :pypi:`pytest-setupinfo` Displaying setup info during pytest command run Jan 23, 2023 N/A N/A :pypi:`pytest-sftpserver` py.test plugin to locally test sftp server connections. Sep 16, 2019 4 - Beta N/A :pypi:`pytest-shard` Dec 11, 2020 4 - Beta pytest - :pypi:`pytest-shared-session-scope` Pytest session-scoped fixture that works with xdist Sep 08, 2024 N/A pytest>=7 + :pypi:`pytest-shared-session-scope` Pytest session-scoped fixture that works with xdist Sep 19, 2024 N/A pytest>=7.0.0 :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A @@ -1298,7 +1303,7 @@ This list contains 1515 plugins. :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 Sep 04, 2024 N/A pytest<8,>5.4.0 - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jul 10, 2024 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Sep 19, 2024 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 @@ -1498,6 +1503,7 @@ This list contains 1515 plugins. :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-webstage` Test web apps with pytest Sep 20, 2024 N/A pytest<9.0,>=7.0 :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Jun 08, 2024 N/A pytest>=7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 28, 2024 N/A pytest>=7.3.1 @@ -1554,6 +1560,13 @@ This list contains 1515 plugins. .. only:: latex + :pypi:`databricks-labs-pytester` + *last release*: Sep 19, 2024, + *status*: 4 - Beta, + *requires*: pytest>=8.3 + + Python Testing for Databricks + :pypi:`logassert` *last release*: May 20, 2022, *status*: 5 - Production/Stable, @@ -1806,6 +1819,13 @@ This list contains 1515 plugins. Static code checks used at Alphamoon + :pypi:`pytest-amaranth-sim` + *last release*: Sep 21, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + Fixture to automate running Amaranth simulations + :pypi:`pytest-analyzer` *last release*: Feb 21, 2024, *status*: N/A, @@ -2395,7 +2415,7 @@ This list contains 1515 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Sep 13, 2024, + *last release*: Sep 18, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2801,7 +2821,7 @@ This list contains 1515 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-celery` - *last release*: Aug 12, 2024, + *last release*: Sep 20, 2024, *status*: 4 - Beta, *requires*: N/A @@ -3151,7 +3171,7 @@ This list contains 1515 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Mar 19, 2024, + *last release*: Sep 20, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3375,9 +3395,9 @@ This list contains 1515 plugins. Too many faillure, less tests. :pypi:`pytest-cpp` - *last release*: Nov 01, 2023, + *last release*: Sep 18, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.0 + *requires*: pytest Use pytest's runner to discover and execute C++ tests @@ -4663,9 +4683,9 @@ This list contains 1515 plugins. Improvements for pytest (rejected upstream) :pypi:`pytest-env` - *last release*: Sep 07, 2024, + *last release*: Sep 17, 2024, *status*: 5 - Production/Stable, - *requires*: pytest>=8.3.2 + *requires*: pytest>=8.3.3 pytest plugin that allows you to add environment variables. @@ -4760,8 +4780,8 @@ This list contains 1515 plugins. Applies eventlet monkey-patch as a pytest plugin. - :pypi:`pytest-evm` - *last release*: Apr 22, 2024, + :pypi:`pytest_evm` + *last release*: Sep 15, 2024, *status*: 4 - Beta, *requires*: pytest<9.0.0,>=8.1.1 @@ -4782,7 +4802,14 @@ This list contains 1515 plugins. Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-exasol-backend` - *last release*: Aug 23, 2024, + *last release*: Sep 18, 2024, + *status*: N/A, + *requires*: pytest<9,>=7 + + + + :pypi:`pytest-exasol-extension` + *last release*: Sep 18, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -4901,9 +4928,9 @@ This list contains 1515 plugins. A Pytest plugin to ignore certain marked tests by default :pypi:`pytest-exploratory` - *last release*: Aug 18, 2023, + *last release*: Sep 18, 2024, *status*: N/A, - *requires*: pytest (>=6.2) + *requires*: pytest>=6.2 Interactive console for pytest. @@ -5643,7 +5670,7 @@ This list contains 1515 plugins. py.test plugin to ignore the same files as git :pypi:`pytest-gitlab` - *last release*: Sep 06, 2024, + *last release*: Sep 18, 2024, *status*: N/A, *requires*: N/A @@ -5881,7 +5908,7 @@ This list contains 1515 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Sep 07, 2024, + *last release*: Sep 17, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.1 @@ -6014,9 +6041,9 @@ This list contains 1515 plugins. Fixture "http" for http requests :pypi:`pytest-httpbin` - *last release*: May 08, 2023, + *last release*: Sep 18, 2024, *status*: 5 - Production/Stable, - *requires*: pytest ; extra == 'test' + *requires*: pytest; extra == "test" Easily test your HTTP library against a local copy of httpbin @@ -6056,9 +6083,9 @@ This list contains 1515 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Feb 21, 2024, + *last release*: Sep 20, 2024, *status*: 5 - Production/Stable, - *requires*: pytest <9,>=7 + *requires*: pytest==8.* Send responses to httpx. @@ -6343,7 +6370,7 @@ This list contains 1515 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Aug 09, 2024, + *last release*: Sep 18, 2024, *status*: 4 - Beta, *requires*: pytest @@ -6391,6 +6418,13 @@ This list contains 1515 plugins. + :pypi:`pytest-isolate-mpi` + *last release*: Sep 18, 2024, + *status*: 4 - Beta, + *requires*: pytest>=5 + + pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner + :pypi:`pytest-isort` *last release*: Mar 05, 2024, *status*: 5 - Production/Stable, @@ -7239,7 +7273,7 @@ This list contains 1515 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Aug 02, 2024, + *last release*: Sep 19, 2024, *status*: N/A, *requires*: pytest @@ -7351,7 +7385,7 @@ This list contains 1515 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Jun 20, 2024, + *last release*: Sep 17, 2024, *status*: N/A, *requires*: pytest>=1.0 @@ -7834,9 +7868,9 @@ This list contains 1515 plugins. A pytest plugin for simplifying ODC database tests :pypi:`pytest-odoo` - *last release*: Jul 06, 2023, + *last release*: Sep 20, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.2.0) + *requires*: pytest<8.0.0,>=7.2.0 py.test plugin to run Odoo tests @@ -8057,6 +8091,13 @@ This list contains 1515 plugins. Simpler PyTest parametrization + :pypi:`pytest-parametrize` + *last release*: Sep 16, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest<9.0.0,>=8.3.0 + + pytest decorator for parametrizing test cases in a dict-way + :pypi:`pytest-parametrize-cases` *last release*: Mar 13, 2022, *status*: N/A, @@ -8562,7 +8603,7 @@ This list contains 1515 plugins. Minitest-style test colors :pypi:`pytest-print` - *last release*: Sep 08, 2024, + *last release*: Sep 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=8.3.2 @@ -9766,7 +9807,7 @@ This list contains 1515 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Sep 12, 2024, + *last release*: Sep 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9843,7 +9884,7 @@ This list contains 1515 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Sep 12, 2024, + *last release*: Sep 16, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9913,7 +9954,7 @@ This list contains 1515 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Aug 15, 2024, + *last release*: Sep 17, 2024, *status*: 3 - Alpha, *requires*: pytest>=6.2 @@ -9976,9 +10017,9 @@ This list contains 1515 plugins. :pypi:`pytest-shared-session-scope` - *last release*: Sep 08, 2024, + *last release*: Sep 19, 2024, *status*: N/A, - *requires*: pytest>=7 + *requires*: pytest>=7.0.0 Pytest session-scoped fixture that works with xdist @@ -10403,7 +10444,7 @@ This list contains 1515 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Jul 10, 2024, + *last release*: Sep 19, 2024, *status*: N/A, *requires*: N/A @@ -11802,6 +11843,13 @@ This list contains 1515 plugins. Selenium webdriver fixture for py.test + :pypi:`pytest-webstage` + *last release*: Sep 20, 2024, + *status*: N/A, + *requires*: pytest<9.0,>=7.0 + + Test web apps with pytest + :pypi:`pytest-webtest-extras` *last release*: Jun 08, 2024, *status*: N/A, From 3231199a092f81c9aac5aca57b2d5452f36b6161 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:11:22 +0200 Subject: [PATCH 0887/1271] build(deps): Bump pytest-bdd in /testing/plugins_integration (#12835) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 7.2.0 to 7.3.0. - [Release notes](https://github.com/pytest-dev/pytest-bdd/releases) - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/7.2.0...7.3.0) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 379b4ffa5e8..5e153444847 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,7 +1,7 @@ anyio[curio,trio]==4.4.0 django==5.1.1 pytest-asyncio==0.24.0 -pytest-bdd==7.2.0 +pytest-bdd==7.3.0 pytest-cov==5.0.0 pytest-django==4.9.0 pytest-flakes==4.0.5 From 1413f45b6f467d66b877c007104b99544e356ad0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:11:54 +0200 Subject: [PATCH 0888/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#12834) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 4.4.0 to 4.6.0. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.4.0...4.6.0) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 5e153444847..9ee706fdc70 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==4.4.0 +anyio[curio,trio]==4.6.0 django==5.1.1 pytest-asyncio==0.24.0 pytest-bdd==7.3.0 From 25401d0b1d1b0f89e4e58fc5aab0f18e3f3e5984 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:07:54 -0300 Subject: [PATCH 0889/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.10.1 to 1.10.2 (#12832) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.10.1 to 1.10.2. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.10.1...v1.10.2) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cb053552ccd..f2e2dd4a407 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.10.1 + uses: pypa/gh-action-pypi-publish@v1.10.2 with: attestations: true From 245e44203952c5c1149016a18475799793cb8b5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 09:08:30 -0300 Subject: [PATCH 0890/1271] build(deps): Bump peter-evans/create-pull-request from 7.0.2 to 7.0.5 (#12833) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.2 to 7.0.5. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/d121e62763d8cc35b5fb1710e887d6e69a52d3a4...5e914681df9dc83aa4e4905692ca88beb2f9e91f) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 3029436ce79..0c76b91843c 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -47,7 +47,7 @@ jobs: - name: Create Pull Request id: pr - uses: peter-evans/create-pull-request@d121e62763d8cc35b5fb1710e887d6e69a52d3a4 + uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From fda1bbd187d99e9b076eaf4b2b2a03f1c242f8d4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 24 Sep 2024 06:50:09 +0200 Subject: [PATCH 0891/1271] [pre-commit.ci] pre-commit autoupdate (#12838) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.5 → v0.6.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.5...v0.6.7) - [github.com/tox-dev/pyproject-fmt: 2.2.3 → 2.2.4](https://github.com/tox-dev/pyproject-fmt/compare/2.2.3...2.2.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b6f2a16424a..b4d10558b88 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.5" + rev: "v0.6.7" hooks: - id: ruff args: ["--fix"] @@ -46,7 +46,7 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "2.2.3" + rev: "2.2.4" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version From 68ac4a12e362fedfec7b963739571c7c326b61da Mon Sep 17 00:00:00 2001 From: sven <42868792+FreerGit@users.noreply.github.com> Date: Tue, 24 Sep 2024 14:28:10 +0200 Subject: [PATCH 0892/1271] `collect_imported_tests` option --- changelog/12749.feature.rst | 4 +- src/_pytest/main.py | 30 ++++++- src/_pytest/python.py | 6 -- testing/test_discover_imports.py | 144 ++++++++++++++++++++++--------- 4 files changed, 133 insertions(+), 51 deletions(-) diff --git a/changelog/12749.feature.rst b/changelog/12749.feature.rst index 138a5bc7914..798d02c6e49 100644 --- a/changelog/12749.feature.rst +++ b/changelog/12749.feature.rst @@ -1,3 +1,3 @@ -Add :confval:`discover_imports`, when disabled (default) will make sure to not consider classes which are imported by a test file and starts with Test. +Add :confval:`collect_imported_tests`, when enabled (default is disabled) will make sure to not consider classes/functions which are imported by a test file and contains Test/test_*/*_test. --- by :user:`FreerGit` \ No newline at end of file +-- by :user:`FreerGit` diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 4887d336b2d..611ce033ea9 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -79,8 +79,9 @@ def pytest_addoption(parser: Parser) -> None: default=[], ) parser.addini( - "discover_imports", - "Whether to discover tests in imported modules outside `testpaths`", + "collect_imported_tests", + "Whether to collect tests in imported modules outside `testpaths`", + type="bool", default=False, ) group = parser.getgroup("general", "Running and selection options") @@ -963,9 +964,22 @@ def collect(self) -> Iterator[nodes.Item | nodes.Collector]: self.trace.root.indent -= 1 def genitems(self, node: nodes.Item | nodes.Collector) -> Iterator[nodes.Item]: + import inspect + + from _pytest.python import Class + from _pytest.python import Function + from _pytest.python import Module + self.trace("genitems", node) if isinstance(node, nodes.Item): node.ihook.pytest_itemcollected(item=node) + if self.config.getini("collect_imported_tests"): + if isinstance(node.parent, Module) and isinstance(node, Function): + if inspect.isfunction(node._getobj()): + fn_defined_at = node._getobj().__module__ + in_module = node.parent._getobj().__name__ + if fn_defined_at != in_module: + return yield node else: assert isinstance(node, nodes.Collector) @@ -973,6 +987,18 @@ def genitems(self, node: nodes.Item | nodes.Collector) -> Iterator[nodes.Item]: # For backward compat, dedup only applies to files. handle_dupes = not (keepduplicates and isinstance(node, nodes.File)) rep, duplicate = self._collect_one_node(node, handle_dupes) + + if self.config.getini("collect_imported_tests"): + for subnode in rep.result: + if isinstance(subnode, Class) and isinstance( + subnode.parent, Module + ): + if inspect.isclass(subnode._getobj()): + class_defined_at = subnode._getobj().__module__ + in_module = subnode.parent._getobj().__name__ + if class_defined_at != in_module: + rep.result.remove(subnode) + if duplicate and not keepduplicates: return if rep.passed: diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 9467b26fd02..9c54dd20f80 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -741,12 +741,6 @@ def newinstance(self): return self.obj() def collect(self) -> Iterable[nodes.Item | nodes.Collector]: - if self.config.getini("discover_imports") == ("false" or False): - paths = self.config.getini("testpaths") - class_file = inspect.getfile(self.obj) - if not any(string in class_file for string in paths): - return [] - if not safe_getattr(self.obj, "__test__", True): return [] if hasinit(self.obj): diff --git a/testing/test_discover_imports.py b/testing/test_discover_imports.py index 829b614ed46..e328d16a182 100644 --- a/testing/test_discover_imports.py +++ b/testing/test_discover_imports.py @@ -1,29 +1,31 @@ -import pytest +from __future__ import annotations + import textwrap -def test_discover_imports_enabled(pytester): +from _pytest.pytester import Pytester + + +def run_import_class_test(pytester: Pytester, passed: int = 0, errors: int = 0) -> None: src_dir = pytester.mkdir("src") tests_dir = pytester.mkdir("tests") - pytester.makeini(""" - [pytest] - testpaths = "tests" - discover_imports = true - """) - src_file = src_dir / "foo.py" - src_file.write_text(textwrap.dedent("""\ - class TestClass(object): + src_file.write_text( + textwrap.dedent("""\ + class Testament(object): def __init__(self): super().__init__() + self.collections = ["stamp", "coin"] - def test_foobar(self): - return true - """ - ), encoding="utf-8") + def personal_property(self): + return [f"my {x} collection" for x in self.collections] + """), + encoding="utf-8", + ) test_file = tests_dir / "foo_test.py" - test_file.write_text(textwrap.dedent("""\ + test_file.write_text( + textwrap.dedent("""\ import sys import os @@ -32,42 +34,78 @@ def test_foobar(self): parent_dir = os.path.abspath(os.path.join(current_dir, '..')) sys.path.append(parent_dir) - from src.foo import TestClass + from src.foo import Testament class TestDomain: def test_testament(self): - testament = TestClass() - pass - """), encoding="utf-8") + testament = Testament() + assert testament.personal_property() + """), + encoding="utf-8", + ) result = pytester.runpytest() - result.assert_outcomes(errors=1) + result.assert_outcomes(passed=passed, errors=errors) -def test_discover_imports_disabled(pytester): - - src_dir = pytester.mkdir("src") - tests_dir = pytester.mkdir("tests") + +def test_collect_imports_disabled(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + testpaths = "tests" + collect_imported_tests = false + """) + + run_import_class_test(pytester, errors=1) + + +def test_collect_imports_default(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + testpaths = "tests" + """) + + run_import_class_test(pytester, errors=1) + + +def test_collect_imports_enabled(pytester: Pytester) -> None: pytester.makeini(""" [pytest] testpaths = "tests" - discover_imports = false + collect_imported_tests = true """) + run_import_class_test(pytester, passed=1) + + +def run_import_functions_test( + pytester: Pytester, passed: int, errors: int, failed: int +) -> None: + src_dir = pytester.mkdir("src") + tests_dir = pytester.mkdir("tests") + src_file = src_dir / "foo.py" - src_file.write_text(textwrap.dedent("""\ - class Testament(object): - def __init__(self): - super().__init__() - self.collections = ["stamp", "coin"] + # Note that these "tests" are should _not_ be treated as tests. + # They are normal functions that happens to have test_* or *_test in the name. + # Thus should _not_ be collected! + src_file.write_text( + textwrap.dedent("""\ + def test_function(): + some_random_computation = 5 + return some_random_computation - def personal_property(self): - return [f"my {x} collection" for x in self.collections] - """ - ), encoding="utf-8") + def test_bar(): + pass + """), + encoding="utf-8", + ) test_file = tests_dir / "foo_test.py" - test_file.write_text(textwrap.dedent("""\ + + # Inferred from the comment above, this means that there is _only_ one actual test + # which should result in only 1 passing test being ran. + test_file.write_text( + textwrap.dedent("""\ import sys import os @@ -76,13 +114,37 @@ def personal_property(self): parent_dir = os.path.abspath(os.path.join(current_dir, '..')) sys.path.append(parent_dir) - from src.foo import Testament + from src.foo import * class TestDomain: - def test_testament(self): - testament = Testament() - assert testament.personal_property() - """), encoding="utf-8") + def test_important(self): + res = test_function() + if res == 5: + pass + + """), + encoding="utf-8", + ) result = pytester.runpytest() - result.assert_outcomes(passed=1) \ No newline at end of file + result.assert_outcomes(passed=passed, errors=errors, failed=failed) + + +def test_collect_function_imports_enabled(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + testpaths = "tests" + collect_imported_tests = true + """) + + run_import_functions_test(pytester, passed=1, errors=0, failed=0) + + +def test_collect_function_imports_disabled(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + testpaths = "tests" + collect_imported_tests = false + """) + + run_import_functions_test(pytester, passed=2, errors=0, failed=1) From 326faa25f4e776f082eea5603d84b0812b57773c Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Date: Wed, 25 Sep 2024 18:29:03 +0530 Subject: [PATCH 0893/1271] Docs: improve "How to capture stdout/stderr output" (#12840) Improve the section by reordering how the topics about text/binary capture are presented, and add proper links to the fixtures. Co-authored-by: Bruno Oliveira --- doc/en/how-to/capture-stdout-stderr.rst | 42 +++++++++---------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index 5e23f0c024e..9f7ddce3499 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -106,9 +106,10 @@ of the failing function and hide the other one: Accessing captured output from a test function --------------------------------------------------- -The ``capsys``, ``capsysbinary``, ``capfd``, and ``capfdbinary`` fixtures -allow access to stdout/stderr output created during test execution. Here is -an example test function that performs some output related checks: +The :fixture:`capsys`, :fixture:`capsysbinary`, :fixture:`capfd`, and :fixture:`capfdbinary` fixtures +allow access to ``stdout``/``stderr`` output created during test execution. + +Here is an example test function that performs some output related checks: .. code-block:: python @@ -125,40 +126,27 @@ an example test function that performs some output related checks: The ``readouterr()`` call snapshots the output so far - and capturing will be continued. After the test function finishes the original streams will -be restored. Using ``capsys`` this way frees your +be restored. Using :fixture:`capsys` this way frees your test from having to care about setting/resetting output streams and also interacts well with pytest's own per-test capturing. -If you want to capture on filedescriptor level you can use -the ``capfd`` fixture which offers the exact -same interface but allows to also capture output from -libraries or subprocesses that directly write to operating -system level output streams (FD1 and FD2). - - - The return value from ``readouterr`` changed to a ``namedtuple`` with two attributes, ``out`` and ``err``. - - -If the code under test writes non-textual data, you can capture this using -the ``capsysbinary`` fixture which instead returns ``bytes`` from +If the code under test writes non-textual data (``bytes``), you can capture this using +the :fixture:`capsysbinary` fixture which instead returns ``bytes`` from the ``readouterr`` method. +If you want to capture at the file descriptor level you can use +the :fixture:`capfd` fixture which offers the exact +same interface but allows to also capture output from +libraries or subprocesses that directly write to operating +system level output streams (FD1 and FD2). Similarly to :fixture:`capsysbinary`, :fixture:`capfdbinary` can be +used to capture ``bytes`` at the file descriptor level. - -If the code under test writes non-textual data, you can capture this using -the ``capfdbinary`` fixture which instead returns ``bytes`` from -the ``readouterr`` method. The ``capfdbinary`` fixture operates on the -filedescriptor level. - - - - -To temporarily disable capture within a test, both ``capsys`` -and ``capfd`` have a ``disabled()`` method that can be used +To temporarily disable capture within a test, the capture fixtures +have a ``disabled()`` method that can be used as a context manager, disabling capture inside the ``with`` block: .. code-block:: python From 6486c3f3a858a0c8043f5c3f7c24297b82a0abe4 Mon Sep 17 00:00:00 2001 From: dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com> Date: Thu, 26 Sep 2024 09:08:42 +0800 Subject: [PATCH 0894/1271] Fix KeyError with importlib mode (directories with same name) (#12752) Directories inside a namespace package with the same name as the namespace package would cause a `KeyError` with `--import-mode=importlib`. Fixes #12592 Co-authored-by: Bruno Oliveira --- changelog/12592.bugfix.rst | 1 + src/_pytest/pathlib.py | 131 +++++++++++++++++++++++++++---------- testing/test_pathlib.py | 74 ++++++++++++++++++++- 3 files changed, 171 insertions(+), 35 deletions(-) create mode 100644 changelog/12592.bugfix.rst diff --git a/changelog/12592.bugfix.rst b/changelog/12592.bugfix.rst new file mode 100644 index 00000000000..605783bcab4 --- /dev/null +++ b/changelog/12592.bugfix.rst @@ -0,0 +1 @@ +Fixed :class:`KeyError` crash when using ``--import-mode=importlib`` in a directory layout where a directory contains a child directory with the same name. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 81e52ea729d..dd36559ce1b 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -10,6 +10,7 @@ import fnmatch from functools import partial from importlib.machinery import ModuleSpec +from importlib.machinery import PathFinder import importlib.util import itertools import os @@ -37,8 +38,12 @@ from _pytest.warning_types import PytestWarning -LOCK_TIMEOUT = 60 * 60 * 24 * 3 +if sys.version_info < (3, 11): + from importlib._bootstrap_external import _NamespaceLoader as NamespaceLoader +else: + from importlib.machinery import NamespaceLoader +LOCK_TIMEOUT = 60 * 60 * 24 * 3 _AnyPurePath = TypeVar("_AnyPurePath", bound=PurePath) @@ -611,13 +616,78 @@ def _import_module_using_spec( module_name: str, module_path: Path, module_location: Path, *, insert_modules: bool ) -> ModuleType | None: """ - Tries to import a module by its canonical name, path to the .py file, and its - parent location. + Tries to import a module by its canonical name, path, and its parent location. + + :param module_name: + The expected module name, will become the key of `sys.modules`. + + :param module_path: + The file path of the module, for example `/foo/bar/test_demo.py`. + If module is a package, pass the path to the `__init__.py` of the package. + If module is a namespace package, pass directory path. + + :param module_location: + The parent location of the module. + If module is a package, pass the directory containing the `__init__.py` file. :param insert_modules: - If True, will call insert_missing_modules to create empty intermediate modules - for made-up module names (when importing test files not reachable from sys.path). + If True, will call `insert_missing_modules` to create empty intermediate modules + with made-up module names (when importing test files not reachable from `sys.path`). + + Example 1 of parent_module_*: + + module_name: "a.b.c.demo" + module_path: Path("a/b/c/demo.py") + module_location: Path("a/b/c/") + if "a.b.c" is package ("a/b/c/__init__.py" exists), then + parent_module_name: "a.b.c" + parent_module_path: Path("a/b/c/__init__.py") + parent_module_location: Path("a/b/c/") + else: + parent_module_name: "a.b.c" + parent_module_path: Path("a/b/c") + parent_module_location: Path("a/b/") + + Example 2 of parent_module_*: + + module_name: "a.b.c" + module_path: Path("a/b/c/__init__.py") + module_location: Path("a/b/c/") + if "a.b" is package ("a/b/__init__.py" exists), then + parent_module_name: "a.b" + parent_module_path: Path("a/b/__init__.py") + parent_module_location: Path("a/b/") + else: + parent_module_name: "a.b" + parent_module_path: Path("a/b/") + parent_module_location: Path("a/") """ + # Attempt to import the parent module, seems is our responsibility: + # https://github.com/python/cpython/blob/73906d5c908c1e0b73c5436faeff7d93698fc074/Lib/importlib/_bootstrap.py#L1308-L1311 + parent_module_name, _, name = module_name.rpartition(".") + parent_module: ModuleType | None = None + if parent_module_name: + parent_module = sys.modules.get(parent_module_name) + if parent_module is None: + # Get parent_location based on location, get parent_path based on path. + if module_path.name == "__init__.py": + # If the current module is in a package, + # need to leave the package first and then enter the parent module. + parent_module_path = module_path.parent.parent + else: + parent_module_path = module_path.parent + + if (parent_module_path / "__init__.py").is_file(): + # If the parent module is a package, loading by __init__.py file. + parent_module_path = parent_module_path / "__init__.py" + + parent_module = _import_module_using_spec( + parent_module_name, + parent_module_path, + parent_module_path.parent, + insert_modules=insert_modules, + ) + # Checking with sys.meta_path first in case one of its hooks can import this module, # such as our own assertion-rewrite hook. for meta_importer in sys.meta_path: @@ -627,36 +697,18 @@ def _import_module_using_spec( if spec_matches_module_path(spec, module_path): break else: - spec = importlib.util.spec_from_file_location(module_name, str(module_path)) + loader = None + if module_path.is_dir(): + # The `spec_from_file_location` matches a loader based on the file extension by default. + # For a namespace package, need to manually specify a loader. + loader = NamespaceLoader(name, module_path, PathFinder()) + + spec = importlib.util.spec_from_file_location( + module_name, str(module_path), loader=loader + ) if spec_matches_module_path(spec, module_path): assert spec is not None - # Attempt to import the parent module, seems is our responsibility: - # https://github.com/python/cpython/blob/73906d5c908c1e0b73c5436faeff7d93698fc074/Lib/importlib/_bootstrap.py#L1308-L1311 - parent_module_name, _, name = module_name.rpartition(".") - parent_module: ModuleType | None = None - if parent_module_name: - parent_module = sys.modules.get(parent_module_name) - if parent_module is None: - # Find the directory of this module's parent. - parent_dir = ( - module_path.parent.parent - if module_path.name == "__init__.py" - else module_path.parent - ) - # Consider the parent module path as its __init__.py file, if it has one. - parent_module_path = ( - parent_dir / "__init__.py" - if (parent_dir / "__init__.py").is_file() - else parent_dir - ) - parent_module = _import_module_using_spec( - parent_module_name, - parent_module_path, - parent_dir, - insert_modules=insert_modules, - ) - # Find spec and import this module. mod = importlib.util.module_from_spec(spec) sys.modules[module_name] = mod @@ -675,10 +727,21 @@ def _import_module_using_spec( def spec_matches_module_path(module_spec: ModuleSpec | None, module_path: Path) -> bool: """Return true if the given ModuleSpec can be used to import the given module path.""" - if module_spec is None or module_spec.origin is None: + if module_spec is None: return False - return Path(module_spec.origin) == module_path + if module_spec.origin: + return Path(module_spec.origin) == module_path + + # Compare the path with the `module_spec.submodule_Search_Locations` in case + # the module is part of a namespace package. + # https://docs.python.org/3/library/importlib.html#importlib.machinery.ModuleSpec.submodule_search_locations + if module_spec.submodule_search_locations: # can be None. + for path in module_spec.submodule_search_locations: + if Path(path) == module_path: + return True + + return False # Implement a special _is_same function on Windows which returns True if the two filenames diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 7c0a0e03d76..62359303f3b 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -17,7 +17,9 @@ from typing import Sequence import unittest.mock +from _pytest.config import ExitCode from _pytest.monkeypatch import MonkeyPatch +from _pytest.pathlib import _import_module_using_spec from _pytest.pathlib import bestrelpath from _pytest.pathlib import commonpath from _pytest.pathlib import compute_module_name @@ -36,6 +38,7 @@ from _pytest.pathlib import resolve_package_path from _pytest.pathlib import resolve_pkg_root_and_module_name from _pytest.pathlib import safe_exists +from _pytest.pathlib import spec_matches_module_path from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit from _pytest.pytester import Pytester @@ -416,7 +419,7 @@ def test_no_meta_path_found( del sys.modules[module.__name__] monkeypatch.setattr( - importlib.util, "spec_from_file_location", lambda *args: None + importlib.util, "spec_from_file_location", lambda *args, **kwargs: None ) with pytest.raises(ImportError): import_path( @@ -780,6 +783,62 @@ def test_insert_missing_modules( insert_missing_modules(modules, "") assert modules == {} + @pytest.mark.parametrize("b_is_package", [True, False]) + @pytest.mark.parametrize("insert_modules", [True, False]) + def test_import_module_using_spec( + self, b_is_package, insert_modules, tmp_path: Path + ): + """ + Verify that `_import_module_using_spec` can obtain a spec based on the path, thereby enabling the import. + When importing, not only the target module is imported, but also the parent modules are recursively imported. + """ + file_path = tmp_path / "a/b/c/demo.py" + file_path.parent.mkdir(parents=True) + file_path.write_text("my_name='demo'", encoding="utf-8") + + if b_is_package: + (tmp_path / "a/b/__init__.py").write_text( + "my_name='b.__init__'", encoding="utf-8" + ) + + mod = _import_module_using_spec( + "a.b.c.demo", + file_path, + file_path.parent, + insert_modules=insert_modules, + ) + + # target module is imported + assert mod is not None + assert spec_matches_module_path(mod.__spec__, file_path) is True + + mod_demo = sys.modules["a.b.c.demo"] + assert "demo.py" in str(mod_demo) + assert mod_demo.my_name == "demo" # Imported and available for use + + # parent modules are recursively imported. + mod_a = sys.modules["a"] + mod_b = sys.modules["a.b"] + mod_c = sys.modules["a.b.c"] + + assert mod_a.b is mod_b + assert mod_a.b.c is mod_c + assert mod_a.b.c.demo is mod_demo + + assert "namespace" in str(mod_a).lower() + assert "namespace" in str(mod_c).lower() + + # Compatibility package and namespace package. + if b_is_package: + assert "namespace" not in str(mod_b).lower() + assert "__init__.py" in str(mod_b).lower() # Imported __init__.py + assert mod_b.my_name == "b.__init__" # Imported and available for use + + else: + assert "namespace" in str(mod_b).lower() + with pytest.raises(AttributeError): # Not imported __init__.py + assert mod_b.my_name + def test_parent_contains_child_module_attribute( self, monkeypatch: MonkeyPatch, tmp_path: Path ): @@ -1542,6 +1601,19 @@ def test_full_ns_packages_without_init_files( ) == (tmp_path / "src/dist2", "ns.a.core.foo.m") +def test_ns_import_same_name_directory_12592( + tmp_path: Path, pytester: Pytester +) -> None: + """Regression for `--import-mode=importlib` with directory parent and child with same name (#12592).""" + y_dir = tmp_path / "x/y/y" + y_dir.mkdir(parents=True) + test_y = tmp_path / "x/y/test_y.py" + test_y.write_text("def test(): pass", encoding="UTF-8") + + result = pytester.runpytest("--import-mode=importlib", test_y) + assert result.ret == ExitCode.OK + + def test_is_importable(pytester: Pytester) -> None: pytester.syspathinsert() From 758a4bea481240a3e005620cd01a53d7ad1ee0a4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 07:26:49 -0300 Subject: [PATCH 0895/1271] [automated] Update plugin list (#12845) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 146 +++++++++++++++++++------------ 1 file changed, 89 insertions(+), 57 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 53028c576da..96ee4fc3830 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,14 +27,14 @@ please refer to `the update script =8.3 + :pypi:`databricks-labs-pytester` Python Testing for Databricks Sep 24, 2024 4 - Beta pytest>=8.3 :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 @@ -130,7 +130,7 @@ This list contains 1521 plugins. :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest - :pypi:`pytest-aux` templates/examples and aux for pytest Aug 06, 2024 N/A N/A + :pypi:`pytest-aux` templates/examples and aux for pytest Sep 23, 2024 N/A N/A :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -146,8 +146,8 @@ This list contains 1521 plugins. :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 - :pypi:`pytest-bazel` A pytest runner with bazel support Jul 20, 2024 4 - Beta pytest - :pypi:`pytest-bdd` BDD for pytest Jun 04, 2024 6 - Mature pytest>=6.2.0 + :pypi:`pytest-bazel` A pytest runner with bazel support Sep 27, 2024 4 - Beta pytest + :pypi:`pytest-bdd` BDD for pytest Sep 26, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Sep 01, 2024 4 - Beta pytest>=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 26, 2024 N/A pytest>=7.1.3 @@ -210,7 +210,7 @@ This list contains 1521 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-cases` Separate test code from test cases in pytest. Apr 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-cases` Separate test code from test cases in pytest. Sep 26, 2024 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A @@ -264,7 +264,7 @@ This list contains 1521 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Sep 20, 2024 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Sep 27, 2024 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -293,7 +293,7 @@ This list contains 1521 plugins. :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Aug 14, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Sep 27, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Sep 18, 2024 5 - Production/Stable pytest @@ -439,6 +439,7 @@ This list contains 1521 plugins. :pypi:`pytest-drf` A Django REST framework plugin for pytest. Jul 12, 2022 5 - Production/Stable pytest (>=3.7) :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection Mar 04, 2024 5 - Production/Stable pytest >=7 + :pypi:`pytest-dryci` Test caching plugin for pytest Sep 27, 2024 4 - Beta N/A :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 18, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A @@ -494,14 +495,14 @@ This list contains 1521 plugins. :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' - :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 15, 2024 4 - Beta pytest<9.0.0,>=8.1.1 + :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Aug 13, 2024 4 - Beta pytest>=7 :pypi:`pytest-exasol-backend` Sep 18, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-extension` Sep 18, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-slc` Aug 29, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-slc` Sep 24, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -599,6 +600,7 @@ This list contains 1521 plugins. :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Sep 11, 2024 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A + :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Sep 25, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A :pypi:`pytest-fzf` fzf-based test selector for pytest Jul 03, 2024 4 - Beta pytest>=6.0.0 :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A @@ -621,7 +623,7 @@ This list contains 1521 plugins. :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A - :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Sep 18, 2024 N/A N/A + :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Sep 25, 2024 N/A N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Sep 09, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 @@ -655,10 +657,10 @@ This list contains 1521 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Sep 17, 2024 3 - Alpha pytest==8.3.1 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Sep 28, 2024 3 - Alpha pytest==8.3.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` Apr 18, 2024 N/A N/A + :pypi:`pytest-hot-reloading` Sep 23, 2024 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. Jul 15, 2024 N/A pytest :pypi:`pytest-hoverfly` Simplify working with Hoverfly from pytest Jan 30, 2023 N/A pytest (>=5.0) @@ -680,7 +682,7 @@ This list contains 1521 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Aug 10, 2024 N/A pytest<9.0.0,>=8.2.0 - :pypi:`pytest-httpx` Send responses to httpx. Sep 20, 2024 5 - Production/Stable pytest==8.* + :pypi:`pytest-httpx` Send responses to httpx. Sep 27, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -721,7 +723,7 @@ This list contains 1521 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 18, 2024 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Sep 25, 2024 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 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 @@ -827,7 +829,7 @@ This list contains 1521 plugins. :pypi:`pytest-mark-manage` 用例标签化管理 Aug 15, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A - :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Aug 06, 2024 N/A N/A + :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Sep 27, 2024 N/A N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Aug 01, 2024 5 - Production/Stable pytest :pypi:`pytest-matchers` Matchers for pytest Aug 26, 2024 N/A pytest<9.0,>=7.0 :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) @@ -967,7 +969,7 @@ This list contains 1521 plugins. :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A - :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Sep 16, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 + :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Sep 23, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest @@ -1009,7 +1011,7 @@ This list contains 1521 plugins. :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Sep 06, 2024 N/A pytest<9.0.0,>=6.2.4 - :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright May 24, 2024 N/A N/A + :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Sep 28, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A @@ -1052,7 +1054,7 @@ This list contains 1521 plugins. :pypi:`pytest-prysk` Pytest plugin for prysk Mar 12, 2024 4 - Beta pytest (>=7.3.2) :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) - :pypi:`pytest-pt` pytest plugin to use \*.pt files as tests May 15, 2024 4 - Beta pytest + :pypi:`pytest-pt` pytest plugin to use \*.pt files as tests Sep 22, 2024 5 - Production/Stable pytest :pypi:`pytest-ptera` Use ptera probes in tests Mar 01, 2022 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-publish` Jun 04, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-pudb` Pytest PuDB debugger integration Oct 25, 2018 3 - Alpha pytest (>=2.0) @@ -1125,7 +1127,7 @@ This list contains 1521 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 - :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Feb 26, 2024 N/A pytest>7.2 + :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Sep 25, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relative-path` Handle relative path in pytest options or ini configs Aug 30, 2024 N/A pytest :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Mar 29, 2024 5 - Production/Stable pytest>=7 @@ -1187,7 +1189,7 @@ This list contains 1521 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 10, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 24, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1212,7 +1214,7 @@ This list contains 1521 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 26, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1223,7 +1225,7 @@ This list contains 1521 plugins. :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 Feb 01, 2024 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. Sep 16, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Sep 26, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1242,7 +1244,7 @@ This list contains 1521 plugins. :pypi:`pytest-setupinfo` Displaying setup info during pytest command run Jan 23, 2023 N/A N/A :pypi:`pytest-sftpserver` py.test plugin to locally test sftp server connections. Sep 16, 2019 4 - Beta N/A :pypi:`pytest-shard` Dec 11, 2020 4 - Beta pytest - :pypi:`pytest-shared-session-scope` Pytest session-scoped fixture that works with xdist Sep 19, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-shared-session-scope` Pytest session-scoped fixture that works with xdist Sep 22, 2024 N/A pytest>=7.0.0 :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A @@ -1303,7 +1305,7 @@ This list contains 1521 plugins. :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 Sep 04, 2024 N/A pytest<8,>5.4.0 - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Sep 19, 2024 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Sep 26, 2024 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 @@ -1323,7 +1325,7 @@ This list contains 1521 plugins. :pypi:`pytest-stepfunctions` A small description May 08, 2021 4 - Beta pytest :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A - :pypi:`pytest-stf` pytest plugin for openSTF Mar 25, 2024 N/A pytest>=5.0 + :pypi:`pytest-stf` pytest plugin for openSTF Sep 24, 2024 N/A pytest>=5.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Sep 04, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) @@ -1504,7 +1506,7 @@ This list contains 1521 plugins. :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-webstage` Test web apps with pytest Sep 20, 2024 N/A pytest<9.0,>=7.0 - :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Jun 08, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Sep 25, 2024 N/A pytest>=7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 28, 2024 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A @@ -1521,6 +1523,7 @@ This list contains 1521 plugins. :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A + :pypi:`pytest-xflaky` A simple plugin to use with pytest Sep 23, 2024 4 - Beta pytest>=8.2.1 :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Aug 07, 2024 N/A pytest~=8.2.2 @@ -1549,7 +1552,8 @@ This list contains 1521 plugins. :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) - :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Sep 11, 2024 N/A pytest + :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Sep 23, 2024 N/A pytest + :pypi:`pytest-zephyr-telegram` Плагин для отправки данных автотестов в Телеграм и Зефир Sep 27, 2024 N/A pytest==8.3.2 :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) @@ -1561,7 +1565,7 @@ This list contains 1521 plugins. :pypi:`databricks-labs-pytester` - *last release*: Sep 19, 2024, + *last release*: Sep 24, 2024, *status*: 4 - Beta, *requires*: pytest>=8.3 @@ -2233,7 +2237,7 @@ This list contains 1521 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: Aug 06, 2024, + *last release*: Sep 23, 2024, *status*: N/A, *requires*: N/A @@ -2345,14 +2349,14 @@ This list contains 1521 plugins. A pytest plugin to repeat the entire test suite in batches. :pypi:`pytest-bazel` - *last release*: Jul 20, 2024, + *last release*: Sep 27, 2024, *status*: 4 - Beta, *requires*: pytest A pytest runner with bazel support :pypi:`pytest-bdd` - *last release*: Jun 04, 2024, + *last release*: Sep 26, 2024, *status*: 6 - Mature, *requires*: pytest>=6.2.0 @@ -2793,7 +2797,7 @@ This list contains 1521 plugins. pytest plugin to capture all warnings and put them in one file of your choice :pypi:`pytest-cases` - *last release*: Apr 04, 2024, + *last release*: Sep 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -3171,7 +3175,7 @@ This list contains 1521 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Sep 20, 2024, + *last release*: Sep 27, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3374,7 +3378,7 @@ This list contains 1521 plugins. Coverage dynamic context support for PyTest, including sub-processes :pypi:`pytest-coveragemarkers` - *last release*: Aug 14, 2024, + *last release*: Sep 27, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -4395,6 +4399,13 @@ This list contains 1521 plugins. A Pytest plugin to drop duplicated tests during collection + :pypi:`pytest-dryci` + *last release*: Sep 27, 2024, + *status*: 4 - Beta, + *requires*: N/A + + Test caching plugin for pytest + :pypi:`pytest-dryrun` *last release*: Jul 18, 2023, *status*: 5 - Production/Stable, @@ -4781,7 +4792,7 @@ This list contains 1521 plugins. Applies eventlet monkey-patch as a pytest plugin. :pypi:`pytest_evm` - *last release*: Sep 15, 2024, + *last release*: Sep 23, 2024, *status*: 4 - Beta, *requires*: pytest<9.0.0,>=8.1.1 @@ -4830,7 +4841,7 @@ This list contains 1521 plugins. :pypi:`pytest-exasol-slc` - *last release*: Aug 29, 2024, + *last release*: Sep 24, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -5515,6 +5526,13 @@ This list contains 1521 plugins. pytest plugin for Firefox Accounts + :pypi:`pytest-fxa-mte` + *last release*: Sep 25, 2024, + *status*: 5 - Production/Stable, + *requires*: N/A + + pytest plugin for Firefox Accounts + :pypi:`pytest-fxtest` *last release*: Oct 27, 2020, *status*: N/A, @@ -5670,7 +5688,7 @@ This list contains 1521 plugins. py.test plugin to ignore the same files as git :pypi:`pytest-gitlab` - *last release*: Sep 18, 2024, + *last release*: Sep 25, 2024, *status*: N/A, *requires*: N/A @@ -5908,9 +5926,9 @@ This list contains 1521 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Sep 17, 2024, + *last release*: Sep 28, 2024, *status*: 3 - Alpha, - *requires*: pytest==8.3.1 + *requires*: pytest==8.3.3 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -5929,7 +5947,7 @@ This list contains 1521 plugins. Report on tests that honor constraints, and guard against regressions :pypi:`pytest-hot-reloading` - *last release*: Apr 18, 2024, + *last release*: Sep 23, 2024, *status*: N/A, *requires*: N/A @@ -6083,7 +6101,7 @@ This list contains 1521 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Sep 20, 2024, + *last release*: Sep 27, 2024, *status*: 5 - Production/Stable, *requires*: pytest==8.* @@ -6370,7 +6388,7 @@ This list contains 1521 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Sep 18, 2024, + *last release*: Sep 25, 2024, *status*: 4 - Beta, *requires*: pytest @@ -7112,7 +7130,7 @@ This list contains 1521 plugins. UNKNOWN :pypi:`pytest-mask-secrets` - *last release*: Aug 06, 2024, + *last release*: Sep 27, 2024, *status*: N/A, *requires*: N/A @@ -8092,7 +8110,7 @@ This list contains 1521 plugins. Simpler PyTest parametrization :pypi:`pytest-parametrize` - *last release*: Sep 16, 2024, + *last release*: Sep 23, 2024, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=8.3.0 @@ -8386,7 +8404,7 @@ This list contains 1521 plugins. A pytest wrapper with fixtures for Playwright to automate web browsers :pypi:`pytest_playwright_async` - *last release*: May 24, 2024, + *last release*: Sep 28, 2024, *status*: N/A, *requires*: N/A @@ -8687,8 +8705,8 @@ This list contains 1521 plugins. pytest plugin for testing applications that use psqlgraph :pypi:`pytest-pt` - *last release*: May 15, 2024, - *status*: 4 - Beta, + *last release*: Sep 22, 2024, + *status*: 5 - Production/Stable, *requires*: pytest pytest plugin to use \*.pt files as tests @@ -9198,7 +9216,7 @@ This list contains 1521 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Feb 26, 2024, + *last release*: Sep 25, 2024, *status*: N/A, *requires*: pytest>7.2 @@ -9632,7 +9650,7 @@ This list contains 1521 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Sep 10, 2024, + *last release*: Sep 24, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9807,7 +9825,7 @@ This list contains 1521 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Sep 16, 2024, + *last release*: Sep 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9884,7 +9902,7 @@ This list contains 1521 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Sep 16, 2024, + *last release*: Sep 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10017,7 +10035,7 @@ This list contains 1521 plugins. :pypi:`pytest-shared-session-scope` - *last release*: Sep 19, 2024, + *last release*: Sep 22, 2024, *status*: N/A, *requires*: pytest>=7.0.0 @@ -10444,7 +10462,7 @@ This list contains 1521 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Sep 19, 2024, + *last release*: Sep 26, 2024, *status*: N/A, *requires*: N/A @@ -10584,7 +10602,7 @@ This list contains 1521 plugins. Run a test suite one failing test at a time. :pypi:`pytest-stf` - *last release*: Mar 25, 2024, + *last release*: Sep 24, 2024, *status*: N/A, *requires*: pytest>=5.0 @@ -11851,7 +11869,7 @@ This list contains 1521 plugins. Test web apps with pytest :pypi:`pytest-webtest-extras` - *last release*: Jun 08, 2024, + *last release*: Sep 25, 2024, *status*: N/A, *requires*: pytest>=7.0.0 @@ -11969,6 +11987,13 @@ This list contains 1521 plugins. Pytest fixtures providing data read from function, module or package related (x)files. + :pypi:`pytest-xflaky` + *last release*: Sep 23, 2024, + *status*: 4 - Beta, + *requires*: pytest>=8.2.1 + + A simple plugin to use with pytest + :pypi:`pytest-xiuyu` *last release*: Jul 25, 2023, *status*: 5 - Production/Stable, @@ -12166,12 +12191,19 @@ This list contains 1521 plugins. Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. :pypi:`pytest-zephyr-scale-integration` - *last release*: Sep 11, 2024, + *last release*: Sep 23, 2024, *status*: N/A, *requires*: pytest A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest + :pypi:`pytest-zephyr-telegram` + *last release*: Sep 27, 2024, + *status*: N/A, + *requires*: pytest==8.3.2 + + Плагин для отправки данных автотестов в Телеграм и Зефир + :pypi:`pytest-zest` *last release*: Nov 17, 2022, *status*: N/A, From 7add2af7087dc32af19a38f5950a5b64a19d1de5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:32:25 +0200 Subject: [PATCH 0896/1271] [pre-commit.ci] pre-commit autoupdate (#12848) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.7 → v0.6.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.7...v0.6.8) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b4d10558b88..7b54534b45d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.7" + rev: "v0.6.8" hooks: - id: ruff args: ["--fix"] From eb8592c526b3d7967573d816efc5b35fc88be2a8 Mon Sep 17 00:00:00 2001 From: sven <42868792+FreerGit@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:41:30 +0200 Subject: [PATCH 0897/1271] update default and add docs --- changelog/12749.feature.rst | 4 +++- doc/en/reference/reference.rst | 10 +++++++++- src/_pytest/main.py | 6 +++--- testing/test_collect_imports.py | 26 ++++++++++++++++++++++---- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/changelog/12749.feature.rst b/changelog/12749.feature.rst index 798d02c6e49..cda0db6c930 100644 --- a/changelog/12749.feature.rst +++ b/changelog/12749.feature.rst @@ -1,3 +1,5 @@ -Add :confval:`collect_imported_tests`, when enabled (default is disabled) will make sure to not consider classes/functions which are imported by a test file and contains Test/test_*/*_test. +New :confval:`collect_imported_tests`: when enabled (the default) pytest will collect classes/functions in test modules even if they are imported from another file. + +Setting this to False will make pytest collect classes/functions from test files only if they are defined in that file (as opposed to imported there). -- by :user:`FreerGit` diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index f7dfb3ffa71..99b1a19c3a4 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1839,9 +1839,17 @@ passed multiple times. The expected format is ``name=value``. For example:: pytest testing doc -.. confval:: tmp_path_retention_count +.. confval:: collect_imported_tests + + Setting this to `false` will make pytest collect classes/functions from test + files only if they are defined in that file (as opposed to imported there). + + .. code-block:: ini + [pytest] + collect_imported_tests = false +.. confval:: tmp_path_retention_count How many sessions should we keep the `tmp_path` directories, according to `tmp_path_retention_policy`. diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 611ce033ea9..e40f09a9acb 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -82,7 +82,7 @@ def pytest_addoption(parser: Parser) -> None: "collect_imported_tests", "Whether to collect tests in imported modules outside `testpaths`", type="bool", - default=False, + default=True, ) group = parser.getgroup("general", "Running and selection options") group._addoption( @@ -973,7 +973,7 @@ def genitems(self, node: nodes.Item | nodes.Collector) -> Iterator[nodes.Item]: self.trace("genitems", node) if isinstance(node, nodes.Item): node.ihook.pytest_itemcollected(item=node) - if self.config.getini("collect_imported_tests"): + if not self.config.getini("collect_imported_tests"): if isinstance(node.parent, Module) and isinstance(node, Function): if inspect.isfunction(node._getobj()): fn_defined_at = node._getobj().__module__ @@ -988,7 +988,7 @@ def genitems(self, node: nodes.Item | nodes.Collector) -> Iterator[nodes.Item]: handle_dupes = not (keepduplicates and isinstance(node, nodes.File)) rep, duplicate = self._collect_one_node(node, handle_dupes) - if self.config.getini("collect_imported_tests"): + if not self.config.getini("collect_imported_tests"): for subnode in rep.result: if isinstance(subnode, Class) and isinstance( subnode.parent, Module diff --git a/testing/test_collect_imports.py b/testing/test_collect_imports.py index e328d16a182..7922058721c 100644 --- a/testing/test_collect_imports.py +++ b/testing/test_collect_imports.py @@ -55,7 +55,7 @@ def test_collect_imports_disabled(pytester: Pytester) -> None: collect_imported_tests = false """) - run_import_class_test(pytester, errors=1) + run_import_class_test(pytester, passed=1) def test_collect_imports_default(pytester: Pytester) -> None: @@ -74,7 +74,7 @@ def test_collect_imports_enabled(pytester: Pytester) -> None: collect_imported_tests = true """) - run_import_class_test(pytester, passed=1) + run_import_class_test(pytester, errors=1) def run_import_functions_test( @@ -137,14 +137,32 @@ def test_collect_function_imports_enabled(pytester: Pytester) -> None: collect_imported_tests = true """) - run_import_functions_test(pytester, passed=1, errors=0, failed=0) + run_import_functions_test(pytester, passed=2, errors=0, failed=1) def test_collect_function_imports_disabled(pytester: Pytester) -> None: pytester.makeini(""" [pytest] - testpaths = "tests" + # testpaths = "tests" collect_imported_tests = false """) + run_import_functions_test(pytester, passed=1, errors=0, failed=0) + + +def test_behaviour_without_testpaths_set_and_false(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + collect_imported_tests = false + """) + + run_import_functions_test(pytester, passed=1, errors=0, failed=0) + + +def test_behaviour_without_testpaths_set_and_true(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + collect_imported_tests = true + """) + run_import_functions_test(pytester, passed=2, errors=0, failed=1) From 410c510118e8963d122102f8426dfa3fff626d50 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 6 Oct 2024 05:46:07 +0200 Subject: [PATCH 0898/1271] [automated] Update plugin list (#12856) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 104 ++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 36 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 96ee4fc3830..e09656e3a61 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) + :pypi:`pytest-annotated` Pytest plugin to allow use of Annotated in tests to resolve fixtures Sep 30, 2024 N/A pytest>=8.3.3 :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Sep 11, 2024 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) @@ -156,7 +157,7 @@ This list contains 1525 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Sep 18, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 02, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -293,7 +294,7 @@ This list contains 1525 plugins. :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Sep 27, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Sep 30, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Sep 18, 2024 5 - Production/Stable pytest @@ -591,6 +592,7 @@ This list contains 1525 plugins. :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Jul 30, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-freethreaded` pytest plugin for running parallel tests Oct 03, 2024 5 - Production/Stable pytest :pypi:`pytest-freezeblaster` Wrap tests with fixtures in freeze_time Jul 10, 2024 N/A pytest>=6.2.5 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 @@ -598,9 +600,9 @@ This list contains 1525 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Sep 11, 2024 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Oct 03, 2024 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A - :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Sep 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A :pypi:`pytest-fzf` fzf-based test selector for pytest Jul 03, 2024 4 - Beta pytest>=6.0.0 :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A @@ -657,7 +659,7 @@ This list contains 1525 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Sep 28, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Oct 05, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -788,7 +790,7 @@ This list contains 1525 plugins. :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 - :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Sep 05, 2024 4 - Beta N/A + :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Oct 01, 2024 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-ligo` Jan 16, 2020 4 - Beta N/A :pypi:`pytest-lineno` A pytest plugin to show the line numbers of test functions Dec 04, 2020 N/A pytest @@ -815,7 +817,7 @@ This list contains 1525 plugins. :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logikal` Common testing environment Aug 30, 2024 5 - Production/Stable pytest==8.3.2 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A - :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Jul 19, 2024 4 - Beta N/A + :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Sep 04, 2024 3 - Alpha pytest @@ -1037,14 +1039,14 @@ This list contains 1525 plugins. :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Sep 05, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) - :pypi:`pytest-powerpack` Mar 17, 2024 N/A pytest (>=8.1.1,<9.0.0) + :pypi:`pytest-powerpack` A plugin containing extra batteries for pytest Oct 01, 2024 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Sep 17, 2024 5 - Production/Stable pytest>=8.3.2 :pypi:`pytest-priority` pytest plugin for add priority for tests Aug 19, 2024 N/A pytest - :pypi:`pytest-proceed` Apr 10, 2024 N/A pytest + :pypi:`pytest-proceed` Oct 01, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-progress` pytest plugin for instant test progress status Jun 18, 2024 5 - Production/Stable pytest>=2.7 @@ -1127,7 +1129,7 @@ This list contains 1525 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 - :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Sep 25, 2024 N/A pytest>7.2 + :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Oct 05, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relative-path` Handle relative path in pytest options or ini configs Aug 30, 2024 N/A pytest :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Mar 29, 2024 5 - Production/Stable pytest>=7 @@ -1199,6 +1201,7 @@ This list contains 1525 plugins. :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 21, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A + :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Sep 30, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 @@ -1214,7 +1217,7 @@ This list contains 1525 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Sep 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 04, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1225,7 +1228,7 @@ This list contains 1525 plugins. :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 Feb 01, 2024 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. Sep 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 04, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1492,6 +1495,7 @@ This list contains 1525 plugins. :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest + :pypi:`pytest-vtestify` A pytest plugin for visual assertion using SSIM and image comparison. Oct 03, 2024 N/A pytest :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Jun 01, 2023 N/A pytest (>=7.0.0) :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A @@ -1506,7 +1510,7 @@ This list contains 1525 plugins. :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest :pypi:`pytest-webstage` Test web apps with pytest Sep 20, 2024 N/A pytest<9.0,>=7.0 - :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Sep 25, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Oct 03, 2024 N/A pytest>=7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 28, 2024 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A @@ -1523,7 +1527,7 @@ This list contains 1525 plugins. :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A - :pypi:`pytest-xflaky` A simple plugin to use with pytest Sep 23, 2024 4 - Beta pytest>=8.2.1 + :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 04, 2024 4 - Beta pytest>=8.2.1 :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Aug 07, 2024 N/A pytest~=8.2.2 @@ -1535,7 +1539,7 @@ This list contains 1525 plugins. :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-xstress` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 :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. Jul 03, 2024 4 - Beta pytest>=7.2.2 + :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Oct 01, 2024 4 - Beta pytest>=7.2.2 :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 with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Aug 16, 2024 N/A pytest~=8.2.2 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) @@ -1553,7 +1557,7 @@ This list contains 1525 plugins. :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Sep 23, 2024 N/A pytest - :pypi:`pytest-zephyr-telegram` Плагин для отправки данных автотестов в Телеграм и Зефир Sep 27, 2024 N/A pytest==8.3.2 + :pypi:`pytest-zephyr-telegram` Плагин для отправки данных автотестов в Телеграм и Зефир Sep 30, 2024 N/A pytest==8.3.2 :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) @@ -1858,6 +1862,13 @@ This list contains 1525 plugins. pytest-annotate: Generate PyAnnotate annotations from your pytest tests. + :pypi:`pytest-annotated` + *last release*: Sep 30, 2024, + *status*: N/A, + *requires*: pytest>=8.3.3 + + Pytest plugin to allow use of Annotated in tests to resolve fixtures + :pypi:`pytest-ansible` *last release*: Sep 11, 2024, *status*: 5 - Production/Stable, @@ -2419,7 +2430,7 @@ This list contains 1525 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Sep 18, 2024, + *last release*: Oct 02, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3378,7 +3389,7 @@ This list contains 1525 plugins. Coverage dynamic context support for PyTest, including sub-processes :pypi:`pytest-coveragemarkers` - *last release*: Sep 27, 2024, + *last release*: Sep 30, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -5463,6 +5474,13 @@ This list contains 1525 plugins. Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications + :pypi:`pytest-freethreaded` + *last release*: Oct 03, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest + + pytest plugin for running parallel tests + :pypi:`pytest-freezeblaster` *last release*: Jul 10, 2024, *status*: N/A, @@ -5513,7 +5531,7 @@ This list contains 1525 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Sep 11, 2024, + *last release*: Oct 03, 2024, *status*: N/A, *requires*: pytest @@ -5527,7 +5545,7 @@ This list contains 1525 plugins. pytest plugin for Firefox Accounts :pypi:`pytest-fxa-mte` - *last release*: Sep 25, 2024, + *last release*: Oct 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5926,7 +5944,7 @@ This list contains 1525 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Sep 28, 2024, + *last release*: Oct 05, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6843,7 +6861,7 @@ This list contains 1525 plugins. A python-libfaketime plugin for pytest :pypi:`pytest-libiio` - *last release*: Sep 05, 2024, + *last release*: Oct 01, 2024, *status*: 4 - Beta, *requires*: N/A @@ -7032,9 +7050,9 @@ This list contains 1525 plugins. Package for creating a pytest test run reprot :pypi:`pytest-logscanner` - *last release*: Jul 19, 2024, + *last release*: Sep 30, 2024, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest>=8.2.2 Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) @@ -8586,11 +8604,11 @@ This list contains 1525 plugins. pytest plugin with powerful fixtures :pypi:`pytest-powerpack` - *last release*: Mar 17, 2024, + *last release*: Oct 01, 2024, *status*: N/A, - *requires*: pytest (>=8.1.1,<9.0.0) - + *requires*: pytest<9.0.0,>=8.1.1 + A plugin containing extra batteries for pytest :pypi:`pytest-prefer-nested-dup-tests` *last release*: Apr 27, 2022, @@ -8635,7 +8653,7 @@ This list contains 1525 plugins. pytest plugin for add priority for tests :pypi:`pytest-proceed` - *last release*: Apr 10, 2024, + *last release*: Oct 01, 2024, *status*: N/A, *requires*: pytest @@ -9216,7 +9234,7 @@ This list contains 1525 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Sep 25, 2024, + *last release*: Oct 05, 2024, *status*: N/A, *requires*: pytest>7.2 @@ -9719,6 +9737,13 @@ This list contains 1525 plugins. implement a --failed option for pytest + :pypi:`pytest-run-parallel` + *last release*: Sep 30, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A simple pytest plugin to run tests concurrently + :pypi:`pytest-run-subprocess` *last release*: Nov 12, 2022, *status*: 5 - Production/Stable, @@ -9825,7 +9850,7 @@ This list contains 1525 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Sep 26, 2024, + *last release*: Oct 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9902,7 +9927,7 @@ This list contains 1525 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Sep 26, 2024, + *last release*: Oct 04, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -11770,6 +11795,13 @@ This list contains 1525 plugins. A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. + :pypi:`pytest-vtestify` + *last release*: Oct 03, 2024, + *status*: N/A, + *requires*: pytest + + A pytest plugin for visual assertion using SSIM and image comparison. + :pypi:`pytest-vts` *last release*: Jun 05, 2019, *status*: N/A, @@ -11869,7 +11901,7 @@ This list contains 1525 plugins. Test web apps with pytest :pypi:`pytest-webtest-extras` - *last release*: Sep 25, 2024, + *last release*: Oct 03, 2024, *status*: N/A, *requires*: pytest>=7.0.0 @@ -11988,7 +12020,7 @@ This list contains 1525 plugins. Pytest fixtures providing data read from function, module or package related (x)files. :pypi:`pytest-xflaky` - *last release*: Sep 23, 2024, + *last release*: Oct 04, 2024, *status*: 4 - Beta, *requires*: pytest>=8.2.1 @@ -12072,7 +12104,7 @@ This list contains 1525 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-xvirt` - *last release*: Jul 03, 2024, + *last release*: Oct 01, 2024, *status*: 4 - Beta, *requires*: pytest>=7.2.2 @@ -12198,7 +12230,7 @@ This list contains 1525 plugins. A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest :pypi:`pytest-zephyr-telegram` - *last release*: Sep 27, 2024, + *last release*: Sep 30, 2024, *status*: N/A, *requires*: pytest==8.3.2 From b451a18cc9db46636bd873e0d8bc7cc71dc818e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 09:34:41 -0300 Subject: [PATCH 0899/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.10.2 to 1.10.3 (#12858) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.10.2 to 1.10.3. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.10.2...v1.10.3) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f2e2dd4a407..998a2839dc2 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.10.2 + uses: pypa/gh-action-pypi-publish@v1.10.3 with: attestations: true From 294e1139ec464b569e589fb4173bb7b26d61163a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 06:45:53 +0200 Subject: [PATCH 0900/1271] [pre-commit.ci] pre-commit autoupdate (#12862) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.8 → v0.6.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.8...v0.6.9) - [github.com/pre-commit/pre-commit-hooks: v4.6.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.6.0...v5.0.0) - [github.com/adamchainz/blacken-docs: 1.18.0 → 1.19.0](https://github.com/adamchainz/blacken-docs/compare/1.18.0...1.19.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7b54534b45d..7a3fa1a428a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,18 +1,18 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.8" + rev: "v0.6.9" hooks: - id: ruff args: ["--fix"] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/adamchainz/blacken-docs - rev: 1.18.0 + rev: 1.19.0 hooks: - id: blacken-docs additional_dependencies: [black==24.1.1] From fb740251fe1d7facd1f8a341e22d4aa07ba7833c Mon Sep 17 00:00:00 2001 From: Frank Hoffmann <44680962+15r10nk@users.noreply.github.com> Date: Wed, 9 Oct 2024 21:10:56 +0200 Subject: [PATCH 0901/1271] Preserve source positions for assertion rewriting Closes #12818 --- AUTHORS | 1 + changelog/12818.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 21 ++- testing/test_assertrewrite.py | 211 ++++++++++++++++++++++++++++++- 4 files changed, 223 insertions(+), 11 deletions(-) create mode 100644 changelog/12818.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 1ee868448d4..a42f4ab0c13 100644 --- a/AUTHORS +++ b/AUTHORS @@ -160,6 +160,7 @@ Feng Ma Florian Bruhin Florian Dahlitz Floris Bruynooghe +Frank Hoffmann Fraser Stark Gabriel Landau Gabriel Reis diff --git a/changelog/12818.bugfix.rst b/changelog/12818.bugfix.rst new file mode 100644 index 00000000000..9d74f2fda2a --- /dev/null +++ b/changelog/12818.bugfix.rst @@ -0,0 +1 @@ +Assertion rewriting now preserves the source ranges of the original instructions, making it play well with tools that deal with the ``AST``, like `executing `__. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index a7a92c0f1fe..37c09b03467 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -792,7 +792,7 @@ def assign(self, expr: ast.expr) -> ast.Name: """Give *expr* a name.""" name = self.variable() self.statements.append(ast.Assign([ast.Name(name, ast.Store())], expr)) - return ast.Name(name, ast.Load()) + return ast.copy_location(ast.Name(name, ast.Load()), expr) def display(self, expr: ast.expr) -> ast.expr: """Call saferepr on the expression.""" @@ -975,7 +975,10 @@ def visit_Assert(self, assert_: ast.Assert) -> list[ast.stmt]: # Fix locations (line numbers/column offsets). for stmt in self.statements: for node in traverse_node(stmt): - ast.copy_location(node, assert_) + if getattr(node, "lineno", None) is None: + # apply the assertion location to all generated ast nodes without source location + # and preserve the location of existing nodes or generated nodes with an correct location. + ast.copy_location(node, assert_) return self.statements def visit_NamedExpr(self, name: ast.NamedExpr) -> tuple[ast.NamedExpr, str]: @@ -1052,7 +1055,7 @@ def visit_BoolOp(self, boolop: ast.BoolOp) -> tuple[ast.Name, str]: def visit_UnaryOp(self, unary: ast.UnaryOp) -> tuple[ast.Name, str]: pattern = UNARY_MAP[unary.op.__class__] operand_res, operand_expl = self.visit(unary.operand) - res = self.assign(ast.UnaryOp(unary.op, operand_res)) + res = self.assign(ast.copy_location(ast.UnaryOp(unary.op, operand_res), unary)) return res, pattern % (operand_expl,) def visit_BinOp(self, binop: ast.BinOp) -> tuple[ast.Name, str]: @@ -1060,7 +1063,9 @@ def visit_BinOp(self, binop: ast.BinOp) -> tuple[ast.Name, str]: left_expr, left_expl = self.visit(binop.left) right_expr, right_expl = self.visit(binop.right) explanation = f"({left_expl} {symbol} {right_expl})" - res = self.assign(ast.BinOp(left_expr, binop.op, right_expr)) + res = self.assign( + ast.copy_location(ast.BinOp(left_expr, binop.op, right_expr), binop) + ) return res, explanation def visit_Call(self, call: ast.Call) -> tuple[ast.Name, str]: @@ -1089,7 +1094,7 @@ def visit_Call(self, call: ast.Call) -> tuple[ast.Name, str]: arg_expls.append("**" + expl) expl = "{}({})".format(func_expl, ", ".join(arg_expls)) - new_call = ast.Call(new_func, new_args, new_kwargs) + new_call = ast.copy_location(ast.Call(new_func, new_args, new_kwargs), call) res = self.assign(new_call) res_expl = self.explanation_param(self.display(res)) outer_expl = f"{res_expl}\n{{{res_expl} = {expl}\n}}" @@ -1105,7 +1110,9 @@ def visit_Attribute(self, attr: ast.Attribute) -> tuple[ast.Name, str]: if not isinstance(attr.ctx, ast.Load): return self.generic_visit(attr) value, value_expl = self.visit(attr.value) - res = self.assign(ast.Attribute(value, attr.attr, ast.Load())) + res = self.assign( + ast.copy_location(ast.Attribute(value, attr.attr, ast.Load()), attr) + ) res_expl = self.explanation_param(self.display(res)) pat = "%s\n{%s = %s.%s\n}" expl = pat % (res_expl, res_expl, value_expl, attr.attr) @@ -1146,7 +1153,7 @@ def visit_Compare(self, comp: ast.Compare) -> tuple[ast.expr, str]: syms.append(ast.Constant(sym)) expl = f"{left_expl} {sym} {next_expl}" expls.append(ast.Constant(expl)) - res_expr = ast.Compare(left_res, [op], [next_res]) + res_expr = ast.copy_location(ast.Compare(left_res, [op], [next_res]), comp) self.statements.append(ast.Assign([store_names[i]], res_expr)) left_res, left_expl = next_res, next_expl # Use pytest.assertion.util._reprcompare if that's available. diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 73c11a1a9d8..7be473d897a 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -2,10 +2,12 @@ from __future__ import annotations import ast +import dis import errno from functools import partial import glob import importlib +import inspect import marshal import os from pathlib import Path @@ -131,10 +133,211 @@ def test_location_is_set(self) -> None: continue for n in [node, *ast.iter_child_nodes(node)]: assert isinstance(n, (ast.stmt, ast.expr)) - assert n.lineno == 3 - assert n.col_offset == 0 - assert n.end_lineno == 6 - assert n.end_col_offset == 3 + for location in [ + (n.lineno, n.col_offset), + (n.end_lineno, n.end_col_offset), + ]: + assert (3, 0) <= location <= (6, 3) + + def test_positions_are_preserved(self) -> None: + """Ensure AST positions are preserved during rewriting (#12818).""" + + def preserved(code: str) -> None: + s = textwrap.dedent(code) + locations = [] + + def loc(msg: str | None = None) -> None: + frame = inspect.currentframe() + assert frame + frame = frame.f_back + assert frame + frame = frame.f_back + assert frame + + offset = frame.f_lasti + + instructions = {i.offset: i for i in dis.get_instructions(frame.f_code)} + + # skip CACHE instructions + while offset not in instructions and offset >= 0: + offset -= 1 + + instruction = instructions[offset] + if sys.version_info >= (3, 11): + position = instruction.positions + else: + position = instruction.starts_line + + locations.append((msg, instruction.opname, position)) + + globals = {"loc": loc} + + m = rewrite(s) + mod = compile(m, "", "exec") + exec(mod, globals, globals) + transformed_locations = locations + locations = [] + + mod = compile(s, "", "exec") + exec(mod, globals, globals) + original_locations = locations + + assert len(original_locations) > 0 + assert original_locations == transformed_locations + + preserved(""" + def f(): + loc() + return 8 + + assert f() in [8] + assert (f() + in + [8]) + """) + + preserved(""" + class T: + def __init__(self): + loc("init") + def __getitem__(self,index): + loc("getitem") + return index + + assert T()[5] == 5 + assert (T + () + [5] + == + 5) + """) + + for name, op in [ + ("pos", "+"), + ("neg", "-"), + ("invert", "~"), + ]: + preserved(f""" + class T: + def __{name}__(self): + loc("{name}") + return "{name}" + + assert {op}T() == "{name}" + assert ({op} + T + () + == + "{name}") + """) + + for name, op in [ + ("add", "+"), + ("sub", "-"), + ("mul", "*"), + ("truediv", "/"), + ("floordiv", "//"), + ("mod", "%"), + ("pow", "**"), + ("lshift", "<<"), + ("rshift", ">>"), + ("or", "|"), + ("xor", "^"), + ("and", "&"), + ("matmul", "@"), + ]: + preserved(f""" + class T: + def __{name}__(self,other): + loc("{name}") + return other + + def __r{name}__(self,other): + loc("r{name}") + return other + + assert T() {op} 2 == 2 + assert 2 {op} T() == 2 + + assert (T + () + {op} + 2 + == + 2) + + assert (2 + {op} + T + () + == + 2) + """) + + for name, op in [ + ("eq", "=="), + ("ne", "!="), + ("lt", "<"), + ("le", "<="), + ("gt", ">"), + ("ge", ">="), + ]: + preserved(f""" + class T: + def __{name}__(self,other): + loc() + return True + + assert T() {op} 5 + assert (T + () + {op} + 5) + """) + + for name, op in [ + ("eq", "=="), + ("ne", "!="), + ("lt", ">"), + ("le", ">="), + ("gt", "<"), + ("ge", "<="), + ("contains", "in"), + ]: + preserved(f""" + class T: + def __{name}__(self,other): + loc() + return True + + assert 5 {op} T() + assert (5 + {op} + T + ()) + """) + + preserved(""" + def func(value): + loc("func") + return value + + class T: + def __iter__(self): + loc("iter") + return iter([5]) + + assert func(*T()) == 5 + """) + + preserved(""" + class T: + def __getattr__(self,name): + loc() + return name + + assert T().attr == "attr" + """) def test_dont_rewrite(self) -> None: s = """'PYTEST_DONT_REWRITE'\nassert 14""" From 23256dd9677db448a36c9e863cd1591d68c8ce94 Mon Sep 17 00:00:00 2001 From: Christopher Head Date: Wed, 9 Oct 2024 12:13:56 -0700 Subject: [PATCH 0902/1271] Prohibit pytest.mark.usefixtures in pytest.param (#12828) Mitigates #4112 a bit. Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/4112.improvement.rst | 1 + src/_pytest/mark/__init__.py | 7 ++++++- src/_pytest/mark/structures.py | 5 +++++ testing/python/integration.py | 17 +++++++++++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 changelog/4112.improvement.rst diff --git a/AUTHORS b/AUTHORS index a42f4ab0c13..47a83379224 100644 --- a/AUTHORS +++ b/AUTHORS @@ -95,6 +95,7 @@ Christine Mecklenborg Christoph Buelter Christopher Dignam Christopher Gilling +Christopher Head Claire Cecil Claudio Madotto Clément M.T. Robert diff --git a/changelog/4112.improvement.rst b/changelog/4112.improvement.rst new file mode 100644 index 00000000000..426b87ffa19 --- /dev/null +++ b/changelog/4112.improvement.rst @@ -0,0 +1 @@ +Using :ref:`pytest.mark.usefixtures ` on :func:`pytest.param` now produces an error instead of silently doing nothing. diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index a4f942c5ae3..f76e5212057 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -66,7 +66,12 @@ def test_eval(test_input, expected): assert eval(test_input) == expected :param values: Variable args of the values of the parameter set, in order. - :param marks: A single mark or a list of marks to be applied to this parameter set. + + :param marks: + A single mark or a list of marks to be applied to this parameter set. + + :ref:`pytest.mark.usefixtures ` cannot be added via this parameter. + :param id: The id to attribute to this parameter set. """ return ParameterSet.param(*values, marks=marks, id=id) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 92ade55f7c0..8a92c9470a7 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -88,6 +88,11 @@ def param( marks = (marks,) else: assert isinstance(marks, collections.abc.Collection) + if any(i.name == "usefixtures" for i in marks): + raise ValueError( + "pytest.param cannot add pytest.mark.usefixtures; see " + "https://docs.pytest.org/en/stable/reference/reference.html#pytest-param" + ) if id is not None: if not isinstance(id, str): diff --git a/testing/python/integration.py b/testing/python/integration.py index c52a683a322..c96b6e4c260 100644 --- a/testing/python/integration.py +++ b/testing/python/integration.py @@ -407,6 +407,23 @@ def test_params(a, b): res = pytester.runpytest("--collect-only") res.stdout.fnmatch_lines(["*spam-2*", "*ham-2*"]) + def test_param_rejects_usefixtures(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize("x", [ + pytest.param(1, marks=[pytest.mark.usefixtures("foo")]), + ]) + def test_foo(x): + pass + """ + ) + res = pytester.runpytest("--collect-only") + res.stdout.fnmatch_lines( + ["*test_param_rejects_usefixtures.py:4*", "*pytest.param(*"] + ) + def test_function_instance(pytester: Pytester) -> None: items = pytester.getitems( From a14c718867a9e7a664e2c957fd4694a4b5cc355b Mon Sep 17 00:00:00 2001 From: moajo Date: Thu, 10 Oct 2024 05:52:26 +0900 Subject: [PATCH 0903/1271] Fix `disable_test_id_escaping_and_forfeit_all_rights_to_community_support` option when using `pytest.param(..., id="...")` Fixes #9037 --------- Co-authored-by: Ronny Pfannschmidt Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/9037.bugfix.rst | 1 + doc/en/reference/reference.rst | 23 +++++++++++++++++++++++ src/_pytest/mark/structures.py | 2 -- src/_pytest/python.py | 2 +- testing/python/metafunc.py | 31 +++++++++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 changelog/9037.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 47a83379224..69089354a44 100644 --- a/AUTHORS +++ b/AUTHORS @@ -408,6 +408,7 @@ Sviatoslav Sydorenko Sylvain Marié Tadek Teleżyński Takafumi Arakaki +Takumi Otani Taneli Hukkinen Tanvi Mehta Tanya Agarwal diff --git a/changelog/9037.bugfix.rst b/changelog/9037.bugfix.rst new file mode 100644 index 00000000000..5367452337e --- /dev/null +++ b/changelog/9037.bugfix.rst @@ -0,0 +1 @@ +Honor :confval:`disable_test_id_escaping_and_forfeit_all_rights_to_community_support` when escaping ids in parametrized tests. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 3bb03cc0386..baf781d4356 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1332,6 +1332,29 @@ passed multiple times. The expected format is ``name=value``. For example:: console_output_style = classic +.. confval:: disable_test_id_escaping_and_forfeit_all_rights_to_community_support + + .. versionadded:: 4.4 + + pytest by default escapes any non-ascii characters used in unicode strings + for the parametrization because it has several downsides. + If however you would like to use unicode strings in parametrization + and see them in the terminal as is (non-escaped), use this option + in your ``pytest.ini``: + + .. code-block:: ini + + [pytest] + disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True + + Keep in mind however that this might cause unwanted side effects and + even bugs depending on the OS used and plugins currently installed, + so use it at your own risk. + + Default: ``False``. + + See :ref:`parametrizemark`. + .. confval:: doctest_encoding diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 8a92c9470a7..14650a64759 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -21,7 +21,6 @@ import warnings from .._code import getfslineno -from ..compat import ascii_escaped from ..compat import NOTSET from ..compat import NotSetType from _pytest.config import Config @@ -97,7 +96,6 @@ def param( if id is not None: if not isinstance(id, str): raise TypeError(f"Expected id to be a string, got {type(id)}: {id!r}") - id = ascii_escaped(id) return cls(values, marks, id) @classmethod diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 9c54dd20f80..dde442e8eda 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -924,7 +924,7 @@ def _resolve_ids(self) -> Iterable[str]: for idx, parameterset in enumerate(self.parametersets): if parameterset.id is not None: # ID provided directly - pytest.param(..., id="...") - yield parameterset.id + yield _ascii_escaped_by_config(parameterset.id, self.config) elif self.ids and idx < len(self.ids) and self.ids[idx] is not None: # ID provided in the IDs list - parametrize(..., ids=[...]). yield self._idval_from_value_required(self.ids[idx], idx) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index be224d9e20b..0a4ebf2c9af 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -625,6 +625,37 @@ def getini(self, name): ).make_unique_parameterset_ids() assert result == [expected] + def test_idmaker_with_param_id_and_config(self) -> None: + """Unit test for expected behavior to create ids with pytest.param(id=...) and + disable_test_id_escaping_and_forfeit_all_rights_to_community_support + option (#9037). + """ + + class MockConfig: + def __init__(self, config): + self.config = config + + def getini(self, name): + return self.config[name] + + option = "disable_test_id_escaping_and_forfeit_all_rights_to_community_support" + + values: list[tuple[Any, str]] = [ + (MockConfig({option: True}), "ação"), + (MockConfig({option: False}), "a\\xe7\\xe3o"), + ] + for config, expected in values: + result = IdMaker( + ("a",), + [pytest.param("string", id="ação")], + None, + None, + config, + None, + None, + ).make_unique_parameterset_ids() + assert result == [expected] + def test_idmaker_duplicated_empty_str(self) -> None: """Regression test for empty strings parametrized more than once (#11563).""" result = IdMaker( From 26a29bdade7efccdf6233942749f02cef57ce694 Mon Sep 17 00:00:00 2001 From: Stefaan Lippens Date: Thu, 10 Oct 2024 12:43:36 +0200 Subject: [PATCH 0904/1271] Docs: improve/cleanup reference from/to recwarn (#12866) Co-authored-by: Bruno Oliveira --- changelog/12866.doc.rst | 1 + doc/en/builtin.rst | 3 +-- doc/en/how-to/capture-warnings.rst | 17 ++++++++--------- doc/en/reference/reference.rst | 3 ++- src/_pytest/recwarn.py | 3 +-- 5 files changed, 13 insertions(+), 14 deletions(-) create mode 100644 changelog/12866.doc.rst diff --git a/changelog/12866.doc.rst b/changelog/12866.doc.rst new file mode 100644 index 00000000000..865b2bbc600 --- /dev/null +++ b/changelog/12866.doc.rst @@ -0,0 +1 @@ +Improved cross-references concerning the :fixture:`recwarn` fixture. diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 9b406a6a512..822ee48b3fb 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -234,8 +234,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a recwarn -- .../_pytest/recwarn.py:35 Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. - See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information - on warning categories. + See :ref:`warnings` for information on warning categories. tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:242 Return a :class:`pytest.TempPathFactory` instance for the test session. diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index afabad5da14..44ed87508a3 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -195,7 +195,7 @@ user code and third-party libraries, as recommended by :pep:`565`. This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed. However, in the specific case where users capture any type of warnings in their test, either with -:func:`pytest.warns`, :func:`pytest.deprecated_call` or using the :ref:`recwarn ` fixture, +:func:`pytest.warns`, :func:`pytest.deprecated_call` or using the :fixture:`recwarn` fixture, no warning will be displayed at all. Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over @@ -332,10 +332,10 @@ additional information: assert record[0].message.args[0] == "another warning" Alternatively, you can examine raised warnings in detail using the -:ref:`recwarn ` fixture (see below). +:fixture:`recwarn` fixture (see :ref:`below `). -The :ref:`recwarn ` fixture automatically ensures to reset the warnings +The :fixture:`recwarn` fixture automatically ensures to reset the warnings filter at the end of the test, so no global state is leaked. .. _`recording warnings`: @@ -345,8 +345,8 @@ filter at the end of the test, so no global state is leaked. Recording warnings ------------------ -You can record raised warnings either using :func:`pytest.warns` or with -the ``recwarn`` fixture. +You can record raised warnings either using the :func:`pytest.warns` context manager or with +the :fixture:`recwarn` fixture. To record with :func:`pytest.warns` without asserting anything about the warnings, pass no arguments as the expected warning type and it will default to a generic Warning: @@ -361,7 +361,7 @@ pass no arguments as the expected warning type and it will default to a generic assert str(record[0].message) == "user" assert str(record[1].message) == "runtime" -The ``recwarn`` fixture will record warnings for the whole function: +The :fixture:`recwarn` fixture will record warnings for the whole function: .. code-block:: python @@ -377,12 +377,11 @@ The ``recwarn`` fixture will record warnings for the whole function: assert w.filename assert w.lineno -Both ``recwarn`` and :func:`pytest.warns` return the same interface for recorded -warnings: a WarningsRecorder instance. To view the recorded warnings, you can +Both the :fixture:`recwarn` fixture and the :func:`pytest.warns` context manager return the same interface for recorded +warnings: a :class:`~_pytest.recwarn.WarningsRecorder` instance. To view the recorded warnings, you can iterate over this instance, call ``len`` on it to get the number of recorded warnings, or index into it to get a particular recorded warning. -Full API: :class:`~_pytest.recwarn.WarningsRecorder`. .. _`warns use cases`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index baf781d4356..b6ec5c65e1e 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -529,13 +529,14 @@ record_testsuite_property recwarn ~~~~~~~ -**Tutorial**: :ref:`assertwarnings` +**Tutorial**: :ref:`recwarn` .. autofunction:: _pytest.recwarn.recwarn() :no-auto-options: .. autoclass:: pytest.WarningsRecorder() :members: + :special-members: __getitem__, __iter__, __len__ .. fixture:: request diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 85d8de84abb..0dc002edd94 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -35,8 +35,7 @@ def recwarn() -> Generator[WarningsRecorder]: """Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. - See https://docs.pytest.org/en/latest/how-to/capture-warnings.html for information - on warning categories. + See :ref:`warnings` for information on warning categories. """ wrec = WarningsRecorder(_ispytest=True) with wrec: From 2242cd43eb5601e3f282003c049e37e56ece932a Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 10 Oct 2024 12:52:08 +0200 Subject: [PATCH 0905/1271] [pre-commit] Use --python-version for mypy instead of forcing a python interpreter (#12869) --- .pre-commit-config.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7a3fa1a428a..7cebd15c0d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,8 +32,7 @@ repos: hooks: - id: mypy files: ^(src/|testing/|scripts/) - args: [] - language_version: "3.8" + args: ["--python-version=3.8"] additional_dependencies: - iniconfig>=1.1.0 - attrs>=19.2.0 From cfd2e209e3958a4f5b0857707f3c6328418fde55 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 10 Oct 2024 14:31:36 +0200 Subject: [PATCH 0906/1271] [mypy] python-version independant from pre-commit --- .pre-commit-config.yaml | 1 - pyproject.toml | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7cebd15c0d1..c0d7750cf43 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,6 @@ repos: hooks: - id: mypy files: ^(src/|testing/|scripts/) - args: ["--python-version=3.8"] additional_dependencies: - iniconfig>=1.1.0 - attrs>=19.2.0 diff --git a/pyproject.toml b/pyproject.toml index 2fd11df1bf4..caeb4bf7f83 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -481,6 +481,7 @@ files = [ mypy_path = [ "src", ] +python_version = "3.8" check_untyped_defs = true disallow_any_generics = true disallow_untyped_defs = true From f92597c664a6caec8b09703eb341af24307466be Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sun, 13 Oct 2024 14:13:51 +0200 Subject: [PATCH 0907/1271] Fix pdb selftests on Python 3.13 Python 3.13 makes pdb break on the breakpoint() call, rather than on the next line: https://docs.python.org/3/whatsnew/3.13.html#pdb Also runs the pdb tests on Python 3.13 in CI. See #12884 for a more proper solution for that. Fixes #12497 --- .github/workflows/test.yml | 2 +- changelog/12497.contrib.rst | 1 + testing/test_debugging.py | 16 ++++++++++++---- 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 changelog/12497.contrib.rst diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8e66f5eae5c..ff5b18e2fca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -147,7 +147,7 @@ jobs: - name: "ubuntu-py313" python: "3.13-dev" os: ubuntu-latest - tox_env: "py313" + tox_env: "py313-pexpect" use_coverage: true - name: "ubuntu-pypy3" python: "pypy-3.9" diff --git a/changelog/12497.contrib.rst b/changelog/12497.contrib.rst new file mode 100644 index 00000000000..ccf89731053 --- /dev/null +++ b/changelog/12497.contrib.rst @@ -0,0 +1 @@ +Fixed two failing pdb-related tests on Python 3.13. diff --git a/testing/test_debugging.py b/testing/test_debugging.py index d86c9018b80..9588da8936f 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -771,9 +771,13 @@ def test_pdb_used_outside_test(self, pytester: Pytester) -> None: x = 5 """ ) + if sys.version_info[:2] >= (3, 13): + break_line = "pytest.set_trace()" + else: + break_line = "x = 5" child = pytester.spawn(f"{sys.executable} {p1}") - child.expect("x = 5") - child.expect("Pdb") + child.expect_exact(break_line) + child.expect_exact("Pdb") child.sendeof() self.flush(child) @@ -788,9 +792,13 @@ def test_foo(a): pass """ ) + if sys.version_info[:2] >= (3, 13): + break_line = "pytest.set_trace()" + else: + break_line = "x = 5" child = pytester.spawn_pytest(str(p1)) - child.expect("x = 5") - child.expect("Pdb") + child.expect_exact(break_line) + child.expect_exact("Pdb") child.sendeof() self.flush(child) From b1ad6d3793fd3b560effe7c0034f55091640208b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 13 Oct 2024 17:42:25 +0200 Subject: [PATCH 0908/1271] [automated] Update plugin list (#12881) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 128 +++++++++++++++++-------------- 1 file changed, 72 insertions(+), 56 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index e09656e3a61..45a6f5fb2ba 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,14 +27,14 @@ please refer to `the update script =8.3 + :pypi:`databricks-labs-pytester` Python Testing for Databricks Oct 11, 2024 4 - Beta pytest>=8.3 :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 @@ -137,7 +137,7 @@ This list contains 1529 plugins. :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 24, 2024 4 - Beta pytest :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A - :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Jul 30, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Oct 07, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest @@ -150,14 +150,14 @@ This list contains 1529 plugins. :pypi:`pytest-bazel` A pytest runner with bazel support Sep 27, 2024 4 - Beta pytest :pypi:`pytest-bdd` BDD for pytest Sep 26, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) - :pypi:`pytest-bdd-ng` BDD for pytest Sep 01, 2024 4 - Beta pytest>=5.0 + :pypi:`pytest-bdd-ng` BDD for pytest Oct 07, 2024 4 - Beta pytest>=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 26, 2024 N/A pytest>=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 02, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 11, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -247,14 +247,14 @@ This list contains 1529 plugins. :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Aug 15, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Oct 08, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Aug 16, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Oct 12, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) @@ -301,13 +301,14 @@ This list contains 1529 plugins. :pypi:`pytest-cqase` Custom qase pytest plugin Aug 22, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) + :pypi:`pytest-cratedb` Manage CrateDB instances for integration tests Oct 08, 2024 4 - Beta pytest<9 :pypi:`pytest-crayons` A pytest plugin for colorful print statements Oct 08, 2023 N/A pytest :pypi:`pytest-create` pytest-create Feb 15, 2023 1 - Planning N/A :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest :pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A :pypi:`pytest-csv` CSV output for pytest. Apr 22, 2021 N/A pytest (>=6.0) :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Jul 01, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) - :pypi:`pytest-curio` Pytest support for curio. Oct 07, 2020 N/A N/A + :pypi:`pytest-curio` Pytest support for curio. Oct 06, 2024 N/A pytest :pypi:`pytest-curl-report` pytest plugin to generate curl command line report Dec 11, 2016 4 - Beta N/A :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A :pypi:`pytest-custom-exit-code` Exit pytest test session with custom exit code in different scenarios Aug 07, 2019 4 - Beta pytest (>=4.0.2) @@ -500,7 +501,7 @@ This list contains 1529 plugins. :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Aug 13, 2024 4 - Beta pytest>=7 :pypi:`pytest-exasol-backend` Sep 18, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-extension` Sep 18, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-extension` Oct 10, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-slc` Sep 24, 2024 N/A pytest<9,>=7 @@ -545,7 +546,7 @@ This list contains 1529 plugins. :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) - :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Jul 31, 2024 N/A N/A + :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Oct 10, 2024 N/A N/A :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A :pypi:`pytest-file` Pytest File Mar 18, 2024 1 - Planning N/A @@ -600,7 +601,7 @@ This list contains 1529 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Oct 03, 2024 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Oct 11, 2024 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A @@ -659,7 +660,7 @@ This list contains 1529 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Oct 05, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Oct 12, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -711,8 +712,8 @@ This list contains 1529 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :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 19, 2024 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Jul 22, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Oct 10, 2024 5 - Production/Stable pytest + :pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 10, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Aug 20, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A @@ -750,7 +751,7 @@ This list contains 1529 plugins. :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-json` Generate JSON test reports Jan 18, 2016 4 - Beta N/A - :pypi:`pytest-json-ctrf` Pytest plugin to generate json report in CTRF (Common Test Report Format) Aug 17, 2024 N/A pytest>6.0.0 + :pypi:`pytest-json-ctrf` Pytest plugin to generate json report in CTRF (Common Test Report Format) Oct 10, 2024 N/A pytest>6.0.0 :pypi:`pytest-json-fixtures` JSON output for the --fixtures flag Mar 14, 2023 4 - Beta N/A :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) @@ -803,7 +804,7 @@ This list contains 1529 plugins. :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 May 19, 2024 5 - Production/Stable pytest - :pypi:`pytest-localserver` pytest plugin to test server connections locally. Aug 17, 2024 4 - Beta N/A + :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 06, 2024 4 - Beta N/A :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lock` pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. Feb 03, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-lockable` lockable resource plugin for pytest Jan 24, 2024 5 - Production/Stable pytest @@ -843,7 +844,7 @@ This list contains 1529 plugins. :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. May 18, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 - :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Aug 27, 2024 N/A pytest>=7.4.3 + :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Oct 08, 2024 N/A pytest>=7.4.3 :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 @@ -939,7 +940,7 @@ This list contains 1529 plugins. :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-odoo` py.test plugin to run Odoo tests Sep 20, 2024 4 - Beta pytest<8.0.0,>=7.2.0 + :pypi:`pytest-odoo` py.test plugin to run Odoo tests Oct 08, 2024 5 - Production/Stable pytest>=8 :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) @@ -956,6 +957,7 @@ This list contains 1529 plugins. :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 Aug 22, 2024 5 - Production/Stable pytest>=5.0; python_version < "3.10" + :pypi:`pytest-ordered` Declare the order in which tests should run in your pytest.ini Oct 07, 2024 N/A pytest>=6.2.0 :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 @@ -1065,10 +1067,10 @@ This list contains 1529 plugins. :pypi:`pytest-pusher` pytest plugin for push report to minio Jan 06, 2023 5 - Production/Stable pytest (>=3.6) :pypi:`pytest-py125` Dec 03, 2022 N/A N/A :pypi:`pytest-pycharm` Plugin for py.test to enter PyCharm debugger on uncaught exceptions Aug 13, 2020 5 - Production/Stable pytest (>=2.3) - :pypi:`pytest-pycodestyle` pytest plugin to run pycodestyle Oct 28, 2022 3 - Alpha N/A + :pypi:`pytest-pycodestyle` pytest plugin to run pycodestyle Oct 10, 2024 3 - Alpha pytest>=7.0 :pypi:`pytest-pydantic-schema-sync` Pytest plugin to synchronise Pydantic model schemas with JSONSchema files Aug 29, 2024 N/A pytest>=6 :pypi:`pytest-pydev` py.test plugin to connect to a remote debug server with PyDev or PyCharm. Nov 15, 2017 3 - Alpha N/A - :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Jan 05, 2023 3 - Alpha N/A + :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Oct 09, 2024 3 - Alpha pytest>=7.0 :pypi:`pytest-pylint` pytest plugin to check source code with pylint Oct 06, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Jul 23, 2024 N/A pytest @@ -1144,7 +1146,7 @@ This list contains 1529 plugins. :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest - :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Aug 08, 2024 4 - Beta N/A + :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) @@ -1217,7 +1219,7 @@ This list contains 1529 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 07, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1228,7 +1230,7 @@ This list contains 1529 plugins. :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 Feb 01, 2024 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. Oct 04, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 07, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1495,7 +1497,7 @@ This list contains 1529 plugins. :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest - :pypi:`pytest-vtestify` A pytest plugin for visual assertion using SSIM and image comparison. Oct 03, 2024 N/A pytest + :pypi:`pytest-vtestify` A pytest plugin for visual assertion using SSIM and image comparison. Oct 10, 2024 N/A pytest :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Jun 01, 2023 N/A pytest (>=7.0.0) :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A @@ -1527,7 +1529,7 @@ This list contains 1529 plugins. :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A - :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 04, 2024 4 - Beta pytest>=8.2.1 + :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 08, 2024 4 - Beta pytest>=8.2.1 :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Aug 07, 2024 N/A pytest~=8.2.2 @@ -1556,7 +1558,7 @@ This list contains 1529 plugins. :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) - :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Sep 23, 2024 N/A pytest + :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Oct 08, 2024 N/A pytest :pypi:`pytest-zephyr-telegram` Плагин для отправки данных автотестов в Телеграм и Зефир Sep 30, 2024 N/A pytest==8.3.2 :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A @@ -1569,7 +1571,7 @@ This list contains 1529 plugins. :pypi:`databricks-labs-pytester` - *last release*: Sep 24, 2024, + *last release*: Oct 11, 2024, *status*: 4 - Beta, *requires*: pytest>=8.3 @@ -2290,7 +2292,7 @@ This list contains 1529 plugins. Protect your AWS credentials in unit tests :pypi:`pytest-aws-fixtures` - *last release*: Jul 30, 2024, + *last release*: Oct 07, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -2381,7 +2383,7 @@ This list contains 1529 plugins. pytest plugin to display BDD info in HTML test report :pypi:`pytest-bdd-ng` - *last release*: Sep 01, 2024, + *last release*: Oct 07, 2024, *status*: 4 - Beta, *requires*: pytest>=5.0 @@ -2430,7 +2432,7 @@ This list contains 1529 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Oct 02, 2024, + *last release*: Oct 11, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3060,7 +3062,7 @@ This list contains 1529 plugins. A cleanup plugin for pytest :pypi:`pytest-clerk` - *last release*: Aug 15, 2024, + *last release*: Oct 08, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -3109,7 +3111,7 @@ This list contains 1529 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Aug 16, 2024, + *last release*: Oct 12, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3437,6 +3439,13 @@ This list contains 1529 plugins. Manages CrateDB instances during your integration tests + :pypi:`pytest-cratedb` + *last release*: Oct 08, 2024, + *status*: 4 - Beta, + *requires*: pytest<9 + + Manage CrateDB instances for integration tests + :pypi:`pytest-crayons` *last release*: Oct 08, 2023, *status*: N/A, @@ -3480,9 +3489,9 @@ This list contains 1529 plugins. Pytest plugin for Test Case Parametrization with CSV files :pypi:`pytest-curio` - *last release*: Oct 07, 2020, + *last release*: Oct 06, 2024, *status*: N/A, - *requires*: N/A + *requires*: pytest Pytest support for curio. @@ -4831,7 +4840,7 @@ This list contains 1529 plugins. :pypi:`pytest-exasol-extension` - *last release*: Sep 18, 2024, + *last release*: Oct 10, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -5146,7 +5155,7 @@ This list contains 1529 plugins. py.test plugin that activates the fault handler module for tests (dummy package) :pypi:`pytest-fauna` - *last release*: Jul 31, 2024, + *last release*: Oct 10, 2024, *status*: N/A, *requires*: N/A @@ -5531,7 +5540,7 @@ This list contains 1529 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Oct 03, 2024, + *last release*: Oct 11, 2024, *status*: N/A, *requires*: pytest @@ -5944,7 +5953,7 @@ This list contains 1529 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Oct 05, 2024, + *last release*: Oct 12, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6308,14 +6317,14 @@ This list contains 1529 plugins. A pytest plugin for writing inline tests. :pypi:`pytest-inmanta` - *last release*: Aug 19, 2024, + *last release*: Oct 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Jul 22, 2024, + *last release*: Oct 10, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6581,7 +6590,7 @@ This list contains 1529 plugins. Generate JSON test reports :pypi:`pytest-json-ctrf` - *last release*: Aug 17, 2024, + *last release*: Oct 10, 2024, *status*: N/A, *requires*: pytest>6.0.0 @@ -6952,7 +6961,7 @@ This list contains 1529 plugins. A PyTest plugin which provides an FTP fixture for your tests :pypi:`pytest-localserver` - *last release*: Aug 17, 2024, + *last release*: Oct 06, 2024, *status*: 4 - Beta, *requires*: N/A @@ -7232,7 +7241,7 @@ This list contains 1529 plugins. A pytest plugin to generate test outcomes reports with markdown table format. :pypi:`pytest-meilisearch` - *last release*: Aug 27, 2024, + *last release*: Oct 08, 2024, *status*: N/A, *requires*: pytest>=7.4.3 @@ -7904,9 +7913,9 @@ This list contains 1529 plugins. A pytest plugin for simplifying ODC database tests :pypi:`pytest-odoo` - *last release*: Sep 20, 2024, - *status*: 4 - Beta, - *requires*: pytest<8.0.0,>=7.2.0 + *last release*: Oct 08, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=8 py.test plugin to run Odoo tests @@ -8022,6 +8031,13 @@ This list contains 1529 plugins. pytest plugin to run your tests in a specific order + :pypi:`pytest-ordered` + *last release*: Oct 07, 2024, + *status*: N/A, + *requires*: pytest>=6.2.0 + + Declare the order in which tests should run in your pytest.ini + :pypi:`pytest-ordering` *last release*: Nov 14, 2018, *status*: 4 - Beta, @@ -8786,9 +8802,9 @@ This list contains 1529 plugins. Plugin for py.test to enter PyCharm debugger on uncaught exceptions :pypi:`pytest-pycodestyle` - *last release*: Oct 28, 2022, + *last release*: Oct 10, 2024, *status*: 3 - Alpha, - *requires*: N/A + *requires*: pytest>=7.0 pytest plugin to run pycodestyle @@ -8807,9 +8823,9 @@ This list contains 1529 plugins. py.test plugin to connect to a remote debug server with PyDev or PyCharm. :pypi:`pytest-pydocstyle` - *last release*: Jan 05, 2023, + *last release*: Oct 09, 2024, *status*: 3 - Alpha, - *requires*: N/A + *requires*: pytest>=7.0 pytest plugin to run pydocstyle @@ -9339,7 +9355,7 @@ This list contains 1529 plugins. Generate Pytest reports with templates :pypi:`pytest-reporter-html1` - *last release*: Aug 08, 2024, + *last release*: Oct 11, 2024, *status*: 4 - Beta, *requires*: N/A @@ -9850,7 +9866,7 @@ This list contains 1529 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Oct 04, 2024, + *last release*: Oct 07, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9927,7 +9943,7 @@ This list contains 1529 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Oct 04, 2024, + *last release*: Oct 07, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -11796,7 +11812,7 @@ This list contains 1529 plugins. A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. :pypi:`pytest-vtestify` - *last release*: Oct 03, 2024, + *last release*: Oct 10, 2024, *status*: N/A, *requires*: pytest @@ -12020,7 +12036,7 @@ This list contains 1529 plugins. Pytest fixtures providing data read from function, module or package related (x)files. :pypi:`pytest-xflaky` - *last release*: Oct 04, 2024, + *last release*: Oct 08, 2024, *status*: 4 - Beta, *requires*: pytest>=8.2.1 @@ -12223,7 +12239,7 @@ This list contains 1529 plugins. Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. :pypi:`pytest-zephyr-scale-integration` - *last release*: Sep 23, 2024, + *last release*: Oct 08, 2024, *status*: N/A, *requires*: pytest From d8d607e937bf5a36815007322bf10239f3330475 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 13 Oct 2024 15:33:56 -0300 Subject: [PATCH 0909/1271] Improve pytest.Config.getoption docstring (#12886) Closes #10558. --------- Co-authored-by: suspe --- AUTHORS | 1 + changelog/10558.doc.rst | 1 + src/_pytest/config/__init__.py | 9 +++++---- testing/test_config.py | 20 +++++++++++++------- 4 files changed, 20 insertions(+), 11 deletions(-) create mode 100644 changelog/10558.doc.rst diff --git a/AUTHORS b/AUTHORS index 69089354a44..c38f74d9980 100644 --- a/AUTHORS +++ b/AUTHORS @@ -118,6 +118,7 @@ Dave Hunt David Díaz-Barquero David Mohr David Paul Röthlisberger +David Peled David Szotten David Vierra Daw-Ran Liou diff --git a/changelog/10558.doc.rst b/changelog/10558.doc.rst new file mode 100644 index 00000000000..1c242b9cf71 --- /dev/null +++ b/changelog/10558.doc.rst @@ -0,0 +1 @@ +Fix ambiguous docstring of :func:`pytest.Config.getoption`. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index c53661dbeb5..35ab622de31 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1697,11 +1697,12 @@ def _get_override_ini_value(self, name: str) -> str | None: def getoption(self, name: str, default=notset, skip: bool = False): """Return command line option value. - :param name: Name of the option. You may also specify + :param name: Name of the option. You may also specify the literal ``--OPT`` option instead of the "dest" option name. - :param default: Default value if no option of that name exists. - :param skip: If True, raise pytest.skip if option does not exists - or has a None value. + :param default: Fallback value if no option of that name is **declared** via :hook:`pytest_addoption`. + Note this parameter will be ignored when the option is **declared** even if the option's value is ``None``. + :param skip: If ``True``, raise :func:`pytest.skip` if option is undeclared or has a ``None`` value. + Note that even if ``True``, if a default was specified it will be returned instead of a skip. """ name = self._opt2dest.get(name, name) try: diff --git a/testing/test_config.py b/testing/test_config.py index 3f5f884ef7a..13ba66e8f9d 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -636,7 +636,7 @@ def test_config_trace(self, pytester: Pytester) -> None: assert len(values) == 1 assert values[0] == "hello [config]\n" - def test_config_getoption(self, pytester: Pytester) -> None: + def test_config_getoption_declared_option_name(self, pytester: Pytester) -> None: pytester.makeconftest( """ def pytest_addoption(parser): @@ -648,6 +648,18 @@ def pytest_addoption(parser): assert config.getoption(x) == "this" pytest.raises(ValueError, config.getoption, "qweqwe") + config_novalue = pytester.parseconfig() + assert config_novalue.getoption("hello") is None + assert config_novalue.getoption("hello", default=1) is None + assert config_novalue.getoption("hello", default=1, skip=True) == 1 + + def test_config_getoption_undeclared_option_name(self, pytester: Pytester) -> None: + config = pytester.parseconfig() + with pytest.raises(ValueError): + config.getoption("x") + assert config.getoption("x", default=1) == 1 + assert config.getoption("x", default=1, skip=True) == 1 + def test_config_getoption_unicode(self, pytester: Pytester) -> None: pytester.makeconftest( """ @@ -675,12 +687,6 @@ def pytest_addoption(parser): with pytest.raises(pytest.skip.Exception): config.getvalueorskip("hello") - def test_getoption(self, pytester: Pytester) -> None: - config = pytester.parseconfig() - with pytest.raises(ValueError): - config.getvalue("x") - assert config.getoption("x", 1) == 1 - def test_getconftest_pathlist(self, pytester: Pytester, tmp_path: Path) -> None: somepath = tmp_path.joinpath("x", "y", "z") p = tmp_path.joinpath("conftest.py") From 8c894f5120360edc5a35940bcd7f93d112959dca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 09:20:50 +0200 Subject: [PATCH 0910/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#12891) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 4.6.0 to 4.6.2. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.6.0...4.6.2) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 9ee706fdc70..98623b7ce22 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==4.6.0 +anyio[curio,trio]==4.6.2 django==5.1.1 pytest-asyncio==0.24.0 pytest-bdd==7.3.0 From b90c7825d7f047309c1abd7b299fc1e8c68ecec3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 07:33:24 +0000 Subject: [PATCH 0911/1271] build(deps): Bump django in /testing/plugins_integration (#12890) Bumps [django](https://github.com/django/django) from 5.1.1 to 5.1.2. - [Commits](https://github.com/django/django/compare/5.1.1...5.1.2) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Co-authored-by: Pierre Sassoulas --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 98623b7ce22..c154149652c 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.6.2 -django==5.1.1 +django==5.1.2 pytest-asyncio==0.24.0 pytest-bdd==7.3.0 pytest-cov==5.0.0 From 9cc6b501c07e1f1e7f9b72b0bd3fc0fc786a6335 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 22:45:35 -0300 Subject: [PATCH 0912/1271] [pre-commit.ci] pre-commit autoupdate (#12893) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/tox-dev/pyproject-fmt: 2.2.4 → 2.3.1](https://github.com/tox-dev/pyproject-fmt/compare/2.2.4...2.3.1) - [github.com/asottile/pyupgrade: v3.17.0 → v3.18.0](https://github.com/asottile/pyupgrade/compare/v3.17.0...v3.18.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c0d7750cf43..096228acf9f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -44,13 +44,13 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "2.2.4" + rev: "2.3.1" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version additional_dependencies: ["tox>=4.9"] - repo: https://github.com/asottile/pyupgrade - rev: v3.17.0 + rev: v3.18.0 hooks: - id: pyupgrade stages: [manual] From 931f87c9f58d797ea28bbf45ae78636d26e23e21 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:52:28 +0000 Subject: [PATCH 0913/1271] [automated] Update plugin list (#12903) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 182 +++++++++++++++++-------------- 1 file changed, 99 insertions(+), 83 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 45a6f5fb2ba..e5bd2f8805b 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 :pypi:`pytest-bazel` A pytest runner with bazel support Sep 27, 2024 4 - Beta pytest - :pypi:`pytest-bdd` BDD for pytest Sep 26, 2024 6 - Mature pytest>=6.2.0 + :pypi:`pytest-bdd` BDD for pytest Oct 15, 2024 6 - Mature pytest>=6.2.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Oct 07, 2024 4 - Beta pytest>=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 26, 2024 N/A pytest>=7.1.3 @@ -157,7 +157,7 @@ This list contains 1531 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 11, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 18, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -254,7 +254,7 @@ This list contains 1531 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Oct 12, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Oct 16, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) @@ -294,7 +294,7 @@ This list contains 1531 plugins. :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Sep 30, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Oct 15, 2024 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Sep 18, 2024 5 - Production/Stable pytest @@ -360,7 +360,7 @@ This list contains 1531 plugins. :pypi:`pytest-describe` Describe-style plugin for pytest Feb 10, 2024 5 - Production/Stable pytest <9,>=4.6 :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest :pypi:`pytest-deselect-if` A plugin to deselect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-devpi-server` DevPI server fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-devpi-server` DevPI server fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-dhos` Common fixtures for pytest in DHOS services and libraries Sep 07, 2022 N/A N/A :pypi:`pytest-diamond` pytest plugin for diamond Aug 31, 2015 4 - Beta N/A :pypi:`pytest-dicom` pytest plugin to provide DICOM fixtures Dec 19, 2018 3 - Alpha pytest @@ -465,14 +465,14 @@ This list contains 1531 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 Jul 25, 2024 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. Aug 19, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Aug 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Aug 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Aug 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Aug 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Aug 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Aug 19, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Aug 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Oct 18, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Oct 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Oct 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Oct 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Oct 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Oct 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Oct 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Oct 18, 2024 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) @@ -546,7 +546,7 @@ This list contains 1531 plugins. :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) - :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Oct 10, 2024 N/A N/A + :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Oct 17, 2024 N/A N/A :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A :pypi:`pytest-file` Pytest File Mar 18, 2024 1 - Planning N/A @@ -561,7 +561,7 @@ This list contains 1531 plugins. :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Feb 22, 2024 4 - Beta pytest >=3.5.0 - :pypi:`pytest-fixture-config` Fixture configuration utils for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-fixture-config` Fixture configuration utils for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-fixture-maker` Pytest plugin to load fixtures from YAML files Sep 21, 2021 N/A N/A :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A :pypi:`pytest-fixture-order` pytest plugin to control fixture evaluation order May 16, 2022 5 - Production/Stable pytest (>=3.0) @@ -617,7 +617,7 @@ This list contains 1531 plugins. :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. Jul 08, 2024 N/A pytest>=3.6 - :pypi:`pytest-git` Git repository fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 4 - Beta pytest>=7.1.2 :pypi:`pytest-gitcov` Pytest plugin for reporting on coverage of the last git commit. Jan 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-git-diff` Pytest plugin that allows the user to select the tests affected by a range of git commits Apr 02, 2024 N/A N/A @@ -626,7 +626,7 @@ This list contains 1531 plugins. :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A - :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Sep 25, 2024 N/A N/A + :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Oct 16, 2024 N/A N/A :pypi:`pytest-gitlabci-parallelized` Parallelize pytest across GitLab CI workers. Mar 08, 2023 N/A N/A :pypi:`pytest-gitlab-code-quality` Collects warnings while testing and generates a GitLab Code Quality Report. Sep 09, 2024 N/A pytest>=8.1.1 :pypi:`pytest-gitlab-fold` Folds output sections in GitLab CI build log Dec 31, 2023 4 - Beta pytest >=2.6.0 @@ -660,7 +660,7 @@ This list contains 1531 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Oct 12, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Oct 19, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -704,6 +704,7 @@ This list contains 1531 plugins. :pypi:`pytest-import-check` pytest plugin to check whether Python modules can be imported Jul 19, 2024 3 - Alpha pytest>=8.1 :pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A :pypi:`pytest-infinity` Jun 09, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-influx` Pytest plugin for managing your influx instance between test runs Oct 16, 2024 N/A pytest<9.0.0,>=8.3.3 :pypi:`pytest-influxdb` Plugin for influxdb and pytest integration. Apr 20, 2021 N/A N/A :pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A @@ -731,7 +732,7 @@ This list contains 1531 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Aug 30, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Oct 15, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Sep 18, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) @@ -798,7 +799,7 @@ This list contains 1531 plugins. :pypi:`pytest-line-profiler` Profile code executed by pytest Aug 10, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-line-profiler-apn` Profile code executed by pytest Dec 05, 2022 N/A pytest (>=3.5.0) :pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-listener` A simple network listener May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-listener` A simple network listener Oct 17, 2024 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. Nov 23, 2023 4 - Beta pytest >=6.1 :pypi:`pytest-live` Live results for pytest Mar 08, 2020 N/A pytest @@ -820,9 +821,10 @@ This list contains 1531 plugins. :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-loop` pytest plugin for looping tests Mar 30, 2024 5 - Production/Stable pytest + :pypi:`pytest-loop` pytest plugin for looping tests Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Sep 04, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 + :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Oct 18, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 05, 2024 N/A pytest (>=7.0.0) @@ -986,7 +988,7 @@ This list contains 1531 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 Jun 14, 2024 4 - Beta N/A + :pypi:`pytest-patterns` pytest plugin to make testing complicated long string output easy to write and easy to debug Oct 19, 2024 4 - Beta pytest>=6 :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 @@ -1050,7 +1052,7 @@ This list contains 1531 plugins. :pypi:`pytest-priority` pytest plugin for add priority for tests Aug 19, 2024 N/A pytest :pypi:`pytest-proceed` Oct 01, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) - :pypi:`pytest-profiling` Profiling plugin for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-profiling` Profiling plugin for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-progress` pytest plugin for instant test progress status Jun 18, 2024 5 - Production/Stable pytest>=2.7 :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest @@ -1079,7 +1081,7 @@ This list contains 1531 plugins. :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest - :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report May 05, 2024 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Jan 26, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Aug 17, 2024 N/A pytest<9.0.0,>=8.3.2 @@ -1099,11 +1101,11 @@ This list contains 1531 plugins. :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 Feb 07, 2024 5 - Production/Stable pytest - :pypi:`pytest-qt-app` QT app fixture for py.test Dec 23, 2015 5 - Production/Stable N/A + :pypi:`pytest-qt-app` QT app fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-quarantine` A plugin for pytest to manage expected test failures Nov 24, 2019 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-quickcheck` pytest plugin to generate random data inspired by QuickCheck Nov 05, 2022 4 - Beta pytest (>=4.0) :pypi:`pytest_quickify` Run test suites with pytest-quickify. Jun 14, 2019 N/A pytest - :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest May 08, 2024 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-rabbitmq` RabbitMQ process and client fixtures for pytest Oct 15, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-race` Race conditions tester for pytest Jun 07, 2022 4 - Beta N/A :pypi:`pytest-rage` pytest plugin to implement PEP712 Oct 21, 2011 3 - Alpha N/A :pypi:`pytest-rail` pytest plugin for creating TestRail runs and adding results May 02, 2022 N/A pytest (>=3.6) @@ -1131,7 +1133,7 @@ This list contains 1531 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 - :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Oct 05, 2024 N/A pytest>7.2 + :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Oct 17, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relative-path` Handle relative path in pytest options or ini configs Aug 30, 2024 N/A pytest :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Mar 29, 2024 5 - Production/Stable pytest>=7 @@ -1193,7 +1195,7 @@ This list contains 1531 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Sep 24, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Oct 15, 2024 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1238,7 +1240,7 @@ This list contains 1531 plugins. :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Apr 25, 2024 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A - :pypi:`pytest-server-fixtures` Extensible server fixures for py.test Dec 19, 2023 5 - Production/Stable pytest + :pypi:`pytest-server-fixtures` Extensible server fixtures for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A :pypi:`pytest-servers` pytest servers Sep 17, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-service` Aug 06, 2024 5 - Production/Stable pytest>=6.0.0 @@ -1253,11 +1255,11 @@ This list contains 1531 plugins. :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A - :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Aug 26, 2024 5 - Production/Stable pytest>=7.4.0 + :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Oct 18, 2024 5 - Production/Stable pytest>=7.4.0 :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-simbind` Pytest plugin to operate with objects generated by Simbind tool. Mar 28, 2024 N/A pytest>=7.0.0 :pypi:`pytest-simplehttpserver` Simple pytest fixture to spin up an HTTP server Jun 24, 2021 4 - Beta N/A :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A @@ -1304,7 +1306,7 @@ This list contains 1531 plugins. :pypi:`pytest-spiratest` Exports unit tests as test runs in Spira (SpiraTest/Team/Plan) Jan 01, 2024 N/A N/A :pypi:`pytest-splinter` Splinter plugin for pytest testing framework Sep 09, 2022 6 - Mature pytest (>=3.0.0) :pypi:`pytest-splinter4` Pytest plugin for the splinter automation library Feb 01, 2024 6 - Mature pytest >=8.0.0 - :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Jun 19, 2024 4 - Beta pytest<9,>=5 + :pypi:`pytest-split` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Oct 16, 2024 4 - Beta pytest<9,>=5 :pypi:`pytest-split-ext` Pytest plugin which splits the test suite to equally sized sub suites based on test execution time. Sep 23, 2023 4 - Beta pytest (>=5,<8) :pypi:`pytest-splitio` Split.io SDK integration for e2e tests Sep 22, 2020 N/A pytest (<7,>=5.0) :pypi:`pytest-split-tests` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Forked from Mark Adams' original project pytest-test-groups. Jul 30, 2021 5 - Production/Stable pytest (>=2.5) @@ -1348,7 +1350,7 @@ This list contains 1531 plugins. :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A :pypi:`pytest-suite-timeout` A pytest plugin for ensuring max suite time Jan 26, 2024 N/A pytest>=7.0.0 :pypi:`pytest-supercov` Pytest plugin for measuring explicit test-file to source-file coverage Jul 02, 2023 N/A N/A - :pypi:`pytest-svn` SVN repository fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-svn` SVN repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A @@ -1489,9 +1491,9 @@ This list contains 1531 plugins. :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 Nov 23, 2023 4 - Beta pytest - :pypi:`pytest-verbose-parametrize` More descriptive output for parametrized py.test tests May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-verbose-parametrize` More descriptive output for parametrized py.test tests Oct 17, 2024 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 + :pypi:`pytest-virtualenv` Virtualenv fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-visual` Nov 01, 2023 3 - Alpha pytest >=7.0.0 :pypi:`pytest-vnc` VNC client for Pytest Nov 06, 2023 N/A pytest :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest @@ -1510,7 +1512,7 @@ This list contains 1531 plugins. :pypi:`pytest_wdb` Trace pytest tests with wdb to halt on error with --wdb. Jul 04, 2016 N/A N/A :pypi:`pytest-wdl` Pytest plugin for testing WDL workflows. Nov 17, 2020 5 - Production/Stable N/A :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest - :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test May 28, 2019 5 - Production/Stable pytest + :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-webstage` Test web apps with pytest Sep 20, 2024 N/A pytest<9.0,>=7.0 :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Oct 03, 2024 N/A pytest>=7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A @@ -1529,7 +1531,7 @@ This list contains 1531 plugins. :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A - :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 08, 2024 4 - Beta pytest>=8.2.1 + :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 14, 2024 4 - Beta pytest>=8.2.1 :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Aug 07, 2024 N/A pytest~=8.2.2 @@ -1550,7 +1552,7 @@ This list contains 1531 plugins. :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A - :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Mar 30, 2024 N/A pytest<8.0.0,>=7.2.2 + :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Oct 18, 2024 N/A pytest<9.0.0,>=8.3.3 :pypi:`pytest-youqu-playwright` pytest-youqu-playwright Jun 12, 2024 N/A pytest :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) @@ -1558,7 +1560,7 @@ This list contains 1531 plugins. :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) - :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Oct 08, 2024 N/A pytest + :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Oct 15, 2024 N/A pytest :pypi:`pytest-zephyr-telegram` Плагин для отправки данных автотестов в Телеграм и Зефир Sep 30, 2024 N/A pytest==8.3.2 :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A @@ -2369,7 +2371,7 @@ This list contains 1531 plugins. A pytest runner with bazel support :pypi:`pytest-bdd` - *last release*: Sep 26, 2024, + *last release*: Oct 15, 2024, *status*: 6 - Mature, *requires*: pytest>=6.2.0 @@ -2432,7 +2434,7 @@ This list contains 1531 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Oct 11, 2024, + *last release*: Oct 18, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3111,7 +3113,7 @@ This list contains 1531 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Oct 12, 2024, + *last release*: Oct 16, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3391,7 +3393,7 @@ This list contains 1531 plugins. Coverage dynamic context support for PyTest, including sub-processes :pypi:`pytest-coveragemarkers` - *last release*: Sep 30, 2024, + *last release*: Oct 15, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -3853,7 +3855,7 @@ This list contains 1531 plugins. A plugin to deselect pytests tests rather than using skipif :pypi:`pytest-devpi-server` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -4588,56 +4590,56 @@ This list contains 1531 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Aug 19, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Aug 19, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Aug 19, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Aug 19, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Aug 19, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Aug 19, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Aug 19, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Aug 19, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5155,7 +5157,7 @@ This list contains 1531 plugins. py.test plugin that activates the fault handler module for tests (dummy package) :pypi:`pytest-fauna` - *last release*: Oct 10, 2024, + *last release*: Oct 17, 2024, *status*: N/A, *requires*: N/A @@ -5260,7 +5262,7 @@ This list contains 1531 plugins. A pytest plugin to collect tests based on fixtures being used by tests :pypi:`pytest-fixture-config` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -5652,7 +5654,7 @@ This list contains 1531 plugins. A set of pytest fixtures for testing Girder applications. :pypi:`pytest-git` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -5715,7 +5717,7 @@ This list contains 1531 plugins. py.test plugin to ignore the same files as git :pypi:`pytest-gitlab` - *last release*: Sep 25, 2024, + *last release*: Oct 16, 2024, *status*: N/A, *requires*: N/A @@ -5953,7 +5955,7 @@ This list contains 1531 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Oct 12, 2024, + *last release*: Oct 19, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6260,6 +6262,13 @@ This list contains 1531 plugins. + :pypi:`pytest-influx` + *last release*: Oct 16, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.3.3 + + Pytest plugin for managing your influx instance between test runs + :pypi:`pytest-influxdb` *last release*: Apr 20, 2021, *status*: N/A, @@ -6450,7 +6459,7 @@ This list contains 1531 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Aug 30, 2024, + *last release*: Oct 15, 2024, *status*: N/A, *requires*: pytest @@ -6919,7 +6928,7 @@ This list contains 1531 plugins. Pytest plugin for organizing tests. :pypi:`pytest-listener` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -7073,7 +7082,7 @@ This list contains 1531 plugins. Pytest Loguru :pypi:`pytest-loop` - *last release*: Mar 30, 2024, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -7093,6 +7102,13 @@ This list contains 1531 plugins. pytest marker for marking manual tests + :pypi:`pytest-mark-count` + *last release*: Oct 18, 2024, + *status*: 4 - Beta, + *requires*: pytest>=8.0.0 + + Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers + :pypi:`pytest-markdoctest` *last release*: Jul 22, 2022, *status*: 4 - Beta, @@ -8235,9 +8251,9 @@ This list contains 1531 plugins. A contextmanager pytest fixture for handling multiple mock patches :pypi:`pytest-patterns` - *last release*: Jun 14, 2024, + *last release*: Oct 19, 2024, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest>=6 pytest plugin to make testing complicated long string output easy to write and easy to debug @@ -8683,7 +8699,7 @@ This list contains 1531 plugins. pytest plugin for configuration profiles :pypi:`pytest-profiling` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -8886,7 +8902,7 @@ This list contains 1531 plugins. pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite :pypi:`pytest-pyramid-server` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -9026,9 +9042,9 @@ This list contains 1531 plugins. pytest support for PyQt and PySide applications :pypi:`pytest-qt-app` - *last release*: Dec 23, 2015, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest QT app fixture for py.test @@ -9054,7 +9070,7 @@ This list contains 1531 plugins. Run test suites with pytest-quickify. :pypi:`pytest-rabbitmq` - *last release*: May 08, 2024, + *last release*: Oct 15, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.2 @@ -9250,7 +9266,7 @@ This list contains 1531 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Oct 05, 2024, + *last release*: Oct 17, 2024, *status*: N/A, *requires*: pytest>7.2 @@ -9684,7 +9700,7 @@ This list contains 1531 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Sep 24, 2024, + *last release*: Oct 15, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -9999,11 +10015,11 @@ This list contains 1531 plugins. test server exec cmd :pypi:`pytest-server-fixtures` - *last release*: Dec 19, 2023, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest - Extensible server fixures for py.test + Extensible server fixtures for py.test :pypi:`pytest-serverless` *last release*: May 09, 2022, @@ -10104,7 +10120,7 @@ This list contains 1531 plugins. A pytest plugin to help with testing shell scripts / black box commands :pypi:`pytest-shell-utilities` - *last release*: Aug 26, 2024, + *last release*: Oct 18, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.4.0 @@ -10132,7 +10148,7 @@ This list contains 1531 plugins. Expand command-line shortcuts listed in pytest configuration :pypi:`pytest-shutil` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -10461,7 +10477,7 @@ This list contains 1531 plugins. Pytest plugin for the splinter automation library :pypi:`pytest-split` - *last release*: Jun 19, 2024, + *last release*: Oct 16, 2024, *status*: 4 - Beta, *requires*: pytest<9,>=5 @@ -10769,7 +10785,7 @@ This list contains 1531 plugins. Pytest plugin for measuring explicit test-file to source-file coverage :pypi:`pytest-svn` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -11756,7 +11772,7 @@ This list contains 1531 plugins. py.test fixture for creating a virtual environment :pypi:`pytest-verbose-parametrize` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -11770,7 +11786,7 @@ This list contains 1531 plugins. A simple pytest plugin that will shrink pytest output when specified, to fit vim quickfix window. :pypi:`pytest-virtualenv` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -11903,7 +11919,7 @@ This list contains 1531 plugins. A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. :pypi:`pytest-webdriver` - *last release*: May 28, 2019, + *last release*: Oct 17, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -12036,7 +12052,7 @@ This list contains 1531 plugins. Pytest fixtures providing data read from function, module or package related (x)files. :pypi:`pytest-xflaky` - *last release*: Oct 08, 2024, + *last release*: Oct 14, 2024, *status*: 4 - Beta, *requires*: pytest>=8.2.1 @@ -12183,9 +12199,9 @@ This list contains 1531 plugins. PyTest plugin to run tests concurrently, each \`yield\` switch context to other one :pypi:`pytest-yls` - *last release*: Mar 30, 2024, + *last release*: Oct 18, 2024, *status*: N/A, - *requires*: pytest<8.0.0,>=7.2.2 + *requires*: pytest<9.0.0,>=8.3.3 Pytest plugin to test the YLS as a whole. @@ -12239,7 +12255,7 @@ This list contains 1531 plugins. Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. :pypi:`pytest-zephyr-scale-integration` - *last release*: Oct 08, 2024, + *last release*: Oct 15, 2024, *status*: N/A, *requires*: pytest From 26215b8f795a2b13acc1a8827fdfb6a29b502a6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 09:21:43 +0200 Subject: [PATCH 0914/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#12905) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 4.6.2 to 4.6.2.post1. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.6.2...4.6.2.post1) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index c154149652c..d5ed74940d3 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==4.6.2 +anyio[curio,trio]==4.6.2.post1 django==5.1.2 pytest-asyncio==0.24.0 pytest-bdd==7.3.0 From 922d6841b0fe3dd1030f2ec4b816778a74a3bf84 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Wed, 23 Oct 2024 17:12:04 +0200 Subject: [PATCH 0915/1271] avoid test failing if the working path contains the string 'error' --- testing/python/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 46f0a762cbb..c939b221f22 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2996,7 +2996,7 @@ def test_finish(): *3 passed* """ ) - result.stdout.no_fnmatch_line("*error*") + assert result.ret == 0 def test_fixture_finalizer(self, pytester: Pytester) -> None: pytester.makeconftest( From 216ec3c0ba87b50af11a3fd6f633b69105a7708e Mon Sep 17 00:00:00 2001 From: jakkdl Date: Fri, 25 Oct 2024 13:36:55 +0200 Subject: [PATCH 0916/1271] Remove PytestReturnNotNoneWarning and PytestUnhandledCoroutineWarning. Make tests fail instead of raising warning/exception. fix tests. add changelog. --- src/_pytest/config/exceptions.py | 3 ++ src/_pytest/python.py | 48 +++++++++++--------------------- src/_pytest/warning_types.py | 18 ------------ src/pytest/__init__.py | 4 --- testing/acceptance_test.py | 12 ++++---- testing/test_unittest.py | 2 +- 6 files changed, 28 insertions(+), 59 deletions(-) diff --git a/src/_pytest/config/exceptions.py b/src/_pytest/config/exceptions.py index 147afb03e26..90108eca904 100644 --- a/src/_pytest/config/exceptions.py +++ b/src/_pytest/config/exceptions.py @@ -1,6 +1,9 @@ from __future__ import annotations +from typing import final + +@final class UsageError(Exception): """Error in pytest usage or invocation.""" diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 180ef439dd6..d48a6c4a9fb 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -51,7 +51,6 @@ from _pytest.config import Config from _pytest.config import hookimpl from _pytest.config.argparsing import Parser -from _pytest.config.exceptions import UsageError from _pytest.deprecated import check_ispytest from _pytest.fixtures import FixtureDef from _pytest.fixtures import FixtureRequest @@ -74,7 +73,6 @@ from _pytest.scope import Scope from _pytest.stash import StashKey from _pytest.warning_types import PytestCollectionWarning -from _pytest.warning_types import PytestReturnNotNoneWarning if TYPE_CHECKING: @@ -135,48 +133,36 @@ def pytest_configure(config: Config) -> None: ) -@final -class PytestUnhandledCoroutineError(UsageError): - """An unraisable exception resulted in an error. - - Unraisable exceptions are exceptions raised in :meth:`__del__ ` - implementations and similar situations when the exception cannot be raised - as normal. - """ - - -def async_warn_and_skip(nodeid: str) -> None: - msg = "async def functions are not natively supported and have been skipped.\n" - msg += ( +def async_fail(nodeid: str) -> None: + msg = ( + "async def functions are not natively supported.\n" "You need to install a suitable plugin for your async framework, for example:\n" + " - anyio\n" + " - pytest-asyncio\n" + " - pytest-tornasync\n" + " - pytest-trio\n" + " - pytest-twisted" ) - msg += " - anyio\n" - msg += " - pytest-asyncio\n" - msg += " - pytest-tornasync\n" - msg += " - pytest-trio\n" - msg += " - pytest-twisted" - raise PytestUnhandledCoroutineError( - msg.format(nodeid) - ) # TODO: This is the warning to look at - skip(reason="async def function and no async plugin installed (see warnings)") + fail(msg, pytrace=False) @hookimpl(trylast=True) def pytest_pyfunc_call(pyfuncitem: Function) -> object | None: testfunction = pyfuncitem.obj if is_async_function(testfunction): - async_warn_and_skip(pyfuncitem.nodeid) + async_fail(pyfuncitem.nodeid) funcargs = pyfuncitem.funcargs testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames} result = testfunction(**testargs) if hasattr(result, "__await__") or hasattr(result, "__aiter__"): - async_warn_and_skip(pyfuncitem.nodeid) + async_fail(pyfuncitem.nodeid) elif result is not None: - warnings.warn( - PytestReturnNotNoneWarning( - f"Expected None, but {pyfuncitem.nodeid} returned {result!r}, which will be an error in a " - "future version of pytest. Did you mean to use `assert` instead of `return`?" - ) + fail( + ( + f"Expected None, but test returned {result!r}. " + "Did you mean to use `assert` instead of `return`?" + ), + pytrace=False, ) return True diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index cf189a407c1..b8e9998cd2e 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -56,12 +56,6 @@ class PytestRemovedIn9Warning(PytestDeprecationWarning): __module__ = "pytest" -class PytestReturnNotNoneWarning(PytestWarning): - """Warning emitted when a test function is returning value other than None.""" - - __module__ = "pytest" - - @final class PytestExperimentalApiWarning(PytestWarning, FutureWarning): """Warning category used to denote experiments in pytest. @@ -77,18 +71,6 @@ def simple(cls, apiname: str) -> PytestExperimentalApiWarning: return cls(f"{apiname} is an experimental api that may change over time") -@final -class PytestUnhandledCoroutineWarning(PytestReturnNotNoneWarning): # TODO: look at this - """Warning emitted for an unhandled coroutine. - - A coroutine was encountered when collecting test functions, but was not - handled by any async-aware plugin. - Coroutine test functions are not natively supported. - """ - - __module__ = "pytest" - - @final class PytestUnknownMarkWarning(PytestWarning): """Warning emitted on use of unknown markers. diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 92152b7c7b4..5ab2a22b0c0 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -78,8 +78,6 @@ from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestExperimentalApiWarning from _pytest.warning_types import PytestRemovedIn9Warning -from _pytest.warning_types import PytestReturnNotNoneWarning -from _pytest.warning_types import PytestUnhandledCoroutineWarning from _pytest.warning_types import PytestUnhandledThreadExceptionWarning from _pytest.warning_types import PytestUnknownMarkWarning from _pytest.warning_types import PytestUnraisableExceptionWarning @@ -142,10 +140,8 @@ "PytestDeprecationWarning", "PytestExperimentalApiWarning", "PytestRemovedIn9Warning", - "PytestReturnNotNoneWarning", "Pytester", "PytestPluginManager", - "PytestUnhandledCoroutineWarning", "PytestUnhandledThreadExceptionWarning", "PytestUnknownMarkWarning", "PytestUnraisableExceptionWarning", diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 6d0537f092c..7a8d871144a 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1235,7 +1235,7 @@ def test_usage_error_code(pytester: Pytester) -> None: assert result.ret == ExitCode.USAGE_ERROR -def test_error_on_async_function(pytester: Pytester) -> None: # TODO: Change this +def test_error_on_async_function(pytester: Pytester) -> None: # In the below we .close() the coroutine only to avoid # "RuntimeWarning: coroutine 'test_2' was never awaited" # which messes with other tests. @@ -1254,16 +1254,16 @@ def test_3(): result = pytester.runpytest() result.stdout.fnmatch_lines( [ + "*async def functions are not natively supported*", "*test_async.py::test_1*", "*test_async.py::test_2*", "*test_async.py::test_3*", - "*async def functions are not natively supported*", ] ) result.assert_outcomes(failed=3) -def test_error_on_async_gen_function(pytester: Pytester) -> None: # TODO: Change this +def test_error_on_async_gen_function(pytester: Pytester) -> None: pytester.makepyfile( test_async=""" async def test_1(): @@ -1277,12 +1277,13 @@ def test_3(): result = pytester.runpytest() result.stdout.fnmatch_lines( [ + "*async def functions are not natively supported*", "*test_async.py::test_1*", "*test_async.py::test_2*", "*test_async.py::test_3*", - "*async def functions are not natively supported*", ] ) + result.assert_outcomes(failed=3) def test_pdb_can_be_rewritten(pytester: Pytester) -> None: @@ -1368,7 +1369,7 @@ def test_no_brokenpipeerror_message(pytester: Pytester) -> None: popen.stderr.close() -def test_function_return_non_none_warning(pytester: Pytester) -> None: +def test_function_return_non_none_error(pytester: Pytester) -> None: pytester.makepyfile( """ def test_stuff(): @@ -1376,6 +1377,7 @@ def test_stuff(): """ ) res = pytester.runpytest() + res.assert_outcomes(failed=1) res.stdout.fnmatch_lines(["*Did you mean to use `assert` instead of `return`?*"]) diff --git a/testing/test_unittest.py b/testing/test_unittest.py index 1f7b2f091c0..56224c08228 100644 --- a/testing/test_unittest.py +++ b/testing/test_unittest.py @@ -1314,7 +1314,7 @@ def test_1(self): assert tracked == [] -def test_async_support(pytester: Pytester) -> None: # TODO: Change this +def test_async_support(pytester: Pytester) -> None: pytest.importorskip("unittest.async_case") pytester.copy_example("unittest/test_unittest_asyncio.py") From c7eae3a9575e2822e560156aef9530ec96ae5427 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Fri, 25 Oct 2024 13:37:54 +0200 Subject: [PATCH 0917/1271] add changelog entries --- changelog/11372.improvement.rst | 1 + changelog/12346.misc.rst | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog/11372.improvement.rst create mode 100644 changelog/12346.misc.rst diff --git a/changelog/11372.improvement.rst b/changelog/11372.improvement.rst new file mode 100644 index 00000000000..f4b5c3c6f6b --- /dev/null +++ b/changelog/11372.improvement.rst @@ -0,0 +1 @@ +Async tests will now fail, instead of warning+skipping, if you don't have any suitable plugin installed. diff --git a/changelog/12346.misc.rst b/changelog/12346.misc.rst new file mode 100644 index 00000000000..7013cf734c8 --- /dev/null +++ b/changelog/12346.misc.rst @@ -0,0 +1 @@ +Tests will now fail, instead of raising a warning, if they return any value other than None. From 29490af255630b3e4c949e50c3ead1756820707c Mon Sep 17 00:00:00 2001 From: jakkdl Date: Fri, 25 Oct 2024 14:52:34 +0200 Subject: [PATCH 0918/1271] fix docs --- doc/en/changelog.rst | 2 +- doc/en/deprecations.rst | 2 +- doc/en/reference/reference.rst | 6 ------ 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 9f30c86be3a..0a32f88c6ff 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -1462,7 +1462,7 @@ pytest 7.2.0 (2022-10-23) Deprecations ------------ -- `#10012 `_: Update :class:`pytest.PytestUnhandledCoroutineWarning` to a deprecation; it will raise an error in pytest 8. +- `#10012 `_: Update ``pytest.PytestUnhandledCoroutineWarning`` to a deprecation; it will raise an error in pytest 8. - `#10396 `_: pytest no longer depends on the ``py`` library. ``pytest`` provides a vendored copy of ``py.error`` and ``py.path`` modules but will use the ``py`` library if it is installed. If you need other ``py.*`` modules, continue to install the deprecated ``py`` library separately, otherwise it can usually be removed as a dependency. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 153d5195476..e55f0d71c2e 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -251,7 +251,7 @@ Returning non-None value in test functions .. deprecated:: 7.2 -A :class:`pytest.PytestReturnNotNoneWarning` is now emitted if a test function returns something other than `None`. +A ``pytest.PytestReturnNotNoneWarning`` is now emitted if a test function returns something other than `None`. This prevents a common mistake among beginners that expect that returning a `bool` would cause a test to pass or fail, for example: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index b6ec5c65e1e..71bf6a8986d 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1229,15 +1229,9 @@ Custom warnings generated in some situations such as improper usage or deprecate .. autoclass:: pytest.PytestExperimentalApiWarning :show-inheritance: -.. autoclass:: pytest.PytestReturnNotNoneWarning - :show-inheritance: - .. autoclass:: pytest.PytestRemovedIn9Warning :show-inheritance: -.. autoclass:: pytest.PytestUnhandledCoroutineWarning - :show-inheritance: - .. autoclass:: pytest.PytestUnknownMarkWarning :show-inheritance: From edfe778bb9f783f10c4270bb83df18f0803c655f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 27 Oct 2024 10:38:53 +0100 Subject: [PATCH 0919/1271] [automated] Update plugin list (#12921) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 184 +++++++++++++++++-------------- 1 file changed, 104 insertions(+), 80 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index e5bd2f8805b..1cd265578eb 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -157,7 +157,7 @@ This list contains 1533 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 18, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 22, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -250,7 +250,7 @@ This list contains 1533 plugins. :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Oct 08, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) - :pypi:`pytest-clld` Jul 06, 2022 N/A pytest (>=3.6) + :pypi:`pytest-clld` Oct 23, 2024 N/A pytest>=3.9 :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) @@ -307,7 +307,7 @@ This list contains 1533 plugins. :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest :pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A :pypi:`pytest-csv` CSV output for pytest. Apr 22, 2021 N/A pytest (>=6.0) - :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Jul 01, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) + :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Oct 25, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 :pypi:`pytest-curio` Pytest support for curio. Oct 06, 2024 N/A pytest :pypi:`pytest-curl-report` pytest plugin to generate curl command line report Dec 11, 2016 4 - Beta N/A :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A @@ -322,7 +322,7 @@ This list contains 1533 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Sep 07, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Oct 20, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -448,7 +448,7 @@ This list contains 1533 plugins. :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Sep 11, 2024 5 - Production/Stable pytest>=4.6 :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A - :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Mar 12, 2024 5 - Production/Stable pytest + :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Feb 16, 2024 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A @@ -465,14 +465,14 @@ This list contains 1533 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 Jul 25, 2024 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. Oct 18, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Oct 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Oct 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Oct 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Oct 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Oct 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Oct 18, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Oct 18, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Oct 25, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Oct 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Oct 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Oct 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Oct 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Oct 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Oct 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Oct 25, 2024 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) @@ -572,7 +572,7 @@ This list contains 1533 plugins. :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 15, 2024 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Jul 21, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Jul 10, 2023 5 - Production/Stable pytest + :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) @@ -647,7 +647,7 @@ This list contains 1533 plugins. :pypi:`pytest-hardware-test-report` A simple plugin to use with pytest Apr 01, 2024 4 - Beta pytest<9.0.0,>=8.0.0 :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Mar 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Feb 07, 2024 4 - Beta pytest (>=8.0.0,<9.0.0) + :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Oct 23, 2024 4 - Beta pytest<9.0.0,>=8.0.0 :pypi:`pytest-helm-templates` Pytest fixtures for unit testing the output of helm templates Aug 07, 2024 N/A pytest~=7.4.0; extra == "dev" :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest @@ -660,7 +660,7 @@ This list contains 1533 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Oct 19, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Oct 26, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -680,7 +680,7 @@ This list contains 1533 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Sep 18, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 10, 2024 3 - Alpha pytest >=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Oct 21, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A @@ -712,7 +712,7 @@ This list contains 1533 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-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 - :pypi:`pytest-inline` A pytest plugin for writing inline tests. Oct 19, 2023 4 - Beta pytest >=7.0.0 + :pypi:`pytest-inline` A pytest plugin for writing inline tests Oct 24, 2024 4 - Beta pytest<9.0,>=7.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Oct 10, 2024 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 10, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Aug 20, 2024 5 - Production/Stable N/A @@ -827,7 +827,7 @@ This list contains 1533 plugins. :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Oct 18, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) - :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 05, 2024 N/A pytest (>=7.0.0) + :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Oct 22, 2024 N/A pytest>=7.0.0 :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A @@ -841,6 +841,7 @@ This list contains 1533 plugins. :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) :pypi:`pytest-maxcov` Compute the maximum coverage available through pytest with the minimum execution time cost Sep 24, 2023 N/A pytest (>=7.4.0,<8.0.0) + :pypi:`pytest-max-warnings` A Pytest plugin to exit non-zero exit code when the configured maximum warnings has been exceeded. Oct 23, 2024 4 - Beta pytest>=8.3.3 :pypi:`pytest-maybe-context` Simplify tests with warning and exception cases. Apr 16, 2023 N/A pytest (>=7,<8) :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) @@ -888,13 +889,14 @@ This list contains 1533 plugins. :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A :pypi:`pytest-moto` Fixtures for integration tests of AWS services,uses moto mocking library. Aug 28, 2015 1 - Planning N/A + :pypi:`pytest-moto-fixtures` Fixtures for testing code that interacts with AWS Oct 24, 2024 1 - Planning pytest<9.0,>=8.3; extra == "pytest" :pypi:`pytest-motor` A pytest plugin for motor, the non-blocking MongoDB driver. Jul 21, 2021 3 - Alpha pytest :pypi:`pytest-mp` A test batcher for multiprocessed Pytest runs May 23, 2018 4 - Beta pytest :pypi:`pytest-mpi` pytest plugin to collect information from tests Jan 08, 2022 3 - Alpha pytest :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Jul 29, 2024 3 - Alpha pytest :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Feb 14, 2024 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Jul 29, 2024 4 - Beta pytest<9; extra == "test" + :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Oct 19, 2024 4 - Beta pytest<9; extra == "test" :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Aug 05, 2024 N/A N/A @@ -977,7 +979,7 @@ This list contains 1533 plugins. :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Sep 23, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) - :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Nov 03, 2023 5 - Production/Stable pytest + :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Oct 22, 2024 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest :pypi:`pytest_param_files` Create pytest parametrize decorators from external files. Jul 29, 2023 N/A pytest :pypi:`pytest-params` Simplified pytest test case parameters. Aug 05, 2024 N/A pytest>=7.0.0 @@ -988,7 +990,7 @@ This list contains 1533 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 Oct 19, 2024 4 - Beta pytest>=6 + :pypi:`pytest-patterns` pytest plugin to make testing complicated long string output easy to write and easy to debug Oct 22, 2024 4 - Beta pytest>=6 :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 @@ -1080,7 +1082,7 @@ This list contains 1533 plugins. :pypi:`pytest-pypom-navigation` Core engine for cookiecutter-qa and pytest-play packages Feb 18, 2019 4 - Beta pytest (>=3.0.7) :pypi:`pytest-pyppeteer` A plugin to run pyppeteer in pytest Apr 28, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-pyq` Pytest fixture "q" for pyq Mar 10, 2020 5 - Production/Stable N/A - :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 11, 2023 5 - Production/Stable pytest + :pypi:`pytest-pyramid` pytest_pyramid - provides fixtures for testing pyramid applications with pytest test suite Oct 24, 2024 5 - Production/Stable pytest :pypi:`pytest-pyramid-server` Pyramid server fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report May 05, 2024 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Jan 26, 2024 4 - Beta pytest >=7.0.0 @@ -1114,7 +1116,7 @@ This list contains 1533 plugins. :pypi:`pytest-raisesregexp` Simple pytest plugin to look for regex in Exceptions Dec 18, 2015 N/A N/A :pypi:`pytest-raisin` Plugin enabling the use of exception instances with pytest.raises Feb 06, 2022 N/A pytest :pypi:`pytest-random` py.test plugin to randomize tests Apr 28, 2013 3 - Alpha N/A - :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Aug 15, 2023 5 - Production/Stable pytest + :pypi:`pytest-randomly` Pytest plugin to randomly order tests and control random.seed. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 @@ -1155,7 +1157,7 @@ This list contains 1533 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Sep 06, 2024 N/A pytest>=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Oct 22, 2024 N/A pytest>=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A :pypi:`pytest-req` pytest requests plugin Aug 31, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.2 @@ -1178,7 +1180,7 @@ This list contains 1533 plugins. :pypi:`pytest-responsemock` Simplified requests calls mocking for pytest Mar 10, 2022 5 - Production/Stable N/A :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Jul 10, 2023 5 - Production/Stable pytest + :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Oct 24, 2024 5 - Production/Stable pytest :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) @@ -1186,7 +1188,7 @@ This list contains 1533 plugins. :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments May 14, 2024 N/A pytest>=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A - :pypi:`pytest-reverse` Pytest plugin to reverse test order. Jul 10, 2023 5 - Production/Stable pytest + :pypi:`pytest-reverse` Pytest plugin to reverse test order. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) @@ -1213,7 +1215,7 @@ This list contains 1533 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 Mar 22, 2024 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-salt-factories` Pytest Salt Plugin Oct 22, 2024 5 - Production/Stable pytest>=7.4.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-sample-argvalues` A utility function to help choose a random sample from your argvalues in pytest. May 07, 2024 N/A pytest @@ -1221,7 +1223,7 @@ This list contains 1533 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 07, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 26, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A @@ -1232,7 +1234,7 @@ This list contains 1533 plugins. :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 Feb 01, 2024 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. Oct 07, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Oct 26, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1255,7 +1257,7 @@ This list contains 1533 plugins. :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) :pypi:`pytest-shell` A pytest plugin to help with testing shell scripts / black box commands Mar 27, 2022 N/A N/A - :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Oct 18, 2024 5 - Production/Stable pytest>=7.4.0 + :pypi:`pytest-shell-utilities` Pytest plugin to simplify running shell commands against the system Oct 22, 2024 5 - Production/Stable pytest>=7.4.0 :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) @@ -1325,7 +1327,7 @@ This list contains 1533 plugins. :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A - :pypi:`pytest-static` pytest-static Aug 09, 2024 1 - Planning pytest<8.0.0,>=7.4.3 + :pypi:`pytest-static` pytest-static Oct 20, 2024 1 - Planning pytest<8.0.0,>=7.4.3 :pypi:`pytest-stats` Collects tests metadata for future analysis, easy to extend for any data store Jul 18, 2024 N/A pytest>=8.0.0 :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-status` Add status mark for tests Aug 22, 2024 N/A pytest @@ -1474,8 +1476,9 @@ This list contains 1533 plugins. :pypi:`pytest-uncollect-if` A plugin to uncollect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unflakable` Unflakable plugin for PyTest Apr 30, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) - :pypi:`pytest-unique` Pytest fixture to generate unique values. Sep 15, 2023 N/A pytest (>=7.4.2,<8.0.0) + :pypi:`pytest-unique` Pytest fixture to generate unique values. Oct 21, 2024 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) + :pypi:`pytest-unmagic` Pytest fixtures with conventional import semantics Oct 22, 2024 5 - Production/Stable pytest :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Jul 05, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A @@ -2252,11 +2255,11 @@ This list contains 1533 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. :pypi:`pytest-aux` - *last release*: Sep 23, 2024, + *last release*: Oct 25, 2024, *status*: N/A, *requires*: N/A - templates/examples and aux for pytest + all moved into module FUNCS_AUXt :pypi:`pytest-aviator` *last release*: Nov 04, 2022, @@ -2434,7 +2437,7 @@ This list contains 1533 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Oct 18, 2024, + *last release*: Oct 22, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3085,9 +3088,9 @@ This list contains 1533 plugins. Automatically register fixtures for custom CLI arguments :pypi:`pytest-clld` - *last release*: Jul 06, 2022, + *last release*: Oct 23, 2024, *status*: N/A, - *requires*: pytest (>=3.6) + *requires*: pytest>=3.9 @@ -3484,9 +3487,9 @@ This list contains 1533 plugins. CSV output for pytest. :pypi:`pytest-csv-params` - *last release*: Jul 01, 2023, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.4.0,<8.0.0) + *requires*: pytest<9.0.0,>=8.3.0 Pytest plugin for Test Case Parametrization with CSV files @@ -3589,7 +3592,7 @@ This list contains 1533 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Sep 07, 2024, + *last release*: Oct 20, 2024, *status*: 4 - Beta, *requires*: pytest @@ -4471,7 +4474,7 @@ This list contains 1533 plugins. A pytest plugin to rerun tests dynamically based off of test outcome and output. :pypi:`pytest-dynamodb` - *last release*: Mar 12, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -4590,56 +4593,56 @@ This list contains 1533 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Oct 18, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Oct 18, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Oct 18, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Oct 18, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Oct 18, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Oct 18, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Oct 18, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Oct 18, 2024, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5339,7 +5342,7 @@ This list contains 1533 plugins. pytest plugin to check FLAKE8 requirements :pypi:`pytest-flake8-path` - *last release*: Jul 10, 2023, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -5864,9 +5867,9 @@ This list contains 1533 plugins. Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. :pypi:`pytest-helm-charts` - *last release*: Feb 07, 2024, + *last release*: Oct 23, 2024, *status*: 4 - Beta, - *requires*: pytest (>=8.0.0,<9.0.0) + *requires*: pytest<9.0.0,>=8.0.0 A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. @@ -5955,7 +5958,7 @@ This list contains 1533 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Oct 19, 2024, + *last release*: Oct 26, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6095,9 +6098,9 @@ This list contains 1533 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Jan 10, 2024, - *status*: 3 - Alpha, - *requires*: pytest >=7.0.0 + *last release*: Oct 21, 2024, + *status*: 4 - Beta, + *requires*: pytest>=7.0.0 A pytest plugin to record HTTP(S) requests with stack trace @@ -6319,11 +6322,11 @@ This list contains 1533 plugins. Plugin for sending automation test data from Pytest to the initry :pypi:`pytest-inline` - *last release*: Oct 19, 2023, + *last release*: Oct 24, 2024, *status*: 4 - Beta, - *requires*: pytest >=7.0.0 + *requires*: pytest<9.0,>=7.0 - A pytest plugin for writing inline tests. + A pytest plugin for writing inline tests :pypi:`pytest-inmanta` *last release*: Oct 10, 2024, @@ -7124,9 +7127,9 @@ This list contains 1533 plugins. Test your markdown docs with pytest :pypi:`pytest-markdown-docs` - *last release*: Mar 05, 2024, + *last release*: Oct 22, 2024, *status*: N/A, - *requires*: pytest (>=7.0.0) + *requires*: pytest>=7.0.0 Run markdown code fences through pytest @@ -7221,6 +7224,13 @@ This list contains 1533 plugins. Compute the maximum coverage available through pytest with the minimum execution time cost + :pypi:`pytest-max-warnings` + *last release*: Oct 23, 2024, + *status*: 4 - Beta, + *requires*: pytest>=8.3.3 + + A Pytest plugin to exit non-zero exit code when the configured maximum warnings has been exceeded. + :pypi:`pytest-maybe-context` *last release*: Apr 16, 2023, *status*: N/A, @@ -7550,6 +7560,13 @@ This list contains 1533 plugins. Fixtures for integration tests of AWS services,uses moto mocking library. + :pypi:`pytest-moto-fixtures` + *last release*: Oct 24, 2024, + *status*: 1 - Planning, + *requires*: pytest<9.0,>=8.3; extra == "pytest" + + Fixtures for testing code that interacts with AWS + :pypi:`pytest-motor` *last release*: Jul 21, 2021, *status*: 3 - Alpha, @@ -7593,7 +7610,7 @@ This list contains 1533 plugins. low-startup-overhead, scalable, distributed-testing pytest plugin :pypi:`pytest-mqtt` - *last release*: Jul 29, 2024, + *last release*: Oct 19, 2024, *status*: 4 - Beta, *requires*: pytest<9; extra == "test" @@ -8174,7 +8191,7 @@ This list contains 1533 plugins. A more user-friendly way to write parametrized tests. :pypi:`pytest-parametrized` - *last release*: Nov 03, 2023, + *last release*: Oct 22, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -8251,7 +8268,7 @@ This list contains 1533 plugins. A contextmanager pytest fixture for handling multiple mock patches :pypi:`pytest-patterns` - *last release*: Oct 19, 2024, + *last release*: Oct 22, 2024, *status*: 4 - Beta, *requires*: pytest>=6 @@ -8895,7 +8912,7 @@ This list contains 1533 plugins. Pytest fixture "q" for pyq :pypi:`pytest-pyramid` - *last release*: Oct 11, 2023, + *last release*: Oct 24, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -9133,7 +9150,7 @@ This list contains 1533 plugins. py.test plugin to randomize tests :pypi:`pytest-randomly` - *last release*: Aug 15, 2023, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -9420,7 +9437,7 @@ This list contains 1533 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Sep 06, 2024, + *last release*: Oct 22, 2024, *status*: N/A, *requires*: pytest>=3.8.0 @@ -9581,7 +9598,7 @@ This list contains 1533 plugins. :pypi:`pytest-restrict` - *last release*: Jul 10, 2023, + *last release*: Oct 24, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -9637,7 +9654,7 @@ This list contains 1533 plugins. :pypi:`pytest-reverse` - *last release*: Jul 10, 2023, + *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -9826,9 +9843,9 @@ This list contains 1533 plugins. A Pytest plugin that builds and creates docker containers :pypi:`pytest-salt-factories` - *last release*: Mar 22, 2024, + *last release*: Oct 22, 2024, *status*: 5 - Production/Stable, - *requires*: pytest>=7.0.0 + *requires*: pytest>=7.4.0 Pytest Salt Plugin @@ -9882,7 +9899,7 @@ This list contains 1533 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Oct 07, 2024, + *last release*: Oct 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9959,7 +9976,7 @@ This list contains 1533 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Oct 07, 2024, + *last release*: Oct 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10120,7 +10137,7 @@ This list contains 1533 plugins. A pytest plugin to help with testing shell scripts / black box commands :pypi:`pytest-shell-utilities` - *last release*: Oct 18, 2024, + *last release*: Oct 22, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.4.0 @@ -10610,7 +10627,7 @@ This list contains 1533 plugins. A package to prevent Dependency Confusion attacks against Yandex. :pypi:`pytest-static` - *last release*: Aug 09, 2024, + *last release*: Oct 20, 2024, *status*: 1 - Planning, *requires*: pytest<8.0.0,>=7.4.3 @@ -11653,9 +11670,9 @@ This list contains 1533 plugins. Plugin for py.test set a different exit code on uncaught exceptions :pypi:`pytest-unique` - *last release*: Sep 15, 2023, + *last release*: Oct 21, 2024, *status*: N/A, - *requires*: pytest (>=7.4.2,<8.0.0) + *requires*: pytest<8.0.0,>=7.4.2 Pytest fixture to generate unique values. @@ -11666,6 +11683,13 @@ This list contains 1533 plugins. A pytest plugin for filtering unittest-based test classes + :pypi:`pytest-unmagic` + *last release*: Oct 22, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest + + Pytest fixtures with conventional import semantics + :pypi:`pytest-unmarked` *last release*: Aug 27, 2019, *status*: 5 - Production/Stable, From 256203a5c9aae87741ca195c29510414dd5ddc73 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 06:05:23 +0100 Subject: [PATCH 0920/1271] build(deps): Bump twisted in /testing/plugins_integration (#12922) Bumps [twisted](https://github.com/twisted/twisted) from 24.7.0 to 24.10.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-24.7.0...twisted-24.10.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d5ed74940d3..c465041d64d 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -11,5 +11,5 @@ pytest-rerunfailures==14.0 pytest-sugar==1.0.0 pytest-trio==0.8.0 pytest-twisted==1.14.3 -twisted==24.7.0 +twisted==24.10.0 pytest-xvfb==3.0.0 From a1a491837b35b719d77b4f03be318b505d495386 Mon Sep 17 00:00:00 2001 From: Stefaan Lippens Date: Thu, 31 Oct 2024 11:28:03 +0100 Subject: [PATCH 0921/1271] Improve docs on basetemp and retention (#12912) Improve coverage of current handling of `--basetemp` option and its lack of retention functionality. Also document `PYTEST_DEBUG_TEMPROOT`. Related to #10829 --------- Co-authored-by: Bruno Oliveira --- changelog/10829.doc.rst | 1 + doc/en/how-to/tmp_path.rst | 50 ++++++++++++++++++++++++---------- doc/en/reference/reference.rst | 5 ++++ src/_pytest/legacypath.py | 15 ++++------ src/_pytest/tmpdir.py | 22 +++++---------- 5 files changed, 53 insertions(+), 40 deletions(-) create mode 100644 changelog/10829.doc.rst diff --git a/changelog/10829.doc.rst b/changelog/10829.doc.rst new file mode 100644 index 00000000000..1be45c7049d --- /dev/null +++ b/changelog/10829.doc.rst @@ -0,0 +1 @@ +Improve documentation on the current handling of the ``--basetemp`` option and its lack of retention functionality (:ref:`temporary directory location and retention`). diff --git a/doc/en/how-to/tmp_path.rst b/doc/en/how-to/tmp_path.rst index 3cc5152e992..d19950431e5 100644 --- a/doc/en/how-to/tmp_path.rst +++ b/doc/en/how-to/tmp_path.rst @@ -133,27 +133,47 @@ API for details. Temporary directory location and retention ------------------------------------------ -Temporary directories are by default created as sub-directories of -the system temporary directory. The base name will be ``pytest-NUM`` where -``NUM`` will be incremented with each test run. -By default, entries older than 3 temporary directories will be removed. -This behavior can be configured with :confval:`tmp_path_retention_count` and -:confval:`tmp_path_retention_policy`. +The temporary directories, +as returned by the :fixture:`tmp_path` and (now deprecated) :fixture:`tmpdir` fixtures, +are automatically created under a base temporary directory, +in a structure that depends on the ``--basetemp`` option: -Using the ``--basetemp`` -option will remove the directory before every run, effectively meaning the temporary directories -of only the most recent run will be kept. +- By default (when the ``--basetemp`` option is not set), + the temporary directories will follow this template: -You can override the default temporary directory setting like this: + .. code-block:: text -.. code-block:: bash + {temproot}/pytest-of-{user}/pytest-{num}/{testname}/ - pytest --basetemp=mydir + where: -.. warning:: + - ``{temproot}`` is the system temporary directory + as determined by :py:func:`tempfile.gettempdir`. + It can be overridden by the :envvar:`PYTEST_DEBUG_TEMPROOT` environment variable. + - ``{user}`` is the user name running the tests, + - ``{num}`` is a number that is incremented with each test suite run + - ``{testname}`` is a sanitized version of :py:attr:`the name of the current test <_pytest.nodes.Node.name>`. - The contents of ``mydir`` will be completely removed, so make sure to use a directory - for that purpose only. + The auto-incrementing ``{num}`` placeholder provides a basic retention feature + and avoids that existing results of previous test runs are blindly removed. + By default, the last 3 temporary directories are kept, + but this behavior can be configured with + :confval:`tmp_path_retention_count` and :confval:`tmp_path_retention_policy`. + +- When the ``--basetemp`` option is used (e.g. ``pytest --basetemp=mydir``), + it will be used directly as base temporary directory: + + .. code-block:: text + + {basetemp}/{testname}/ + + Note that there is no retention feature in this case: + only the results of the most recent run will be kept. + + .. warning:: + + The directory given to ``--basetemp`` will be cleared blindly before each test run, + so make sure to use a directory for that purpose only. When distributing tests on the local machine using ``pytest-xdist``, care is taken to automatically configure a `basetemp` directory for the sub processes such that all temporary diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 71bf6a8986d..bb77806c6a3 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1153,6 +1153,11 @@ processes can inspect it, see :ref:`pytest current test env` for more informatio When set, pytest will print tracing and debug information. +.. envvar:: PYTEST_DEBUG_TEMPROOT + +Root for temporary directories produced by fixtures like :fixture:`tmp_path` +as discussed in :ref:`temporary directory location and retention`. + .. envvar:: PYTEST_DISABLE_PLUGIN_AUTOLOAD When set, disables plugin auto-loading through :std:doc:`entry point packaging diff --git a/src/_pytest/legacypath.py b/src/_pytest/legacypath.py index 61476d68932..59e8ef6e742 100644 --- a/src/_pytest/legacypath.py +++ b/src/_pytest/legacypath.py @@ -304,16 +304,11 @@ def tmpdir_factory(request: FixtureRequest) -> TempdirFactory: @staticmethod @fixture def tmpdir(tmp_path: Path) -> LEGACY_PATH: - """Return a temporary directory path object which is unique to each test - function invocation, created as a sub directory of the base temporary - directory. - - By default, a new base temporary directory is created each test session, - and old bases are removed after 3 sessions, to aid in debugging. If - ``--basetemp`` is used then it is cleared each session. See - :ref:`temporary directory location and retention`. - - The returned object is a `legacy_path`_ object. + """Return a temporary directory (as `legacy_path`_ object) + which is unique to each test function invocation. + The temporary directory is created as a subdirectory + of the base temporary directory, with configurable retention, + as discussed in :ref:`temporary directory location and retention`. .. note:: These days, it is preferred to use ``tmp_path``. diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index de0cbcfeb1c..1731a4b8d0d 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -41,9 +41,8 @@ @final @dataclasses.dataclass class TempPathFactory: - """Factory for temporary directories under the common base temp directory. - - The base directory can be configured using the ``--basetemp`` option. + """Factory for temporary directories under the common base temp directory, + as discussed at :ref:`temporary directory location and retention`. """ _given_basetemp: Path | None @@ -257,18 +256,11 @@ def _mk_tmp(request: FixtureRequest, factory: TempPathFactory) -> Path: def tmp_path( request: FixtureRequest, tmp_path_factory: TempPathFactory ) -> Generator[Path]: - """Return a temporary directory path object which is unique to each test - function invocation, created as a sub directory of the base temporary - directory. - - By default, a new base temporary directory is created each test session, - and old bases are removed after 3 sessions, to aid in debugging. - This behavior can be configured with :confval:`tmp_path_retention_count` and - :confval:`tmp_path_retention_policy`. - If ``--basetemp`` is used then it is cleared each session. See - :ref:`temporary directory location and retention`. - - The returned object is a :class:`pathlib.Path` object. + """Return a temporary directory (as :class:`pathlib.Path` object) + which is unique to each test function invocation. + The temporary directory is created as a subdirectory + of the base temporary directory, with configurable retention, + as discussed in :ref:`temporary directory location and retention`. """ path = _mk_tmp(request, tmp_path_factory) yield path From 6728ec5606dd7e2eb70ef64972f97eab061f95e2 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Thu, 31 Oct 2024 16:48:11 +0100 Subject: [PATCH 0922/1271] Raise error if sync test relies on async fixture, and warn if the fixture is autouse. --- src/_pytest/fixtures.py | 36 +++++++++++++++- testing/acceptance_test.py | 87 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 6b882fa3515..499d065c4a9 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -73,6 +73,7 @@ from _pytest.scope import _ScopeName from _pytest.scope import HIGH_SCOPES from _pytest.scope import Scope +from _pytest.warning_types import PytestRemovedIn9Warning if sys.version_info < (3, 11): @@ -575,6 +576,7 @@ def _get_active_fixturedef( # The are no fixtures with this name applicable for the function. if not fixturedefs: raise FixtureLookupError(argname, self) + # A fixture may override another fixture with the same name, e.g. a # fixture in a module can override a fixture in a conftest, a fixture in # a class can override a fixture in the module, and so on. @@ -593,6 +595,32 @@ def _get_active_fixturedef( raise FixtureLookupError(argname, self) fixturedef = fixturedefs[index] + if not inspect.iscoroutinefunction(self.function) and ( + inspect.iscoroutinefunction(fixturedef.func) + or inspect.isasyncgenfunction(fixturedef.func) + ): + if fixturedef._autouse: + warnings.warn( + PytestRemovedIn9Warning( + "Sync test requested an async fixture with autouse=True. " + "If you intended to use the fixture you may want to make the " + "test asynchronous. If you did not intend to use it you should " + "restructure your test setup. " + "This will turn into an error in pytest 9." + ), + stacklevel=3, + ) + else: + raise FixtureLookupError( + argname, + self, + ( + "ERROR: Sync test requested async fixture. " + "You may want to make the test asynchronous and run it with " + "a suitable async framework test plugin." + ), + ) + # Prepare a SubRequest object for calling the fixture. try: callspec = self._pyfuncitem.callspec @@ -805,7 +833,7 @@ def formatrepr(self) -> FixtureLookupErrorRepr: stack = [self.request._pyfuncitem.obj] stack.extend(map(lambda x: x.func, self.fixturestack)) msg = self.msg - if msg is not None: + if msg is not None and len(stack) > 1: # The last fixture raise an error, let's present # it at the requesting side. stack = stack[:-1] @@ -959,6 +987,8 @@ def __init__( ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None, *, _ispytest: bool = False, + # only used to emit a deprecationwarning, can be removed in pytest9 + _autouse: bool = False, ) -> None: check_ispytest(_ispytest) # The "base" node ID for the fixture. @@ -1005,6 +1035,9 @@ def __init__( self.cached_result: _FixtureCachedResult[FixtureValue] | None = None self._finalizers: Final[list[Callable[[], object]]] = [] + # only used to emit a deprecationwarning, can be removed in pytest9 + self._autouse = _autouse + @property def scope(self) -> _ScopeName: """Scope string, one of "function", "class", "module", "package", "session".""" @@ -1666,6 +1699,7 @@ def _register_fixture( params=params, ids=ids, _ispytest=True, + _autouse=autouse, ) faclist = self._arg2fixturedefs.setdefault(name, []) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 7a8d871144a..0437cae4047 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1286,6 +1286,93 @@ def test_3(): result.assert_outcomes(failed=3) +def test_error_on_sync_test_async_fixture(pytester: Pytester) -> None: + pytester.makepyfile( + test_sync=""" + import pytest + + @pytest.fixture + async def async_fixture(): + ... + + def test_foo(async_fixture): + ... + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + ( + "*ERROR: Sync test requested async fixture. " + "You may want to make the test asynchronous and run it with " + "a suitable async framework test plugin.*" + ), + "*ERROR test_sync.py::test_foo*", + ] + ) + result.assert_outcomes(errors=1) + + +def test_error_on_sync_test_async_fixture_gen(pytester: Pytester) -> None: + pytester.makepyfile( + test_sync=""" + import pytest + + @pytest.fixture + async def async_fixture(): + yield + + def test_foo(async_fixture): + ... + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + ( + "*ERROR: Sync test requested async fixture. " + "You may want to make the test asynchronous and run it with " + "a suitable async framework test plugin.*" + ), + "*ERROR test_sync.py::test_foo*", + ] + ) + result.assert_outcomes(errors=1) + + +def test_warning_on_sync_test_async_autouse_fixture(pytester: Pytester) -> None: + pytester.makepyfile( + test_sync=""" + import pytest + + @pytest.fixture(autouse=True) + async def async_fixture(): + ... + + # We explicitly request the fixture to be able to + # suppress the RuntimeWarning for unawaited coroutine. + def test_foo(async_fixture): + try: + async_fixture.send(None) + except StopIteration: + pass + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + [ + ( + "*Sync test requested an async fixture with autouse=True. " + "If you intended to use the fixture you may want to make the " + "test asynchronous. If you did not intend to use it you should " + "restructure your test setup. " + "This will turn into an error in pytest 9.*" + ), + ] + ) + result.assert_outcomes(passed=1) + + def test_pdb_can_be_rewritten(pytester: Pytester) -> None: pytester.makepyfile( **{ From 8e100ea2c70ea7252141902af819a7aae44a53c1 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Fri, 1 Nov 2024 11:56:59 +0100 Subject: [PATCH 0923/1271] fix tests --- src/_pytest/fixtures.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 499d065c4a9..da6625fb7e1 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -595,9 +595,16 @@ def _get_active_fixturedef( raise FixtureLookupError(argname, self) fixturedef = fixturedefs[index] - if not inspect.iscoroutinefunction(self.function) and ( - inspect.iscoroutinefunction(fixturedef.func) - or inspect.isasyncgenfunction(fixturedef.func) + # Check for attempted use of an async fixture by a sync test + # `self.scope` here is not the scope of the requested fixture, but the scope of + # the requester. + if ( + self.scope == "function" + and not inspect.iscoroutinefunction(self._pyfuncitem.obj) + and ( + inspect.iscoroutinefunction(fixturedef.func) + or inspect.isasyncgenfunction(fixturedef.func) + ) ): if fixturedef._autouse: warnings.warn( From 283db4ed9f803c6b1f19b8920ed8b01cfda20b59 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Fri, 1 Nov 2024 12:15:23 +0100 Subject: [PATCH 0924/1271] add changelog --- changelog/10839.deprecation.rst | 1 + changelog/10839.improvement.rst | 1 + 2 files changed, 2 insertions(+) create mode 100644 changelog/10839.deprecation.rst create mode 100644 changelog/10839.improvement.rst diff --git a/changelog/10839.deprecation.rst b/changelog/10839.deprecation.rst new file mode 100644 index 00000000000..c0628191663 --- /dev/null +++ b/changelog/10839.deprecation.rst @@ -0,0 +1 @@ +Synchronous tests that request an asynchronous fixture with ``autouse=True`` will now give a DeprecationWarning. diff --git a/changelog/10839.improvement.rst b/changelog/10839.improvement.rst new file mode 100644 index 00000000000..0a382053c85 --- /dev/null +++ b/changelog/10839.improvement.rst @@ -0,0 +1 @@ +Synchronous tests that request asynchronous fixtures will now error, instead of silently accepting an unawaited coroutine object as the fixture value. From 935c06de09df95c48e867fa70851b9a2acd9fcf7 Mon Sep 17 00:00:00 2001 From: sven <42868792+FreerGit@users.noreply.github.com> Date: Mon, 4 Nov 2024 02:02:18 +0100 Subject: [PATCH 0925/1271] WIP: don't collect instead of filtering out --- doc/en/reference/reference.rst | 25 +++++---- src/_pytest/main.py | 25 --------- src/_pytest/python.py | 19 +++++++ testing/test_collect_imports.py | 99 +++++++++++++++++++++++++++------ 4 files changed, 115 insertions(+), 53 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 99b1a19c3a4..53f9470f756 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1301,6 +1301,20 @@ passed multiple times. The expected format is ``name=value``. For example:: variables, that will be expanded. For more information about cache plugin please refer to :ref:`cache_provider`. +.. confval:: collect_imported_tests + + .. versionadded:: 8.4 + + Setting this to ``false`` will make pytest collect classes/functions from test + files only if they are defined in that file (as opposed to imported there). + + .. code-block:: ini + + [pytest] + collect_imported_tests = false + + Default: ``true`` + .. confval:: consider_namespace_packages Controls if pytest should attempt to identify `namespace packages `__ @@ -1838,17 +1852,6 @@ passed multiple times. The expected format is ``name=value``. For example:: pytest testing doc - -.. confval:: collect_imported_tests - - Setting this to `false` will make pytest collect classes/functions from test - files only if they are defined in that file (as opposed to imported there). - - .. code-block:: ini - - [pytest] - collect_imported_tests = false - .. confval:: tmp_path_retention_count How many sessions should we keep the `tmp_path` directories, diff --git a/src/_pytest/main.py b/src/_pytest/main.py index e40f09a9acb..41063a9bc18 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -964,22 +964,9 @@ def collect(self) -> Iterator[nodes.Item | nodes.Collector]: self.trace.root.indent -= 1 def genitems(self, node: nodes.Item | nodes.Collector) -> Iterator[nodes.Item]: - import inspect - - from _pytest.python import Class - from _pytest.python import Function - from _pytest.python import Module - self.trace("genitems", node) if isinstance(node, nodes.Item): node.ihook.pytest_itemcollected(item=node) - if not self.config.getini("collect_imported_tests"): - if isinstance(node.parent, Module) and isinstance(node, Function): - if inspect.isfunction(node._getobj()): - fn_defined_at = node._getobj().__module__ - in_module = node.parent._getobj().__name__ - if fn_defined_at != in_module: - return yield node else: assert isinstance(node, nodes.Collector) @@ -987,18 +974,6 @@ def genitems(self, node: nodes.Item | nodes.Collector) -> Iterator[nodes.Item]: # For backward compat, dedup only applies to files. handle_dupes = not (keepduplicates and isinstance(node, nodes.File)) rep, duplicate = self._collect_one_node(node, handle_dupes) - - if not self.config.getini("collect_imported_tests"): - for subnode in rep.result: - if isinstance(subnode, Class) and isinstance( - subnode.parent, Module - ): - if inspect.isclass(subnode._getobj()): - class_defined_at = subnode._getobj().__module__ - in_module = subnode.parent._getobj().__name__ - if class_defined_at != in_module: - rep.result.remove(subnode) - if duplicate and not keepduplicates: return if rep.passed: diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 9c54dd20f80..9c00252c5f8 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -416,6 +416,15 @@ def collect(self) -> Iterable[nodes.Item | nodes.Collector]: if name in seen: continue seen.add(name) + + if not self.session.config.getini("collect_imported_tests"): + # Do not collect imported functions + if inspect.isfunction(obj) and isinstance(self, Module): + fn_defined_at = obj.__module__ + in_module = self._getobj().__name__ + if fn_defined_at != in_module: + continue + res = ihook.pytest_pycollect_makeitem( collector=self, name=name, obj=obj ) @@ -741,6 +750,16 @@ def newinstance(self): return self.obj() def collect(self) -> Iterable[nodes.Item | nodes.Collector]: + if not self.config.getini("collect_imported_tests"): + # This entire branch will discard (not collect) a class + # if it is imported (defined in a different module) + if isinstance(self, Class) and isinstance(self.parent, Module): + if inspect.isclass(self._getobj()): + class_defined_at = self._getobj().__module__ + in_module = self.parent._getobj().__name__ + if class_defined_at != in_module: + return [] + if not safe_getattr(self.obj, "__test__", True): return [] if hasinit(self.obj): diff --git a/testing/test_collect_imports.py b/testing/test_collect_imports.py index 7922058721c..fe1e6b3e863 100644 --- a/testing/test_collect_imports.py +++ b/testing/test_collect_imports.py @@ -5,6 +5,9 @@ from _pytest.pytester import Pytester +# Start of tests for classes + + def run_import_class_test(pytester: Pytester, passed: int = 0, errors: int = 0) -> None: src_dir = pytester.mkdir("src") tests_dir = pytester.mkdir("tests") @@ -57,26 +60,37 @@ def test_collect_imports_disabled(pytester: Pytester) -> None: run_import_class_test(pytester, passed=1) + # Verify that the state of hooks + reprec = pytester.inline_run() + items_collected = reprec.getcalls("pytest_itemcollected") + assert len(items_collected) == 1 + for x in items_collected: + assert x.item._getobj().__name__ == "test_testament" -def test_collect_imports_default(pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - testpaths = "tests" - """) +def test_collect_imports_default(pytester: Pytester) -> None: run_import_class_test(pytester, errors=1) + # TODO, hooks + def test_collect_imports_enabled(pytester: Pytester) -> None: pytester.makeini(""" [pytest] - testpaths = "tests" collect_imported_tests = true """) run_import_class_test(pytester, errors=1) +# # TODO, hooks + + +# End of tests for classes +################################# +# Start of tests for functions + + def run_import_functions_test( pytester: Pytester, passed: int, errors: int, failed: int ) -> None: @@ -85,8 +99,8 @@ def run_import_functions_test( src_file = src_dir / "foo.py" - # Note that these "tests" are should _not_ be treated as tests. - # They are normal functions that happens to have test_* or *_test in the name. + # Note that these "tests" should _not_ be treated as tests if `collect_imported_tests = false` + # They are normal functions in that case, that happens to have test_* or *_test in the name. # Thus should _not_ be collected! src_file.write_text( textwrap.dedent("""\ @@ -121,7 +135,6 @@ def test_important(self): res = test_function() if res == 5: pass - """), encoding="utf-8", ) @@ -138,31 +151,83 @@ def test_collect_function_imports_enabled(pytester: Pytester) -> None: """) run_import_functions_test(pytester, passed=2, errors=0, failed=1) + reprec = pytester.inline_run() + items_collected = reprec.getcalls("pytest_itemcollected") + # Recall that the default is `collect_imported_tests = true`. + # Which means that the normal functions are now interpreted as + # valid tests and `test_function()` will fail. + assert len(items_collected) == 3 + for x in items_collected: + assert x.item._getobj().__name__ in [ + "test_important", + "test_bar", + "test_function", + ] -def test_collect_function_imports_disabled(pytester: Pytester) -> None: +def test_behaviour_without_testpaths_set_and_false(pytester: Pytester) -> None: + # Make sure `collect_imported_tests` has no dependence on `testpaths` pytester.makeini(""" [pytest] - # testpaths = "tests" collect_imported_tests = false """) run_import_functions_test(pytester, passed=1, errors=0, failed=0) + reprec = pytester.inline_run() + items_collected = reprec.getcalls("pytest_itemcollected") + assert len(items_collected) == 1 + for x in items_collected: + assert x.item._getobj().__name__ == "test_important" -def test_behaviour_without_testpaths_set_and_false(pytester: Pytester) -> None: +def test_behaviour_without_testpaths_set_and_true(pytester: Pytester) -> None: + # Make sure `collect_imported_tests` has no dependence on `testpaths` pytester.makeini(""" [pytest] - collect_imported_tests = false + collect_imported_tests = true """) - run_import_functions_test(pytester, passed=1, errors=0, failed=0) + run_import_functions_test(pytester, passed=2, errors=0, failed=1) + reprec = pytester.inline_run() + items_collected = reprec.getcalls("pytest_itemcollected") + assert len(items_collected) == 3 -def test_behaviour_without_testpaths_set_and_true(pytester: Pytester) -> None: +def test_hook_behaviour_when_collect_off(pytester: Pytester) -> None: pytester.makeini(""" [pytest] - collect_imported_tests = true + collect_imported_tests = false """) - run_import_functions_test(pytester, passed=2, errors=0, failed=1) + run_import_functions_test(pytester, passed=1, errors=0, failed=0) + reprec = pytester.inline_run() + + # reports = reprec.getreports("pytest_collectreport") + items_collected = reprec.getcalls("pytest_itemcollected") + modified = reprec.getcalls("pytest_collection_modifyitems") + + # print("Reports: ----------------") + # print(reports) + # for r in reports: + # print(r) + + # TODO this is want I want, I think.... + # + # + # + # + # + + # TODO + # assert(reports.outcome == "passed") + # assert(len(reports.result) == 1) + + # print("Items collected: ----------------") + # print(items_collected) + # print("Modified : ----------------") + + assert len(items_collected) == 1 + for x in items_collected: + assert x.item._getobj().__name__ == "test_important" + + assert len(modified) == 1 From 3ef3c2d83498f550e8e678e209c6739dccfabe55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 06:15:25 +0100 Subject: [PATCH 0926/1271] build(deps): Bump hynek/build-and-inspect-python-package (#12936) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.9.0 to 2.10.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.9.0...v2.10.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 998a2839dc2..974fe4947db 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.9.0 + uses: hynek/build-and-inspect-python-package@v2.10.0 with: attest-build-provenance-github: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ff5b18e2fca..52faca6ddef 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.9.0 + uses: hynek/build-and-inspect-python-package@v2.10.0 build: needs: [package] From 3ce9be96a11aad3f148c6ab11709cfa940cadea2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 13:42:16 +0100 Subject: [PATCH 0927/1271] build(deps): Bump pytest-cov in /testing/plugins_integration (#12937) Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 5.0.0 to 6.0.0. - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v5.0.0...v6.0.0) --- updated-dependencies: - dependency-name: pytest-cov dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index c465041d64d..ef01747f2fd 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -2,7 +2,7 @@ anyio[curio,trio]==4.6.2.post1 django==5.1.2 pytest-asyncio==0.24.0 pytest-bdd==7.3.0 -pytest-cov==5.0.0 +pytest-cov==6.0.0 pytest-django==4.9.0 pytest-flakes==4.0.5 pytest-html==4.1.1 From 8889e9b7f4fa6e0acf3088c7049330137903af85 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 08:16:16 -0300 Subject: [PATCH 0928/1271] [automated] Update plugin list (#12933) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 176 +++++++++++++++++-------------- 1 file changed, 96 insertions(+), 80 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 1cd265578eb..50206c34150 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest - :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Aug 08, 2024 N/A pytest + :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 22, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A - :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 25, 2022 5 - Production/Stable pytest (>=3.8) + :pypi:`pytest-benchmark` A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. Oct 30, 2024 5 - Production/Stable pytest>=8.1 :pypi:`pytest-better-datadir` A small example package Mar 13, 2023 N/A N/A :pypi:`pytest-better-parametrize` Better description of parametrized test cases Mar 05, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-bg-process` Pytest plugin to initialize background process Jan 24, 2022 4 - Beta pytest (>=3.5.0) @@ -234,7 +234,7 @@ This list contains 1536 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 20, 2024 N/A N/A :pypi:`pytest-ch-framework` My pytest framework Apr 17, 2024 N/A pytest==8.0.1 - :pypi:`pytest-chic-report` A pytest plugin to send a report and printing summary of tests. Jan 31, 2023 5 - Production/Stable N/A + :pypi:`pytest-chic-report` Simple pytest plugin for generating and sending report to messengers. Nov 01, 2024 N/A pytest>=6.0 :pypi:`pytest-choose` Provide the pytest with the ability to collect use cases based on rules in text files Feb 04, 2024 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_cid` Compare data structures containing matching CIDs of different versions and encoding Sep 01, 2023 4 - Beta pytest >= 5.0, < 7.0 @@ -254,7 +254,7 @@ This list contains 1536 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Oct 16, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Oct 27, 2024 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) @@ -265,7 +265,7 @@ This list contains 1536 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Sep 27, 2024 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Oct 29, 2024 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -290,7 +290,7 @@ This list contains 1536 plugins. :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A - :pypi:`pytest-cov` Pytest plugin for measuring coverage. Mar 24, 2024 5 - Production/Stable pytest>=4.6 + :pypi:`pytest-cov` Pytest plugin for measuring coverage. Oct 29, 2024 5 - Production/Stable pytest>=4.6 :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A @@ -465,14 +465,14 @@ This list contains 1536 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 Jul 25, 2024 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. Oct 25, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Oct 25, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Oct 25, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Oct 25, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Oct 25, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Oct 25, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Oct 25, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Oct 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Oct 29, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Oct 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Oct 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Oct 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Oct 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Oct 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Oct 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Oct 29, 2024 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) @@ -500,11 +500,11 @@ This list contains 1536 plugins. :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Aug 13, 2024 4 - Beta pytest>=7 - :pypi:`pytest-exasol-backend` Sep 18, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-backend` Oct 31, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-extension` Oct 10, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-slc` Sep 24, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-slc` Nov 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -647,7 +647,7 @@ This list contains 1536 plugins. :pypi:`pytest-hardware-test-report` A simple plugin to use with pytest Apr 01, 2024 4 - Beta pytest<9.0.0,>=8.0.0 :pypi:`pytest-harmony` Chain tests and data with pytest Jan 17, 2023 N/A pytest (>=7.2.1,<8.0.0) :pypi:`pytest-harvest` Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. Mar 16, 2024 5 - Production/Stable N/A - :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Oct 23, 2024 4 - Beta pytest<9.0.0,>=8.0.0 + :pypi:`pytest-helm-charts` A plugin to provide different types and configs of Kubernetes clusters that can be used for testing. Oct 31, 2024 4 - Beta pytest<9.0.0,>=8.0.0 :pypi:`pytest-helm-templates` Pytest fixtures for unit testing the output of helm templates Aug 07, 2024 N/A pytest~=7.4.0; extra == "dev" :pypi:`pytest-helper` Functions to help in using the pytest testing framework May 31, 2019 5 - Production/Stable N/A :pypi:`pytest-helpers` pytest helpers May 17, 2020 N/A pytest @@ -660,7 +660,7 @@ This list contains 1536 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Oct 26, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Nov 01, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -685,7 +685,7 @@ This list contains 1536 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Aug 10, 2024 N/A pytest<9.0.0,>=8.2.0 - :pypi:`pytest-httpx` Send responses to httpx. Sep 27, 2024 5 - Production/Stable pytest==8.* + :pypi:`pytest-httpx` Send responses to httpx. Oct 28, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -715,7 +715,7 @@ This list contains 1536 plugins. :pypi:`pytest-inline` A pytest plugin for writing inline tests Oct 24, 2024 4 - Beta pytest<9.0,>=7.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Oct 10, 2024 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 10, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Aug 20, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Oct 29, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest @@ -732,11 +732,12 @@ This list contains 1536 plugins. :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Oct 15, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Oct 28, 2024 N/A pytest :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Sep 18, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A + :pypi:`pytest-item-dict` Get a hierarchical dict of session.items Oct 30, 2024 4 - Beta pytest>=8.3.0 :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iteration` Add iteration mark for tests Aug 22, 2024 N/A pytest :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A @@ -747,7 +748,7 @@ This list contains 1536 plugins. :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 30, 2024 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jul 09, 2024 N/A pytest>=7.2.0 - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Jul 19, 2024 4 - Beta pytest>=6.2.4 + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Oct 27, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -775,7 +776,7 @@ This list contains 1536 plugins. :pypi:`pytest-kookit` Your simple but kooky integration testing with pytest Sep 10, 2024 N/A N/A :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A - :pypi:`pytest-kubernetes` Sep 14, 2023 N/A pytest (>=7.2.1,<8.0.0) + :pypi:`pytest-kubernetes` Oct 28, 2024 N/A pytest<9.0.0,>=8.3.0 :pypi:`pytest-kuunda` pytest plugin to help with test data setup for PySpark tests Feb 25, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-kwparametrize` Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks Jan 22, 2021 N/A pytest (>=6) :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. May 27, 2024 5 - Production/Stable pytest<9,>=3.6 @@ -817,7 +818,7 @@ This list contains 1536 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Aug 30, 2024 5 - Production/Stable pytest==8.3.2 + :pypi:`pytest-logikal` Common testing environment Oct 28, 2024 5 - Production/Stable pytest==8.3.3 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" @@ -829,7 +830,7 @@ This list contains 1536 plugins. :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Oct 22, 2024 N/A pytest>=7.0.0 :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A - :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Feb 04, 2021 4 - Beta pytest (>=6.0) + :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Oct 30, 2024 4 - Beta pytest>=6.0 :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A :pypi:`pytest-mark-manage` 用例标签化管理 Aug 15, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest @@ -977,7 +978,7 @@ This list contains 1536 plugins. :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A - :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Sep 23, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 + :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Oct 30, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Oct 22, 2024 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest @@ -1096,7 +1097,7 @@ This list contains 1536 plugins. :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-qanova` A pytest plugin to collect test information Sep 05, 2024 3 - Alpha pytest - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration May 30, 2024 4 - Beta pytest<9.0.0,>=7.2.2 + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Oct 28, 2024 5 - Production/Stable pytest<9.0.0,>=7.2.2 :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 14, 2024 5 - Production/Stable pytest>=6.0 @@ -1126,7 +1127,7 @@ This list contains 1536 plugins. :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jun 27, 2024 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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-record-video` 用例执行过程中录制视频 Aug 15, 2024 N/A N/A + :pypi:`pytest-record-video` 用例执行过程中录制视频 Oct 31, 2024 N/A N/A :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Jun 19, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A @@ -1157,7 +1158,7 @@ This list contains 1536 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Oct 22, 2024 N/A pytest>=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Oct 31, 2024 N/A pytest>=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A :pypi:`pytest-req` pytest requests plugin Aug 31, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.2 @@ -1223,10 +1224,10 @@ This list contains 1536 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Oct 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 01, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 - :pypi:`pytest-schedule` The job of test scheduling for humans. Jan 07, 2023 5 - Production/Stable N/A + :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Feb 16, 2024 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-scrutinize` Scrutinize your pytest test suites for slow fixtures, tests and more. Aug 19, 2024 4 - Beta pytest>=6 @@ -1234,7 +1235,7 @@ This list contains 1536 plugins. :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 Feb 01, 2024 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. Oct 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 01, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1313,7 +1314,7 @@ This list contains 1536 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 Sep 04, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Oct 28, 2024 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Sep 26, 2024 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 @@ -1335,6 +1336,7 @@ This list contains 1536 plugins. :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A :pypi:`pytest-stf` pytest plugin for openSTF Sep 24, 2024 N/A pytest>=5.0 + :pypi:`pytest-stochastics` pytest plugin that allows selectively running tests several times and accepting \*some\* failures. Oct 31, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Sep 04, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) @@ -1467,7 +1469,7 @@ This list contains 1536 plugins. :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 Feb 01, 2024 4 - Beta N/A :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Aug 15, 2023 4 - Beta N/A - :pypi:`pytest-typing-runner` Pytest plugin to make it easier to run and check python code against static type checkers Sep 09, 2024 N/A pytest==8.2.2; extra == "tests" + :pypi:`pytest-typing-runner` Pytest plugin to make it easier to run and check python code against static type checkers Oct 27, 2024 N/A N/A :pypi:`pytest-tytest` Typhoon HIL plugin for pytest May 25, 2020 4 - Beta pytest (>=5.4.2) :pypi:`pytest-ubersmith` Easily mock calls to ubersmith at the \`requests\` level. Apr 13, 2015 N/A N/A :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest @@ -2430,7 +2432,7 @@ This list contains 1536 plugins. A pytest plugin that reports test results to the BeakerLib framework :pypi:`pytest-beartype` - *last release*: Aug 08, 2024, + *last release*: Oct 31, 2024, *status*: N/A, *requires*: pytest @@ -2465,9 +2467,9 @@ This list contains 1536 plugins. Benchmark utility that plugs into pytest. :pypi:`pytest-benchmark` - *last release*: Oct 25, 2022, + *last release*: Oct 30, 2024, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.8) + *requires*: pytest>=8.1 A \`\`pytest\`\` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. @@ -2976,11 +2978,11 @@ This list contains 1536 plugins. My pytest framework :pypi:`pytest-chic-report` - *last release*: Jan 31, 2023, - *status*: 5 - Production/Stable, - *requires*: N/A + *last release*: Nov 01, 2024, + *status*: N/A, + *requires*: pytest>=6.0 - A pytest plugin to send a report and printing summary of tests. + Simple pytest plugin for generating and sending report to messengers. :pypi:`pytest-choose` *last release*: Feb 04, 2024, @@ -3116,7 +3118,7 @@ This list contains 1536 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Oct 16, 2024, + *last release*: Oct 27, 2024, *status*: N/A, *requires*: pytest<9,>=4 @@ -3193,7 +3195,7 @@ This list contains 1536 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Sep 27, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3368,7 +3370,7 @@ This list contains 1536 plugins. count erros and send email :pypi:`pytest-cov` - *last release*: Mar 24, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=4.6 @@ -4593,56 +4595,56 @@ This list contains 1536 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Oct 25, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Oct 25, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Oct 25, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Oct 25, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-qemu` - *last release*: Oct 25, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Oct 25, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Oct 25, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Oct 25, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4838,7 +4840,7 @@ This list contains 1536 plugins. Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-exasol-backend` - *last release*: Sep 18, 2024, + *last release*: Oct 31, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -4866,7 +4868,7 @@ This list contains 1536 plugins. :pypi:`pytest-exasol-slc` - *last release*: Sep 24, 2024, + *last release*: Nov 01, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -5867,7 +5869,7 @@ This list contains 1536 plugins. Store data created during your pytest tests execution, and retrieve it at the end of the session, e.g. for applicative benchmarking purposes. :pypi:`pytest-helm-charts` - *last release*: Oct 23, 2024, + *last release*: Oct 31, 2024, *status*: 4 - Beta, *requires*: pytest<9.0.0,>=8.0.0 @@ -5958,7 +5960,7 @@ This list contains 1536 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Oct 26, 2024, + *last release*: Nov 01, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6133,7 +6135,7 @@ This list contains 1536 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Sep 27, 2024, + *last release*: Oct 28, 2024, *status*: 5 - Production/Stable, *requires*: pytest==8.* @@ -6343,7 +6345,7 @@ This list contains 1536 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Aug 20, 2024, + *last release*: Oct 29, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6462,7 +6464,7 @@ This list contains 1536 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Oct 15, 2024, + *last release*: Oct 28, 2024, *status*: N/A, *requires*: pytest @@ -6496,6 +6498,13 @@ This list contains 1536 plugins. Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. + :pypi:`pytest-item-dict` + *last release*: Oct 30, 2024, + *status*: 4 - Beta, + *requires*: pytest>=8.3.0 + + Get a hierarchical dict of session.items + :pypi:`pytest-iterassert` *last release*: May 11, 2020, *status*: 3 - Alpha, @@ -6567,7 +6576,7 @@ This list contains 1536 plugins. Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: Jul 19, 2024, + *last release*: Oct 27, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.4 @@ -6763,9 +6772,9 @@ This list contains 1536 plugins. pytest krtech common library :pypi:`pytest-kubernetes` - *last release*: Sep 14, 2023, + *last release*: Oct 28, 2024, *status*: N/A, - *requires*: pytest (>=7.2.1,<8.0.0) + *requires*: pytest<9.0.0,>=8.3.0 @@ -7057,9 +7066,9 @@ This list contains 1536 plugins. :pypi:`pytest-logikal` - *last release*: Aug 30, 2024, + *last release*: Oct 28, 2024, *status*: 5 - Production/Stable, - *requires*: pytest==8.3.2 + *requires*: pytest==8.3.3 Common testing environment @@ -7141,9 +7150,9 @@ This list contains 1536 plugins. py.test bugzilla integration plugin, using markers :pypi:`pytest-markers-presence` - *last release*: Feb 04, 2021, + *last release*: Oct 30, 2024, *status*: 4 - Beta, - *requires*: pytest (>=6.0) + *requires*: pytest>=6.0 A simple plugin to detect missed pytest tags and markers" @@ -8177,7 +8186,7 @@ This list contains 1536 plugins. Simpler PyTest parametrization :pypi:`pytest-parametrize` - *last release*: Sep 23, 2024, + *last release*: Oct 30, 2024, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=8.3.0 @@ -9010,8 +9019,8 @@ This list contains 1536 plugins. A pytest plugin to collect test information :pypi:`pytest-qaseio` - *last release*: May 30, 2024, - *status*: 4 - Beta, + *last release*: Oct 28, 2024, + *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=7.2.2 Pytest plugin for Qase.io integration @@ -9220,7 +9229,7 @@ This list contains 1536 plugins. Provides pytest plugins for reporting request/response traffic, screenshots, and more to ReportPortal :pypi:`pytest-record-video` - *last release*: Aug 15, 2024, + *last release*: Oct 31, 2024, *status*: N/A, *requires*: N/A @@ -9437,7 +9446,7 @@ This list contains 1536 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Oct 22, 2024, + *last release*: Oct 31, 2024, *status*: N/A, *requires*: pytest>=3.8.0 @@ -9899,7 +9908,7 @@ This list contains 1536 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Oct 26, 2024, + *last release*: Nov 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9920,11 +9929,11 @@ This list contains 1536 plugins. A pytest plugin that generates unit test scenarios from data files. :pypi:`pytest-schedule` - *last release*: Jan 07, 2023, - *status*: 5 - Production/Stable, + *last release*: Oct 31, 2024, + *status*: N/A, *requires*: N/A - The job of test scheduling for humans. + Automate and customize test scheduling effortlessly on local machines. :pypi:`pytest-schema` *last release*: Feb 16, 2024, @@ -9976,7 +9985,7 @@ This list contains 1536 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Oct 26, 2024, + *last release*: Nov 01, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10529,7 +10538,7 @@ This list contains 1536 plugins. :pypi:`pytest-splunk-addon` - *last release*: Sep 04, 2024, + *last release*: Oct 28, 2024, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10682,6 +10691,13 @@ This list contains 1536 plugins. pytest plugin for openSTF + :pypi:`pytest-stochastics` + *last release*: Oct 31, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.0.0 + + pytest plugin that allows selectively running tests several times and accepting \*some\* failures. + :pypi:`pytest-stoq` *last release*: Feb 09, 2021, *status*: 4 - Beta, @@ -11607,9 +11623,9 @@ This list contains 1536 plugins. Typhoon HIL plugin for pytest :pypi:`pytest-typing-runner` - *last release*: Sep 09, 2024, + *last release*: Oct 27, 2024, *status*: N/A, - *requires*: pytest==8.2.2; extra == "tests" + *requires*: N/A Pytest plugin to make it easier to run and check python code against static type checkers From 5beab07de39dc4dd8a8db289f934288ae5be6bfc Mon Sep 17 00:00:00 2001 From: jakkdl Date: Wed, 6 Nov 2024 14:02:25 +0100 Subject: [PATCH 0929/1271] improve warning message. Make it warn regardless of autouse or not. Add section to deprecations.rst --- changelog/10839.deprecation.rst | 2 +- changelog/10839.improvement.rst | 1 - doc/en/deprecations.rst | 55 +++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- src/_pytest/fixtures.py | 19 +++++++----- testing/acceptance_test.py | 40 +++++++++++++++--------- 6 files changed, 93 insertions(+), 26 deletions(-) delete mode 100644 changelog/10839.improvement.rst diff --git a/changelog/10839.deprecation.rst b/changelog/10839.deprecation.rst index c0628191663..78ad4e118e4 100644 --- a/changelog/10839.deprecation.rst +++ b/changelog/10839.deprecation.rst @@ -1 +1 @@ -Synchronous tests that request an asynchronous fixture with ``autouse=True`` will now give a DeprecationWarning. +Synchronous tests that request an asynchronous fixture will now give a DeprecationWarning. This will introduce warnings in several pytest plugins that handle async tests/fixtures and for some users with custom setups. For guidance on how to manage this see :ref:`sync-test-async-fixture`. diff --git a/changelog/10839.improvement.rst b/changelog/10839.improvement.rst deleted file mode 100644 index 0a382053c85..00000000000 --- a/changelog/10839.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Synchronous tests that request asynchronous fixtures will now error, instead of silently accepting an unawaited coroutine object as the fixture value. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index e55f0d71c2e..b384f01dfab 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -15,6 +15,61 @@ Below is a complete list of all pytest features which are considered deprecated. :class:`~pytest.PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters `. +.. _sync-test-async-fixture: + +sync test depending on async fixture +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. deprecated:: 8.4 + +Pytest has for a long time given an error when encountering an asynchronous test function, prompting the user to install +a plugin that can handle it. It has not given any errors if you have an asynchronous fixture that's depended on by a +synchronous test. This is a problem even if you do have a plugin installed for handling async tests, as they may require +special decorators for async fixtures to be handled, and some may not robustly handle if a user accidentally requests an +async fixture from their sync tests. Fixture values being cached can make this even more unintuitive, where everything will +"work" if the fixture is first requested by an async test, and then requested by a synchronous test. + +Unfortunately there is no 100% reliable method of identifying when a user has made a mistake, versus when they expect an +unawaited object from their fixture that they will handle - either on their own, or by a plugin. To suppress this warning +when you in fact did intend to handle this you can wrap your async fixture in a synchronous fixture: + +.. code-block:: python + + import asyncio + import pytest + + + @pytest.fixture + async def unawaited_fixture(): + return 1 + + + def test_foo(unawaited_fixture): + assert 1 == asyncio.run(unawaited_fixture) + +should be changed to + + +.. code-block:: python + + import asyncio + import pytest + + + @pytest.fixture + def unawaited_fixture(): + async def inner_fixture(): + return 1 + + return inner_fixture() + + + def test_foo(unawaited_fixture): + assert 1 == asyncio.run(unawaited_fixture) + +If a user has an async fixture with ``autouse=True`` in their ``conftest.py``, or in a file where they also have synchronous tests, they will also get this warning. We strongly recommend against this practice, and they should restructure their testing infrastructure so the fixture is synchronous or to separate the fixture from their synchronous tests. Plugins that handle async may want to introduce helpers to make that easier in scenarios where that might be wanted, e.g. if setting up a database in an asynchronous way, or the user may opt to make their test async even though it might not strictly need to be. + + .. _import-or-skip-import-error: ``pytest.importorskip`` default behavior regarding :class:`ImportError` diff --git a/pyproject.toml b/pyproject.toml index caeb4bf7f83..b023f788563 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -308,7 +308,7 @@ disable = [ ] [tool.codespell] -ignore-words-list = "afile,asser,assertio,feld,hove,ned,noes,notin,paramete,parth,socio-economic,tesults,varius,wil" +ignore-words-list = "afile,asend,asser,assertio,feld,hove,ned,noes,notin,paramete,parth,socio-economic,tesults,varius,wil" skip = "*/plugin_list.rst" write-changes = true diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index da6625fb7e1..4b45489cd96 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -609,23 +609,26 @@ def _get_active_fixturedef( if fixturedef._autouse: warnings.warn( PytestRemovedIn9Warning( - "Sync test requested an async fixture with autouse=True. " + f"Sync test {self._pyfuncitem.name!r} requested async fixture " + f"{argname!r} with autouse=True. " "If you intended to use the fixture you may want to make the " - "test asynchronous. If you did not intend to use it you should " + "test asynchronous or the fixture synchronous. " + "If you did not intend to use it you should " "restructure your test setup. " "This will turn into an error in pytest 9." ), stacklevel=3, ) else: - raise FixtureLookupError( - argname, - self, - ( - "ERROR: Sync test requested async fixture. " + warnings.warn( + PytestRemovedIn9Warning( + f"Sync test {self._pyfuncitem.name!r} requested async fixture " + f"{argname!r}. " "You may want to make the test asynchronous and run it with " - "a suitable async framework test plugin." + "a suitable async framework test plugin, or make the fixture synchronous. " + "This will turn into an error in pytest 9." ), + stacklevel=3, ) # Prepare a SubRequest object for calling the fixture. diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 0437cae4047..699ad4797b9 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1296,21 +1296,26 @@ async def async_fixture(): ... def test_foo(async_fixture): - ... + # suppress unawaited coroutine warning + try: + async_fixture.send(None) + except StopIteration: + pass """ ) result = pytester.runpytest() result.stdout.fnmatch_lines( [ ( - "*ERROR: Sync test requested async fixture. " + "*Sync test 'test_foo' requested async fixture " + "'async_fixture'. " "You may want to make the test asynchronous and run it with " - "a suitable async framework test plugin.*" + "a suitable async framework test plugin, or make the fixture synchronous. " + "This will turn into an error in pytest 9." ), - "*ERROR test_sync.py::test_foo*", ] ) - result.assert_outcomes(errors=1) + result.assert_outcomes(passed=1, warnings=1) def test_error_on_sync_test_async_fixture_gen(pytester: Pytester) -> None: @@ -1323,21 +1328,26 @@ async def async_fixture(): yield def test_foo(async_fixture): - ... + # suppress unawaited coroutine warning + try: + async_fixture.asend(None) + except StopIteration: + pass """ ) result = pytester.runpytest() result.stdout.fnmatch_lines( [ ( - "*ERROR: Sync test requested async fixture. " + "*Sync test 'test_foo' requested async fixture " + "'async_fixture'. " "You may want to make the test asynchronous and run it with " - "a suitable async framework test plugin.*" + "a suitable async framework test plugin, or make the fixture synchronous. " + "This will turn into an error in pytest 9." ), - "*ERROR test_sync.py::test_foo*", ] ) - result.assert_outcomes(errors=1) + result.assert_outcomes(passed=1, warnings=1) def test_warning_on_sync_test_async_autouse_fixture(pytester: Pytester) -> None: @@ -1362,11 +1372,11 @@ def test_foo(async_fixture): result.stdout.fnmatch_lines( [ ( - "*Sync test requested an async fixture with autouse=True. " - "If you intended to use the fixture you may want to make the " - "test asynchronous. If you did not intend to use it you should " - "restructure your test setup. " - "This will turn into an error in pytest 9.*" + "*Sync test 'test_foo' requested async fixture " + "'async_fixture' with autouse=True. " + "You may want to make the test asynchronous and run it with " + "a suitable async framework test plugin, or make the fixture synchronous. " + "This will turn into an error in pytest 9." ), ] ) From 0de5302bfde78747ca6b4d468d7d60658f43307c Mon Sep 17 00:00:00 2001 From: jakkdl Date: Wed, 6 Nov 2024 14:12:12 +0100 Subject: [PATCH 0930/1271] fix test --- testing/acceptance_test.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 699ad4797b9..a7a9afedbc0 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1286,7 +1286,7 @@ def test_3(): result.assert_outcomes(failed=3) -def test_error_on_sync_test_async_fixture(pytester: Pytester) -> None: +def test_warning_on_sync_test_async_fixture(pytester: Pytester) -> None: pytester.makepyfile( test_sync=""" import pytest @@ -1318,7 +1318,7 @@ def test_foo(async_fixture): result.assert_outcomes(passed=1, warnings=1) -def test_error_on_sync_test_async_fixture_gen(pytester: Pytester) -> None: +def test_warning_on_sync_test_async_fixture_gen(pytester: Pytester) -> None: pytester.makepyfile( test_sync=""" import pytest @@ -1374,13 +1374,15 @@ def test_foo(async_fixture): ( "*Sync test 'test_foo' requested async fixture " "'async_fixture' with autouse=True. " - "You may want to make the test asynchronous and run it with " - "a suitable async framework test plugin, or make the fixture synchronous. " + "If you intended to use the fixture you may want to make the " + "test asynchronous or the fixture synchronous. " + "If you did not intend to use it you should " + "restructure your test setup. " "This will turn into an error in pytest 9." ), ] ) - result.assert_outcomes(passed=1) + result.assert_outcomes(passed=1, warnings=1) def test_pdb_can_be_rewritten(pytester: Pytester) -> None: From c85faf05d9db7c4bc2c24cd855b058d856efe8a2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 6 Nov 2024 13:30:49 -0300 Subject: [PATCH 0931/1271] Rename changelog entries to 'breaking' (#12942) Follow up to https://github.com/pytest-dev/pytest/pull/12346. --- changelog/{11372.improvement.rst => 11372.breaking.rst} | 0 changelog/{12346.misc.rst => 12346.breaking.rst} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename changelog/{11372.improvement.rst => 11372.breaking.rst} (100%) rename changelog/{12346.misc.rst => 12346.breaking.rst} (100%) diff --git a/changelog/11372.improvement.rst b/changelog/11372.breaking.rst similarity index 100% rename from changelog/11372.improvement.rst rename to changelog/11372.breaking.rst diff --git a/changelog/12346.misc.rst b/changelog/12346.breaking.rst similarity index 100% rename from changelog/12346.misc.rst rename to changelog/12346.breaking.rst From 48bcb05e1d87e5128b94285b4a00ecff8e00f778 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:01:37 +0000 Subject: [PATCH 0932/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.9 → v0.7.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.9...v0.7.2) - [github.com/adamchainz/blacken-docs: 1.19.0 → 1.19.1](https://github.com/adamchainz/blacken-docs/compare/1.19.0...1.19.1) - [github.com/pre-commit/mirrors-mypy: v1.11.2 → v1.13.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.11.2...v1.13.0) - [github.com/tox-dev/pyproject-fmt: 2.3.1 → v2.5.0](https://github.com/tox-dev/pyproject-fmt/compare/2.3.1...v2.5.0) - [github.com/asottile/pyupgrade: v3.18.0 → v3.19.0](https://github.com/asottile/pyupgrade/compare/v3.18.0...v3.19.0) [mypy] Remove useless noqa, add noqa for new false positives Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) --- .pre-commit-config.yaml | 11 ++++++----- pyproject.toml | 3 ++- src/_pytest/_io/pprint.py | 6 +++--- src/_pytest/capture.py | 6 ++++-- testing/test_runner.py | 4 ++-- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 096228acf9f..04971cf9fb2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.9" + rev: "v0.7.2" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/adamchainz/blacken-docs - rev: 1.19.0 + rev: 1.19.1 hooks: - id: blacken-docs additional_dependencies: [black==24.1.1] @@ -28,7 +28,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.2 + rev: v1.13.0 hooks: - id: mypy files: ^(src/|testing/|scripts/) @@ -44,13 +44,13 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "2.3.1" + rev: "v2.5.0" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version additional_dependencies: ["tox>=4.9"] - repo: https://github.com/asottile/pyupgrade - rev: v3.18.0 + rev: v3.19.0 hooks: - id: pyupgrade stages: [manual] @@ -62,6 +62,7 @@ repos: language: system types: [python] args: ["-rn", "-sn", "--fail-on=I"] + require_serial: true stages: [manual] - id: rst name: rst diff --git a/pyproject.toml b/pyproject.toml index caeb4bf7f83..2f3a17e04b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ dependencies = [ "exceptiongroup>=1.0.0rc8; python_version<'3.11'", "iniconfig", "packaging", - "pluggy<2,>=1.5", + "pluggy>=1.5,<2", "tomli>=1; python_version<'3.11'", ] optional-dependencies.dev = [ @@ -275,6 +275,7 @@ disable = [ "too-many-lines", "too-many-locals", "too-many-nested-blocks", + "too-many-positional-arguments", "too-many-public-methods", "too-many-return-statements", # disabled in ruff "too-many-statements", # disabled in ruff diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index fc29989be0b..7a6433d9128 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -111,15 +111,15 @@ def _format( p(self, object, stream, indent, allowance, context, level + 1) context.remove(objid) elif ( - _dataclasses.is_dataclass(object) # type:ignore[unreachable] + _dataclasses.is_dataclass(object) and not isinstance(object, type) - and object.__dataclass_params__.repr + and object.__dataclass_params__.repr # type:ignore[attr-defined] and # Check dataclass has generated repr method. hasattr(object.__repr__, "__wrapped__") and "__create_fn__" in object.__repr__.__wrapped__.__qualname__ ): - context.add(objid) # type:ignore[unreachable] + context.add(objid) self._pprint_dataclass( object, stream, indent, allowance, context, level + 1 ) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 506c0b3d287..2ac3b6bbc7f 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -15,6 +15,7 @@ from typing import Any from typing import AnyStr from typing import BinaryIO +from typing import cast from typing import Final from typing import final from typing import Generator @@ -177,7 +178,8 @@ def name(self) -> str: def mode(self) -> str: # TextIOWrapper doesn't expose a mode, but at least some of our # tests check it. - return self.buffer.mode.replace("b", "") + assert hasattr(self.buffer, "mode") + return cast(str, self.buffer.mode.replace("b", "")) class CaptureIO(io.TextIOWrapper): @@ -550,7 +552,7 @@ def snap(self) -> bytes: res = self.tmpfile.buffer.read() self.tmpfile.seek(0) self.tmpfile.truncate() - return res + return res # type: ignore[return-value] def writeorg(self, data: bytes) -> None: """Write to original file descriptor.""" diff --git a/testing/test_runner.py b/testing/test_runner.py index 0d9facdcd71..0245438a47d 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -137,8 +137,8 @@ def raiser(exc): ss.teardown_exact(None) mod, func = e.value.exceptions assert isinstance(mod, KeyError) - assert isinstance(func.exceptions[0], TypeError) # type: ignore - assert isinstance(func.exceptions[1], ValueError) # type: ignore + assert isinstance(func.exceptions[0], TypeError) + assert isinstance(func.exceptions[1], ValueError) def test_cached_exception_doesnt_get_longer(self, pytester: Pytester) -> None: """Regression test for #12204 (the "BTW" case).""" From 227b4602eedc9988557c83a3ebcf01b08d79f2fb Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 29 Oct 2024 10:08:27 +0100 Subject: [PATCH 0933/1271] Upgrade pylint version, activate all extensions --- .pre-commit-config.yaml | 2 +- pyproject.toml | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 04971cf9fb2..b8e7053e1c8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -61,7 +61,7 @@ repos: entry: pylint language: system types: [python] - args: ["-rn", "-sn", "--fail-on=I"] + args: ["-rn", "-sn", "--fail-on=I", "--enable-all-extentions"] require_serial: true stages: [manual] - id: rst diff --git a/pyproject.toml b/pyproject.toml index 2f3a17e04b8..020997e7869 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -200,7 +200,9 @@ disable = [ "arguments-renamed", "assigning-non-slot", "attribute-defined-outside-init", + "bad-builtin", "bad-classmethod-argument", + "bad-dunder-name", "bad-mcs-method-argument", "broad-exception-caught", "broad-exception-raised", @@ -209,25 +211,41 @@ disable = [ "comparison-with-callable", "comparison-with-itself", # PLR0124 from ruff "condition-evals-to-constant", + "consider-alternative-union-syntax", + "confusing-consecutive-elif", + "consider-using-any-or-all", + "consider-using-assignment-expr", "consider-using-dict-items", "consider-using-from-import", "consider-using-f-string", "consider-using-in", + "consider-using-namedtuple-or-dataclass", "consider-using-ternary", + "consider-using-tuple", "consider-using-with", "consider-using-from-import", # not activated by default, PLR0402 disabled in ruff + "consider-ternary-expression", "cyclic-import", + "differing-param-doc", + "docstring-first-line-empty", + "deprecated-argument", + "deprecated-attribute", + "deprecated-class", + "deprecated-typing-alias", + "dict-init-mutate", "disallowed-name", # foo / bar are used often in tests "duplicate-code", "else-if-used", # not activated by default, PLR5501 disabled in ruff "empty-comment", # not activated by default, PLR2044 disabled in ruff "eval-used", + "eq-without-hash", "exec-used", "expression-not-assigned", "fixme", "global-statement", # PLW0603 disabled in ruff "import-error", "import-outside-toplevel", + "import-private-name", "inconsistent-return-statements", "invalid-bool-returned", "invalid-name", @@ -238,8 +256,12 @@ disable = [ "magic-value-comparison", # not activated by default, PLR2004 disabled in ruff "method-hidden", "missing-docstring", + "missing-param-doc", + "missing-raises-doc", "missing-timeout", + "missing-type-doc", "misplaced-bare-raise", # PLE0704 from ruff + "misplaced-comparison-constant", "multiple-statements", # multiple-statements-on-one-line-colon (E701) from ruff "no-else-break", "no-else-continue", @@ -248,6 +270,7 @@ disable = [ "no-member", "no-name-in-module", "no-self-argument", + "no-self-use", "not-an-iterable", "not-callable", "pointless-exception-statement", # https://github.com/pytest-dev/pytest/pull/12379 @@ -260,12 +283,14 @@ disable = [ "redefined-builtin", "redefined-loop-name", # PLW2901 disabled in ruff "redefined-outer-name", + "redefined-variable-type", "reimported", "simplifiable-condition", "simplifiable-if-expression", "singleton-comparison", "superfluous-parens", "super-init-not-called", + "too-complex", "too-few-public-methods", "too-many-ancestors", "too-many-arguments", # disabled in ruff @@ -279,6 +304,7 @@ disable = [ "too-many-public-methods", "too-many-return-statements", # disabled in ruff "too-many-statements", # disabled in ruff + "too-many-try-statements", "try-except-raise", "typevar-name-incorrect-variance", # PLC0105 disabled in ruff "unbalanced-tuple-unpacking", @@ -300,10 +326,12 @@ disable = [ "use-dict-literal", "use-implicit-booleaness-not-comparison", "use-implicit-booleaness-not-len", + "use-set-for-membership", "useless-else-on-loop", # PLC0414 disabled in ruff "useless-import-alias", "useless-return", "using-constant-test", + "while-used", "wrong-import-order", # handled by isort / ruff "wrong-import-position", # handled by isort / ruff ] From 607b9f71bb666f0f748b09b70dc2b496c706edd2 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 29 Oct 2024 10:09:09 +0100 Subject: [PATCH 0934/1271] [pylint dict-init-mutate] Initialize a dict right off for speed --- pyproject.toml | 1 - src/_pytest/junitxml.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 020997e7869..ad0bca4374b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -232,7 +232,6 @@ disable = [ "deprecated-attribute", "deprecated-class", "deprecated-typing-alias", - "dict-init-mutate", "disallowed-name", # foo / bar are used often in tests "duplicate-code", "else-if-used", # not activated by default, PLR5501 disabled in ruff diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 3a2cb59a6c1..efe6f489b48 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -74,10 +74,10 @@ def merge_family(left, right) -> None: left.update(result) -families = {} -families["_base"] = {"testcase": ["classname", "name"]} -families["_base_legacy"] = {"testcase": ["file", "line", "url"]} - +families = { # pylint: disable=dict-init-mutate + "_base": {"testcase": ["classname", "name"]}, + "_base_legacy": {"testcase": ["file", "line", "url"]}, +} # xUnit 1.x inherits legacy attributes. families["xunit1"] = families["_base"].copy() merge_family(families["xunit1"], families["_base_legacy"]) From de56152bf57d5b450593b8f01c231428dec6e23c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 10 Nov 2024 08:39:36 +0000 Subject: [PATCH 0935/1271] [automated] Update plugin list (#12950) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 78 +++++++++++++++++++------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 50206c34150..ecd96b89967 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,15 +27,15 @@ please refer to `the update script =8.3 - :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A + :pypi:`databricks-labs-pytester` Python Testing for Databricks Nov 04, 2024 4 - Beta pytest>=8.3 + :pypi:`logassert` Simple but powerful assertion and verification of logged lines. Nov 08, 2024 5 - Production/Stable N/A :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A @@ -157,7 +157,7 @@ This list contains 1538 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 22, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Nov 05, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -246,7 +246,7 @@ This list contains 1538 plugins. :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A - :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Nov 08, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Oct 08, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) @@ -571,7 +571,7 @@ This list contains 1538 plugins. :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 15, 2024 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest - :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Jul 21, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Nov 09, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) @@ -601,7 +601,7 @@ This list contains 1538 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Oct 11, 2024 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Nov 07, 2024 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A @@ -616,7 +616,7 @@ This list contains 1538 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jul 08, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Nov 07, 2024 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -660,7 +660,7 @@ This list contains 1538 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 01, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Nov 09, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -730,6 +730,7 @@ This list contains 1538 plugins. :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Sep 25, 2024 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 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-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipywidgets` Oct 28, 2024 N/A pytest @@ -818,7 +819,7 @@ This list contains 1538 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Oct 28, 2024 5 - Production/Stable pytest==8.3.3 + :pypi:`pytest-logikal` Common testing environment Nov 09, 2024 5 - Production/Stable pytest==8.3.3 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" @@ -859,7 +860,7 @@ This list contains 1538 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 Feb 12, 2024 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 19, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Nov 04, 2024 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) @@ -1006,7 +1007,7 @@ This list contains 1538 plugins. :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) - :pypi:`pytest-picked` Run the tests related to the changed files Jul 27, 2023 N/A pytest (>=3.7.0) + :pypi:`pytest-picked` Run the tests related to the changed files Nov 06, 2024 N/A pytest>=3.7.0 :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) :pypi:`pytest-pikachu` Show surprise when tests are passing Aug 05, 2021 5 - Production/Stable pytest :pypi:`pytest-pilot` Slice in your test base thanks to powerful markers. Oct 09, 2020 5 - Production/Stable N/A @@ -1224,7 +1225,7 @@ This list contains 1538 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 09, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1235,7 +1236,7 @@ This list contains 1538 plugins. :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 Feb 01, 2024 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 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 09, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1281,6 +1282,7 @@ This list contains 1538 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A + :pypi:`pytest-smoke` pytest plugin for supporting smoke testing Nov 07, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -1358,7 +1360,7 @@ This list contains 1538 plugins. :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A - :pypi:`pytest_tagging` a pytest plugin to tag tests Aug 31, 2024 N/A pytest<8.0.0,>=7.1.3 + :pypi:`pytest_tagging` a pytest plugin to tag tests Nov 08, 2024 N/A pytest>=7.1.3 :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Sep 07, 2024 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) @@ -1578,14 +1580,14 @@ This list contains 1538 plugins. :pypi:`databricks-labs-pytester` - *last release*: Oct 11, 2024, + *last release*: Nov 04, 2024, *status*: 4 - Beta, *requires*: pytest>=8.3 Python Testing for Databricks :pypi:`logassert` - *last release*: May 20, 2022, + *last release*: Nov 08, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -2439,7 +2441,7 @@ This list contains 1538 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Oct 22, 2024, + *last release*: Nov 05, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3062,7 +3064,7 @@ This list contains 1538 plugins. Automated, comprehensive and well-organised pytest test cases. :pypi:`pytest-cleanuptotal` - *last release*: Sep 14, 2024, + *last release*: Nov 08, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5337,7 +5339,7 @@ This list contains 1538 plugins. A pytest plugin to assert type annotations at runtime. :pypi:`pytest-flake8` - *last release*: Jul 21, 2024, + *last release*: Nov 09, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -5547,7 +5549,7 @@ This list contains 1538 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Oct 11, 2024, + *last release*: Nov 07, 2024, *status*: N/A, *requires*: pytest @@ -5652,7 +5654,7 @@ This list contains 1538 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jul 08, 2024, + *last release*: Nov 07, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5960,7 +5962,7 @@ This list contains 1538 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Nov 01, 2024, + *last release*: Nov 09, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6449,6 +6451,13 @@ This list contains 1538 plugins. Run tests covering a specific file or changeset + :pypi:`pytest-iovis` + *last release*: Nov 06, 2024, + *status*: 4 - Beta, + *requires*: pytest>=7.1.0 + + A Pytest plugin to enable Jupyter Notebook testing with Papermill + :pypi:`pytest-ipdb` *last release*: Mar 20, 2013, *status*: 2 - Pre-Alpha, @@ -7066,7 +7075,7 @@ This list contains 1538 plugins. :pypi:`pytest-logikal` - *last release*: Oct 28, 2024, + *last release*: Nov 09, 2024, *status*: 5 - Production/Stable, *requires*: pytest==8.3.3 @@ -7353,7 +7362,7 @@ This list contains 1538 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Sep 19, 2024, + *last release*: Nov 04, 2024, *status*: N/A, *requires*: pytest @@ -8382,9 +8391,9 @@ This list contains 1538 plugins. pytest plugin to test Python examples in Markdown using phmdoctest. :pypi:`pytest-picked` - *last release*: Jul 27, 2023, + *last release*: Nov 06, 2024, *status*: N/A, - *requires*: pytest (>=3.7.0) + *requires*: pytest>=3.7.0 Run the tests related to the changed files @@ -9908,7 +9917,7 @@ This list contains 1538 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Nov 01, 2024, + *last release*: Nov 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9985,7 +9994,7 @@ This list contains 1538 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Nov 01, 2024, + *last release*: Nov 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10306,6 +10315,13 @@ This list contains 1538 plugins. Automated bad smell detection tool for Pytest + :pypi:`pytest-smoke` + *last release*: Nov 07, 2024, + *status*: 4 - Beta, + *requires*: pytest<9,>=7.0.0 + + pytest plugin for supporting smoke testing + :pypi:`pytest-smtp` *last release*: Feb 20, 2021, *status*: N/A, @@ -10846,9 +10862,9 @@ This list contains 1538 plugins. Pyst - Pytest System-Test Plugin :pypi:`pytest_tagging` - *last release*: Aug 31, 2024, + *last release*: Nov 08, 2024, *status*: N/A, - *requires*: pytest<8.0.0,>=7.1.3 + *requires*: pytest>=7.1.3 a pytest plugin to tag tests From 5f29c3e272557d3fc5c1c0eb68b76cfc41bded0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 07:39:17 +0100 Subject: [PATCH 0936/1271] build(deps): Bump django in /testing/plugins_integration (#12951) Bumps [django](https://github.com/django/django) from 5.1.2 to 5.1.3. - [Commits](https://github.com/django/django/compare/5.1.2...5.1.3) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index ef01747f2fd..32992dc2589 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.6.2.post1 -django==5.1.2 +django==5.1.3 pytest-asyncio==0.24.0 pytest-bdd==7.3.0 pytest-cov==6.0.0 From ea0fa639445ae08616edd2c15189a1a76168f018 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 08:39:14 +0100 Subject: [PATCH 0937/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.10.3 to 1.12.2 (#12953) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.10.3 to 1.12.2. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.10.3...v1.12.2) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 974fe4947db..3d3cb7534a4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.10.3 + uses: pypa/gh-action-pypi-publish@v1.12.2 with: attestations: true From 1891fedbb1e37c9e61cbdcdaf2d05f5493a24d2c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 6 Nov 2024 13:30:49 -0300 Subject: [PATCH 0938/1271] Rename changelog entries to 'breaking' (#12942) Follow up to https://github.com/pytest-dev/pytest/pull/12346. --- changelog/{11372.improvement.rst => 11372.breaking.rst} | 0 changelog/{12346.misc.rst => 12346.breaking.rst} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename changelog/{11372.improvement.rst => 11372.breaking.rst} (100%) rename changelog/{12346.misc.rst => 12346.breaking.rst} (100%) diff --git a/changelog/11372.improvement.rst b/changelog/11372.breaking.rst similarity index 100% rename from changelog/11372.improvement.rst rename to changelog/11372.breaking.rst diff --git a/changelog/12346.misc.rst b/changelog/12346.breaking.rst similarity index 100% rename from changelog/12346.misc.rst rename to changelog/12346.breaking.rst From 6b9de2ab2e52181102bdaf9acbaf7815eb078ed2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 23:01:37 +0000 Subject: [PATCH 0939/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.6.9 → v0.7.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.9...v0.7.2) - [github.com/adamchainz/blacken-docs: 1.19.0 → 1.19.1](https://github.com/adamchainz/blacken-docs/compare/1.19.0...1.19.1) - [github.com/pre-commit/mirrors-mypy: v1.11.2 → v1.13.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.11.2...v1.13.0) - [github.com/tox-dev/pyproject-fmt: 2.3.1 → v2.5.0](https://github.com/tox-dev/pyproject-fmt/compare/2.3.1...v2.5.0) - [github.com/asottile/pyupgrade: v3.18.0 → v3.19.0](https://github.com/asottile/pyupgrade/compare/v3.18.0...v3.19.0) [mypy] Remove useless noqa, add noqa for new false positives Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) --- .pre-commit-config.yaml | 11 ++++++----- pyproject.toml | 3 ++- src/_pytest/_io/pprint.py | 6 +++--- src/_pytest/capture.py | 6 ++++-- testing/test_runner.py | 4 ++-- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 096228acf9f..04971cf9fb2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.6.9" + rev: "v0.7.2" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/adamchainz/blacken-docs - rev: 1.19.0 + rev: 1.19.1 hooks: - id: blacken-docs additional_dependencies: [black==24.1.1] @@ -28,7 +28,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.11.2 + rev: v1.13.0 hooks: - id: mypy files: ^(src/|testing/|scripts/) @@ -44,13 +44,13 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "2.3.1" + rev: "v2.5.0" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version additional_dependencies: ["tox>=4.9"] - repo: https://github.com/asottile/pyupgrade - rev: v3.18.0 + rev: v3.19.0 hooks: - id: pyupgrade stages: [manual] @@ -62,6 +62,7 @@ repos: language: system types: [python] args: ["-rn", "-sn", "--fail-on=I"] + require_serial: true stages: [manual] - id: rst name: rst diff --git a/pyproject.toml b/pyproject.toml index b023f788563..da47e4b045e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ dependencies = [ "exceptiongroup>=1.0.0rc8; python_version<'3.11'", "iniconfig", "packaging", - "pluggy<2,>=1.5", + "pluggy>=1.5,<2", "tomli>=1; python_version<'3.11'", ] optional-dependencies.dev = [ @@ -275,6 +275,7 @@ disable = [ "too-many-lines", "too-many-locals", "too-many-nested-blocks", + "too-many-positional-arguments", "too-many-public-methods", "too-many-return-statements", # disabled in ruff "too-many-statements", # disabled in ruff diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index fc29989be0b..7a6433d9128 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -111,15 +111,15 @@ def _format( p(self, object, stream, indent, allowance, context, level + 1) context.remove(objid) elif ( - _dataclasses.is_dataclass(object) # type:ignore[unreachable] + _dataclasses.is_dataclass(object) and not isinstance(object, type) - and object.__dataclass_params__.repr + and object.__dataclass_params__.repr # type:ignore[attr-defined] and # Check dataclass has generated repr method. hasattr(object.__repr__, "__wrapped__") and "__create_fn__" in object.__repr__.__wrapped__.__qualname__ ): - context.add(objid) # type:ignore[unreachable] + context.add(objid) self._pprint_dataclass( object, stream, indent, allowance, context, level + 1 ) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 506c0b3d287..2ac3b6bbc7f 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -15,6 +15,7 @@ from typing import Any from typing import AnyStr from typing import BinaryIO +from typing import cast from typing import Final from typing import final from typing import Generator @@ -177,7 +178,8 @@ def name(self) -> str: def mode(self) -> str: # TextIOWrapper doesn't expose a mode, but at least some of our # tests check it. - return self.buffer.mode.replace("b", "") + assert hasattr(self.buffer, "mode") + return cast(str, self.buffer.mode.replace("b", "")) class CaptureIO(io.TextIOWrapper): @@ -550,7 +552,7 @@ def snap(self) -> bytes: res = self.tmpfile.buffer.read() self.tmpfile.seek(0) self.tmpfile.truncate() - return res + return res # type: ignore[return-value] def writeorg(self, data: bytes) -> None: """Write to original file descriptor.""" diff --git a/testing/test_runner.py b/testing/test_runner.py index 0d9facdcd71..0245438a47d 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -137,8 +137,8 @@ def raiser(exc): ss.teardown_exact(None) mod, func = e.value.exceptions assert isinstance(mod, KeyError) - assert isinstance(func.exceptions[0], TypeError) # type: ignore - assert isinstance(func.exceptions[1], ValueError) # type: ignore + assert isinstance(func.exceptions[0], TypeError) + assert isinstance(func.exceptions[1], ValueError) def test_cached_exception_doesnt_get_longer(self, pytester: Pytester) -> None: """Regression test for #12204 (the "BTW" case).""" From 94dd15341a036b0a464992c2be0e48d4a8b9d23c Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 29 Oct 2024 10:08:27 +0100 Subject: [PATCH 0940/1271] Upgrade pylint version, activate all extensions --- .pre-commit-config.yaml | 2 +- pyproject.toml | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 04971cf9fb2..b8e7053e1c8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -61,7 +61,7 @@ repos: entry: pylint language: system types: [python] - args: ["-rn", "-sn", "--fail-on=I"] + args: ["-rn", "-sn", "--fail-on=I", "--enable-all-extentions"] require_serial: true stages: [manual] - id: rst diff --git a/pyproject.toml b/pyproject.toml index da47e4b045e..c968b826554 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -200,7 +200,9 @@ disable = [ "arguments-renamed", "assigning-non-slot", "attribute-defined-outside-init", + "bad-builtin", "bad-classmethod-argument", + "bad-dunder-name", "bad-mcs-method-argument", "broad-exception-caught", "broad-exception-raised", @@ -209,25 +211,41 @@ disable = [ "comparison-with-callable", "comparison-with-itself", # PLR0124 from ruff "condition-evals-to-constant", + "consider-alternative-union-syntax", + "confusing-consecutive-elif", + "consider-using-any-or-all", + "consider-using-assignment-expr", "consider-using-dict-items", "consider-using-from-import", "consider-using-f-string", "consider-using-in", + "consider-using-namedtuple-or-dataclass", "consider-using-ternary", + "consider-using-tuple", "consider-using-with", "consider-using-from-import", # not activated by default, PLR0402 disabled in ruff + "consider-ternary-expression", "cyclic-import", + "differing-param-doc", + "docstring-first-line-empty", + "deprecated-argument", + "deprecated-attribute", + "deprecated-class", + "deprecated-typing-alias", + "dict-init-mutate", "disallowed-name", # foo / bar are used often in tests "duplicate-code", "else-if-used", # not activated by default, PLR5501 disabled in ruff "empty-comment", # not activated by default, PLR2044 disabled in ruff "eval-used", + "eq-without-hash", "exec-used", "expression-not-assigned", "fixme", "global-statement", # PLW0603 disabled in ruff "import-error", "import-outside-toplevel", + "import-private-name", "inconsistent-return-statements", "invalid-bool-returned", "invalid-name", @@ -238,8 +256,12 @@ disable = [ "magic-value-comparison", # not activated by default, PLR2004 disabled in ruff "method-hidden", "missing-docstring", + "missing-param-doc", + "missing-raises-doc", "missing-timeout", + "missing-type-doc", "misplaced-bare-raise", # PLE0704 from ruff + "misplaced-comparison-constant", "multiple-statements", # multiple-statements-on-one-line-colon (E701) from ruff "no-else-break", "no-else-continue", @@ -248,6 +270,7 @@ disable = [ "no-member", "no-name-in-module", "no-self-argument", + "no-self-use", "not-an-iterable", "not-callable", "pointless-exception-statement", # https://github.com/pytest-dev/pytest/pull/12379 @@ -260,12 +283,14 @@ disable = [ "redefined-builtin", "redefined-loop-name", # PLW2901 disabled in ruff "redefined-outer-name", + "redefined-variable-type", "reimported", "simplifiable-condition", "simplifiable-if-expression", "singleton-comparison", "superfluous-parens", "super-init-not-called", + "too-complex", "too-few-public-methods", "too-many-ancestors", "too-many-arguments", # disabled in ruff @@ -279,6 +304,7 @@ disable = [ "too-many-public-methods", "too-many-return-statements", # disabled in ruff "too-many-statements", # disabled in ruff + "too-many-try-statements", "try-except-raise", "typevar-name-incorrect-variance", # PLC0105 disabled in ruff "unbalanced-tuple-unpacking", @@ -300,10 +326,12 @@ disable = [ "use-dict-literal", "use-implicit-booleaness-not-comparison", "use-implicit-booleaness-not-len", + "use-set-for-membership", "useless-else-on-loop", # PLC0414 disabled in ruff "useless-import-alias", "useless-return", "using-constant-test", + "while-used", "wrong-import-order", # handled by isort / ruff "wrong-import-position", # handled by isort / ruff ] From b19fd523e18a35dd17bc3ae61a251b73cb940551 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 29 Oct 2024 10:09:09 +0100 Subject: [PATCH 0941/1271] [pylint dict-init-mutate] Initialize a dict right off for speed --- pyproject.toml | 1 - src/_pytest/junitxml.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c968b826554..3636ee455ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -232,7 +232,6 @@ disable = [ "deprecated-attribute", "deprecated-class", "deprecated-typing-alias", - "dict-init-mutate", "disallowed-name", # foo / bar are used often in tests "duplicate-code", "else-if-used", # not activated by default, PLR5501 disabled in ruff diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 3a2cb59a6c1..efe6f489b48 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -74,10 +74,10 @@ def merge_family(left, right) -> None: left.update(result) -families = {} -families["_base"] = {"testcase": ["classname", "name"]} -families["_base_legacy"] = {"testcase": ["file", "line", "url"]} - +families = { # pylint: disable=dict-init-mutate + "_base": {"testcase": ["classname", "name"]}, + "_base_legacy": {"testcase": ["file", "line", "url"]}, +} # xUnit 1.x inherits legacy attributes. families["xunit1"] = families["_base"].copy() merge_family(families["xunit1"], families["_base_legacy"]) From 987904c13cdd03fd49f46a88738e13f808db99bd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 10 Nov 2024 08:39:36 +0000 Subject: [PATCH 0942/1271] [automated] Update plugin list (#12950) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 78 +++++++++++++++++++------------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 50206c34150..ecd96b89967 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,15 +27,15 @@ please refer to `the update script =8.3 - :pypi:`logassert` Simple but powerful assertion and verification of logged lines. May 20, 2022 5 - Production/Stable N/A + :pypi:`databricks-labs-pytester` Python Testing for Databricks Nov 04, 2024 4 - Beta pytest>=8.3 + :pypi:`logassert` Simple but powerful assertion and verification of logged lines. Nov 08, 2024 5 - Production/Stable N/A :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A @@ -157,7 +157,7 @@ This list contains 1538 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Oct 22, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Nov 05, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -246,7 +246,7 @@ This list contains 1538 plugins. :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A - :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Sep 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Nov 08, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Oct 08, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) @@ -571,7 +571,7 @@ This list contains 1538 plugins. :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 15, 2024 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest - :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Jul 21, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Nov 09, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) @@ -601,7 +601,7 @@ This list contains 1538 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Oct 11, 2024 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Nov 07, 2024 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A @@ -616,7 +616,7 @@ This list contains 1538 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jul 08, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Nov 07, 2024 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -660,7 +660,7 @@ This list contains 1538 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 01, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Nov 09, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -730,6 +730,7 @@ This list contains 1538 plugins. :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Sep 25, 2024 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 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-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipywidgets` Oct 28, 2024 N/A pytest @@ -818,7 +819,7 @@ This list contains 1538 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Oct 28, 2024 5 - Production/Stable pytest==8.3.3 + :pypi:`pytest-logikal` Common testing environment Nov 09, 2024 5 - Production/Stable pytest==8.3.3 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" @@ -859,7 +860,7 @@ This list contains 1538 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 Feb 12, 2024 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 19, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Nov 04, 2024 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) @@ -1006,7 +1007,7 @@ This list contains 1538 plugins. :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) - :pypi:`pytest-picked` Run the tests related to the changed files Jul 27, 2023 N/A pytest (>=3.7.0) + :pypi:`pytest-picked` Run the tests related to the changed files Nov 06, 2024 N/A pytest>=3.7.0 :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) :pypi:`pytest-pikachu` Show surprise when tests are passing Aug 05, 2021 5 - Production/Stable pytest :pypi:`pytest-pilot` Slice in your test base thanks to powerful markers. Oct 09, 2020 5 - Production/Stable N/A @@ -1224,7 +1225,7 @@ This list contains 1538 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 09, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1235,7 +1236,7 @@ This list contains 1538 plugins. :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 Feb 01, 2024 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 01, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 09, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1281,6 +1282,7 @@ This list contains 1538 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A + :pypi:`pytest-smoke` pytest plugin for supporting smoke testing Nov 07, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -1358,7 +1360,7 @@ This list contains 1538 plugins. :pypi:`pytest-symbols` pytest-symbols is a pytest plugin that adds support for passing test environment symbols into pytest tests. Nov 20, 2017 3 - Alpha N/A :pypi:`pytest-system-statistics` Pytest plugin to track and report system usage statistics Feb 16, 2022 5 - Production/Stable pytest (>=6.0.0) :pypi:`pytest-system-test-plugin` Pyst - Pytest System-Test Plugin Feb 03, 2022 N/A N/A - :pypi:`pytest_tagging` a pytest plugin to tag tests Aug 31, 2024 N/A pytest<8.0.0,>=7.1.3 + :pypi:`pytest_tagging` a pytest plugin to tag tests Nov 08, 2024 N/A pytest>=7.1.3 :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Sep 07, 2024 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) @@ -1578,14 +1580,14 @@ This list contains 1538 plugins. :pypi:`databricks-labs-pytester` - *last release*: Oct 11, 2024, + *last release*: Nov 04, 2024, *status*: 4 - Beta, *requires*: pytest>=8.3 Python Testing for Databricks :pypi:`logassert` - *last release*: May 20, 2022, + *last release*: Nov 08, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -2439,7 +2441,7 @@ This list contains 1538 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Oct 22, 2024, + *last release*: Nov 05, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3062,7 +3064,7 @@ This list contains 1538 plugins. Automated, comprehensive and well-organised pytest test cases. :pypi:`pytest-cleanuptotal` - *last release*: Sep 14, 2024, + *last release*: Nov 08, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5337,7 +5339,7 @@ This list contains 1538 plugins. A pytest plugin to assert type annotations at runtime. :pypi:`pytest-flake8` - *last release*: Jul 21, 2024, + *last release*: Nov 09, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -5547,7 +5549,7 @@ This list contains 1538 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Oct 11, 2024, + *last release*: Nov 07, 2024, *status*: N/A, *requires*: pytest @@ -5652,7 +5654,7 @@ This list contains 1538 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jul 08, 2024, + *last release*: Nov 07, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -5960,7 +5962,7 @@ This list contains 1538 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Nov 01, 2024, + *last release*: Nov 09, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6449,6 +6451,13 @@ This list contains 1538 plugins. Run tests covering a specific file or changeset + :pypi:`pytest-iovis` + *last release*: Nov 06, 2024, + *status*: 4 - Beta, + *requires*: pytest>=7.1.0 + + A Pytest plugin to enable Jupyter Notebook testing with Papermill + :pypi:`pytest-ipdb` *last release*: Mar 20, 2013, *status*: 2 - Pre-Alpha, @@ -7066,7 +7075,7 @@ This list contains 1538 plugins. :pypi:`pytest-logikal` - *last release*: Oct 28, 2024, + *last release*: Nov 09, 2024, *status*: 5 - Production/Stable, *requires*: pytest==8.3.3 @@ -7353,7 +7362,7 @@ This list contains 1538 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Sep 19, 2024, + *last release*: Nov 04, 2024, *status*: N/A, *requires*: pytest @@ -8382,9 +8391,9 @@ This list contains 1538 plugins. pytest plugin to test Python examples in Markdown using phmdoctest. :pypi:`pytest-picked` - *last release*: Jul 27, 2023, + *last release*: Nov 06, 2024, *status*: N/A, - *requires*: pytest (>=3.7.0) + *requires*: pytest>=3.7.0 Run the tests related to the changed files @@ -9908,7 +9917,7 @@ This list contains 1538 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Nov 01, 2024, + *last release*: Nov 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9985,7 +9994,7 @@ This list contains 1538 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Nov 01, 2024, + *last release*: Nov 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10306,6 +10315,13 @@ This list contains 1538 plugins. Automated bad smell detection tool for Pytest + :pypi:`pytest-smoke` + *last release*: Nov 07, 2024, + *status*: 4 - Beta, + *requires*: pytest<9,>=7.0.0 + + pytest plugin for supporting smoke testing + :pypi:`pytest-smtp` *last release*: Feb 20, 2021, *status*: N/A, @@ -10846,9 +10862,9 @@ This list contains 1538 plugins. Pyst - Pytest System-Test Plugin :pypi:`pytest_tagging` - *last release*: Aug 31, 2024, + *last release*: Nov 08, 2024, *status*: N/A, - *requires*: pytest<8.0.0,>=7.1.3 + *requires*: pytest>=7.1.3 a pytest plugin to tag tests From 70639efe8d33cdbf2590742b70da59efe09c977f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 07:39:17 +0100 Subject: [PATCH 0943/1271] build(deps): Bump django in /testing/plugins_integration (#12951) Bumps [django](https://github.com/django/django) from 5.1.2 to 5.1.3. - [Commits](https://github.com/django/django/compare/5.1.2...5.1.3) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index ef01747f2fd..32992dc2589 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.6.2.post1 -django==5.1.2 +django==5.1.3 pytest-asyncio==0.24.0 pytest-bdd==7.3.0 pytest-cov==6.0.0 From 7256c0c226b0eea2453cc532e6786366aa2400c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 08:39:14 +0100 Subject: [PATCH 0944/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.10.3 to 1.12.2 (#12953) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.10.3 to 1.12.2. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.10.3...v1.12.2) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 974fe4947db..3d3cb7534a4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.10.3 + uses: pypa/gh-action-pypi-publish@v1.12.2 with: attestations: true From c98ef2bdcaf4f0478c77c38534bce788e6581967 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Mon, 11 Nov 2024 15:09:18 +0100 Subject: [PATCH 0945/1271] change implementation so the check happens in pytest_fixture_setup after any hooks (from async plugins) has had a chance to resolve the awaitable --- src/_pytest/compat.py | 1 + src/_pytest/fixtures.py | 57 ++++++++++++++------------------------ testing/acceptance_test.py | 40 +++++++++++++------------- 3 files changed, 43 insertions(+), 55 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 614848e0dba..64240135313 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -44,6 +44,7 @@ class NotSetType(enum.Enum): def is_generator(func: object) -> bool: + # note: this also returns true for async generator functions genfunc = inspect.isgeneratorfunction(func) return genfunc and not iscoroutinefunction(func) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 4b45489cd96..0737773f047 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -595,42 +595,6 @@ def _get_active_fixturedef( raise FixtureLookupError(argname, self) fixturedef = fixturedefs[index] - # Check for attempted use of an async fixture by a sync test - # `self.scope` here is not the scope of the requested fixture, but the scope of - # the requester. - if ( - self.scope == "function" - and not inspect.iscoroutinefunction(self._pyfuncitem.obj) - and ( - inspect.iscoroutinefunction(fixturedef.func) - or inspect.isasyncgenfunction(fixturedef.func) - ) - ): - if fixturedef._autouse: - warnings.warn( - PytestRemovedIn9Warning( - f"Sync test {self._pyfuncitem.name!r} requested async fixture " - f"{argname!r} with autouse=True. " - "If you intended to use the fixture you may want to make the " - "test asynchronous or the fixture synchronous. " - "If you did not intend to use it you should " - "restructure your test setup. " - "This will turn into an error in pytest 9." - ), - stacklevel=3, - ) - else: - warnings.warn( - PytestRemovedIn9Warning( - f"Sync test {self._pyfuncitem.name!r} requested async fixture " - f"{argname!r}. " - "You may want to make the test asynchronous and run it with " - "a suitable async framework test plugin, or make the fixture synchronous. " - "This will turn into an error in pytest 9." - ), - stacklevel=3, - ) - # Prepare a SubRequest object for calling the fixture. try: callspec = self._pyfuncitem.callspec @@ -921,6 +885,8 @@ def call_fixture_func( fixturefunc: _FixtureFunc[FixtureValue], request: FixtureRequest, kwargs ) -> FixtureValue: if is_generator(fixturefunc): + # note: this also triggers on async generators, suppressing 'unawaited coroutine' + # warning. fixturefunc = cast( Callable[..., Generator[FixtureValue, None, None]], fixturefunc ) @@ -1179,6 +1145,25 @@ def pytest_fixture_setup( fixturefunc = resolve_fixture_function(fixturedef, request) my_cache_key = fixturedef.cache_key(request) + + if inspect.isasyncgenfunction(fixturefunc) or inspect.iscoroutinefunction( + fixturefunc + ): + auto_str = " with autouse=True" if fixturedef._autouse else "" + + warnings.warn( + PytestRemovedIn9Warning( + f"{request.node.name!r} requested an async fixture " + f"{request.fixturename!r}{auto_str}, with no plugin or hook that " + "handled it. This is usually an error, as pytest does not natively " + "support it. If this is intentional, consider making the fixture " + "sync and return a coroutine/asyncgen. " + "This will turn into an error in pytest 9." + ), + # no stacklevel will point at users code, so we just point here + stacklevel=1, + ) + try: result = call_fixture_func(fixturefunc, request, kwargs) except TEST_OUTCOME as e: diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index a7a9afedbc0..ffea0dbf46b 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1306,11 +1306,13 @@ def test_foo(async_fixture): result = pytester.runpytest() result.stdout.fnmatch_lines( [ + "*== warnings summary ==*", ( - "*Sync test 'test_foo' requested async fixture " - "'async_fixture'. " - "You may want to make the test asynchronous and run it with " - "a suitable async framework test plugin, or make the fixture synchronous. " + "*PytestRemovedIn9Warning: 'test_foo' requested an async " + "fixture 'async_fixture', with no plugin or hook that handled it. " + "This is usually an error, as pytest does not natively support it. " + "If this is intentional, consider making the fixture sync and return " + "a coroutine/asyncgen. " "This will turn into an error in pytest 9." ), ] @@ -1328,21 +1330,21 @@ async def async_fixture(): yield def test_foo(async_fixture): - # suppress unawaited coroutine warning - try: - async_fixture.asend(None) - except StopIteration: - pass + # we don't need to suppress RuntimeWarning for unawaited coroutine + # as pytest internals accidentally do so already for async gens + ... """ ) result = pytester.runpytest() result.stdout.fnmatch_lines( [ + "*== warnings summary ==*", ( - "*Sync test 'test_foo' requested async fixture " - "'async_fixture'. " - "You may want to make the test asynchronous and run it with " - "a suitable async framework test plugin, or make the fixture synchronous. " + "*PytestRemovedIn9Warning: 'test_foo' requested an async " + "fixture 'async_fixture', with no plugin or hook that handled it. " + "This is usually an error, as pytest does not natively support it. " + "If this is intentional, consider making the fixture sync and return " + "a coroutine/asyncgen. " "This will turn into an error in pytest 9." ), ] @@ -1371,13 +1373,13 @@ def test_foo(async_fixture): result = pytester.runpytest() result.stdout.fnmatch_lines( [ + "*== warnings summary ==*", ( - "*Sync test 'test_foo' requested async fixture " - "'async_fixture' with autouse=True. " - "If you intended to use the fixture you may want to make the " - "test asynchronous or the fixture synchronous. " - "If you did not intend to use it you should " - "restructure your test setup. " + "*PytestRemovedIn9Warning: Sync test 'test_foo' requested an async " + "fixture 'async_fixture' with autouse=True, with no plugin or hook " + "that handled it. This is usually an error, as pytest does not " + "natively support it. If this is intentional, consider making the " + "fixture sync and return a coroutine/asyncgen. " "This will turn into an error in pytest 9." ), ] From cd3eb9800b8f36c257cfe4deb40ea275bb72e4e9 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Mon, 11 Nov 2024 15:20:25 +0100 Subject: [PATCH 0946/1271] fix test --- testing/acceptance_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index ffea0dbf46b..ca6df943afa 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1375,7 +1375,7 @@ def test_foo(async_fixture): [ "*== warnings summary ==*", ( - "*PytestRemovedIn9Warning: Sync test 'test_foo' requested an async " + "*PytestRemovedIn9Warning: 'test_foo' requested an async " "fixture 'async_fixture' with autouse=True, with no plugin or hook " "that handled it. This is usually an error, as pytest does not " "natively support it. If this is intentional, consider making the " From 876cc2a2b184bb68b0398ce7f9b7bbb3a731e787 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Mon, 11 Nov 2024 15:37:22 +0100 Subject: [PATCH 0947/1271] update docs/changelog --- changelog/10839.deprecation.rst | 2 +- doc/en/deprecations.rst | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/changelog/10839.deprecation.rst b/changelog/10839.deprecation.rst index 78ad4e118e4..01464ca0ba2 100644 --- a/changelog/10839.deprecation.rst +++ b/changelog/10839.deprecation.rst @@ -1 +1 @@ -Synchronous tests that request an asynchronous fixture will now give a DeprecationWarning. This will introduce warnings in several pytest plugins that handle async tests/fixtures and for some users with custom setups. For guidance on how to manage this see :ref:`sync-test-async-fixture`. +Requesting an asynchronous fixture without a `pytest_fixture_setup` to handle it will now give a DeprecationWarning. This most commonly happens if a sync test requests an async fixture. This should have no effect on a majority of users with async tests or fixtures, but may affect non-standard hook setups or ``autouse=True``. For guidance on how to work around this warning see :ref:`sync-test-async-fixture`. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index b384f01dfab..494bd88d282 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -24,13 +24,14 @@ sync test depending on async fixture Pytest has for a long time given an error when encountering an asynchronous test function, prompting the user to install a plugin that can handle it. It has not given any errors if you have an asynchronous fixture that's depended on by a -synchronous test. This is a problem even if you do have a plugin installed for handling async tests, as they may require +synchronous test. If the fixture was an async function you did get an "unawaited coroutine" warning, but for async yield fixtures you didn't even get that. +This is a problem even if you do have a plugin installed for handling async tests, as they may require special decorators for async fixtures to be handled, and some may not robustly handle if a user accidentally requests an async fixture from their sync tests. Fixture values being cached can make this even more unintuitive, where everything will "work" if the fixture is first requested by an async test, and then requested by a synchronous test. Unfortunately there is no 100% reliable method of identifying when a user has made a mistake, versus when they expect an -unawaited object from their fixture that they will handle - either on their own, or by a plugin. To suppress this warning +unawaited object from their fixture that they will handle on their own. To suppress this warning when you in fact did intend to handle this you can wrap your async fixture in a synchronous fixture: .. code-block:: python @@ -67,7 +68,10 @@ should be changed to def test_foo(unawaited_fixture): assert 1 == asyncio.run(unawaited_fixture) -If a user has an async fixture with ``autouse=True`` in their ``conftest.py``, or in a file where they also have synchronous tests, they will also get this warning. We strongly recommend against this practice, and they should restructure their testing infrastructure so the fixture is synchronous or to separate the fixture from their synchronous tests. Plugins that handle async may want to introduce helpers to make that easier in scenarios where that might be wanted, e.g. if setting up a database in an asynchronous way, or the user may opt to make their test async even though it might not strictly need to be. + +You can also make use of `pytest_fixture_setup` to handle the coroutine/asyncgen before pytest sees it - this is the way current async pytest plugins handle it. + +If a user has an async fixture with ``autouse=True`` in their ``conftest.py``, or in a file where they also have synchronous tests, they will also get this warning. We strongly recommend against this practice, and they should restructure their testing infrastructure so the fixture is synchronous or to separate the fixture from their synchronous tests. Note that the anyio pytest plugin has some support for sync test + async fixtures currently. .. _import-or-skip-import-error: From 473452035ac3d2c3828b3dc9ac18d8d82d2c0215 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 12 Nov 2024 06:58:31 +0100 Subject: [PATCH 0948/1271] [pre-commit.ci] pre-commit autoupdate (#12955) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.7.2 → v0.7.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.2...v0.7.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b8e7053e1c8..218a69e2cbc 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.7.2" + rev: "v0.7.3" hooks: - id: ruff args: ["--fix"] From 76b8870f6cf04db8b405c766fc25021d3fc8602a Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 12 Nov 2024 12:42:07 +0100 Subject: [PATCH 0949/1271] [pylint consider-using-any-or-all] Fix or disable all detected issues (#12954) * Avoid constructing a list of names * noqa a a suggestion in already nested for --- pyproject.toml | 1 - src/_pytest/mark/__init__.py | 10 ++-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ad0bca4374b..be99392a85f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -213,7 +213,6 @@ disable = [ "condition-evals-to-constant", "consider-alternative-union-syntax", "confusing-consecutive-elif", - "consider-using-any-or-all", "consider-using-assignment-expr", "consider-using-dict-items", "consider-using-from-import", diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index f76e5212057..a6f0155751a 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -193,12 +193,7 @@ def __call__(self, subname: str, /, **kwargs: str | int | bool | None) -> bool: if kwargs: raise UsageError("Keyword expressions do not support call parameters.") subname = subname.lower() - names = (name.lower() for name in self._names) - - for name in names: - if subname in name: - return True - return False + return any(subname in name.lower() for name in self._names) def deselect_by_keyword(items: list[Item], config: Config) -> None: @@ -243,10 +238,9 @@ def __call__(self, name: str, /, **kwargs: str | int | bool | None) -> bool: if not (matches := self.own_mark_name_mapping.get(name, [])): return False - for mark in matches: + for mark in matches: # pylint: disable=consider-using-any-or-all if all(mark.kwargs.get(k, NOT_SET) == v for k, v in kwargs.items()): return True - return False From 191456e00d89c2c814f8659070eb8863298996be Mon Sep 17 00:00:00 2001 From: sven <42868792+FreerGit@users.noreply.github.com> Date: Tue, 12 Nov 2024 20:00:47 +0100 Subject: [PATCH 0950/1271] WIP: modified items, reports and items collected - pytest_collectreport hook currently gets more reports (TODO) - `pytest_collection_modifyitems` and `pytest_itemcollected` is correct. --- testing/test_collect_imports.py | 477 +++++++++++++++++++------------- 1 file changed, 278 insertions(+), 199 deletions(-) diff --git a/testing/test_collect_imports.py b/testing/test_collect_imports.py index fe1e6b3e863..cf8ff9cb983 100644 --- a/testing/test_collect_imports.py +++ b/testing/test_collect_imports.py @@ -1,88 +1,89 @@ from __future__ import annotations import textwrap +from typing import Any +from _pytest.fixtures import FixtureRequest +from _pytest.main import Session from _pytest.pytester import Pytester +from _pytest.pytester import RecordedHookCall +from _pytest.pytester import RunResult +import pytest # Start of tests for classes +# def run_import_class_test(pytester: Pytester, passed: int = 0, errors: int = 0) -> None: +# src_dir = pytester.mkdir("src") +# tests_dir = pytester.mkdir("tests") +# src_file = src_dir / "foo.py" + +# src_file.write_text( +# textwrap.dedent("""\ +# class Testament(object): +# def __init__(self): +# super().__init__() +# self.collections = ["stamp", "coin"] + +# def personal_property(self): +# return [f"my {x} collection" for x in self.collections] +# """), +# encoding="utf-8", +# ) + +# test_file = tests_dir / "foo_test.py" +# test_file.write_text( +# textwrap.dedent("""\ +# import sys +# import os + +# current_file = os.path.abspath(__file__) +# current_dir = os.path.dirname(current_file) +# parent_dir = os.path.abspath(os.path.join(current_dir, '..')) +# sys.path.append(parent_dir) + +# from src.foo import Testament + +# class TestDomain: +# def test_testament(self): +# testament = Testament() +# assert testament.personal_property() +# """), +# encoding="utf-8", +# ) + +# result = pytester.runpytest() +# result.assert_outcomes(passed=passed, errors=errors) + +# def test_collect_imports_disabled(pytester: Pytester) -> None: +# pytester.makeini(""" +# [pytest] +# testpaths = "tests" +# collect_imported_tests = false +# """) + +# run_import_class_test(pytester, passed=1) + +# # Verify that the state of hooks +# reprec = pytester.inline_run() +# items_collected = reprec.getcalls("pytest_itemcollected") +# assert len(items_collected) == 1 +# for x in items_collected: +# assert x.item._getobj().__name__ == "test_testament" + +# def test_collect_imports_default(pytester: Pytester) -> None: +# run_import_class_test(pytester, errors=1) -def run_import_class_test(pytester: Pytester, passed: int = 0, errors: int = 0) -> None: - src_dir = pytester.mkdir("src") - tests_dir = pytester.mkdir("tests") - src_file = src_dir / "foo.py" - - src_file.write_text( - textwrap.dedent("""\ - class Testament(object): - def __init__(self): - super().__init__() - self.collections = ["stamp", "coin"] - - def personal_property(self): - return [f"my {x} collection" for x in self.collections] - """), - encoding="utf-8", - ) - - test_file = tests_dir / "foo_test.py" - test_file.write_text( - textwrap.dedent("""\ - import sys - import os - - current_file = os.path.abspath(__file__) - current_dir = os.path.dirname(current_file) - parent_dir = os.path.abspath(os.path.join(current_dir, '..')) - sys.path.append(parent_dir) - - from src.foo import Testament - - class TestDomain: - def test_testament(self): - testament = Testament() - assert testament.personal_property() - """), - encoding="utf-8", - ) - - result = pytester.runpytest() - result.assert_outcomes(passed=passed, errors=errors) - - -def test_collect_imports_disabled(pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - testpaths = "tests" - collect_imported_tests = false - """) - - run_import_class_test(pytester, passed=1) - - # Verify that the state of hooks - reprec = pytester.inline_run() - items_collected = reprec.getcalls("pytest_itemcollected") - assert len(items_collected) == 1 - for x in items_collected: - assert x.item._getobj().__name__ == "test_testament" - - -def test_collect_imports_default(pytester: Pytester) -> None: - run_import_class_test(pytester, errors=1) - - # TODO, hooks - - -def test_collect_imports_enabled(pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - collect_imported_tests = true - """) +# # TODO, hooks - run_import_class_test(pytester, errors=1) +# def test_collect_imports_enabled(pytester: Pytester) -> None: +# pytester.makeini(""" +# [pytest] +# collect_imported_tests = true +# """) +# run_import_class_test(pytester, errors=1) # # TODO, hooks @@ -93,141 +94,219 @@ def test_collect_imports_enabled(pytester: Pytester) -> None: def run_import_functions_test( pytester: Pytester, passed: int, errors: int, failed: int -) -> None: - src_dir = pytester.mkdir("src") - tests_dir = pytester.mkdir("tests") - - src_file = src_dir / "foo.py" - +) -> RunResult: # Note that these "tests" should _not_ be treated as tests if `collect_imported_tests = false` # They are normal functions in that case, that happens to have test_* or *_test in the name. # Thus should _not_ be collected! - src_file.write_text( - textwrap.dedent("""\ - def test_function(): - some_random_computation = 5 - return some_random_computation - - def test_bar(): - pass - """), - encoding="utf-8", + pytester.makepyfile( + **{ + "src/foo.py": textwrap.dedent( + """\ + def test_function(): + some_random_computation = 5 + return some_random_computation + + def test_bar(): + pass + """ + ) + } ) - test_file = tests_dir / "foo_test.py" - # Inferred from the comment above, this means that there is _only_ one actual test # which should result in only 1 passing test being ran. - test_file.write_text( - textwrap.dedent("""\ - import sys - import os - - current_file = os.path.abspath(__file__) - current_dir = os.path.dirname(current_file) - parent_dir = os.path.abspath(os.path.join(current_dir, '..')) - sys.path.append(parent_dir) - - from src.foo import * - - class TestDomain: - def test_important(self): - res = test_function() - if res == 5: - pass - """), - encoding="utf-8", + pytester.makepyfile( + **{ + "tests/foo_test.py": textwrap.dedent( + """\ + import sys + import os + + current_file = os.path.abspath(__file__) + current_dir = os.path.dirname(current_file) + parent_dir = os.path.abspath(os.path.join(current_dir, '..')) + sys.path.append(parent_dir) + + from src.foo import * + + class TestDomain: + def test_important(self): + res = test_function() + if res == 5: + pass + """ + ) + } ) result = pytester.runpytest() result.assert_outcomes(passed=passed, errors=errors, failed=failed) - - -def test_collect_function_imports_enabled(pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - testpaths = "tests" - collect_imported_tests = true - """) - - run_import_functions_test(pytester, passed=2, errors=0, failed=1) - reprec = pytester.inline_run() - items_collected = reprec.getcalls("pytest_itemcollected") - # Recall that the default is `collect_imported_tests = true`. - # Which means that the normal functions are now interpreted as - # valid tests and `test_function()` will fail. - assert len(items_collected) == 3 - for x in items_collected: - assert x.item._getobj().__name__ in [ - "test_important", - "test_bar", - "test_function", - ] - - -def test_behaviour_without_testpaths_set_and_false(pytester: Pytester) -> None: - # Make sure `collect_imported_tests` has no dependence on `testpaths` - pytester.makeini(""" - [pytest] - collect_imported_tests = false - """) - - run_import_functions_test(pytester, passed=1, errors=0, failed=0) - reprec = pytester.inline_run() - items_collected = reprec.getcalls("pytest_itemcollected") - assert len(items_collected) == 1 - for x in items_collected: - assert x.item._getobj().__name__ == "test_important" - - -def test_behaviour_without_testpaths_set_and_true(pytester: Pytester) -> None: - # Make sure `collect_imported_tests` has no dependence on `testpaths` - pytester.makeini(""" - [pytest] - collect_imported_tests = true - """) - - run_import_functions_test(pytester, passed=2, errors=0, failed=1) - reprec = pytester.inline_run() - items_collected = reprec.getcalls("pytest_itemcollected") - assert len(items_collected) == 3 - - -def test_hook_behaviour_when_collect_off(pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - collect_imported_tests = false - """) - - run_import_functions_test(pytester, passed=1, errors=0, failed=0) - reprec = pytester.inline_run() - - # reports = reprec.getreports("pytest_collectreport") - items_collected = reprec.getcalls("pytest_itemcollected") - modified = reprec.getcalls("pytest_collection_modifyitems") - - # print("Reports: ----------------") - # print(reports) - # for r in reports: - # print(r) - - # TODO this is want I want, I think.... - # - # - # - # - # - - # TODO - # assert(reports.outcome == "passed") - # assert(len(reports.result) == 1) - - # print("Items collected: ----------------") - # print(items_collected) - # print("Modified : ----------------") - - assert len(items_collected) == 1 - for x in items_collected: - assert x.item._getobj().__name__ == "test_important" - - assert len(modified) == 1 + return result + + +# def test_collect_function_imports_enabled(pytester: Pytester) -> None: +# pytester.makeini(""" +# [pytest] +# testpaths = "tests" +# collect_imported_tests = true +# """) + +# run_import_functions_test(pytester, passed=2, errors=0, failed=1) +# reprec = pytester.inline_run() +# items_collected = reprec.getcalls("pytest_itemcollected") +# # Recall that the default is `collect_imported_tests = true`. +# # Which means that the normal functions are now interpreted as +# # valid tests and `test_function()` will fail. +# assert len(items_collected) == 3 +# for x in items_collected: +# assert x.item._getobj().__name__ in [ +# "test_important", +# "test_bar", +# "test_function", +# ] + + +# def test_behaviour_without_testpaths_set_and_false(pytester: Pytester) -> None: +# # Make sure `collect_imported_tests` has no dependence on `testpaths` +# pytester.makeini(""" +# [pytest] +# collect_imported_tests = false +# """) + +# run_import_functions_test(pytester, passed=1, errors=0, failed=0) +# reprec = pytester.inline_run() +# items_collected = reprec.getcalls("pytest_itemcollected") +# assert len(items_collected) == 1 +# for x in items_collected: +# assert x.item._getobj().__name__ == "test_important" + + +# def test_behaviour_without_testpaths_set_and_true(pytester: Pytester) -> None: +# # Make sure `collect_imported_tests` has no dependence on `testpaths` +# pytester.makeini(""" +# [pytest] +# collect_imported_tests = true +# """) + +# run_import_functions_test(pytester, passed=2, errors=0, failed=1) +# reprec = pytester.inline_run() +# items_collected = reprec.getcalls("pytest_itemcollected") +# assert len(items_collected) == 3 + + +class TestHookBehaviour: + collect_outcomes: dict[str, Any] = {} + + @pytest.mark.parametrize("step", [1, 2, 3]) + def test_hook_behaviour(self, pytester: Pytester, step: int) -> None: + if step == 1: + self._test_hook_default_behaviour(pytester) + elif step == 2: + self._test_hook_behaviour_when_collect_off(pytester) + elif step == 3: + self._test_hook_behaviour() + + @pytest.fixture(scope="class", autouse=True) + def setup_collect_outcomes(self, request: FixtureRequest) -> None: + request.cls.collect_outcomes = {} + + def _test_hook_default_behaviour(self, pytester: Pytester) -> None: + pytester.makepyfile( + **{ + "tests/foo_test.py": textwrap.dedent( + """\ + class TestDomain: + def test_important(self): + pass + """ + ) + } + ) + + result = pytester.runpytest() + result.assert_outcomes(passed=1) + reprec = pytester.inline_run() + reports = reprec.getreports("pytest_collectreport") + modified = reprec.getcalls("pytest_collection_modifyitems") + items_collected = reprec.getcalls("pytest_itemcollected") + + self.collect_outcomes["default"] = { + "result": result.parseoutcomes(), + "modified": modified, + "items_collected": items_collected, + "reports": reports, + } + + def _test_hook_behaviour_when_collect_off(self, pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + collect_imported_tests = false + """) + res = run_import_functions_test(pytester, passed=1, errors=0, failed=0) + reprec = pytester.inline_run() + reports = reprec.getreports("pytest_collectreport") + modified = reprec.getcalls("pytest_collection_modifyitems") + items_collected = reprec.getcalls("pytest_itemcollected") + + self.collect_outcomes["collect_off"] = { + "result": res.parseoutcomes(), + "modified": modified, + "items_collected": items_collected, + "reports": reports, + } + + # Now check that the two tests above did indeed result in the same outcome. + def _test_hook_behaviour(self) -> None: + print("ABCD", self.collect_outcomes) + default = self.collect_outcomes["default"] + collect_off = self.collect_outcomes["collect_off"] + assert default["result"] == collect_off["result"] + + assert len(default["modified"]) == len(collect_off["modified"]) == 1 + + def_modified_record: RecordedHookCall = default["modified"][0] + off_modified_record: RecordedHookCall = collect_off["modified"][0] + def_sess: Session = def_modified_record.__dict__["session"] + off_sess: Session = off_modified_record.__dict__["session"] + + assert def_sess.exitstatus == off_sess.exitstatus + assert def_sess.testsfailed == off_sess.testsfailed + assert def_sess.testscollected == off_sess.testscollected + + def_items = def_modified_record.__dict__["items"] + off_items = off_modified_record.__dict__["items"] + assert len(def_items) == len(off_items) == 1 + assert def_items[0].name == off_items[0].name + + assert ( + len(default["items_collected"]) == len(collect_off["items_collected"]) == 1 + ) + + def_items_record: RecordedHookCall = default["items_collected"][0] + off_items_record: RecordedHookCall = collect_off["items_collected"][0] + def_items = def_items_record.__dict__["item"] + off_items = off_items_record.__dict__["item"] + assert def_items.name == off_items.name + + # TODO: fix diff: + # [ + # , + # - , + # , + # , + # , + # - , + # ? ^ + # + , + # ? ^ + # ] + + # assert len(default['reports']) == len(collect_off['reports']) + # for i in range(len(default['reports'])): + # print("def",default['reports'][i].__dict__) + # print("off",collect_off['reports'][i].__dict__) + + # from pprint import pprint + # pprint(default['reports']) + # pprint(collect_off['reports']) + # assert default['reports'] == collect_off['reports'] From 1a4dfbb593fa63bbb3eeed2f79e730395f86b41a Mon Sep 17 00:00:00 2001 From: jakkdl Date: Thu, 14 Nov 2024 15:13:32 +0100 Subject: [PATCH 0951/1271] remove incorrect comments, add link --- doc/en/deprecations.rst | 2 +- src/_pytest/compat.py | 1 - src/_pytest/fixtures.py | 2 -- testing/acceptance_test.py | 3 +-- 4 files changed, 2 insertions(+), 6 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 494bd88d282..88cf3eccbf3 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -71,7 +71,7 @@ should be changed to You can also make use of `pytest_fixture_setup` to handle the coroutine/asyncgen before pytest sees it - this is the way current async pytest plugins handle it. -If a user has an async fixture with ``autouse=True`` in their ``conftest.py``, or in a file where they also have synchronous tests, they will also get this warning. We strongly recommend against this practice, and they should restructure their testing infrastructure so the fixture is synchronous or to separate the fixture from their synchronous tests. Note that the anyio pytest plugin has some support for sync test + async fixtures currently. +If a user has an async fixture with ``autouse=True`` in their ``conftest.py``, or in a file where they also have synchronous tests, they will also get this warning. We strongly recommend against this practice, and they should restructure their testing infrastructure so the fixture is synchronous or to separate the fixture from their synchronous tests. Note that the `anyio pytest plugin `_ has some support for sync test + async fixtures currently. .. _import-or-skip-import-error: diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 64240135313..614848e0dba 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -44,7 +44,6 @@ class NotSetType(enum.Enum): def is_generator(func: object) -> bool: - # note: this also returns true for async generator functions genfunc = inspect.isgeneratorfunction(func) return genfunc and not iscoroutinefunction(func) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 0737773f047..95e4557fc8e 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -885,8 +885,6 @@ def call_fixture_func( fixturefunc: _FixtureFunc[FixtureValue], request: FixtureRequest, kwargs ) -> FixtureValue: if is_generator(fixturefunc): - # note: this also triggers on async generators, suppressing 'unawaited coroutine' - # warning. fixturefunc = cast( Callable[..., Generator[FixtureValue, None, None]], fixturefunc ) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index ca6df943afa..624a313ca8d 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1330,8 +1330,7 @@ async def async_fixture(): yield def test_foo(async_fixture): - # we don't need to suppress RuntimeWarning for unawaited coroutine - # as pytest internals accidentally do so already for async gens + # async gens don't emit unawaited-coroutine ... """ ) From d35e4ebad03a6f542304573b12e90848d2169c77 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Thu, 14 Nov 2024 15:16:28 +0100 Subject: [PATCH 0952/1271] revert now unrelated fix --- src/_pytest/fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 95e4557fc8e..011dc8e6e3d 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -807,7 +807,7 @@ def formatrepr(self) -> FixtureLookupErrorRepr: stack = [self.request._pyfuncitem.obj] stack.extend(map(lambda x: x.func, self.fixturestack)) msg = self.msg - if msg is not None and len(stack) > 1: + if msg is not None: # The last fixture raise an error, let's present # it at the requesting side. stack = stack[:-1] From ef096cda884d9f001916336e7e8c543badeb191f Mon Sep 17 00:00:00 2001 From: jakkdl Date: Thu, 14 Nov 2024 15:19:38 +0100 Subject: [PATCH 0953/1271] small wording changes --- changelog/10839.deprecation.rst | 2 +- src/_pytest/fixtures.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/10839.deprecation.rst b/changelog/10839.deprecation.rst index 01464ca0ba2..a3e2cbf51d0 100644 --- a/changelog/10839.deprecation.rst +++ b/changelog/10839.deprecation.rst @@ -1 +1 @@ -Requesting an asynchronous fixture without a `pytest_fixture_setup` to handle it will now give a DeprecationWarning. This most commonly happens if a sync test requests an async fixture. This should have no effect on a majority of users with async tests or fixtures, but may affect non-standard hook setups or ``autouse=True``. For guidance on how to work around this warning see :ref:`sync-test-async-fixture`. +Requesting an asynchronous fixture without a `pytest_fixture_setup` hook that resolves it will now give a DeprecationWarning. This most commonly happens if a sync test requests an async fixture. This should have no effect on a majority of users with async tests or fixtures using async pytest plugins, but may affect non-standard hook setups or ``autouse=True``. For guidance on how to work around this warning see :ref:`sync-test-async-fixture`. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 011dc8e6e3d..b5c64856e12 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -961,7 +961,7 @@ def __init__( ids: tuple[object | None, ...] | Callable[[Any], object | None] | None = None, *, _ispytest: bool = False, - # only used to emit a deprecationwarning, can be removed in pytest9 + # only used in a deprecationwarning msg, can be removed in pytest9 _autouse: bool = False, ) -> None: check_ispytest(_ispytest) From 225d910cb68d109eabb6f6bc66ddd4946d9710a1 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Thu, 14 Nov 2024 15:28:42 +0100 Subject: [PATCH 0954/1271] add assertion to FixtureLookupError.formatrepr --- src/_pytest/fixtures.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 6b882fa3515..8f275e4d622 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -805,6 +805,15 @@ def formatrepr(self) -> FixtureLookupErrorRepr: stack = [self.request._pyfuncitem.obj] stack.extend(map(lambda x: x.func, self.fixturestack)) msg = self.msg + # This function currently makes an assumption that a non-None msg means we + # have a non-empty `self.fixturestack`. This is currently true, but if + # somebody at some point want to extend the use of FixtureLookupError to + # new cases it might break. + # Add the assert to make it clearer to developer that this will fail, otherwise + # it crashes because `fspath` does not get set due to `stack` being empty. + assert ( + self.msg is None or self.fixturestack + ), "formatrepr assumptions broken, rewrite it to handle it" if msg is not None: # The last fixture raise an error, let's present # it at the requesting side. From 52ee148b098a5e3f4cba6e4e5aac878c008f195c Mon Sep 17 00:00:00 2001 From: Gupta Arpit Date: Sat, 16 Nov 2024 22:26:53 +0530 Subject: [PATCH 0955/1271] Remove _pytest.compat.is_generator() fix #12960 --- changelog/12960.improvement.rst | 1 + src/_pytest/compat.py | 5 ----- src/_pytest/fixtures.py | 3 +-- src/_pytest/python.py | 3 +-- testing/test_compat.py | 23 ++++++++++++----------- 5 files changed, 15 insertions(+), 20 deletions(-) create mode 100644 changelog/12960.improvement.rst diff --git a/changelog/12960.improvement.rst b/changelog/12960.improvement.rst new file mode 100644 index 00000000000..11767e022db --- /dev/null +++ b/changelog/12960.improvement.rst @@ -0,0 +1 @@ +Removed _pytest.compat.is_generator() and just using inspect.isgeneratorfunction() directly \ No newline at end of file diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 614848e0dba..82aea5e635e 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -43,11 +43,6 @@ class NotSetType(enum.Enum): # fmt: on -def is_generator(func: object) -> bool: - genfunc = inspect.isgeneratorfunction(func) - return genfunc and not iscoroutinefunction(func) - - def iscoroutinefunction(func: object) -> bool: """Return True if func is a coroutine function (a function defined with async def syntax, and doesn't contain yield), or a function decorated with diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 8f275e4d622..6407ae0c48f 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -49,7 +49,6 @@ from _pytest.compat import getfuncargnames from _pytest.compat import getimfunc from _pytest.compat import getlocation -from _pytest.compat import is_generator from _pytest.compat import NOTSET from _pytest.compat import NotSetType from _pytest.compat import safe_getattr @@ -891,7 +890,7 @@ def toterminal(self, tw: TerminalWriter) -> None: def call_fixture_func( fixturefunc: _FixtureFunc[FixtureValue], request: FixtureRequest, kwargs ) -> FixtureValue: - if is_generator(fixturefunc): + if inspect.isgeneratorfunction(fixturefunc): fixturefunc = cast( Callable[..., Generator[FixtureValue, None, None]], fixturefunc ) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index d48a6c4a9fb..63d638e8a8c 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -43,7 +43,6 @@ from _pytest.compat import get_real_func from _pytest.compat import getimfunc from _pytest.compat import is_async_function -from _pytest.compat import is_generator from _pytest.compat import LEGACY_PATH from _pytest.compat import NOTSET from _pytest.compat import safe_getattr @@ -231,7 +230,7 @@ def pytest_pycollect_makeitem( lineno=lineno + 1, ) elif getattr(obj, "__test__", True): - if is_generator(obj): + if inspect.isgeneratorfunction(obj): res = Function.from_parent(collector, name=name) reason = ( f"yield tests were removed in pytest 4.0 - {name} will be ignored" diff --git a/testing/test_compat.py b/testing/test_compat.py index 2c6b0269c27..32a8b771e08 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -6,12 +6,12 @@ from functools import partial from functools import wraps import sys +import inspect from typing import TYPE_CHECKING from _pytest.compat import _PytestWrapper from _pytest.compat import assert_never from _pytest.compat import get_real_func -from _pytest.compat import is_generator from _pytest.compat import safe_getattr from _pytest.compat import safe_isclass from _pytest.outcomes import OutcomeException @@ -30,8 +30,8 @@ def zap(): def foo(): pass # pragma: no cover - assert is_generator(zap) - assert not is_generator(foo) + assert inspect.isgeneratorfunction(zap) + assert not inspect.isgeneratorfunction(foo) def test_real_func_loop_limit() -> None: @@ -99,14 +99,15 @@ def foo(x): def test_is_generator_asyncio(pytester: Pytester) -> None: pytester.makepyfile( """ - from _pytest.compat import is_generator import asyncio + import inspect + @asyncio.coroutine def baz(): yield from [1,2,3] def test_is_generator_asyncio(): - assert not is_generator(baz) + assert not inspect.isgeneratorfunction(baz) """ ) # avoid importing asyncio into pytest's own process, @@ -118,7 +119,7 @@ def test_is_generator_asyncio(): def test_is_generator_async_syntax(pytester: Pytester) -> None: pytester.makepyfile( """ - from _pytest.compat import is_generator + import inspect def test_is_generator_py35(): async def foo(): await foo() @@ -126,8 +127,8 @@ async def foo(): async def bar(): pass - assert not is_generator(foo) - assert not is_generator(bar) + assert not inspect.isgeneratorfunction(foo) + assert not inspect.isgeneratorfunction(bar) """ ) result = pytester.runpytest() @@ -137,7 +138,7 @@ async def bar(): def test_is_generator_async_gen_syntax(pytester: Pytester) -> None: pytester.makepyfile( """ - from _pytest.compat import is_generator + import inspect def test_is_generator(): async def foo(): yield @@ -146,8 +147,8 @@ async def foo(): async def bar(): yield - assert not is_generator(foo) - assert not is_generator(bar) + assert not inspect.isgeneratorfunction(foo) + assert not inspect.isgeneratorfunction(bar) """ ) result = pytester.runpytest() From 16cab96de4d1aed54cc4aefc120f7747942b6587 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:57:24 +0000 Subject: [PATCH 0956/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- changelog/12960.improvement.rst | 2 +- testing/test_compat.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/12960.improvement.rst b/changelog/12960.improvement.rst index 11767e022db..ac9c9e431b1 100644 --- a/changelog/12960.improvement.rst +++ b/changelog/12960.improvement.rst @@ -1 +1 @@ -Removed _pytest.compat.is_generator() and just using inspect.isgeneratorfunction() directly \ No newline at end of file +Removed _pytest.compat.is_generator() and just using inspect.isgeneratorfunction() directly diff --git a/testing/test_compat.py b/testing/test_compat.py index 32a8b771e08..17f343ab5d2 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -5,8 +5,8 @@ from functools import cached_property from functools import partial from functools import wraps -import sys import inspect +import sys from typing import TYPE_CHECKING from _pytest.compat import _PytestWrapper From 71a35d4a3c8bf626cb73be0cb900ede18b1b123d Mon Sep 17 00:00:00 2001 From: Stefaan Lippens Date: Sat, 16 Nov 2024 19:57:06 +0100 Subject: [PATCH 0957/1271] Issue #12966 Clarify filterwarnings docs on precedence when using multiple marks (#12967) --- changelog/12966.doc.rst | 1 + doc/en/how-to/capture-warnings.rst | 33 +++++++++++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 changelog/12966.doc.rst diff --git a/changelog/12966.doc.rst b/changelog/12966.doc.rst new file mode 100644 index 00000000000..8a440c2ec0f --- /dev/null +++ b/changelog/12966.doc.rst @@ -0,0 +1 @@ +Clarify :ref:`filterwarnings` docs on filter precedence/order when using multiple :ref:`@pytest.mark.filterwarnings ` marks. diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 44ed87508a3..65a43cec6e8 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -128,7 +128,7 @@ is performed. -You can use the ``@pytest.mark.filterwarnings`` to add warning filters to specific test items, +You can use the :ref:`@pytest.mark.filterwarnings ` mark to add warning filters to specific test items, allowing you to have finer control of which warnings should be captured at test, class or even module level: @@ -147,10 +147,30 @@ even module level: assert api_v1() == 1 +You can specify multiple filters with separate decorators: + +.. code-block:: python + + # Ignore "api v1" warnings, but fail on all other warnings + @pytest.mark.filterwarnings("ignore:api v1") + @pytest.mark.filterwarnings("error") + def test_one(): + assert api_v1() == 1 + +.. important:: + + Regarding decorator order and filter precedence: + it's important to remember that decorators are evaluated in reverse order, + so you have to list the warning filters in the reverse order + compared to traditional :py:func:`warnings.filterwarnings` and :option:`-W option ` usage. + This means in practice that filters from earlier :ref:`@pytest.mark.filterwarnings ` decorators + take precedence over filters from later decorators, as illustrated in the example above. + + Filters applied using a mark take precedence over filters passed on the command line or configured -by the ``filterwarnings`` ini option. +by the :confval:`filterwarnings` ini option. -You may apply a filter to all tests of a class by using the ``filterwarnings`` mark as a class +You may apply a filter to all tests of a class by using the :ref:`filterwarnings ` mark as a class decorator or to all tests in a module by setting the :globalvar:`pytestmark` variable: .. code-block:: python @@ -159,6 +179,13 @@ decorator or to all tests in a module by setting the :globalvar:`pytestmark` var pytestmark = pytest.mark.filterwarnings("error") +.. note:: + + If you want to apply multiple filters + (by assigning a list of :ref:`filterwarnings ` mark to :globalvar:`pytestmark`), + you must use the traditional :py:func:`warnings.filterwarnings` ordering approach (later filters take precedence), + which is the reverse of the decorator approach mentioned above. + *Credits go to Florian Schulze for the reference implementation in the* `pytest-warnings`_ *plugin.* From a44da2d1282baa8c8687cb2325d81693eee6c777 Mon Sep 17 00:00:00 2001 From: Gupta Arpit Date: Sun, 17 Nov 2024 01:33:53 +0530 Subject: [PATCH 0958/1271] Added suggested changes --- src/_pytest/python.py | 6 ++---- testing/test_compat.py | 39 --------------------------------------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 63d638e8a8c..bae770e2062 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -231,15 +231,13 @@ def pytest_pycollect_makeitem( ) elif getattr(obj, "__test__", True): if inspect.isgeneratorfunction(obj): - res = Function.from_parent(collector, name=name) reason = ( f"yield tests were removed in pytest 4.0 - {name} will be ignored" ) - res.add_marker(MARK_GEN.xfail(run=False, reason=reason)) - res.warn(PytestCollectionWarning(reason)) - return res + raise RuntimeError(reason) # Raise a hard error instead of xfail else: return list(collector._genfunctions(name, obj)) + return None return None diff --git a/testing/test_compat.py b/testing/test_compat.py index 17f343ab5d2..65c4b10ff7f 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -116,45 +116,6 @@ def test_is_generator_asyncio(): result.stdout.fnmatch_lines(["*1 passed*"]) -def test_is_generator_async_syntax(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import inspect - def test_is_generator_py35(): - async def foo(): - await foo() - - async def bar(): - pass - - assert not inspect.isgeneratorfunction(foo) - assert not inspect.isgeneratorfunction(bar) - """ - ) - result = pytester.runpytest() - result.stdout.fnmatch_lines(["*1 passed*"]) - - -def test_is_generator_async_gen_syntax(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import inspect - def test_is_generator(): - async def foo(): - yield - await foo() - - async def bar(): - yield - - assert not inspect.isgeneratorfunction(foo) - assert not inspect.isgeneratorfunction(bar) - """ - ) - result = pytester.runpytest() - result.stdout.fnmatch_lines(["*1 passed*"]) - - class ErrorsHelper: @property def raise_baseexception(self): From 526529a85fbee376de740c76a1397ac43f0a6ab2 Mon Sep 17 00:00:00 2001 From: Gupta Arpit Date: Sat, 16 Nov 2024 22:26:53 +0530 Subject: [PATCH 0959/1271] Remove _pytest.compat.is_generator() fix #12960 --- changelog/12960.improvement.rst | 1 + src/_pytest/compat.py | 5 ----- src/_pytest/fixtures.py | 3 +-- src/_pytest/python.py | 3 +-- testing/test_compat.py | 23 ++++++++++++----------- 5 files changed, 15 insertions(+), 20 deletions(-) create mode 100644 changelog/12960.improvement.rst diff --git a/changelog/12960.improvement.rst b/changelog/12960.improvement.rst new file mode 100644 index 00000000000..11767e022db --- /dev/null +++ b/changelog/12960.improvement.rst @@ -0,0 +1 @@ +Removed _pytest.compat.is_generator() and just using inspect.isgeneratorfunction() directly \ No newline at end of file diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 614848e0dba..82aea5e635e 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -43,11 +43,6 @@ class NotSetType(enum.Enum): # fmt: on -def is_generator(func: object) -> bool: - genfunc = inspect.isgeneratorfunction(func) - return genfunc and not iscoroutinefunction(func) - - def iscoroutinefunction(func: object) -> bool: """Return True if func is a coroutine function (a function defined with async def syntax, and doesn't contain yield), or a function decorated with diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 8f275e4d622..6407ae0c48f 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -49,7 +49,6 @@ from _pytest.compat import getfuncargnames from _pytest.compat import getimfunc from _pytest.compat import getlocation -from _pytest.compat import is_generator from _pytest.compat import NOTSET from _pytest.compat import NotSetType from _pytest.compat import safe_getattr @@ -891,7 +890,7 @@ def toterminal(self, tw: TerminalWriter) -> None: def call_fixture_func( fixturefunc: _FixtureFunc[FixtureValue], request: FixtureRequest, kwargs ) -> FixtureValue: - if is_generator(fixturefunc): + if inspect.isgeneratorfunction(fixturefunc): fixturefunc = cast( Callable[..., Generator[FixtureValue, None, None]], fixturefunc ) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index d48a6c4a9fb..63d638e8a8c 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -43,7 +43,6 @@ from _pytest.compat import get_real_func from _pytest.compat import getimfunc from _pytest.compat import is_async_function -from _pytest.compat import is_generator from _pytest.compat import LEGACY_PATH from _pytest.compat import NOTSET from _pytest.compat import safe_getattr @@ -231,7 +230,7 @@ def pytest_pycollect_makeitem( lineno=lineno + 1, ) elif getattr(obj, "__test__", True): - if is_generator(obj): + if inspect.isgeneratorfunction(obj): res = Function.from_parent(collector, name=name) reason = ( f"yield tests were removed in pytest 4.0 - {name} will be ignored" diff --git a/testing/test_compat.py b/testing/test_compat.py index 2c6b0269c27..32a8b771e08 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -6,12 +6,12 @@ from functools import partial from functools import wraps import sys +import inspect from typing import TYPE_CHECKING from _pytest.compat import _PytestWrapper from _pytest.compat import assert_never from _pytest.compat import get_real_func -from _pytest.compat import is_generator from _pytest.compat import safe_getattr from _pytest.compat import safe_isclass from _pytest.outcomes import OutcomeException @@ -30,8 +30,8 @@ def zap(): def foo(): pass # pragma: no cover - assert is_generator(zap) - assert not is_generator(foo) + assert inspect.isgeneratorfunction(zap) + assert not inspect.isgeneratorfunction(foo) def test_real_func_loop_limit() -> None: @@ -99,14 +99,15 @@ def foo(x): def test_is_generator_asyncio(pytester: Pytester) -> None: pytester.makepyfile( """ - from _pytest.compat import is_generator import asyncio + import inspect + @asyncio.coroutine def baz(): yield from [1,2,3] def test_is_generator_asyncio(): - assert not is_generator(baz) + assert not inspect.isgeneratorfunction(baz) """ ) # avoid importing asyncio into pytest's own process, @@ -118,7 +119,7 @@ def test_is_generator_asyncio(): def test_is_generator_async_syntax(pytester: Pytester) -> None: pytester.makepyfile( """ - from _pytest.compat import is_generator + import inspect def test_is_generator_py35(): async def foo(): await foo() @@ -126,8 +127,8 @@ async def foo(): async def bar(): pass - assert not is_generator(foo) - assert not is_generator(bar) + assert not inspect.isgeneratorfunction(foo) + assert not inspect.isgeneratorfunction(bar) """ ) result = pytester.runpytest() @@ -137,7 +138,7 @@ async def bar(): def test_is_generator_async_gen_syntax(pytester: Pytester) -> None: pytester.makepyfile( """ - from _pytest.compat import is_generator + import inspect def test_is_generator(): async def foo(): yield @@ -146,8 +147,8 @@ async def foo(): async def bar(): yield - assert not is_generator(foo) - assert not is_generator(bar) + assert not inspect.isgeneratorfunction(foo) + assert not inspect.isgeneratorfunction(bar) """ ) result = pytester.runpytest() From 42cd2965e59b110419e2f6ac91e35bcdfdb3e6a8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:57:24 +0000 Subject: [PATCH 0960/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- changelog/12960.improvement.rst | 2 +- testing/test_compat.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/12960.improvement.rst b/changelog/12960.improvement.rst index 11767e022db..ac9c9e431b1 100644 --- a/changelog/12960.improvement.rst +++ b/changelog/12960.improvement.rst @@ -1 +1 @@ -Removed _pytest.compat.is_generator() and just using inspect.isgeneratorfunction() directly \ No newline at end of file +Removed _pytest.compat.is_generator() and just using inspect.isgeneratorfunction() directly diff --git a/testing/test_compat.py b/testing/test_compat.py index 32a8b771e08..17f343ab5d2 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -5,8 +5,8 @@ from functools import cached_property from functools import partial from functools import wraps -import sys import inspect +import sys from typing import TYPE_CHECKING from _pytest.compat import _PytestWrapper From 38a241671ccd56e6c6ff131f8e85bb5ef82fc701 Mon Sep 17 00:00:00 2001 From: Gupta Arpit Date: Sun, 17 Nov 2024 01:33:53 +0530 Subject: [PATCH 0961/1271] Added suggested changes --- src/_pytest/python.py | 6 ++---- testing/test_compat.py | 39 --------------------------------------- 2 files changed, 2 insertions(+), 43 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 63d638e8a8c..bae770e2062 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -231,15 +231,13 @@ def pytest_pycollect_makeitem( ) elif getattr(obj, "__test__", True): if inspect.isgeneratorfunction(obj): - res = Function.from_parent(collector, name=name) reason = ( f"yield tests were removed in pytest 4.0 - {name} will be ignored" ) - res.add_marker(MARK_GEN.xfail(run=False, reason=reason)) - res.warn(PytestCollectionWarning(reason)) - return res + raise RuntimeError(reason) # Raise a hard error instead of xfail else: return list(collector._genfunctions(name, obj)) + return None return None diff --git a/testing/test_compat.py b/testing/test_compat.py index 17f343ab5d2..65c4b10ff7f 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -116,45 +116,6 @@ def test_is_generator_asyncio(): result.stdout.fnmatch_lines(["*1 passed*"]) -def test_is_generator_async_syntax(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import inspect - def test_is_generator_py35(): - async def foo(): - await foo() - - async def bar(): - pass - - assert not inspect.isgeneratorfunction(foo) - assert not inspect.isgeneratorfunction(bar) - """ - ) - result = pytester.runpytest() - result.stdout.fnmatch_lines(["*1 passed*"]) - - -def test_is_generator_async_gen_syntax(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import inspect - def test_is_generator(): - async def foo(): - yield - await foo() - - async def bar(): - yield - - assert not inspect.isgeneratorfunction(foo) - assert not inspect.isgeneratorfunction(bar) - """ - ) - result = pytester.runpytest() - result.stdout.fnmatch_lines(["*1 passed*"]) - - class ErrorsHelper: @property def raise_baseexception(self): From ecc26e04f41d9c60f94cc80d0b2f0c6cd77117dd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Nov 2024 20:04:32 +0000 Subject: [PATCH 0962/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/python.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index bae770e2062..23b65765a53 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -56,7 +56,6 @@ from _pytest.fixtures import FuncFixtureInfo from _pytest.fixtures import get_scope_node from _pytest.main import Session -from _pytest.mark import MARK_GEN from _pytest.mark import ParameterSet from _pytest.mark.structures import get_unpacked_marks from _pytest.mark.structures import Mark From 3ab4a77606652a4aa11f2ffba8dedf84b3474d99 Mon Sep 17 00:00:00 2001 From: Arpit Gupta <113178590+arpitgupta-it@users.noreply.github.com> Date: Sun, 17 Nov 2024 01:50:30 +0530 Subject: [PATCH 0963/1271] Removed stdlib tests as per review --- testing/test_compat.py | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/testing/test_compat.py b/testing/test_compat.py index 65c4b10ff7f..07c28cebdd1 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -23,17 +23,6 @@ from typing_extensions import Literal -def test_is_generator() -> None: - def zap(): - yield # pragma: no cover - - def foo(): - pass # pragma: no cover - - assert inspect.isgeneratorfunction(zap) - assert not inspect.isgeneratorfunction(foo) - - def test_real_func_loop_limit() -> None: class Evil: def __init__(self): @@ -95,27 +84,6 @@ def foo(x): assert get_real_func(partial(foo)) is foo -@pytest.mark.skipif(sys.version_info >= (3, 11), reason="coroutine removed") -def test_is_generator_asyncio(pytester: Pytester) -> None: - pytester.makepyfile( - """ - import asyncio - import inspect - - @asyncio.coroutine - def baz(): - yield from [1,2,3] - - def test_is_generator_asyncio(): - assert not inspect.isgeneratorfunction(baz) - """ - ) - # avoid importing asyncio into pytest's own process, - # which in turn imports logging (#8) - result = pytester.runpytest_subprocess() - result.stdout.fnmatch_lines(["*1 passed*"]) - - class ErrorsHelper: @property def raise_baseexception(self): From 362a2179305139b3c877f0c2b2ed004a2f8ecf09 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 16 Nov 2024 20:20:49 +0000 Subject: [PATCH 0964/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- testing/test_compat.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/testing/test_compat.py b/testing/test_compat.py index 07c28cebdd1..86868858956 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -5,8 +5,6 @@ from functools import cached_property from functools import partial from functools import wraps -import inspect -import sys from typing import TYPE_CHECKING from _pytest.compat import _PytestWrapper @@ -15,7 +13,6 @@ from _pytest.compat import safe_getattr from _pytest.compat import safe_isclass from _pytest.outcomes import OutcomeException -from _pytest.pytester import Pytester import pytest From 8691ff1f368620c112983a5ef7c5ad82b46d9d34 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 03:25:38 +0000 Subject: [PATCH 0965/1271] [automated] Update plugin list (#12970) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 166 +++++++++++++++++++------------ 1 file changed, 103 insertions(+), 63 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index ecd96b89967..ee0981e3694 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,14 +27,14 @@ please refer to `the update script =8.3 + :pypi:`databricks-labs-pytester` Python Testing for Databricks Nov 15, 2024 4 - Beta pytest>=8.3 :pypi:`logassert` Simple but powerful assertion and verification of logged lines. Nov 08, 2024 5 - Production/Stable N/A :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 @@ -148,7 +148,7 @@ This list contains 1540 plugins. :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 :pypi:`pytest-bazel` A pytest runner with bazel support Sep 27, 2024 4 - Beta pytest - :pypi:`pytest-bdd` BDD for pytest Oct 15, 2024 6 - Mature pytest>=6.2.0 + :pypi:`pytest-bdd` BDD for pytest Nov 14, 2024 6 - Mature pytest>=7.0.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Oct 07, 2024 4 - Beta pytest>=5.0 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 26, 2024 N/A pytest>=7.1.3 @@ -157,7 +157,7 @@ This list contains 1540 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Nov 05, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Nov 11, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -243,6 +243,7 @@ This list contains 1540 plugins. :pypi:`pytest-circleci-parallelized-rjp` Parallelize pytest across CircleCI workers. Jun 21, 2022 N/A pytest :pypi:`pytest-ckan` Backport of CKAN 2.9 pytest plugin and fixtures to CAKN 2.8 Apr 28, 2020 4 - Beta pytest :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A + :pypi:`pytest-class-fixtures` Class as PyTest fixtures (and BDD steps) Nov 15, 2024 N/A pytest<9.0.0,>=8.3.3 :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A @@ -352,11 +353,12 @@ This list contains 1540 plugins. :pypi:`pytest-deadfixtures` A simple plugin to list unused fixtures in pytest Jul 23, 2020 5 - Production/Stable N/A :pypi:`pytest-deduplicate` Identifies duplicate unit tests Aug 12, 2023 4 - Beta pytest :pypi:`pytest-deepcov` deepcov Mar 30, 2021 N/A N/A - :pypi:`pytest-defer` Aug 24, 2021 N/A N/A + :pypi:`pytest_defer` A 'defer' fixture for pytest Nov 13, 2024 N/A pytest>=8.3 :pypi:`pytest-demo-plugin` pytest示例插件 May 15, 2021 N/A N/A :pypi:`pytest-dependency` Manage dependencies of tests Dec 31, 2023 4 - Beta N/A :pypi:`pytest-depends` Tests that depend on other tests Apr 05, 2020 5 - Production/Stable pytest (>=3) :pypi:`pytest-deprecate` Mark tests as testing a deprecated feature with a warning note. Jul 01, 2019 N/A N/A + :pypi:`pytest-deprecator` A simple plugin to use with pytest Nov 14, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-describe` Describe-style plugin for pytest Feb 10, 2024 5 - Production/Stable pytest <9,>=4.6 :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest :pypi:`pytest-deselect-if` A plugin to deselect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 @@ -465,14 +467,15 @@ This list contains 1540 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 Jul 25, 2024 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. Oct 29, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Oct 29, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Oct 29, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Oct 29, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Oct 29, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Oct 29, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Oct 29, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Oct 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Nov 14, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Nov 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Nov 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Nov 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Nov 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Nov 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Nov 14, 2024 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) @@ -499,7 +502,7 @@ This list contains 1540 plugins. :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Aug 13, 2024 4 - Beta pytest>=7 + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Nov 15, 2024 N/A pytest>=7 :pypi:`pytest-exasol-backend` Oct 31, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-extension` Oct 10, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 @@ -601,7 +604,7 @@ This list contains 1540 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Nov 07, 2024 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Nov 16, 2024 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A @@ -611,7 +614,7 @@ This list contains 1540 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jun 30, 2024 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Nov 14, 2024 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest @@ -660,7 +663,7 @@ This list contains 1540 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 09, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Nov 16, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -738,7 +741,7 @@ This list contains 1540 plugins. :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Sep 18, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A - :pypi:`pytest-item-dict` Get a hierarchical dict of session.items Oct 30, 2024 4 - Beta pytest>=8.3.0 + :pypi:`pytest-item-dict` Get a hierarchical dict of session.items Nov 14, 2024 4 - Beta pytest>=8.3.0 :pypi:`pytest-iterassert` Nicer list and iterable assertion messages for pytest May 11, 2020 3 - Alpha N/A :pypi:`pytest-iteration` Add iteration mark for tests Aug 22, 2024 N/A pytest :pypi:`pytest-iters` A contextmanager pytest fixture for handling multiple mock iters May 24, 2022 N/A N/A @@ -826,7 +829,7 @@ This list contains 1540 plugins. :pypi:`pytest-loop` pytest plugin for looping tests Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Sep 04, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 - :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Oct 18, 2024 4 - Beta pytest>=8.0.0 + :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Nov 13, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Oct 22, 2024 N/A pytest>=7.0.0 @@ -867,7 +870,7 @@ This list contains 1540 plugins. :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Aug 27, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-missing-modules` Pytest plugin to easily fake missing modules Sep 03, 2024 N/A pytest>=8.3.2 - :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Sep 12, 2024 N/A pytest>=7.0 + :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Nov 13, 2024 N/A pytest>=7.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Mar 21, 2024 5 - Production/Stable pytest>=6.2.5 @@ -979,7 +982,7 @@ This list contains 1540 plugins. :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A - :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Oct 30, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 + :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Nov 10, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Oct 22, 2024 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest @@ -1098,7 +1101,7 @@ This list contains 1540 plugins. :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-qanova` A pytest plugin to collect test information Sep 05, 2024 3 - Alpha pytest - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Oct 28, 2024 5 - Production/Stable pytest<9.0.0,>=7.2.2 + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Nov 15, 2024 5 - Production/Stable pytest<9.0.0,>=7.2.2 :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 14, 2024 5 - Production/Stable pytest>=6.0 @@ -1137,7 +1140,7 @@ This list contains 1540 plugins. :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 - :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Oct 17, 2024 N/A pytest>7.2 + :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Nov 12, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relative-path` Handle relative path in pytest options or ini configs Aug 30, 2024 N/A pytest :pypi:`pytest-relaxed` Relaxed test discovery/organization for pytest Mar 29, 2024 5 - Production/Stable pytest>=7 @@ -1209,7 +1212,7 @@ This list contains 1540 plugins. :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 21, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A - :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Sep 30, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Nov 13, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 @@ -1225,7 +1228,7 @@ This list contains 1540 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 15, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1236,7 +1239,7 @@ This list contains 1540 plugins. :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 Feb 01, 2024 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 09, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 15, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1246,7 +1249,7 @@ This list contains 1540 plugins. :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixtures for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Sep 17, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-servers` pytest servers Nov 14, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-service` Aug 06, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest @@ -1289,6 +1292,7 @@ This list contains 1540 plugins. :pypi:`pytest-smtp-test-server` pytest plugin for using \`smtp-test-server\` as a fixture Dec 03, 2023 2 - Pre-Alpha pytest (>=7.4.3,<8.0.0) :pypi:`pytest-snail` Plugin for adding a marker to slow running tests. 🐌 Nov 04, 2019 3 - Alpha pytest (>=5.0.1) :pypi:`pytest-snapci` py.test plugin for Snap-CI Nov 12, 2015 N/A N/A + :pypi:`pytest-snapmock` Snapshots for your mocks. Nov 15, 2024 N/A N/A :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) :pypi:`pytest-snapshot-with-message-generator` A plugin for snapshot testing with pytest. Jul 25, 2023 4 - Beta pytest (>=3.0.0) :pypi:`pytest-snmpserver` May 12, 2021 N/A N/A @@ -1383,7 +1387,7 @@ This list contains 1540 plugins. :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) - :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Oct 25, 2016 5 - Production/Stable N/A + :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Nov 14, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-testinfra` Test infrastructures May 26, 2024 5 - Production/Stable pytest>=6 :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 @@ -1412,7 +1416,7 @@ This list contains 1540 plugins. :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Aug 20, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 - :pypi:`pytest-tesults` Tesults plugin for pytest Sep 09, 2024 5 - Production/Stable pytest>=3.5.0 + :pypi:`pytest-tesults` Tesults plugin for pytest Nov 12, 2024 5 - Production/Stable pytest>=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 22, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-tf` Test your OpenTofu and Terraform config using a PyTest plugin May 29, 2024 N/A pytest<9.0.0,>=8.2.1 @@ -1542,6 +1546,7 @@ This list contains 1540 plugins. :pypi:`pytest-xiuyu` This is a pytest plugin Jul 25, 2023 5 - Production/Stable N/A :pypi:`pytest-xlog` Extended logging for test and decorators May 31, 2020 4 - Beta N/A :pypi:`pytest-xlsx` pytest plugin for generating test cases by xlsx(excel) Aug 07, 2024 N/A pytest~=8.2.2 + :pypi:`pytest-xml` Create simple XML results for parsing Nov 14, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-xpara` An extended parametrizing plugin of pytest. Aug 07, 2024 3 - Alpha pytest :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. May 19, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A @@ -1580,7 +1585,7 @@ This list contains 1540 plugins. :pypi:`databricks-labs-pytester` - *last release*: Nov 04, 2024, + *last release*: Nov 15, 2024, *status*: 4 - Beta, *requires*: pytest>=8.3 @@ -2378,9 +2383,9 @@ This list contains 1540 plugins. A pytest runner with bazel support :pypi:`pytest-bdd` - *last release*: Oct 15, 2024, + *last release*: Nov 14, 2024, *status*: 6 - Mature, - *requires*: pytest>=6.2.0 + *requires*: pytest>=7.0.0 BDD for pytest @@ -2441,7 +2446,7 @@ This list contains 1540 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Nov 05, 2024, + *last release*: Nov 11, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3042,6 +3047,13 @@ This list contains 1540 plugins. A plugin providing an alternative, colourful diff output for failing assertions. + :pypi:`pytest-class-fixtures` + *last release*: Nov 15, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.3.3 + + Class as PyTest fixtures (and BDD steps) + :pypi:`pytest-cldf` *last release*: Nov 07, 2022, *status*: N/A, @@ -3805,12 +3817,12 @@ This list contains 1540 plugins. deepcov - :pypi:`pytest-defer` - *last release*: Aug 24, 2021, + :pypi:`pytest_defer` + *last release*: Nov 13, 2024, *status*: N/A, - *requires*: N/A - + *requires*: pytest>=8.3 + A 'defer' fixture for pytest :pypi:`pytest-demo-plugin` *last release*: May 15, 2021, @@ -3840,6 +3852,13 @@ This list contains 1540 plugins. Mark tests as testing a deprecated feature with a warning note. + :pypi:`pytest-deprecator` + *last release*: Nov 14, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A simple plugin to use with pytest + :pypi:`pytest-describe` *last release*: Feb 10, 2024, *status*: 5 - Production/Stable, @@ -4597,56 +4616,63 @@ This list contains 1540 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Oct 29, 2024, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Oct 29, 2024, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Oct 29, 2024, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Oct 29, 2024, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. + :pypi:`pytest-embedded-nuttx` + *last release*: Nov 14, 2024, + *status*: 5 - Production/Stable, + *requires*: N/A + + Make pytest-embedded plugin work with NuttX. + :pypi:`pytest-embedded-qemu` - *last release*: Oct 29, 2024, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Oct 29, 2024, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Oct 29, 2024, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Oct 29, 2024, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -4835,8 +4861,8 @@ This list contains 1540 plugins. Parse queries in Lucene and Elasticsearch syntaxes :pypi:`pytest-examples` - *last release*: Aug 13, 2024, - *status*: 4 - Beta, + *last release*: Nov 15, 2024, + *status*: N/A, *requires*: pytest>=7 Pytest plugin for testing examples in docstrings and markdown files. @@ -5549,7 +5575,7 @@ This list contains 1540 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Nov 07, 2024, + *last release*: Nov 16, 2024, *status*: N/A, *requires*: pytest @@ -5619,7 +5645,7 @@ This list contains 1540 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Jun 30, 2024, + *last release*: Nov 14, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -5962,7 +5988,7 @@ This list contains 1540 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Nov 09, 2024, + *last release*: Nov 16, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6508,7 +6534,7 @@ This list contains 1540 plugins. Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. :pypi:`pytest-item-dict` - *last release*: Oct 30, 2024, + *last release*: Nov 14, 2024, *status*: 4 - Beta, *requires*: pytest>=8.3.0 @@ -7124,7 +7150,7 @@ This list contains 1540 plugins. pytest marker for marking manual tests :pypi:`pytest-mark-count` - *last release*: Oct 18, 2024, + *last release*: Nov 13, 2024, *status*: 4 - Beta, *requires*: pytest>=8.0.0 @@ -7411,7 +7437,7 @@ This list contains 1540 plugins. Pytest plugin to easily fake missing modules :pypi:`pytest-mitmproxy` - *last release*: Sep 12, 2024, + *last release*: Nov 13, 2024, *status*: N/A, *requires*: pytest>=7.0 @@ -8195,7 +8221,7 @@ This list contains 1540 plugins. Simpler PyTest parametrization :pypi:`pytest-parametrize` - *last release*: Oct 30, 2024, + *last release*: Nov 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=8.3.0 @@ -9028,7 +9054,7 @@ This list contains 1540 plugins. A pytest plugin to collect test information :pypi:`pytest-qaseio` - *last release*: Oct 28, 2024, + *last release*: Nov 15, 2024, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=7.2.2 @@ -9301,7 +9327,7 @@ This list contains 1540 plugins. Easy to use fixtures to write regression tests. :pypi:`pytest-regtest` - *last release*: Oct 17, 2024, + *last release*: Nov 12, 2024, *status*: N/A, *requires*: pytest>7.2 @@ -9805,7 +9831,7 @@ This list contains 1540 plugins. implement a --failed option for pytest :pypi:`pytest-run-parallel` - *last release*: Sep 30, 2024, + *last release*: Nov 13, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -9917,7 +9943,7 @@ This list contains 1540 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Nov 09, 2024, + *last release*: Nov 15, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9994,7 +10020,7 @@ This list contains 1540 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Nov 09, 2024, + *last release*: Nov 15, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10064,7 +10090,7 @@ This list contains 1540 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Sep 17, 2024, + *last release*: Nov 14, 2024, *status*: 3 - Alpha, *requires*: pytest>=6.2 @@ -10364,6 +10390,13 @@ This list contains 1540 plugins. py.test plugin for Snap-CI + :pypi:`pytest-snapmock` + *last release*: Nov 15, 2024, + *status*: N/A, + *requires*: N/A + + Snapshots for your mocks. + :pypi:`pytest-snapshot` *last release*: Apr 23, 2022, *status*: 4 - Beta, @@ -11023,9 +11056,9 @@ This list contains 1540 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-test-groups` - *last release*: Oct 25, 2016, + *last release*: Nov 14, 2024, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest>=7.0.0 A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. @@ -11226,7 +11259,7 @@ This list contains 1540 plugins. :pypi:`pytest-tesults` - *last release*: Sep 09, 2024, + *last release*: Nov 12, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=3.5.0 @@ -12135,6 +12168,13 @@ This list contains 1540 plugins. pytest plugin for generating test cases by xlsx(excel) + :pypi:`pytest-xml` + *last release*: Nov 14, 2024, + *status*: 4 - Beta, + *requires*: pytest>=8.0.0 + + Create simple XML results for parsing + :pypi:`pytest-xpara` *last release*: Aug 07, 2024, *status*: 3 - Alpha, From 78017f41313f5135f0afe00d9ad57937b4e41045 Mon Sep 17 00:00:00 2001 From: Gupta Arpit Date: Sun, 17 Nov 2024 13:45:51 +0530 Subject: [PATCH 0966/1271] Pushed review changes --- changelog/12960.improvement.rst | 2 +- src/_pytest/python.py | 8 ++------ testing/test_terminal.py | 5 ----- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/changelog/12960.improvement.rst b/changelog/12960.improvement.rst index ac9c9e431b1..e935f90704b 100644 --- a/changelog/12960.improvement.rst +++ b/changelog/12960.improvement.rst @@ -1 +1 @@ -Removed _pytest.compat.is_generator() and just using inspect.isgeneratorfunction() directly +Test functions containing a yield now cause an explicit error. They have not been run since Pytest 4.0, and were previously marked as an expected failure and deprecation warning. \ No newline at end of file diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 23b65765a53..d1e8d369e7c 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -230,12 +230,8 @@ def pytest_pycollect_makeitem( ) elif getattr(obj, "__test__", True): if inspect.isgeneratorfunction(obj): - reason = ( - f"yield tests were removed in pytest 4.0 - {name} will be ignored" - ) - raise RuntimeError(reason) # Raise a hard error instead of xfail - else: - return list(collector._genfunctions(name, obj)) + raise RuntimeError("'yield' keyword is allowed in fixtures, but not in tests ({name})") + return list(collector._genfunctions(name, obj)) return None return None diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 14c152d6123..872703900cd 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1042,10 +1042,6 @@ def test_pass(): class TestClass(object): def test_skip(self): pytest.skip("hello") - def test_gen(): - def check(x): - assert x == 1 - yield check, 0 """ ) @@ -1058,7 +1054,6 @@ def test_verbose_reporting(self, verbose_testfile, pytester: Pytester) -> None: "*test_verbose_reporting.py::test_fail *FAIL*", "*test_verbose_reporting.py::test_pass *PASS*", "*test_verbose_reporting.py::TestClass::test_skip *SKIP*", - "*test_verbose_reporting.py::test_gen *XFAIL*", ] ) assert result.ret == 1 From a074630394daa767ea2bc700f3626a2533288268 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 08:16:14 +0000 Subject: [PATCH 0967/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- changelog/12960.improvement.rst | 2 +- src/_pytest/python.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/changelog/12960.improvement.rst b/changelog/12960.improvement.rst index e935f90704b..43e981dc648 100644 --- a/changelog/12960.improvement.rst +++ b/changelog/12960.improvement.rst @@ -1 +1 @@ -Test functions containing a yield now cause an explicit error. They have not been run since Pytest 4.0, and were previously marked as an expected failure and deprecation warning. \ No newline at end of file +Test functions containing a yield now cause an explicit error. They have not been run since Pytest 4.0, and were previously marked as an expected failure and deprecation warning. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index d1e8d369e7c..d117fa58d01 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -230,7 +230,9 @@ def pytest_pycollect_makeitem( ) elif getattr(obj, "__test__", True): if inspect.isgeneratorfunction(obj): - raise RuntimeError("'yield' keyword is allowed in fixtures, but not in tests ({name})") + raise RuntimeError( + "'yield' keyword is allowed in fixtures, but not in tests ({name})" + ) return list(collector._genfunctions(name, obj)) return None return None From 49c140d286155f91969ce9e4cf6e3b15aee621d2 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Sun, 17 Nov 2024 11:29:02 +0100 Subject: [PATCH 0968/1271] Apply suggestions from code review Co-authored-by: Bruno Oliveira --- src/_pytest/fixtures.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index b5c64856e12..8122d7fe2a8 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -1154,9 +1154,9 @@ def pytest_fixture_setup( f"{request.node.name!r} requested an async fixture " f"{request.fixturename!r}{auto_str}, with no plugin or hook that " "handled it. This is usually an error, as pytest does not natively " - "support it. If this is intentional, consider making the fixture " - "sync and return a coroutine/asyncgen. " - "This will turn into an error in pytest 9." + "support it. " + "This will turn into an error in pytest 9.\n" + "See: https://docs.pytest.org/en/stable/deprecations.html#sync-test-depending-on-async-fixture" ), # no stacklevel will point at users code, so we just point here stacklevel=1, From f434c278e45092e2091cd9358251c58ca9e0bce8 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Sun, 17 Nov 2024 11:44:07 +0100 Subject: [PATCH 0969/1271] be more explicit about the downside of async autouse fixtures --- doc/en/deprecations.rst | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 88cf3eccbf3..59f9d83451b 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -71,7 +71,18 @@ should be changed to You can also make use of `pytest_fixture_setup` to handle the coroutine/asyncgen before pytest sees it - this is the way current async pytest plugins handle it. -If a user has an async fixture with ``autouse=True`` in their ``conftest.py``, or in a file where they also have synchronous tests, they will also get this warning. We strongly recommend against this practice, and they should restructure their testing infrastructure so the fixture is synchronous or to separate the fixture from their synchronous tests. Note that the `anyio pytest plugin `_ has some support for sync test + async fixtures currently. +If a user has an async fixture with ``autouse=True`` in their ``conftest.py``, or in a file +containing both synchronous tests and the fixture, they will receive this warning. +Unless you're using a plugin that specifically handles async fixtures +with synchronous tests, we strongly recommend against this practice. +It can lead to unpredictable behavior (with larger scopes, it may appear to "work" if an async +test is the first to request the fixture, due to value caching) and will generate +unawaited-coroutine runtime warnings (but only for non-yield fixtures). +Additionally, it creates ambiguity for other developers about whether the fixture is intended to perform +setup for synchronous tests. + +The `anyio pytest plugin `_ supports +synchronous tests with async fixtures, though certain limitations apply. .. _import-or-skip-import-error: From 708494008b3976feefeb54f141eeb0ca2e6738a3 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Sun, 17 Nov 2024 11:51:37 +0100 Subject: [PATCH 0970/1271] fix tests after message change --- testing/acceptance_test.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 624a313ca8d..ba1f86f02d9 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1311,10 +1311,9 @@ def test_foo(async_fixture): "*PytestRemovedIn9Warning: 'test_foo' requested an async " "fixture 'async_fixture', with no plugin or hook that handled it. " "This is usually an error, as pytest does not natively support it. " - "If this is intentional, consider making the fixture sync and return " - "a coroutine/asyncgen. " "This will turn into an error in pytest 9." ), + " See: https://docs.pytest.org/en/stable/deprecations.html#sync-test-depending-on-async-fixture", ] ) result.assert_outcomes(passed=1, warnings=1) @@ -1342,10 +1341,9 @@ def test_foo(async_fixture): "*PytestRemovedIn9Warning: 'test_foo' requested an async " "fixture 'async_fixture', with no plugin or hook that handled it. " "This is usually an error, as pytest does not natively support it. " - "If this is intentional, consider making the fixture sync and return " - "a coroutine/asyncgen. " "This will turn into an error in pytest 9." ), + " See: https://docs.pytest.org/en/stable/deprecations.html#sync-test-depending-on-async-fixture", ] ) result.assert_outcomes(passed=1, warnings=1) @@ -1376,11 +1374,11 @@ def test_foo(async_fixture): ( "*PytestRemovedIn9Warning: 'test_foo' requested an async " "fixture 'async_fixture' with autouse=True, with no plugin or hook " - "that handled it. This is usually an error, as pytest does not " - "natively support it. If this is intentional, consider making the " - "fixture sync and return a coroutine/asyncgen. " + "that handled it. " + "This is usually an error, as pytest does not natively support it. " "This will turn into an error in pytest 9." ), + " See: https://docs.pytest.org/en/stable/deprecations.html#sync-test-depending-on-async-fixture", ] ) result.assert_outcomes(passed=1, warnings=1) From 5398d7c15aeb1de7595e5ed4fad0d787feb3d0f2 Mon Sep 17 00:00:00 2001 From: Gupta Arpit Date: Sun, 17 Nov 2024 17:26:00 +0530 Subject: [PATCH 0971/1271] Add test for RuntimeError on 'yield' in tests --- testing/test_collection.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/testing/test_collection.py b/testing/test_collection.py index aba8f8ea48d..80c250027c6 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1878,3 +1878,21 @@ def test_respect_system_exceptions( result.stdout.fnmatch_lines([f"*{head}*"]) result.stdout.fnmatch_lines([msg]) result.stdout.no_fnmatch_line(f"*{tail}*") + + +def test_yield_disallowed_in_tests(pytester: Pytester): + """Ensure generator test functions with 'yield' raise a RuntimeError.""" + pytester.makepyfile( + """ + def test_with_yield(): + yield 1 + """ + ) + result = pytester.runpytest() + assert result.ret == 2 + result.stdout.fnmatch_lines( + ["*RuntimeError: 'yield' keyword is allowed in fixtures, but not in tests (*)*"] + ) + result.stdout.fnmatch_lines( + ["*collected 0 items*"] + ) \ No newline at end of file From bad14eec09c40370270d7fb428deb929c6e2718f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 11:56:25 +0000 Subject: [PATCH 0972/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- testing/test_collection.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/testing/test_collection.py b/testing/test_collection.py index 80c250027c6..53463d81866 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1893,6 +1893,4 @@ def test_with_yield(): result.stdout.fnmatch_lines( ["*RuntimeError: 'yield' keyword is allowed in fixtures, but not in tests (*)*"] ) - result.stdout.fnmatch_lines( - ["*collected 0 items*"] - ) \ No newline at end of file + result.stdout.fnmatch_lines(["*collected 0 items*"]) From 1bcaf2c58d44e4426dd1ef6989206e9790710285 Mon Sep 17 00:00:00 2001 From: Gupta Arpit Date: Mon, 18 Nov 2024 00:37:00 +0530 Subject: [PATCH 0973/1271] Rename changelog/12960.breaking.rst --- changelog/{12960.improvement.rst => 12960.breaking.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog/{12960.improvement.rst => 12960.breaking.rst} (100%) diff --git a/changelog/12960.improvement.rst b/changelog/12960.breaking.rst similarity index 100% rename from changelog/12960.improvement.rst rename to changelog/12960.breaking.rst From f1821eaa13867864ab9048b217ccbaa77e8e781b Mon Sep 17 00:00:00 2001 From: sven <42868792+FreerGit@users.noreply.github.com> Date: Sun, 17 Nov 2024 20:57:38 +0100 Subject: [PATCH 0974/1271] WIP - report collection needs triage --- testing/test_collect_imports.py | 278 +++++++++++++++++--------------- 1 file changed, 148 insertions(+), 130 deletions(-) diff --git a/testing/test_collect_imports.py b/testing/test_collect_imports.py index cf8ff9cb983..cc1c5a80015 100644 --- a/testing/test_collect_imports.py +++ b/testing/test_collect_imports.py @@ -13,78 +13,82 @@ # Start of tests for classes -# def run_import_class_test(pytester: Pytester, passed: int = 0, errors: int = 0) -> None: -# src_dir = pytester.mkdir("src") -# tests_dir = pytester.mkdir("tests") -# src_file = src_dir / "foo.py" - -# src_file.write_text( -# textwrap.dedent("""\ -# class Testament(object): -# def __init__(self): -# super().__init__() -# self.collections = ["stamp", "coin"] - -# def personal_property(self): -# return [f"my {x} collection" for x in self.collections] -# """), -# encoding="utf-8", -# ) - -# test_file = tests_dir / "foo_test.py" -# test_file.write_text( -# textwrap.dedent("""\ -# import sys -# import os - -# current_file = os.path.abspath(__file__) -# current_dir = os.path.dirname(current_file) -# parent_dir = os.path.abspath(os.path.join(current_dir, '..')) -# sys.path.append(parent_dir) - -# from src.foo import Testament - -# class TestDomain: -# def test_testament(self): -# testament = Testament() -# assert testament.personal_property() -# """), -# encoding="utf-8", -# ) - -# result = pytester.runpytest() -# result.assert_outcomes(passed=passed, errors=errors) - -# def test_collect_imports_disabled(pytester: Pytester) -> None: -# pytester.makeini(""" -# [pytest] -# testpaths = "tests" -# collect_imported_tests = false -# """) - -# run_import_class_test(pytester, passed=1) - -# # Verify that the state of hooks -# reprec = pytester.inline_run() -# items_collected = reprec.getcalls("pytest_itemcollected") -# assert len(items_collected) == 1 -# for x in items_collected: -# assert x.item._getobj().__name__ == "test_testament" - -# def test_collect_imports_default(pytester: Pytester) -> None: -# run_import_class_test(pytester, errors=1) - -# # TODO, hooks - - -# def test_collect_imports_enabled(pytester: Pytester) -> None: -# pytester.makeini(""" -# [pytest] -# collect_imported_tests = true -# """) - -# run_import_class_test(pytester, errors=1) -# # TODO, hooks + +def run_import_class_test( + pytester: Pytester, passed: int = 0, errors: int = 0 +) -> RunResult: + src_dir = pytester.mkdir("src") + tests_dir = pytester.mkdir("tests") + src_file = src_dir / "foo.py" + + src_file.write_text( + textwrap.dedent("""\ + class Testament(object): + def __init__(self): + super().__init__() + self.collections = ["stamp", "coin"] + + def personal_property(self): + return [f"my {x} collection" for x in self.collections] + """), + encoding="utf-8", + ) + + test_file = tests_dir / "foo_test.py" + test_file.write_text( + textwrap.dedent("""\ + import sys + import os + + current_file = os.path.abspath(__file__) + current_dir = os.path.dirname(current_file) + parent_dir = os.path.abspath(os.path.join(current_dir, '..')) + sys.path.append(parent_dir) + + from src.foo import Testament + + class TestDomain: + def test_testament(self): + testament = Testament() + assert testament.personal_property() + """), + encoding="utf-8", + ) + + result = pytester.runpytest() + result.assert_outcomes(passed=passed, errors=errors) + return result + + +def test_collect_imports_disabled(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + testpaths = "tests" + collect_imported_tests = false + """) + + run_import_class_test(pytester, passed=1) + + # Verify that the state of hooks + reprec = pytester.inline_run() + items_collected = reprec.getcalls("pytest_itemcollected") + assert len(items_collected) == 1 + for x in items_collected: + assert x.item._getobj().__name__ == "test_testament" + + +def test_collect_imports_default(pytester: Pytester) -> None: + run_import_class_test(pytester, errors=1) + # TODO + + +def test_collect_imports_enabled(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + collect_imported_tests = true + """) + + run_import_class_test(pytester, errors=1) # End of tests for classes @@ -144,54 +148,54 @@ def test_important(self): return result -# def test_collect_function_imports_enabled(pytester: Pytester) -> None: -# pytester.makeini(""" -# [pytest] -# testpaths = "tests" -# collect_imported_tests = true -# """) - -# run_import_functions_test(pytester, passed=2, errors=0, failed=1) -# reprec = pytester.inline_run() -# items_collected = reprec.getcalls("pytest_itemcollected") -# # Recall that the default is `collect_imported_tests = true`. -# # Which means that the normal functions are now interpreted as -# # valid tests and `test_function()` will fail. -# assert len(items_collected) == 3 -# for x in items_collected: -# assert x.item._getobj().__name__ in [ -# "test_important", -# "test_bar", -# "test_function", -# ] - - -# def test_behaviour_without_testpaths_set_and_false(pytester: Pytester) -> None: -# # Make sure `collect_imported_tests` has no dependence on `testpaths` -# pytester.makeini(""" -# [pytest] -# collect_imported_tests = false -# """) - -# run_import_functions_test(pytester, passed=1, errors=0, failed=0) -# reprec = pytester.inline_run() -# items_collected = reprec.getcalls("pytest_itemcollected") -# assert len(items_collected) == 1 -# for x in items_collected: -# assert x.item._getobj().__name__ == "test_important" - - -# def test_behaviour_without_testpaths_set_and_true(pytester: Pytester) -> None: -# # Make sure `collect_imported_tests` has no dependence on `testpaths` -# pytester.makeini(""" -# [pytest] -# collect_imported_tests = true -# """) - -# run_import_functions_test(pytester, passed=2, errors=0, failed=1) -# reprec = pytester.inline_run() -# items_collected = reprec.getcalls("pytest_itemcollected") -# assert len(items_collected) == 3 +def test_collect_function_imports_enabled(pytester: Pytester) -> None: + pytester.makeini(""" + [pytest] + testpaths = "tests" + collect_imported_tests = true + """) + + run_import_functions_test(pytester, passed=2, errors=0, failed=1) + reprec = pytester.inline_run() + items_collected = reprec.getcalls("pytest_itemcollected") + # Recall that the default is `collect_imported_tests = true`. + # Which means that the normal functions are now interpreted as + # valid tests and `test_function()` will fail. + assert len(items_collected) == 3 + for x in items_collected: + assert x.item._getobj().__name__ in [ + "test_important", + "test_bar", + "test_function", + ] + + +def test_behaviour_without_testpaths_set_and_false(pytester: Pytester) -> None: + # Make sure `collect_imported_tests` has no dependence on `testpaths` + pytester.makeini(""" + [pytest] + collect_imported_tests = false + """) + + run_import_functions_test(pytester, passed=1, errors=0, failed=0) + reprec = pytester.inline_run() + items_collected = reprec.getcalls("pytest_itemcollected") + assert len(items_collected) == 1 + for x in items_collected: + assert x.item._getobj().__name__ == "test_important" + + +def test_behaviour_without_testpaths_set_and_true(pytester: Pytester) -> None: + # Make sure `collect_imported_tests` has no dependence on `testpaths` + pytester.makeini(""" + [pytest] + collect_imported_tests = true + """) + + run_import_functions_test(pytester, passed=2, errors=0, failed=1) + reprec = pytester.inline_run() + items_collected = reprec.getcalls("pytest_itemcollected") + assert len(items_collected) == 3 class TestHookBehaviour: @@ -255,11 +259,12 @@ def _test_hook_behaviour_when_collect_off(self, pytester: Pytester) -> None: "reports": reports, } - # Now check that the two tests above did indeed result in the same outcome. def _test_hook_behaviour(self) -> None: print("ABCD", self.collect_outcomes) default = self.collect_outcomes["default"] collect_off = self.collect_outcomes["collect_off"] + + # Check that the two tests above did indeed result in the same outcome. assert default["result"] == collect_off["result"] assert len(default["modified"]) == len(collect_off["modified"]) == 1 @@ -282,13 +287,14 @@ def _test_hook_behaviour(self) -> None: len(default["items_collected"]) == len(collect_off["items_collected"]) == 1 ) + # Check if the same tests got collected def_items_record: RecordedHookCall = default["items_collected"][0] off_items_record: RecordedHookCall = collect_off["items_collected"][0] def_items = def_items_record.__dict__["item"] off_items = off_items_record.__dict__["item"] assert def_items.name == off_items.name - # TODO: fix diff: + # TODO: fix diff: (This will get cleaned up) # [ # , # - , @@ -301,12 +307,24 @@ def _test_hook_behaviour(self) -> None: # ? ^ # ] - # assert len(default['reports']) == len(collect_off['reports']) - # for i in range(len(default['reports'])): - # print("def",default['reports'][i].__dict__) - # print("off",collect_off['reports'][i].__dict__) + for x in default["reports"]: + print("def", x.__dict__) + + for x in collect_off["reports"]: + print("off", x.__dict__) + + # The two above loops prints: + + # def {'nodeid': '', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # def {'nodeid': 'tests/foo_test.py::TestDomain', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # def {'nodeid': 'tests/foo_test.py', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # def {'nodeid': 'tests', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # def {'nodeid': '.', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # off {'nodeid': '', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # off {'nodeid': 'src', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} + # off {'nodeid': 'tests/foo_test.py::TestDomain', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # off {'nodeid': 'tests/foo_test.py', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # off {'nodeid': 'tests', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 + # off {'nodeid': '.', 'outcome': 'passed', 'longrepr': None, 'result': [, ], 'sections': []} # noqa: E501 - # from pprint import pprint - # pprint(default['reports']) - # pprint(collect_off['reports']) - # assert default['reports'] == collect_off['reports'] + assert len(default["reports"]) == len(collect_off["reports"]) From 6cba4e6c1af24fd5940cc0ebdddabdbb1a0b8906 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:03:41 +0100 Subject: [PATCH 0975/1271] build(deps): Bump pytest-bdd in /testing/plugins_integration (#12971) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 7.3.0 to 8.0.0. - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/7.3.0...8.0.0) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 32992dc2589..9ca5d1cfde0 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,7 +1,7 @@ anyio[curio,trio]==4.6.2.post1 django==5.1.3 pytest-asyncio==0.24.0 -pytest-bdd==7.3.0 +pytest-bdd==8.0.0 pytest-cov==6.0.0 pytest-django==4.9.0 pytest-flakes==4.0.5 From 3de3d0d79ed2efe23a6e73d386a54b75a712fcf1 Mon Sep 17 00:00:00 2001 From: Gupta Arpit Date: Mon, 18 Nov 2024 15:54:42 +0530 Subject: [PATCH 0976/1271] Added final review requested changes --- changelog/12960.breaking.rst | 2 +- doc/en/deprecations.rst | 60 ++++++++++++++++++------------------ src/_pytest/python.py | 5 +-- testing/test_collection.py | 7 +++-- 4 files changed, 38 insertions(+), 36 deletions(-) diff --git a/changelog/12960.breaking.rst b/changelog/12960.breaking.rst index 43e981dc648..942348d8245 100644 --- a/changelog/12960.breaking.rst +++ b/changelog/12960.breaking.rst @@ -1 +1 @@ -Test functions containing a yield now cause an explicit error. They have not been run since Pytest 4.0, and were previously marked as an expected failure and deprecation warning. +Test functions containing a yield now cause an explicit error. They have not been run since pytest 4.0, and were previously marked as an expected failure and deprecation warning. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 59f9d83451b..689ba96b615 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -374,6 +374,36 @@ an appropriate period of deprecation has passed. Some breaking changes which could not be deprecated are also listed. +.. _yield tests deprecated: + +``yield`` tests +~~~~~~~~~~~~~~~ + +.. versionremoved:: 8.4 + +pytest no longer supports ``yield``-style tests, where a test function actually ``yield`` functions and values +that are then turned into proper test methods. Example: + +.. code-block:: python + + def check(x, y): + assert x**x == y + + + def test_squared(): + yield check, 2, 4 + yield check, 3, 9 + +This would result in two actual test functions being generated. + +This form of test function doesn't support fixtures properly, and users should switch to ``pytest.mark.parametrize``: + +.. code-block:: python + + @pytest.mark.parametrize("x, y", [(2, 4), (3, 9)]) + def test_squared(x, y): + assert x**x == y + .. _nose-deprecation: Support for tests written for nose @@ -1270,36 +1300,6 @@ with the ``name`` parameter: return cell() -.. _yield tests deprecated: - -``yield`` tests -~~~~~~~~~~~~~~~ - -.. versionremoved:: 4.0 - -pytest supported ``yield``-style tests, where a test function actually ``yield`` functions and values -that are then turned into proper test methods. Example: - -.. code-block:: python - - def check(x, y): - assert x**x == y - - - def test_squared(): - yield check, 2, 4 - yield check, 3, 9 - -This would result into two actual test functions being generated. - -This form of test function doesn't support fixtures properly, and users should switch to ``pytest.mark.parametrize``: - -.. code-block:: python - - @pytest.mark.parametrize("x, y", [(2, 4), (3, 9)]) - def test_squared(x, y): - assert x**x == y - .. _internal classes accessed through node deprecated: Internal classes accessed through ``Node`` diff --git a/src/_pytest/python.py b/src/_pytest/python.py index d117fa58d01..1456b5212d4 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -230,8 +230,9 @@ def pytest_pycollect_makeitem( ) elif getattr(obj, "__test__", True): if inspect.isgeneratorfunction(obj): - raise RuntimeError( - "'yield' keyword is allowed in fixtures, but not in tests ({name})" + fail( + f"'yield' keyword is allowed in fixtures, but not in tests ({name})", + pytrace=False, ) return list(collector._genfunctions(name, obj)) return None diff --git a/testing/test_collection.py b/testing/test_collection.py index 53463d81866..aed0c34091d 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1881,7 +1881,7 @@ def test_respect_system_exceptions( def test_yield_disallowed_in_tests(pytester: Pytester): - """Ensure generator test functions with 'yield' raise a RuntimeError.""" + """Ensure generator test functions with 'yield' fail collection (#12960).""" pytester.makepyfile( """ def test_with_yield(): @@ -1891,6 +1891,7 @@ def test_with_yield(): result = pytester.runpytest() assert result.ret == 2 result.stdout.fnmatch_lines( - ["*RuntimeError: 'yield' keyword is allowed in fixtures, but not in tests (*)*"] + ["*'yield' keyword is allowed in fixtures, but not in tests (test_with_yield)*"] ) - result.stdout.fnmatch_lines(["*collected 0 items*"]) + # Assert that no tests were collected + result.stdout.fnmatch_lines(["*collected 0 items*"]) \ No newline at end of file From 7c24a0ba1919c43e0f4ac8c48bd2126c8a4d64b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 10:26:40 +0000 Subject: [PATCH 0977/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- doc/en/deprecations.rst | 2 +- testing/test_collection.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 689ba96b615..a6b7ed4beab 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -403,7 +403,7 @@ This form of test function doesn't support fixtures properly, and users should s @pytest.mark.parametrize("x, y", [(2, 4), (3, 9)]) def test_squared(x, y): assert x**x == y - + .. _nose-deprecation: Support for tests written for nose diff --git a/testing/test_collection.py b/testing/test_collection.py index aed0c34091d..7d28610e015 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1894,4 +1894,4 @@ def test_with_yield(): ["*'yield' keyword is allowed in fixtures, but not in tests (test_with_yield)*"] ) # Assert that no tests were collected - result.stdout.fnmatch_lines(["*collected 0 items*"]) \ No newline at end of file + result.stdout.fnmatch_lines(["*collected 0 items*"]) From 1a5dbcb04d2677f46175d5b03dfd63f0debbf43e Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 18 Nov 2024 09:30:53 -0300 Subject: [PATCH 0978/1271] Update changelog/12960.breaking.rst --- changelog/12960.breaking.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog/12960.breaking.rst b/changelog/12960.breaking.rst index 942348d8245..3ab87e6fe23 100644 --- a/changelog/12960.breaking.rst +++ b/changelog/12960.breaking.rst @@ -1 +1,3 @@ Test functions containing a yield now cause an explicit error. They have not been run since pytest 4.0, and were previously marked as an expected failure and deprecation warning. + +See :ref:`the docs ` for more information. From 831d061a84c86c2d5ba99a7b3efde65862d8ea58 Mon Sep 17 00:00:00 2001 From: Yann Dirson Date: Mon, 18 Nov 2024 13:33:56 +0100 Subject: [PATCH 0979/1271] Docs: be more precise about TestReport outcome in example (#12535) * Testing only for "failed" should not be reported as "or skipped" * Test for "skipped" explicitly instead Signed-off-by: Yann Dirson --- changelog/12535.doc.rst | 4 ++++ doc/en/example/simple.rst | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 changelog/12535.doc.rst diff --git a/changelog/12535.doc.rst b/changelog/12535.doc.rst new file mode 100644 index 00000000000..d43c1c822ea --- /dev/null +++ b/changelog/12535.doc.rst @@ -0,0 +1,4 @@ +`This +example` +showed ``print`` statements that do not exactly reflect what the +different branches actually do. The fix makes the example more precise. diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index a14c34c19c3..b50fbfed397 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -904,7 +904,9 @@ here is a little example implemented via a local plugin: # "function" scope report = request.node.stash[phase_report_key] if report["setup"].failed: - print("setting up a test failed or skipped", request.node.nodeid) + print("setting up a test failed", request.node.nodeid) + elif report["setup"].skipped: + print("setting up a test skipped", request.node.nodeid) elif ("call" not in report) or report["call"].failed: print("executing test failed or skipped", request.node.nodeid) From fe60ceb06d996965de140ccfc61cede4afe2a389 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 09:39:04 -0300 Subject: [PATCH 0980/1271] build(deps): Bump codecov/codecov-action from 4 to 5 (#12972) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v4...v5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 52faca6ddef..c1ea62f6c8b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -246,7 +246,7 @@ jobs: - name: Upload coverage to Codecov if: "matrix.use_coverage" - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: fail_ci_if_error: false files: ./coverage.xml From 47996bdc3870f9eed82951a15e07f430eb27a665 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Mon, 18 Nov 2024 15:05:04 +0100 Subject: [PATCH 0981/1271] display single contained exception in excgroups in short test summary info --- changelog/12943.improvement.rst | 1 + src/_pytest/_code/code.py | 25 ++++++++++++++- testing/code/test_excinfo.py | 57 +++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 changelog/12943.improvement.rst diff --git a/changelog/12943.improvement.rst b/changelog/12943.improvement.rst new file mode 100644 index 00000000000..eb8ac63650a --- /dev/null +++ b/changelog/12943.improvement.rst @@ -0,0 +1 @@ +If a test fails with an exceptiongroup with a single exception, the contained exception will now be displayed in the short test summary info. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 8fac39ea298..79adc196aea 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1033,6 +1033,24 @@ def _truncate_recursive_traceback( def repr_excinfo(self, excinfo: ExceptionInfo[BaseException]) -> ExceptionChainRepr: repr_chain: list[tuple[ReprTraceback, ReprFileLocation | None, str | None]] = [] + + def _get_single_subexc( + eg: BaseExceptionGroup[BaseException], + ) -> BaseException | None: + res: BaseException | None = None + for subexc in eg.exceptions: + if res is not None: + return None + + if isinstance(subexc, BaseExceptionGroup): + res = _get_single_subexc(subexc) + if res is None: + # there were multiple exceptions in the subgroup + return None + else: + res = subexc + return res + e: BaseException | None = excinfo.value excinfo_: ExceptionInfo[BaseException] | None = excinfo descr = None @@ -1041,6 +1059,7 @@ def repr_excinfo(self, excinfo: ExceptionInfo[BaseException]) -> ExceptionChainR seen.add(id(e)) if excinfo_: + reprcrash = excinfo_._getreprcrash() # Fall back to native traceback as a temporary workaround until # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 @@ -1054,9 +1073,13 @@ def repr_excinfo(self, excinfo: ExceptionInfo[BaseException]) -> ExceptionChainR ) ) ) + if ( + reprcrash is not None + and (subexc := _get_single_subexc(e)) is not None + ): + reprcrash.message = f"[in {type(e).__name__}] {subexc!r}" else: reprtraceback = self.repr_traceback(excinfo_) - reprcrash = excinfo_._getreprcrash() else: # Fallback to native repr if the exception doesn't have a traceback: # ExceptionInfo objects require a full traceback to work. diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index fc60ae9ac99..5bb65bf30af 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1703,6 +1703,63 @@ def test_exceptiongroup(pytester: Pytester, outer_chain, inner_chain) -> None: _exceptiongroup_common(pytester, outer_chain, inner_chain, native=False) +def test_exceptiongroup_short_summary_info(pytester: Pytester): + pytester.makepyfile( + """ + import sys + + if sys.version_info < (3, 11): + from exceptiongroup import BaseExceptionGroup, ExceptionGroup + + def test_base() -> None: + raise BaseExceptionGroup("NOT IN SUMMARY", [SystemExit("a" * 10)]) + + def test_nonbase() -> None: + raise ExceptionGroup("NOT IN SUMMARY", [ValueError("a" * 10)]) + + def test_nested() -> None: + raise ExceptionGroup( + "NOT DISPLAYED", [ + ExceptionGroup("NOT IN SUMMARY", [ValueError("a" * 10)]) + ] + ) + + def test_multiple() -> None: + raise ExceptionGroup( + "b" * 10, + [ + ValueError("NOT IN SUMMARY"), + TypeError("NOT IN SUMMARY"), + ] + ) + """ + ) + result = pytester.runpytest("-vv") + assert result.ret == 1 + result.stdout.fnmatch_lines( + [ + "*= short test summary info =*", + ( + "FAILED test_exceptiongroup_short_summary_info.py::test_base - " + "[in BaseExceptionGroup] SystemExit('aaaaaaaaaa')" + ), + ( + "FAILED test_exceptiongroup_short_summary_info.py::test_nonbase - " + "[in ExceptionGroup] ValueError('aaaaaaaaaa')" + ), + ( + "FAILED test_exceptiongroup_short_summary_info.py::test_nested - " + "[in ExceptionGroup] ValueError('aaaaaaaaaa')" + ), + ( + "FAILED test_exceptiongroup_short_summary_info.py::test_multiple - " + "ExceptionGroup: bbbbbbbbbb (2 sub-exceptions)" + ), + "*= 4 failed in *", + ] + ) + + @pytest.mark.parametrize("tbstyle", ("long", "short", "auto", "line", "native")) def test_all_entries_hidden(pytester: Pytester, tbstyle: str) -> None: """Regression test for #10903.""" From 70e41cb2de00d19761033537574b318c9728fb45 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 18 Nov 2024 15:30:34 -0300 Subject: [PATCH 0982/1271] Update doc/en/deprecations.rst --- doc/en/deprecations.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index a6b7ed4beab..18df64c9204 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -379,8 +379,14 @@ Some breaking changes which could not be deprecated are also listed. ``yield`` tests ~~~~~~~~~~~~~~~ +.. versionremoved:: 4.0 + + ``yield`` tests ``xfail``. + .. versionremoved:: 8.4 + ``yield`` tests raise a collection error. + pytest no longer supports ``yield``-style tests, where a test function actually ``yield`` functions and values that are then turned into proper test methods. Example: From 72f17d10d76e5260906c17f279c5fa6bd29b5a8d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 07:31:40 +0100 Subject: [PATCH 0983/1271] [pre-commit.ci] pre-commit autoupdate (#12976) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.7.3 → v0.7.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.3...v0.7.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 218a69e2cbc..9e7be8cf6db 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.7.3" + rev: "v0.7.4" hooks: - id: ruff args: ["--fix"] From f59a8d18c5e7071e4af06b7f0571cfa22c1b1544 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 19 Nov 2024 17:03:34 +0100 Subject: [PATCH 0984/1271] fix test --- testing/code/test_excinfo.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 5bb65bf30af..3418c433541 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1736,6 +1736,7 @@ def test_multiple() -> None: ) result = pytester.runpytest("-vv") assert result.ret == 1 + backport_str = "exceptiongroup." if sys.version_info < (3, 11) else "" result.stdout.fnmatch_lines( [ "*= short test summary info =*", @@ -1753,7 +1754,7 @@ def test_multiple() -> None: ), ( "FAILED test_exceptiongroup_short_summary_info.py::test_multiple - " - "ExceptionGroup: bbbbbbbbbb (2 sub-exceptions)" + f"{backport_str}ExceptionGroup: bbbbbbbbbb (2 sub-exceptions)" ), "*= 4 failed in *", ] From 3311c180c75b99ab58d4b0b114953db2e80c1ff4 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 19 Nov 2024 17:16:29 +0100 Subject: [PATCH 0985/1271] move logic to ExceptionInfo --- src/_pytest/_code/code.py | 50 ++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 79adc196aea..0d635db132b 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -589,6 +589,31 @@ def exconly(self, tryshort: bool = False) -> str: representation is returned (so 'AssertionError: ' is removed from the beginning). """ + + def _get_single_subexc( + eg: BaseExceptionGroup[BaseException], + ) -> BaseException | None: + res: BaseException | None = None + for subexc in eg.exceptions: + if res is not None: + return None + + if isinstance(subexc, BaseExceptionGroup): + res = _get_single_subexc(subexc) + if res is None: + # there were multiple exceptions in the subgroup + return None + else: + res = subexc + return res + + if ( + tryshort + and isinstance(self.value, BaseExceptionGroup) + and (subexc := _get_single_subexc(self.value)) is not None + ): + return f"[in {type(self.value).__name__}] {subexc!r}" + lines = format_exception_only(self.type, self.value) text = "".join(lines) text = text.rstrip() @@ -1033,24 +1058,6 @@ def _truncate_recursive_traceback( def repr_excinfo(self, excinfo: ExceptionInfo[BaseException]) -> ExceptionChainRepr: repr_chain: list[tuple[ReprTraceback, ReprFileLocation | None, str | None]] = [] - - def _get_single_subexc( - eg: BaseExceptionGroup[BaseException], - ) -> BaseException | None: - res: BaseException | None = None - for subexc in eg.exceptions: - if res is not None: - return None - - if isinstance(subexc, BaseExceptionGroup): - res = _get_single_subexc(subexc) - if res is None: - # there were multiple exceptions in the subgroup - return None - else: - res = subexc - return res - e: BaseException | None = excinfo.value excinfo_: ExceptionInfo[BaseException] | None = excinfo descr = None @@ -1059,7 +1066,6 @@ def _get_single_subexc( seen.add(id(e)) if excinfo_: - reprcrash = excinfo_._getreprcrash() # Fall back to native traceback as a temporary workaround until # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 @@ -1073,13 +1079,9 @@ def _get_single_subexc( ) ) ) - if ( - reprcrash is not None - and (subexc := _get_single_subexc(e)) is not None - ): - reprcrash.message = f"[in {type(e).__name__}] {subexc!r}" else: reprtraceback = self.repr_traceback(excinfo_) + reprcrash = excinfo_._getreprcrash() else: # Fallback to native repr if the exception doesn't have a traceback: # ExceptionInfo objects require a full traceback to work. From 033120b6546955b8b430a1f547879dd50a32775c Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 19 Nov 2024 17:25:07 +0100 Subject: [PATCH 0986/1271] add test case for codecov --- testing/code/test_excinfo.py | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 3418c433541..d23382c898c 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1732,8 +1732,23 @@ def test_multiple() -> None: TypeError("NOT IN SUMMARY"), ] ) + + def test_nested_multiple() -> None: + raise ExceptionGroup( + "b" * 10, + [ + ExceptionGroup( + "c" * 10, + [ + ValueError("NOT IN SUMMARY"), + TypeError("NOT IN SUMMARY"), + ] + ) + ] + ) """ ) + # run with -vv to not truncate summary info, default width in tests is very low result = pytester.runpytest("-vv") assert result.ret == 1 backport_str = "exceptiongroup." if sys.version_info < (3, 11) else "" @@ -1756,7 +1771,11 @@ def test_multiple() -> None: "FAILED test_exceptiongroup_short_summary_info.py::test_multiple - " f"{backport_str}ExceptionGroup: bbbbbbbbbb (2 sub-exceptions)" ), - "*= 4 failed in *", + ( + "FAILED test_exceptiongroup_short_summary_info.py::test_nested_multiple - " + f"{backport_str}ExceptionGroup: bbbbbbbbbb (1 sub-exception)" + ), + "*= 5 failed in *", ] ) From 6f61360a2b195ad15aba0e09354d662647865846 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Fri, 22 Nov 2024 15:50:12 +0100 Subject: [PATCH 0987/1271] fixes after review --- src/_pytest/_code/code.py | 20 ++++++-------------- testing/code/test_excinfo.py | 6 +++--- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 0d635db132b..85ed3145e66 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -593,26 +593,18 @@ def exconly(self, tryshort: bool = False) -> str: def _get_single_subexc( eg: BaseExceptionGroup[BaseException], ) -> BaseException | None: - res: BaseException | None = None - for subexc in eg.exceptions: - if res is not None: - return None - - if isinstance(subexc, BaseExceptionGroup): - res = _get_single_subexc(subexc) - if res is None: - # there were multiple exceptions in the subgroup - return None - else: - res = subexc - return res + if len(eg.exceptions) != 1: + return None + if isinstance(e := eg.exceptions[0], BaseExceptionGroup): + return _get_single_subexc(e) + return e if ( tryshort and isinstance(self.value, BaseExceptionGroup) and (subexc := _get_single_subexc(self.value)) is not None ): - return f"[in {type(self.value).__name__}] {subexc!r}" + return f"{subexc!r} [single exception in {type(self.value).__name__}]" lines = format_exception_only(self.type, self.value) text = "".join(lines) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index d23382c898c..b049e0cf188 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1757,15 +1757,15 @@ def test_nested_multiple() -> None: "*= short test summary info =*", ( "FAILED test_exceptiongroup_short_summary_info.py::test_base - " - "[in BaseExceptionGroup] SystemExit('aaaaaaaaaa')" + "SystemExit('aaaaaaaaaa') [single exception in BaseExceptionGroup]" ), ( "FAILED test_exceptiongroup_short_summary_info.py::test_nonbase - " - "[in ExceptionGroup] ValueError('aaaaaaaaaa')" + "ValueError('aaaaaaaaaa') [single exception in ExceptionGroup]" ), ( "FAILED test_exceptiongroup_short_summary_info.py::test_nested - " - "[in ExceptionGroup] ValueError('aaaaaaaaaa')" + "ValueError('aaaaaaaaaa') [single exception in ExceptionGroup]" ), ( "FAILED test_exceptiongroup_short_summary_info.py::test_multiple - " From 4f777ff5c83273deba23832dd7e3768ba122fe39 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sun, 24 Nov 2024 00:34:59 +0000 Subject: [PATCH 0988/1271] Prevent Config.add_cleanup callbacks preventing other cleanups running (#12982) Ensure all callbacks registered via Config.add_cleanup will be called, regardless if any of them raises an error. --------- Co-authored-by: Bruno Oliveira --- changelog/12981.bugfix.rst | 1 + src/_pytest/config/__init__.py | 28 +++++++++++++++++----------- testing/test_config.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 11 deletions(-) create mode 100644 changelog/12981.bugfix.rst diff --git a/changelog/12981.bugfix.rst b/changelog/12981.bugfix.rst new file mode 100644 index 00000000000..5fc8e29656f --- /dev/null +++ b/changelog/12981.bugfix.rst @@ -0,0 +1 @@ +Prevent exceptions in :func:`pytest.Config.add_cleanup` callbacks preventing further cleanups. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 35ab622de31..92cf565e85f 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -5,6 +5,7 @@ import argparse import collections.abc +import contextlib import copy import dataclasses import enum @@ -73,7 +74,6 @@ from _pytest.cacheprovider import Cache from _pytest.terminal import TerminalReporter - _PluggyPlugin = object """A type to represent plugin objects. @@ -1077,7 +1077,7 @@ def __init__( self._inicache: dict[str, Any] = {} self._override_ini: Sequence[str] = () self._opt2dest: dict[str, str] = {} - self._cleanup: list[Callable[[], None]] = [] + self._cleanup_stack = contextlib.ExitStack() self.pluginmanager.register(self, "pytestconfig") self._configured = False self.hook.pytest_addoption.call_historic( @@ -1106,8 +1106,9 @@ def inipath(self) -> pathlib.Path | None: def add_cleanup(self, func: Callable[[], None]) -> None: """Add a function to be called when the config object gets out of - use (usually coinciding with pytest_unconfigure).""" - self._cleanup.append(func) + use (usually coinciding with pytest_unconfigure). + """ + self._cleanup_stack.callback(func) def _do_configure(self) -> None: assert not self._configured @@ -1117,13 +1118,18 @@ def _do_configure(self) -> None: self.hook.pytest_configure.call_historic(kwargs=dict(config=self)) def _ensure_unconfigure(self) -> None: - if self._configured: - self._configured = False - self.hook.pytest_unconfigure(config=self) - self.hook.pytest_configure._call_history = [] - while self._cleanup: - fin = self._cleanup.pop() - fin() + try: + if self._configured: + self._configured = False + try: + self.hook.pytest_unconfigure(config=self) + finally: + self.hook.pytest_configure._call_history = [] + finally: + try: + self._cleanup_stack.close() + finally: + self._cleanup_stack = contextlib.ExitStack() def get_terminal_writer(self) -> TerminalWriter: terminalreporter: TerminalReporter | None = self.pluginmanager.get_plugin( diff --git a/testing/test_config.py b/testing/test_config.py index 13ba66e8f9d..b2825678b46 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -983,6 +983,37 @@ def test_confcutdir_check_isdir(self, pytester: Pytester) -> None: def test_iter_rewritable_modules(self, names, expected) -> None: assert list(_iter_rewritable_modules(names)) == expected + def test_add_cleanup(self, pytester: Pytester) -> None: + config = Config.fromdictargs({}, []) + config._do_configure() + report = [] + + class MyError(BaseException): + pass + + @config.add_cleanup + def cleanup_last(): + report.append("cleanup_last") + + @config.add_cleanup + def raise_2(): + report.append("raise_2") + raise MyError("raise_2") + + @config.add_cleanup + def raise_1(): + report.append("raise_1") + raise MyError("raise_1") + + @config.add_cleanup + def cleanup_first(): + report.append("cleanup_first") + + with pytest.raises(MyError, match=r"raise_2"): + config._ensure_unconfigure() + + assert report == ["cleanup_first", "raise_1", "raise_2", "cleanup_last"] + class TestConfigFromdictargs: def test_basic_behavior(self, _sys_snapshot) -> None: From 258f76eccb4101717f03747e3384d0c97e4c8138 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 24 Nov 2024 08:09:29 +0000 Subject: [PATCH 0989/1271] [automated] Update plugin list (#12986) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 86 +++++++++++++++++--------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index ee0981e3694..3ac9b0b4c13 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.3.3 :pypi:`pytest-cases` Separate test code from test cases in pytest. Sep 26, 2024 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) @@ -459,7 +460,7 @@ This list contains 1545 plugins. :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 - :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Jun 09, 2024 N/A pytest + :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Nov 17, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 15, 2024 5 - Production/Stable pytest >=7.0 :pypi:`pytest-elasticsearch-test` Elasticsearch fixtures and fixture factories for Pytest. Aug 21, 2024 5 - Production/Stable pytest>=7.0 @@ -502,11 +503,11 @@ This list contains 1545 plugins. :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Nov 15, 2024 N/A pytest>=7 - :pypi:`pytest-exasol-backend` Oct 31, 2024 N/A pytest<9,>=7 + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Nov 20, 2024 N/A pytest>=7 + :pypi:`pytest-exasol-backend` Nov 22, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-extension` Oct 10, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-saas` Aug 06, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-saas` Nov 22, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-slc` Nov 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A @@ -619,7 +620,7 @@ This list contains 1545 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Nov 07, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Nov 19, 2024 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -688,7 +689,7 @@ This list contains 1545 plugins. :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Aug 10, 2024 N/A pytest<9.0.0,>=8.2.0 - :pypi:`pytest-httpx` Send responses to httpx. Oct 28, 2024 5 - Production/Stable pytest==8.* + :pypi:`pytest-httpx` Send responses to httpx. Nov 18, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -730,7 +731,7 @@ This list contains 1545 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 25, 2024 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Nov 19, 2024 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 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-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 @@ -1092,7 +1093,7 @@ This list contains 1545 plugins. :pypi:`pytest-pyreport` PyReport is a lightweight reporting plugin for Pytest that provides concise HTML report May 05, 2024 N/A pytest :pypi:`pytest-pyright` Pytest plugin for type checking code with Pyright Jan 26, 2024 4 - Beta pytest >=7.0.0 :pypi:`pytest-pyspec` A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". Aug 17, 2024 N/A pytest<9.0.0,>=8.3.2 - :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Jan 04, 2024 N/A pytest >=3.5.0 + :pypi:`pytest-pystack` Plugin to run pystack after a timeout for a test suite. Nov 16, 2024 N/A pytest>=3.5.0 :pypi:`pytest-pytestrail` Pytest plugin for interaction with TestRail Aug 27, 2020 4 - Beta pytest (>=3.8.0) :pypi:`pytest-pythonhashseed` Pytest plugin to set PYTHONHASHSEED env var. Feb 25, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-pythonpath` pytest plugin for adding to the PYTHONPATH from command line or configs. Feb 10, 2022 5 - Production/Stable pytest (<7,>=2.5.2) @@ -1101,7 +1102,7 @@ This list contains 1545 plugins. :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-qanova` A pytest plugin to collect test information Sep 05, 2024 3 - Alpha pytest - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Nov 15, 2024 5 - Production/Stable pytest<9.0.0,>=7.2.2 + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Nov 18, 2024 5 - Production/Stable pytest<9.0.0,>=7.2.2 :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 14, 2024 5 - Production/Stable pytest>=6.0 @@ -1175,7 +1176,7 @@ This list contains 1545 plugins. :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-rerunclassfailures` pytest rerun class failures plugin Apr 24, 2024 5 - Production/Stable pytest>=7.2 - :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Mar 13, 2024 5 - Production/Stable pytest >=7.2 + :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Nov 20, 2024 5 - Production/Stable pytest!=8.2.2,>=7.4 :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. Jul 23, 2024 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jul 16, 2024 N/A pytest~=7.0 @@ -1228,9 +1229,9 @@ This list contains 1545 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 15, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 19, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A - :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 19, 2024 5 - Production/Stable pytest>=7.2.0 + :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Feb 16, 2024 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 @@ -1239,7 +1240,7 @@ This list contains 1545 plugins. :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 Feb 01, 2024 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 15, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 19, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1512,11 +1513,11 @@ This list contains 1545 plugins. :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest :pypi:`pytest-vtestify` A pytest plugin for visual assertion using SSIM and image comparison. Oct 10, 2024 N/A pytest :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) - :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Jun 01, 2023 N/A pytest (>=7.0.0) + :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Nov 22, 2024 N/A pytest>=7.0.0 :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-wake` Mar 20, 2024 N/A pytest + :pypi:`pytest-wake` Nov 19, 2024 N/A pytest :pypi:`pytest-watch` Local continuous test runner with pytest and watchdog. May 20, 2018 N/A N/A :pypi:`pytest-watcher` Automatically rerun your tests on file modifications Aug 28, 2024 4 - Beta N/A :pypi:`pytest-watch-plugin` Placeholder for internal package Sep 12, 2024 N/A N/A @@ -1557,7 +1558,7 @@ This list contains 1545 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, 2024 4 - Beta pytest>=7.2.2 :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 with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Aug 16, 2024 N/A pytest~=8.2.2 + :pypi:`pytest-yaml-sanmu` Pytest plugin for generating test cases with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Nov 20, 2024 N/A pytest~=8.2.2 :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) @@ -2446,7 +2447,7 @@ This list contains 1545 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Nov 11, 2024, + *last release*: Nov 18, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2823,6 +2824,13 @@ This list contains 1545 plugins. pytest plugin to capture all warnings and put them in one file of your choice + :pypi:`pytest-case` + *last release*: Nov 22, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.3.3 + + A clean, modern, wrapper for pytest.mark.parametrize + :pypi:`pytest-cases` *last release*: Sep 26, 2024, *status*: 5 - Production/Stable, @@ -4560,7 +4568,7 @@ This list contains 1545 plugins. pytest plugin with mechanisms for echoing environment variables, package version and generic attributes :pypi:`pytest-edit` - *last release*: Jun 09, 2024, + *last release*: Nov 17, 2024, *status*: N/A, *requires*: pytest @@ -4861,14 +4869,14 @@ This list contains 1545 plugins. Parse queries in Lucene and Elasticsearch syntaxes :pypi:`pytest-examples` - *last release*: Nov 15, 2024, + *last release*: Nov 20, 2024, *status*: N/A, *requires*: pytest>=7 Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-exasol-backend` - *last release*: Oct 31, 2024, + *last release*: Nov 22, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -4889,7 +4897,7 @@ This list contains 1545 plugins. :pypi:`pytest-exasol-saas` - *last release*: Aug 06, 2024, + *last release*: Nov 22, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -5680,7 +5688,7 @@ This list contains 1545 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Nov 07, 2024, + *last release*: Nov 19, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -6163,7 +6171,7 @@ This list contains 1545 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Oct 28, 2024, + *last release*: Nov 18, 2024, *status*: 5 - Production/Stable, *requires*: pytest==8.* @@ -6457,7 +6465,7 @@ This list contains 1545 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Sep 25, 2024, + *last release*: Nov 19, 2024, *status*: 4 - Beta, *requires*: pytest @@ -8991,9 +8999,9 @@ This list contains 1545 plugins. A plugin that transforms the pytest output into a result similar to the RSpec. It enables the use of docstrings to display results and also enables the use of the prefixes "describe", "with" and "it". :pypi:`pytest-pystack` - *last release*: Jan 04, 2024, + *last release*: Nov 16, 2024, *status*: N/A, - *requires*: pytest >=3.5.0 + *requires*: pytest>=3.5.0 Plugin to run pystack after a timeout for a test suite. @@ -9054,7 +9062,7 @@ This list contains 1545 plugins. A pytest plugin to collect test information :pypi:`pytest-qaseio` - *last release*: Nov 15, 2024, + *last release*: Nov 18, 2024, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=7.2.2 @@ -9572,9 +9580,9 @@ This list contains 1545 plugins. pytest rerun class failures plugin :pypi:`pytest-rerunfailures` - *last release*: Mar 13, 2024, + *last release*: Nov 20, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.2 + *requires*: pytest!=8.2.2,>=7.4 pytest plugin to re-run tests to eliminate flaky failures @@ -9943,7 +9951,7 @@ This list contains 1545 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Nov 15, 2024, + *last release*: Nov 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -9957,9 +9965,9 @@ This list contains 1545 plugins. pytest plugin for test scenarios :pypi:`pytest-scenario-files` - *last release*: May 19, 2024, + *last release*: Nov 21, 2024, *status*: 5 - Production/Stable, - *requires*: pytest>=7.2.0 + *requires*: pytest>=7.0 A pytest plugin that generates unit test scenarios from data files. @@ -10020,7 +10028,7 @@ This list contains 1545 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Nov 15, 2024, + *last release*: Nov 19, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -11931,9 +11939,9 @@ This list contains 1545 plugins. pytest plugin for automatic recording of http stubbed tests :pypi:`pytest-vulture` - *last release*: Jun 01, 2023, + *last release*: Nov 22, 2024, *status*: N/A, - *requires*: pytest (>=7.0.0) + *requires*: pytest>=7.0.0 A pytest plugin to checks dead code with vulture @@ -11959,7 +11967,7 @@ This list contains 1545 plugins. Pytest plugin for testing whatsapp bots with end to end tests :pypi:`pytest-wake` - *last release*: Mar 20, 2024, + *last release*: Nov 19, 2024, *status*: N/A, *requires*: pytest @@ -12246,7 +12254,7 @@ This list contains 1545 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Aug 16, 2024, + *last release*: Nov 20, 2024, *status*: N/A, *requires*: pytest~=8.2.2 From 022d316addadbe407e813cc902f2439431605cbc Mon Sep 17 00:00:00 2001 From: sven <42868792+FreerGit@users.noreply.github.com> Date: Sun, 24 Nov 2024 23:20:10 +0100 Subject: [PATCH 0990/1271] Ensure correct collection of reports --- testing/test_collect_imports.py | 59 +++++++++++++-------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/testing/test_collect_imports.py b/testing/test_collect_imports.py index cc1c5a80015..1c56c9155e5 100644 --- a/testing/test_collect_imports.py +++ b/testing/test_collect_imports.py @@ -8,6 +8,7 @@ from _pytest.pytester import Pytester from _pytest.pytester import RecordedHookCall from _pytest.pytester import RunResult +from _pytest.reports import CollectReport import pytest @@ -71,7 +72,12 @@ def test_collect_imports_disabled(pytester: Pytester) -> None: # Verify that the state of hooks reprec = pytester.inline_run() + reports = reprec.getreports("pytest_collectreport") + modified = reprec.getcalls("pytest_collection_modifyitems") items_collected = reprec.getcalls("pytest_itemcollected") + + assert len(reports) == 5 + assert len(modified) == 1 assert len(items_collected) == 1 for x in items_collected: assert x.item._getobj().__name__ == "test_testament" @@ -79,7 +85,6 @@ def test_collect_imports_disabled(pytester: Pytester) -> None: def test_collect_imports_default(pytester: Pytester) -> None: run_import_class_test(pytester, errors=1) - # TODO def test_collect_imports_enabled(pytester: Pytester) -> None: @@ -260,7 +265,6 @@ def _test_hook_behaviour_when_collect_off(self, pytester: Pytester) -> None: } def _test_hook_behaviour(self) -> None: - print("ABCD", self.collect_outcomes) default = self.collect_outcomes["default"] collect_off = self.collect_outcomes["collect_off"] @@ -294,37 +298,20 @@ def _test_hook_behaviour(self) -> None: off_items = off_items_record.__dict__["item"] assert def_items.name == off_items.name - # TODO: fix diff: (This will get cleaned up) - # [ - # , - # - , - # , - # , - # , - # - , - # ? ^ - # + , - # ? ^ - # ] - - for x in default["reports"]: - print("def", x.__dict__) - - for x in collect_off["reports"]: - print("off", x.__dict__) - - # The two above loops prints: - - # def {'nodeid': '', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # def {'nodeid': 'tests/foo_test.py::TestDomain', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # def {'nodeid': 'tests/foo_test.py', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # def {'nodeid': 'tests', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # def {'nodeid': '.', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # off {'nodeid': '', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # off {'nodeid': 'src', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} - # off {'nodeid': 'tests/foo_test.py::TestDomain', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # off {'nodeid': 'tests/foo_test.py', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # off {'nodeid': 'tests', 'outcome': 'passed', 'longrepr': None, 'result': [], 'sections': []} # noqa: E501 - # off {'nodeid': '.', 'outcome': 'passed', 'longrepr': None, 'result': [, ], 'sections': []} # noqa: E501 - - assert len(default["reports"]) == len(collect_off["reports"]) + def compare_report(r1: CollectReport, r2: CollectReport) -> None: + assert r1.result[0].name == r2.result[0].name + assert len(r1.result) == len(r2.result) + assert r1.outcome == r2.outcome + + # Function test_important + compare_report(default["reports"][1], collect_off["reports"][2]) + # Class TestDomain + compare_report(default["reports"][2], collect_off["reports"][3]) + # Module foo_test.py + compare_report(default["reports"][3], collect_off["reports"][4]) + + # + 1 since src dir is collected + assert len(default["reports"]) + 1 == len(collect_off["reports"]) + + # Two Dirs will be collected, src and test. + assert len(collect_off["reports"][5].result) == 2 From 3b230e06dbcc6a3472fc7cfecdc33e420b7cdb11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Nov 2024 07:02:43 +0100 Subject: [PATCH 0991/1271] build(deps): Bump pytest-rerunfailures in /testing/plugins_integration (#12988) Bumps [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) from 14.0 to 15.0. - [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/14.0...15.0) --- updated-dependencies: - dependency-name: pytest-rerunfailures dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 9ca5d1cfde0..ec6b9418c93 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -7,7 +7,7 @@ pytest-django==4.9.0 pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.14.0 -pytest-rerunfailures==14.0 +pytest-rerunfailures==15.0 pytest-sugar==1.0.0 pytest-trio==0.8.0 pytest-twisted==1.14.3 From 76e044477010dcc0e31d4a736b7130e044a01a7e Mon Sep 17 00:00:00 2001 From: Leonardus Chen Date: Mon, 25 Nov 2024 19:25:50 +0700 Subject: [PATCH 0992/1271] pytest.fail: fix ANSI escape codes for colored output (#12959) - When `ReprEntry.style == "value"` (happens when calling `pytest.fail(..., pytrace=False)`, the message should not be printed to terminal using `TerminalWriter._write_source` because then it'll try to highlight the message as source code - The message should be printed to terminal directly using `TerminalWriter.line` or `TerminalWriter.write`, I went with the later for testing purposes https://github.com/pytest-dev/pytest/pull/12959#discussion_r1842574618 Closes #12849 --- AUTHORS | 1 + changelog/12849.bugfix.rst | 1 + src/_pytest/_code/code.py | 16 +++++++++++----- testing/code/test_excinfo.py | 17 +++++++++++++++++ testing/conftest.py | 4 ++-- 5 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 changelog/12849.bugfix.rst diff --git a/AUTHORS b/AUTHORS index c38f74d9980..303d04133cb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -247,6 +247,7 @@ Kristoffer Nordström Kyle Altendorf Lawrence Mitchell Lee Kamentsky +Leonardus Chen Lev Maximov Levon Saldamli Lewis Cowles diff --git a/changelog/12849.bugfix.rst b/changelog/12849.bugfix.rst new file mode 100644 index 00000000000..fb72263aadd --- /dev/null +++ b/changelog/12849.bugfix.rst @@ -0,0 +1 @@ +ANSI escape codes for colored output now handled correctly in :func:`pytest.fail` with `pytrace=False`. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 8fac39ea298..fec627b3a36 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -1221,6 +1221,15 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: if not self.lines: return + if self.style == "value": + # Using tw.write instead of tw.line for testing purposes due to TWMock implementation; + # lines written with TWMock.line and TWMock._write_source cannot be distinguished + # from each other, whereas lines written with TWMock.write are marked with TWMock.WRITE + for line in self.lines: + tw.write(line) + tw.write("\n") + return + # separate indents and source lines that are not failures: we want to # highlight the code but not the indentation, which may contain markers # such as "> assert 0" @@ -1236,11 +1245,8 @@ def _write_entry_lines(self, tw: TerminalWriter) -> None: failure_lines.extend(self.lines[index:]) break else: - if self.style == "value": - source_lines.append(line) - else: - indents.append(line[:indent_size]) - source_lines.append(line[indent_size:]) + indents.append(line[:indent_size]) + source_lines.append(line[indent_size:]) tw._write_source(source_lines, indents) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index fc60ae9ac99..97c207e9795 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1194,6 +1194,23 @@ def f(): line = tw_mock.lines[-1] assert line == ":3: ValueError" + def test_toterminal_value(self, importasmod, tw_mock): + mod = importasmod( + """ + def g(x): + raise ValueError(x) + def f(): + g('some_value') + """ + ) + excinfo = pytest.raises(ValueError, mod.f) + excinfo.traceback = excinfo.traceback.filter(excinfo) + repr = excinfo.getrepr(style="value") + repr.toterminal(tw_mock) + + assert tw_mock.get_write_msg(0) == "some_value" + assert tw_mock.get_write_msg(1) == "\n" + @pytest.mark.parametrize( "reproptions", [ diff --git a/testing/conftest.py b/testing/conftest.py index 046bb77a109..69af03324d6 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -119,8 +119,8 @@ def markup(self, text, **kw): return text def get_write_msg(self, idx): - flag, msg = self.lines[idx] - assert flag == TWMock.WRITE + assert self.lines[idx][0] == TWMock.WRITE + msg = self.lines[idx][1] return msg fullwidth = 80 From 2157caf87960d904c8547c9168c94a7d535f21e0 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 25 Nov 2024 12:29:01 +0000 Subject: [PATCH 0993/1271] docs: Fix wrong statement about sys.modules with importlib import mode (#12985) Follow-up to #7870, see #12983. --- doc/en/explanation/goodpractices.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/explanation/goodpractices.rst b/doc/en/explanation/goodpractices.rst index 1390ba4e8fe..51c0b960aed 100644 --- a/doc/en/explanation/goodpractices.rst +++ b/doc/en/explanation/goodpractices.rst @@ -210,8 +210,8 @@ Note that this layout also works in conjunction with the ``src`` layout mentione to avoid surprises such as a test module getting imported twice. With ``--import-mode=importlib`` things are less convoluted because - pytest doesn't need to change ``sys.path`` or ``sys.modules``, making things - much less surprising. + pytest doesn't need to change ``sys.path``, making things much less + surprising. .. _which-import-mode: From a4cb74e8646dc3cfaa1c4d5b36e0d21f177332e6 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Nov 2024 19:25:05 +0100 Subject: [PATCH 0994/1271] Upgrade doc and CI after dropping python 3.8 --- .github/workflows/prepare-release-pr.yml | 2 +- .github/workflows/test.yml | 103 +++++++++++++---------- .pre-commit-config.yaml | 4 + CONTRIBUTING.rst | 2 +- README.rst | 2 +- changelog/12874.breaking.rst | 1 + doc/en/backwards-compatibility.rst | 1 + pyproject.toml | 7 +- scripts/generate-gh-release-notes.py | 2 +- scripts/update-plugin-list.py | 4 +- src/_pytest/_code/code.py | 15 ++-- src/_pytest/_code/source.py | 4 +- src/_pytest/_io/pprint.py | 2 +- src/_pytest/_io/terminalwriter.py | 2 +- src/_pytest/assertion/__init__.py | 2 +- src/_pytest/assertion/rewrite.py | 6 +- src/_pytest/assertion/util.py | 6 +- src/_pytest/cacheprovider.py | 4 +- src/_pytest/capture.py | 6 +- src/_pytest/config/__init__.py | 10 +-- src/_pytest/config/argparsing.py | 7 +- src/_pytest/config/compat.py | 2 +- src/_pytest/config/findpaths.py | 4 +- src/_pytest/debugging.py | 2 +- src/_pytest/doctest.py | 8 +- src/_pytest/faulthandler.py | 2 +- src/_pytest/fixtures.py | 24 +++--- src/_pytest/freeze_support.py | 2 +- src/_pytest/helpconfig.py | 2 +- src/_pytest/hookspec.py | 4 +- src/_pytest/junitxml.py | 2 +- src/_pytest/logging.py | 25 +++--- src/_pytest/main.py | 9 +- src/_pytest/mark/__init__.py | 4 +- src/_pytest/mark/expression.py | 6 +- src/_pytest/mark/structures.py | 12 +-- src/_pytest/monkeypatch.py | 6 +- src/_pytest/nodes.py | 6 +- src/_pytest/outcomes.py | 3 +- src/_pytest/pathlib.py | 4 +- src/_pytest/pytester.py | 6 +- src/_pytest/pytester_assertions.py | 2 +- src/_pytest/python.py | 15 ++-- src/_pytest/python_api.py | 10 +-- src/_pytest/recwarn.py | 6 +- src/_pytest/reports.py | 8 +- src/_pytest/setuponly.py | 2 +- src/_pytest/skipping.py | 2 +- src/_pytest/terminal.py | 6 +- src/_pytest/threadexception.py | 2 +- src/_pytest/tmpdir.py | 5 +- src/_pytest/unittest.py | 10 +-- src/_pytest/unraisableexception.py | 2 +- src/_pytest/warnings.py | 2 +- testing/code/test_excinfo.py | 4 +- testing/code/test_source.py | 2 +- testing/conftest.py | 2 +- testing/io/test_terminalwriter.py | 2 +- testing/logging/test_fixture.py | 2 +- testing/python/metafunc.py | 7 +- testing/test_assertion.py | 2 +- testing/test_assertrewrite.py | 4 +- testing/test_cacheprovider.py | 4 +- testing/test_capture.py | 2 +- testing/test_config.py | 2 +- testing/test_conftest.py | 7 +- testing/test_monkeypatch.py | 2 +- testing/test_pathlib.py | 6 +- testing/test_reports.py | 2 +- tox.ini | 9 +- 70 files changed, 230 insertions(+), 226 deletions(-) create mode 100644 changelog/12874.breaking.rst diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index 1bb23fab844..f46b5cecda5 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -34,7 +34,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: "3.8" + python-version: "3.x" - name: Install dependencies run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c1ea62f6c8b..30536706afb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,25 +54,24 @@ jobs: fail-fast: false matrix: name: [ - "windows-py38", - "windows-py38-pluggy", - "windows-py39", + "windows-py39-unittestextras", + "windows-py39-pluggy", + "windows-py39-xdist", "windows-py310", "windows-py311", "windows-py312", "windows-py313", - "ubuntu-py38", - "ubuntu-py38-pluggy", - "ubuntu-py38-freeze", - "ubuntu-py39", - "ubuntu-py310", + "ubuntu-py39-lsof-numpy-pexpect", + "ubuntu-py39-pluggy", + "ubuntu-py39-freeze", + "ubuntu-py39-xdist", + "ubuntu-py310-xdist", "ubuntu-py311", "ubuntu-py312", - "ubuntu-py313", - "ubuntu-pypy3", + "ubuntu-py313-pexpect", + "ubuntu-pypy3-xdist", - "macos-py38", "macos-py39", "macos-py310", "macos-py312", @@ -83,106 +82,122 @@ jobs: ] include: - - name: "windows-py38" - python: "3.8" + - name: "windows-py39-unittestextras" + python: "3.9" os: windows-latest - tox_env: "py38-unittestextras" + tox_env: "py39-unittestextras" use_coverage: true - - name: "windows-py38-pluggy" - python: "3.8" + + - name: "windows-py39-pluggy" + python: "3.9" os: windows-latest - tox_env: "py38-pluggymain-pylib-xdist" - - name: "windows-py39" + tox_env: "py39-pluggymain-pylib-xdist" + + - name: "windows-py39-xdist" python: "3.9" os: windows-latest tox_env: "py39-xdist" + - name: "windows-py310" python: "3.10" os: windows-latest tox_env: "py310-xdist" + - name: "windows-py311" python: "3.11" os: windows-latest tox_env: "py311" + - name: "windows-py312" python: "3.12" os: windows-latest tox_env: "py312" + - name: "windows-py313" - python: "3.13-dev" + python: "3.13" os: windows-latest tox_env: "py313" - - name: "ubuntu-py38" - python: "3.8" + + - name: "ubuntu-py39-lsof-numpy-pexpect" + python: "3.9" os: ubuntu-latest - tox_env: "py38-lsof-numpy-pexpect" - use_coverage: true - - name: "ubuntu-py38-pluggy" - python: "3.8" + tox_env: "py39-lsof-numpy-pexpect" + + - name: "ubuntu-py39-pluggy" + python: "3.9" os: ubuntu-latest - tox_env: "py38-pluggymain-pylib-xdist" - - name: "ubuntu-py38-freeze" - python: "3.8" + tox_env: "py39-pluggymain-pylib-xdist" + + - name: "ubuntu-py39-freeze" + python: "3.9" os: ubuntu-latest - tox_env: "py38-freeze" - - name: "ubuntu-py39" + tox_env: "py39-freeze" + + - name: "ubuntu-py39-xdist" python: "3.9" os: ubuntu-latest tox_env: "py39-xdist" - - name: "ubuntu-py310" + + - name: "ubuntu-py310-xdist" python: "3.10" os: ubuntu-latest tox_env: "py310-xdist" + - name: "ubuntu-py311" python: "3.11" os: ubuntu-latest tox_env: "py311" use_coverage: true + - name: "ubuntu-py312" python: "3.12" os: ubuntu-latest tox_env: "py312" use_coverage: true - - name: "ubuntu-py313" - python: "3.13-dev" + + - name: "ubuntu-py313-pexpect" + python: "3.13" os: ubuntu-latest tox_env: "py313-pexpect" use_coverage: true - - name: "ubuntu-pypy3" + + - name: "ubuntu-pypy3-xdist" python: "pypy-3.9" os: ubuntu-latest tox_env: "pypy3-xdist" - - name: "macos-py38" - python: "3.8" - os: macos-latest - tox_env: "py38-xdist" + - name: "macos-py39" python: "3.9" os: macos-latest tox_env: "py39-xdist" use_coverage: true + - name: "macos-py310" python: "3.10" os: macos-latest tox_env: "py310-xdist" + - name: "macos-py312" python: "3.12" os: macos-latest tox_env: "py312-xdist" + - name: "macos-py313" - python: "3.13-dev" + python: "3.13" os: macos-latest tox_env: "py313-xdist" + - name: "plugins" python: "3.12" os: ubuntu-latest tox_env: "plugins" + - name: "doctesting" - python: "3.8" + python: "3.9" os: ubuntu-latest tox_env: "doctesting" use_coverage: true @@ -192,12 +207,12 @@ jobs: contains( fromJSON( '[ - "windows-py38-pluggy", + "windows-py39-pluggy", "windows-py313", - "ubuntu-py38-pluggy", - "ubuntu-py38-freeze", + "ubuntu-py39-pluggy", + "ubuntu-py39-freeze", "ubuntu-py313", - "macos-py38", + "macos-py39", "macos-py313" ]' ), diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9e7be8cf6db..cb02fd0f00f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -53,6 +53,10 @@ repos: rev: v3.19.0 hooks: - id: pyupgrade + args: + - "--py39-plus" + # Manual because ruff does what pyupgrade does and the two are not out of sync + # often enough to make launching pyupgrade everytime worth it stages: [manual] - repo: local hooks: diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index d615e5fb113..56824a43ff4 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -270,7 +270,7 @@ Here is a simple overview, with pytest-specific bits: #. Run all the tests - You need to have Python 3.8 or later available in your system. Now + You need to have Python 3.9 or later available in your system. Now running tests is as simple as issuing this command:: $ tox -e linting,py39 diff --git a/README.rst b/README.rst index a81e082cdd7..091afc363da 100644 --- a/README.rst +++ b/README.rst @@ -97,7 +97,7 @@ Features - Can run `unittest `_ (or trial) test suites out of the box -- Python 3.8+ or PyPy3 +- Python 3.9+ or PyPy3 - Rich plugin architecture, with over 1300+ `external plugins `_ and thriving community diff --git a/changelog/12874.breaking.rst b/changelog/12874.breaking.rst new file mode 100644 index 00000000000..a442586eeb5 --- /dev/null +++ b/changelog/12874.breaking.rst @@ -0,0 +1 @@ +We dropped support for Python 3.8 following its end of life (2024-10-07). diff --git a/doc/en/backwards-compatibility.rst b/doc/en/backwards-compatibility.rst index c0feb833ce1..82f678b4dea 100644 --- a/doc/en/backwards-compatibility.rst +++ b/doc/en/backwards-compatibility.rst @@ -83,6 +83,7 @@ Released pytest versions support all Python versions that are actively maintaine ============== =================== pytest version min. Python version ============== =================== +8.4+ 3.9+ 8.0+ 3.8+ 7.1+ 3.7+ 6.2 - 7.0 3.6+ diff --git a/pyproject.toml b/pyproject.toml index 50fcfc65353..0541da9906e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -23,7 +23,7 @@ authors = [ { name = "Florian Bruhin" }, { name = "Others (See AUTHORS)" }, ] -requires-python = ">=3.8" +requires-python = ">=3.9" classifiers = [ "Development Status :: 6 - Mature", "Intended Audience :: Developers", @@ -33,7 +33,6 @@ classifiers = [ "Operating System :: POSIX", "Operating System :: Unix", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -85,7 +84,7 @@ write_to = "src/_pytest/_version.py" [tool.black] target-version = [ - 'py38', + 'py39', ] [tool.ruff] @@ -508,7 +507,7 @@ files = [ mypy_path = [ "src", ] -python_version = "3.8" +python_version = "3.9" check_untyped_defs = true disallow_any_generics = true disallow_untyped_defs = true diff --git a/scripts/generate-gh-release-notes.py b/scripts/generate-gh-release-notes.py index 7f195ba1e0a..b6d92d085e1 100644 --- a/scripts/generate-gh-release-notes.py +++ b/scripts/generate-gh-release-notes.py @@ -11,10 +11,10 @@ from __future__ import annotations +from collections.abc import Sequence from pathlib import Path import re import sys -from typing import Sequence import pypandoc diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 556004d9e98..693a25a00cc 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -1,14 +1,14 @@ # mypy: disallow-untyped-defs from __future__ import annotations +from collections.abc import Iterable +from collections.abc import Iterator import datetime import pathlib import re from textwrap import dedent from textwrap import indent from typing import Any -from typing import Iterable -from typing import Iterator from typing import TypedDict import packaging.version diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index dd3fd7addb6..ea7415be23e 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -2,6 +2,9 @@ from __future__ import annotations import ast +from collections.abc import Iterable +from collections.abc import Mapping +from collections.abc import Sequence import dataclasses import inspect from inspect import CO_VARARGS @@ -10,6 +13,7 @@ import os from pathlib import Path import re +from re import Pattern import sys import traceback from traceback import format_exception_only @@ -22,16 +26,9 @@ from typing import Final from typing import final from typing import Generic -from typing import Iterable -from typing import List from typing import Literal -from typing import Mapping from typing import overload -from typing import Pattern -from typing import Sequence from typing import SupportsIndex -from typing import Tuple -from typing import Type from typing import TypeVar from typing import Union @@ -56,7 +53,7 @@ TracebackStyle = Literal["long", "short", "line", "no", "native", "value", "auto"] -EXCEPTION_OR_MORE = Union[Type[BaseException], Tuple[Type[BaseException], ...]] +EXCEPTION_OR_MORE = Union[type[BaseException], tuple[type[BaseException], ...]] class Code: @@ -320,7 +317,7 @@ def name(self) -> str: return self.frame.code.raw.co_name -class Traceback(List[TracebackEntry]): +class Traceback(list[TracebackEntry]): """Traceback objects encapsulate and offer higher level access to Traceback entries.""" def __init__( diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index 604aff8ba19..e24ee3a260e 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -3,12 +3,12 @@ import ast from bisect import bisect_right +from collections.abc import Iterable +from collections.abc import Iterator import inspect import textwrap import tokenize import types -from typing import Iterable -from typing import Iterator from typing import overload import warnings diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index 7a6433d9128..d212b773166 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -16,6 +16,7 @@ from __future__ import annotations import collections as _collections +from collections.abc import Iterator import dataclasses as _dataclasses from io import StringIO as _StringIO import re @@ -23,7 +24,6 @@ from typing import Any from typing import Callable from typing import IO -from typing import Iterator class _safe_key: diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 70ebd3d061b..50ce463f6b2 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -2,12 +2,12 @@ from __future__ import annotations +from collections.abc import Sequence import os import shutil import sys from typing import final from typing import Literal -from typing import Sequence from typing import TextIO from typing import TYPE_CHECKING diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index cbdf9fa0298..532b96fe431 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -3,9 +3,9 @@ from __future__ import annotations +from collections.abc import Generator import sys from typing import Any -from typing import Generator from typing import TYPE_CHECKING from _pytest.assertion import rewrite diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 37c09b03467..05934797a14 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -4,6 +4,9 @@ import ast from collections import defaultdict +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Sequence import errno import functools import importlib.abc @@ -21,9 +24,6 @@ import types from typing import Callable from typing import IO -from typing import Iterable -from typing import Iterator -from typing import Sequence from typing import TYPE_CHECKING from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 4dc1af4af03..3593f0ce036 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -4,16 +4,16 @@ from __future__ import annotations import collections.abc +from collections.abc import Iterable +from collections.abc import Mapping +from collections.abc import Sequence import os import pprint from typing import AbstractSet from typing import Any from typing import Callable -from typing import Iterable from typing import Literal -from typing import Mapping from typing import Protocol -from typing import Sequence from unicodedata import normalize from _pytest import outcomes diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index 1b236efdc9b..bf643d6f4dc 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -5,6 +5,8 @@ # pytest-cache version. from __future__ import annotations +from collections.abc import Generator +from collections.abc import Iterable import dataclasses import errno import json @@ -12,8 +14,6 @@ from pathlib import Path import tempfile from typing import final -from typing import Generator -from typing import Iterable from .pathlib import resolve_from_str from .pathlib import rm_rf diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 2ac3b6bbc7f..93a3b04182e 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -5,6 +5,9 @@ import abc import collections +from collections.abc import Generator +from collections.abc import Iterable +from collections.abc import Iterator import contextlib import io from io import UnsupportedOperation @@ -18,10 +21,7 @@ from typing import cast from typing import Final from typing import final -from typing import Generator from typing import Generic -from typing import Iterable -from typing import Iterator from typing import Literal from typing import NamedTuple from typing import TextIO diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 92cf565e85f..5ec4d7b52ea 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -5,6 +5,10 @@ import argparse import collections.abc +from collections.abc import Generator +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Sequence import contextlib import copy import dataclasses @@ -26,11 +30,7 @@ from typing import cast from typing import Final from typing import final -from typing import Generator from typing import IO -from typing import Iterable -from typing import Iterator -from typing import Sequence from typing import TextIO from typing import Type from typing import TYPE_CHECKING @@ -1978,7 +1978,7 @@ def _resolve_warning_category(category: str) -> type[Warning]: cat = getattr(m, klass) if not issubclass(cat, Warning): raise UsageError(f"{cat} is not a Warning subclass") - return cast(Type[Warning], cat) + return cast(type[Warning], cat) def apply_warning_filters( diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 85aa4632702..455d2d8db26 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -2,6 +2,8 @@ from __future__ import annotations import argparse +from collections.abc import Mapping +from collections.abc import Sequence from gettext import gettext import os import sys @@ -9,11 +11,8 @@ from typing import Callable from typing import cast from typing import final -from typing import List from typing import Literal -from typing import Mapping from typing import NoReturn -from typing import Sequence import _pytest._io from _pytest.config.exceptions import UsageError @@ -144,7 +143,7 @@ def parse_setoption( parsedoption = self.parse(args, namespace=namespace) for name, value in parsedoption.__dict__.items(): setattr(option, name, value) - return cast(List[str], getattr(parsedoption, FILE_OR_DIR)) + return cast(list[str], getattr(parsedoption, FILE_OR_DIR)) def parse_known_args( self, diff --git a/src/_pytest/config/compat.py b/src/_pytest/config/compat.py index 2856d85d195..21eab4c7e47 100644 --- a/src/_pytest/config/compat.py +++ b/src/_pytest/config/compat.py @@ -1,9 +1,9 @@ from __future__ import annotations +from collections.abc import Mapping import functools from pathlib import Path from typing import Any -from typing import Mapping import warnings import pluggy diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index ce4c990b810..a7f45bf593e 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -1,10 +1,10 @@ from __future__ import annotations +from collections.abc import Iterable +from collections.abc import Sequence import os from pathlib import Path import sys -from typing import Iterable -from typing import Sequence import iniconfig diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 763606cd60e..665d8536262 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -5,12 +5,12 @@ from __future__ import annotations import argparse +from collections.abc import Generator import functools import sys import types from typing import Any from typing import Callable -from typing import Generator import unittest from _pytest import outcomes diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 384dea976ad..a1f680570d8 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -4,21 +4,21 @@ from __future__ import annotations import bdb +from collections.abc import Generator +from collections.abc import Iterable +from collections.abc import Sequence from contextlib import contextmanager import functools import inspect import os from pathlib import Path import platform +from re import Pattern import sys import traceback import types from typing import Any from typing import Callable -from typing import Generator -from typing import Iterable -from typing import Pattern -from typing import Sequence from typing import TYPE_CHECKING import warnings diff --git a/src/_pytest/faulthandler.py b/src/_pytest/faulthandler.py index d16aea1eb88..79efc1d1704 100644 --- a/src/_pytest/faulthandler.py +++ b/src/_pytest/faulthandler.py @@ -1,8 +1,8 @@ from __future__ import annotations +from collections.abc import Generator import os import sys -from typing import Generator from _pytest.config import Config from _pytest.config.argparsing import Parser diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 5817e88f47d..c4a8a09f84a 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -4,6 +4,13 @@ import abc from collections import defaultdict from collections import deque +from collections import OrderedDict +from collections.abc import Generator +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Mapping +from collections.abc import MutableMapping +from collections.abc import Sequence import dataclasses import functools import inspect @@ -15,21 +22,12 @@ from typing import Any from typing import Callable from typing import cast -from typing import Dict from typing import Final from typing import final -from typing import Generator from typing import Generic -from typing import Iterable -from typing import Iterator -from typing import Mapping -from typing import MutableMapping from typing import NoReturn from typing import Optional -from typing import OrderedDict from typing import overload -from typing import Sequence -from typing import Tuple from typing import TYPE_CHECKING from typing import TypeVar from typing import Union @@ -95,19 +93,19 @@ ] # The type of FixtureDef.cached_result (type alias generic in fixture value). _FixtureCachedResult = Union[ - Tuple[ + tuple[ # The result. FixtureValue, # Cache key. object, None, ], - Tuple[ + tuple[ None, # Cache key. object, # The exception and the original traceback. - Tuple[BaseException, Optional[types.TracebackType]], + tuple[BaseException, Optional[types.TracebackType]], ], ] @@ -177,7 +175,7 @@ class FixtureArgKey: _V = TypeVar("_V") -OrderedSet = Dict[_V, None] +OrderedSet = dict[_V, None] def get_parametrized_fixture_argkeys( diff --git a/src/_pytest/freeze_support.py b/src/_pytest/freeze_support.py index 2ba6f9b8bcc..959ff071d86 100644 --- a/src/_pytest/freeze_support.py +++ b/src/_pytest/freeze_support.py @@ -3,8 +3,8 @@ from __future__ import annotations +from collections.abc import Iterator import types -from typing import Iterator def freeze_includes() -> list[str]: diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 1886d5c9342..3d607189dbe 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -4,9 +4,9 @@ from __future__ import annotations from argparse import Action +from collections.abc import Generator import os import sys -from typing import Generator from _pytest.config import Config from _pytest.config import ExitCode diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 0a41b0aca47..8b20061d6f0 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -5,10 +5,10 @@ from __future__ import annotations +from collections.abc import Mapping +from collections.abc import Sequence from pathlib import Path from typing import Any -from typing import Mapping -from typing import Sequence from typing import TYPE_CHECKING from pluggy import HookspecMarker diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index efe6f489b48..46c456a5b6e 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -16,8 +16,8 @@ import os import platform import re +from re import Match from typing import Callable -from typing import Match import xml.etree.ElementTree as ET from _pytest import nodes diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 08c826ff6d4..00645dae2da 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -3,6 +3,8 @@ from __future__ import annotations +from collections.abc import Generator +from collections.abc import Mapping from contextlib import contextmanager from contextlib import nullcontext from datetime import datetime @@ -17,13 +19,9 @@ import re from types import TracebackType from typing import AbstractSet -from typing import Dict from typing import final -from typing import Generator from typing import Generic -from typing import List from typing import Literal -from typing import Mapping from typing import TYPE_CHECKING from typing import TypeVar @@ -53,7 +51,7 @@ DEFAULT_LOG_DATE_FORMAT = "%H:%M:%S" _ANSI_ESCAPE_SEQ = re.compile(r"\x1b\[[\d;]+m") caplog_handler_key = StashKey["LogCaptureHandler"]() -caplog_records_key = StashKey[Dict[str, List[logging.LogRecord]]]() +caplog_records_key = StashKey[dict[str, list[logging.LogRecord]]]() def _remove_ansi_escape_sequences(text: str) -> str: @@ -813,13 +811,16 @@ def pytest_runtest_logreport(self) -> None: def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None]: """Implement the internals of the pytest_runtest_xxx() hooks.""" - with catching_logs( - self.caplog_handler, - level=self.log_level, - ) as caplog_handler, catching_logs( - self.report_handler, - level=self.log_level, - ) as report_handler: + with ( + catching_logs( + self.caplog_handler, + level=self.log_level, + ) as caplog_handler, + catching_logs( + self.report_handler, + level=self.log_level, + ) as report_handler, + ): caplog_handler.reset() report_handler.reset() item.stash[caplog_records_key][when] = caplog_handler.records diff --git a/src/_pytest/main.py b/src/_pytest/main.py index e5534e98d69..1e18a60141d 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -3,6 +3,9 @@ from __future__ import annotations import argparse +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Sequence import dataclasses import fnmatch import functools @@ -13,13 +16,9 @@ import sys from typing import AbstractSet from typing import Callable -from typing import Dict from typing import final -from typing import Iterable -from typing import Iterator from typing import Literal from typing import overload -from typing import Sequence from typing import TYPE_CHECKING import warnings @@ -476,7 +475,7 @@ class Failed(Exception): @dataclasses.dataclass -class _bestrelpath_cache(Dict[Path, str]): +class _bestrelpath_cache(dict[Path, str]): __slots__ = ("path",) path: Path diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index a6f0155751a..c8c51d19aa0 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -3,10 +3,10 @@ from __future__ import annotations import collections +from collections.abc import Collection +from collections.abc import Iterable import dataclasses from typing import AbstractSet -from typing import Collection -from typing import Iterable from typing import Optional from typing import TYPE_CHECKING diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index 89cc0e94d3b..d0ab190e3b6 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -23,18 +23,18 @@ from __future__ import annotations import ast +from collections.abc import Iterator +from collections.abc import Mapping +from collections.abc import Sequence import dataclasses import enum import keyword import re import types -from typing import Iterator from typing import Literal -from typing import Mapping from typing import NoReturn from typing import overload from typing import Protocol -from typing import Sequence __all__ = [ diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 14650a64759..09ef7d02cef 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -2,19 +2,19 @@ from __future__ import annotations import collections.abc +from collections.abc import Collection +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Mapping +from collections.abc import MutableMapping +from collections.abc import Sequence import dataclasses import inspect from typing import Any from typing import Callable -from typing import Collection from typing import final -from typing import Iterable -from typing import Iterator -from typing import Mapping -from typing import MutableMapping from typing import NamedTuple from typing import overload -from typing import Sequence from typing import TYPE_CHECKING from typing import TypeVar from typing import Union diff --git a/src/_pytest/monkeypatch.py b/src/_pytest/monkeypatch.py index 46eb1724e35..1285e571551 100644 --- a/src/_pytest/monkeypatch.py +++ b/src/_pytest/monkeypatch.py @@ -3,15 +3,15 @@ from __future__ import annotations +from collections.abc import Generator +from collections.abc import Mapping +from collections.abc import MutableMapping from contextlib import contextmanager import os import re import sys from typing import Any from typing import final -from typing import Generator -from typing import Mapping -from typing import MutableMapping from typing import overload from typing import TypeVar import warnings diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 51bc5174628..e84fb37c9d0 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -2,6 +2,9 @@ from __future__ import annotations import abc +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import MutableMapping from functools import cached_property from inspect import signature import os @@ -10,9 +13,6 @@ from typing import Any from typing import Callable from typing import cast -from typing import Iterable -from typing import Iterator -from typing import MutableMapping from typing import NoReturn from typing import overload from typing import TYPE_CHECKING diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index 5b20803e586..ab39bac61b9 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -9,7 +9,6 @@ from typing import cast from typing import NoReturn from typing import Protocol -from typing import Type from typing import TypeVar from .warning_types import PytestDeprecationWarning @@ -82,7 +81,7 @@ def __init__( # Ideally would just be `exit.Exception = Exit` etc. _F = TypeVar("_F", bound=Callable[..., object]) -_ET = TypeVar("_ET", bound=Type[BaseException]) +_ET = TypeVar("_ET", bound=type[BaseException]) class _WithException(Protocol[_F, _ET]): diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index dd36559ce1b..f6392561951 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,6 +1,8 @@ from __future__ import annotations import atexit +from collections.abc import Iterable +from collections.abc import Iterator import contextlib from enum import Enum from errno import EBADF @@ -27,8 +29,6 @@ from types import ModuleType from typing import Any from typing import Callable -from typing import Iterable -from typing import Iterator from typing import TypeVar import uuid import warnings diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 3f7520ee4ad..d19151391b0 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -7,6 +7,9 @@ from __future__ import annotations import collections.abc +from collections.abc import Generator +from collections.abc import Iterable +from collections.abc import Sequence import contextlib from fnmatch import fnmatch import gc @@ -25,12 +28,9 @@ from typing import Callable from typing import Final from typing import final -from typing import Generator from typing import IO -from typing import Iterable from typing import Literal from typing import overload -from typing import Sequence from typing import TextIO from typing import TYPE_CHECKING from weakref import WeakKeyDictionary diff --git a/src/_pytest/pytester_assertions.py b/src/_pytest/pytester_assertions.py index d543798f75a..915cc8a10ff 100644 --- a/src/_pytest/pytester_assertions.py +++ b/src/_pytest/pytester_assertions.py @@ -6,7 +6,7 @@ # module to not be already imported. from __future__ import annotations -from typing import Sequence +from collections.abc import Sequence from _pytest.reports import CollectReport from _pytest.reports import TestReport diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 1456b5212d4..153fbf8893b 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -6,6 +6,11 @@ import abc from collections import Counter from collections import defaultdict +from collections.abc import Generator +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Mapping +from collections.abc import Sequence import dataclasses import enum import fnmatch @@ -14,18 +19,12 @@ import itertools import os from pathlib import Path +from re import Pattern import types from typing import Any from typing import Callable -from typing import Dict from typing import final -from typing import Generator -from typing import Iterable -from typing import Iterator from typing import Literal -from typing import Mapping -from typing import Pattern -from typing import Sequence from typing import TYPE_CHECKING import warnings @@ -1078,7 +1077,7 @@ def get_direct_param_fixture_func(request: FixtureRequest) -> Any: # Used for storing pseudo fixturedefs for direct parametrization. -name2pseudofixturedef_key = StashKey[Dict[str, FixtureDef[Any]]]() +name2pseudofixturedef_key = StashKey[dict[str, FixtureDef[Any]]]() @final diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index d2107c2fc78..30a630c42ff 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -2,24 +2,22 @@ from __future__ import annotations from collections.abc import Collection +from collections.abc import Mapping +from collections.abc import Sequence from collections.abc import Sized from decimal import Decimal import math from numbers import Complex import pprint import re +from re import Pattern from types import TracebackType from typing import Any from typing import Callable from typing import cast from typing import ContextManager from typing import final -from typing import Mapping from typing import overload -from typing import Pattern -from typing import Sequence -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING from typing import TypeVar @@ -1017,7 +1015,7 @@ def __exit__( if not issubclass(exc_type, self.expected_exception): return False # Cast to narrow the exception type now that it's verified. - exc_info = cast(Tuple[Type[E], E, TracebackType], (exc_type, exc_val, exc_tb)) + exc_info = cast(tuple[type[E], E, TracebackType], (exc_type, exc_val, exc_tb)) self.excinfo.fill_unfilled(exc_info) if self.match_expr is not None: self.excinfo.match(self.match_expr) diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 0dc002edd94..fc26fcc78e4 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -3,16 +3,16 @@ from __future__ import annotations +from collections.abc import Generator +from collections.abc import Iterator from pprint import pformat import re +from re import Pattern from types import TracebackType from typing import Any from typing import Callable from typing import final -from typing import Generator -from typing import Iterator from typing import overload -from typing import Pattern from typing import TYPE_CHECKING from typing import TypeVar diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 77cbf773e23..4d926ef6c9e 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -1,6 +1,10 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Mapping +from collections.abc import Sequence import dataclasses from io import StringIO import os @@ -8,12 +12,8 @@ from typing import Any from typing import cast from typing import final -from typing import Iterable -from typing import Iterator from typing import Literal -from typing import Mapping from typing import NoReturn -from typing import Sequence from typing import TYPE_CHECKING from _pytest._code.code import ExceptionChainRepr diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index de297f408d3..1e887a896f5 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Generator +from collections.abc import Generator from _pytest._io.saferepr import saferepr from _pytest.config import Config diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 9818be2ab03..8fa17a01eb0 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -3,13 +3,13 @@ from __future__ import annotations +from collections.abc import Generator from collections.abc import Mapping import dataclasses import os import platform import sys import traceback -from typing import Generator from typing import Optional from _pytest.config import Config diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 55ef1ea8eee..d2baee40d9c 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -8,6 +8,9 @@ import argparse from collections import Counter +from collections.abc import Generator +from collections.abc import Mapping +from collections.abc import Sequence import dataclasses import datetime from functools import partial @@ -20,11 +23,8 @@ from typing import Callable from typing import ClassVar from typing import final -from typing import Generator from typing import Literal -from typing import Mapping from typing import NamedTuple -from typing import Sequence from typing import TextIO from typing import TYPE_CHECKING import warnings diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index c1ed80387aa..49560bf7d7f 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -1,11 +1,11 @@ from __future__ import annotations +from collections.abc import Generator import threading import traceback from types import TracebackType from typing import Any from typing import Callable -from typing import Generator from typing import TYPE_CHECKING import warnings diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index 1731a4b8d0d..c5b51c87741 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -3,6 +3,7 @@ from __future__ import annotations +from collections.abc import Generator import dataclasses import os from pathlib import Path @@ -10,9 +11,7 @@ from shutil import rmtree import tempfile from typing import Any -from typing import Dict from typing import final -from typing import Generator from typing import Literal from .pathlib import cleanup_dead_symlinks @@ -34,7 +33,7 @@ from _pytest.stash import StashKey -tmppath_result_key = StashKey[Dict[str, bool]]() +tmppath_result_key = StashKey[dict[str, bool]]() RetentionType = Literal["all", "failed", "none"] diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 8cecd4f9339..6d967b972ee 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -3,16 +3,14 @@ from __future__ import annotations +from collections.abc import Generator +from collections.abc import Iterable import inspect import sys import traceback import types from typing import Any from typing import Callable -from typing import Generator -from typing import Iterable -from typing import Tuple -from typing import Type from typing import TYPE_CHECKING from typing import Union @@ -43,8 +41,8 @@ _SysExcInfoType = Union[ - Tuple[Type[BaseException], BaseException, types.TracebackType], - Tuple[None, None, None], + tuple[type[BaseException], BaseException, types.TracebackType], + tuple[None, None, None], ] diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index 77a2de20041..9ef583137e1 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -1,11 +1,11 @@ from __future__ import annotations +from collections.abc import Generator import sys import traceback from types import TracebackType from typing import Any from typing import Callable -from typing import Generator from typing import TYPE_CHECKING import warnings diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index eeb4772649d..87cdbda288f 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -1,9 +1,9 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Generator from contextlib import contextmanager import sys -from typing import Generator from typing import Literal import warnings diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index ab56904d040..22e695977e1 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -964,8 +964,8 @@ def raiseos(): upframe = sys._getframe().f_back assert upframe is not None if upframe.f_code.co_name == "_makepath": - # Only raise with expected calls, but not via e.g. inspect for - # py38-windows. + # Only raise with expected calls, and not accidentally via 'inspect' + # See 79ae86cc3f76d69460e1c7beca4ce95e68ab80a6 raised += 1 raise OSError(2, "custom_oserror") return orig_path_cwd() diff --git a/testing/code/test_source.py b/testing/code/test_source.py index a00259976c4..d78d9e7025a 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -336,7 +336,7 @@ def test_findsource(monkeypatch) -> None: assert src is not None assert "if 1:" in str(src) - d: Dict[str, Any] = {} + d: dict[str, Any] = {} eval(co, d) src, lineno = findsource(d["x"]) assert src is not None diff --git a/testing/conftest.py b/testing/conftest.py index 69af03324d6..110ad0d9b35 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -1,10 +1,10 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Generator import dataclasses import re import sys -from typing import Generator from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index 92cde240a11..f14e884b1f0 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -1,13 +1,13 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Generator import io import os from pathlib import Path import re import shutil import sys -from typing import Generator from unittest import mock from _pytest._io import terminalwriter diff --git a/testing/logging/test_fixture.py b/testing/logging/test_fixture.py index 0603eaba218..5f94cb8508a 100644 --- a/testing/logging/test_fixture.py +++ b/testing/logging/test_fixture.py @@ -2,8 +2,8 @@ # mypy: disallow-untyped-defs from __future__ import annotations +from collections.abc import Iterator import logging -from typing import Iterator from _pytest.logging import caplog_records_key from _pytest.pytester import Pytester diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 0a4ebf2c9af..df6dbaee0fd 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1,6 +1,8 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Iterator +from collections.abc import Sequence import dataclasses import itertools import re @@ -8,9 +10,6 @@ import textwrap from typing import Any from typing import cast -from typing import Dict -from typing import Iterator -from typing import Sequence import hypothesis from hypothesis import strategies @@ -154,7 +153,7 @@ class DummyFixtureDef: _scope: Scope fixtures_defs = cast( - Dict[str, Sequence[fixtures.FixtureDef[object]]], + dict[str, Sequence[fixtures.FixtureDef[object]]], dict( session_fix=[DummyFixtureDef(Scope.Session)], package_fix=[DummyFixtureDef(Scope.Package)], diff --git a/testing/test_assertion.py b/testing/test_assertion.py index b10ca1c91f4..a14c4125cf6 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1,10 +1,10 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import MutableSequence import sys import textwrap from typing import Any -from typing import MutableSequence from typing import NamedTuple import attr diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 7be473d897a..2a988149daf 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -2,6 +2,8 @@ from __future__ import annotations import ast +from collections.abc import Generator +from collections.abc import Mapping import dis import errno from functools import partial @@ -17,8 +19,6 @@ import sys import textwrap from typing import cast -from typing import Generator -from typing import Mapping from unittest import mock import zipfile diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 94bc55d3047..1ba4659d84e 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -1,13 +1,13 @@ from __future__ import annotations +from collections.abc import Generator +from collections.abc import Sequence from enum import auto from enum import Enum import os from pathlib import Path import shutil from typing import Any -from typing import Generator -from typing import Sequence from _pytest.compat import assert_never from _pytest.config import ExitCode diff --git a/testing/test_capture.py b/testing/test_capture.py index 328de740e8a..98986af6f1f 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Generator import contextlib import io from io import UnsupportedOperation @@ -10,7 +11,6 @@ import textwrap from typing import BinaryIO from typing import cast -from typing import Generator from typing import TextIO from _pytest import capture diff --git a/testing/test_config.py b/testing/test_config.py index b2825678b46..53f26269f09 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Sequence import dataclasses import importlib.metadata import os @@ -9,7 +10,6 @@ import sys import textwrap from typing import Any -from typing import Sequence import _pytest._code from _pytest.config import _get_plugin_specs_as_list diff --git a/testing/test_conftest.py b/testing/test_conftest.py index ea60c1909c2..bbb1d301ebe 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -1,13 +1,12 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Generator +from collections.abc import Sequence import os from pathlib import Path import textwrap from typing import cast -from typing import Generator -from typing import List -from typing import Sequence from _pytest.config import ExitCode from _pytest.config import PytestPluginManager @@ -459,7 +458,7 @@ def impct(p, importmode, root, consider_namespace_packages): rootpath=pytester.path, consider_namespace_packages=False, ) - mods = cast(List[Path], conftest._getconftestmodules(sub)) + mods = cast(list[Path], conftest._getconftestmodules(sub)) expected = [ct1, ct2] assert mods == expected diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index 7c62d90f2b9..ad75273d703 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -1,12 +1,12 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Generator import os from pathlib import Path import re import sys import textwrap -from typing import Generator from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 62359303f3b..436a6b9cae3 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1,6 +1,9 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Generator +from collections.abc import Iterator +from collections.abc import Sequence import errno import importlib.abc import importlib.machinery @@ -12,9 +15,6 @@ from textwrap import dedent from types import ModuleType from typing import Any -from typing import Generator -from typing import Iterator -from typing import Sequence import unittest.mock from _pytest.config import ExitCode diff --git a/testing/test_reports.py b/testing/test_reports.py index 3e314d2aade..7a893981838 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -1,7 +1,7 @@ # mypy: allow-untyped-defs from __future__ import annotations -from typing import Sequence +from collections.abc import Sequence from _pytest._code.code import ExceptionChainRepr from _pytest._code.code import ExceptionRepr diff --git a/tox.ini b/tox.ini index 61563ca2c5f..80fae513142 100644 --- a/tox.ini +++ b/tox.ini @@ -4,18 +4,17 @@ minversion = 3.20.0 distshare = {homedir}/.tox/distshare envlist = linting - py38 py39 py310 py311 py312 py313 pypy3 - py38-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} + py39-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} doctesting doctesting-coverage plugins - py38-freeze + py39-freeze docs docs-checklinks @@ -58,7 +57,7 @@ setenv = PYTHONWARNDEFAULTENCODING=1 # Configuration to run with coverage similar to CI, e.g. - # "tox -e py38-coverage". + # "tox -e py39-coverage". coverage: _PYTEST_TOX_COVERAGE_RUN=coverage run -m coverage: _PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess coverage: COVERAGE_FILE={toxinidir}/.coverage @@ -178,7 +177,7 @@ commands = pytest pytest_twisted_integration.py pytest simple_integration.py --force-sugar --flakes -[testenv:py38-freeze] +[testenv:py39-freeze] description = test pytest frozen with `pyinstaller` under `{basepython}` changedir = testing/freeze From 05ed0d0f943ce25b635e92e4e166524435386018 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Nov 2024 15:43:08 +0100 Subject: [PATCH 0995/1271] Enable pylint's python 3.8 typing checks (deprecated-typing-alias) --- pyproject.toml | 1 - src/_pytest/_code/code.py | 2 +- src/_pytest/_io/pprint.py | 2 +- src/_pytest/_py/error.py | 2 +- src/_pytest/_py/path.py | 2 +- src/_pytest/assertion/rewrite.py | 2 +- src/_pytest/assertion/util.py | 2 +- src/_pytest/compat.py | 2 +- src/_pytest/config/__init__.py | 2 +- src/_pytest/config/argparsing.py | 2 +- src/_pytest/debugging.py | 2 +- src/_pytest/doctest.py | 2 +- src/_pytest/fixtures.py | 8 +++----- src/_pytest/junitxml.py | 2 +- src/_pytest/main.py | 2 +- src/_pytest/mark/structures.py | 2 +- src/_pytest/nodes.py | 2 +- src/_pytest/outcomes.py | 2 +- src/_pytest/pathlib.py | 2 +- src/_pytest/pytester.py | 2 +- src/_pytest/python.py | 2 +- src/_pytest/python_api.py | 2 +- src/_pytest/recwarn.py | 2 +- src/_pytest/runner.py | 2 +- src/_pytest/terminal.py | 2 +- src/_pytest/threadexception.py | 2 +- src/_pytest/unittest.py | 2 +- src/_pytest/unraisableexception.py | 2 +- testing/test_doctest.py | 2 +- testing/test_mark_expression.py | 2 +- testing/test_tmpdir.py | 2 +- 31 files changed, 32 insertions(+), 35 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0541da9906e..6856e652829 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -229,7 +229,6 @@ disable = [ "deprecated-argument", "deprecated-attribute", "deprecated-class", - "deprecated-typing-alias", "disallowed-name", # foo / bar are used often in tests "duplicate-code", "else-if-used", # not activated by default, PLR5501 disabled in ruff diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index ea7415be23e..14ac545490f 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -2,6 +2,7 @@ from __future__ import annotations import ast +from collections.abc import Callable from collections.abc import Iterable from collections.abc import Mapping from collections.abc import Sequence @@ -21,7 +22,6 @@ from types import FrameType from types import TracebackType from typing import Any -from typing import Callable from typing import ClassVar from typing import Final from typing import final diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index d212b773166..ca780c41344 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -16,13 +16,13 @@ from __future__ import annotations import collections as _collections +from collections.abc import Callable from collections.abc import Iterator import dataclasses as _dataclasses from io import StringIO as _StringIO import re import types as _types from typing import Any -from typing import Callable from typing import IO diff --git a/src/_pytest/_py/error.py b/src/_pytest/_py/error.py index ab3a4ed318e..3a63304008a 100644 --- a/src/_pytest/_py/error.py +++ b/src/_pytest/_py/error.py @@ -2,10 +2,10 @@ from __future__ import annotations +from collections.abc import Callable import errno import os import sys -from typing import Callable from typing import TYPE_CHECKING from typing import TypeVar diff --git a/src/_pytest/_py/path.py b/src/_pytest/_py/path.py index c7ab1182f4a..e353c1a9b52 100644 --- a/src/_pytest/_py/path.py +++ b/src/_pytest/_py/path.py @@ -4,6 +4,7 @@ from __future__ import annotations import atexit +from collections.abc import Callable from contextlib import contextmanager import fnmatch import importlib.util @@ -23,7 +24,6 @@ from stat import S_ISREG import sys from typing import Any -from typing import Callable from typing import cast from typing import Literal from typing import overload diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 05934797a14..93a08a4e69f 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -4,6 +4,7 @@ import ast from collections import defaultdict +from collections.abc import Callable from collections.abc import Iterable from collections.abc import Iterator from collections.abc import Sequence @@ -22,7 +23,6 @@ import sys import tokenize import types -from typing import Callable from typing import IO from typing import TYPE_CHECKING diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 3593f0ce036..49e977171b9 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -4,6 +4,7 @@ from __future__ import annotations import collections.abc +from collections.abc import Callable from collections.abc import Iterable from collections.abc import Mapping from collections.abc import Sequence @@ -11,7 +12,6 @@ import pprint from typing import AbstractSet from typing import Any -from typing import Callable from typing import Literal from typing import Protocol from unicodedata import normalize diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 82aea5e635e..2f7413d466a 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -3,6 +3,7 @@ from __future__ import annotations +from collections.abc import Callable import dataclasses import enum import functools @@ -13,7 +14,6 @@ from pathlib import Path import sys from typing import Any -from typing import Callable from typing import Final from typing import NoReturn diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 5ec4d7b52ea..fb012d081e1 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -5,6 +5,7 @@ import argparse import collections.abc +from collections.abc import Callable from collections.abc import Generator from collections.abc import Iterable from collections.abc import Iterator @@ -26,7 +27,6 @@ import types from types import FunctionType from typing import Any -from typing import Callable from typing import cast from typing import Final from typing import final diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 455d2d8db26..5a4e2e7993e 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -2,13 +2,13 @@ from __future__ import annotations import argparse +from collections.abc import Callable from collections.abc import Mapping from collections.abc import Sequence from gettext import gettext import os import sys from typing import Any -from typing import Callable from typing import cast from typing import final from typing import Literal diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 665d8536262..a9886c29d3c 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -5,12 +5,12 @@ from __future__ import annotations import argparse +from collections.abc import Callable from collections.abc import Generator import functools import sys import types from typing import Any -from typing import Callable import unittest from _pytest import outcomes diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index a1f680570d8..94868d06106 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -4,6 +4,7 @@ from __future__ import annotations import bdb +from collections.abc import Callable from collections.abc import Generator from collections.abc import Iterable from collections.abc import Sequence @@ -18,7 +19,6 @@ import traceback import types from typing import Any -from typing import Callable from typing import TYPE_CHECKING import warnings diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index c4a8a09f84a..80c4ec962b8 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -5,6 +5,7 @@ from collections import defaultdict from collections import deque from collections import OrderedDict +from collections.abc import Callable from collections.abc import Generator from collections.abc import Iterable from collections.abc import Iterator @@ -20,7 +21,6 @@ import types from typing import AbstractSet from typing import Any -from typing import Callable from typing import cast from typing import Final from typing import final @@ -89,7 +89,7 @@ FixtureFunction = TypeVar("FixtureFunction", bound=Callable[..., object]) # The type of a fixture function (type alias generic in fixture value). _FixtureFunc = Union[ - Callable[..., FixtureValue], Callable[..., Generator[FixtureValue, None, None]] + Callable[..., FixtureValue], Callable[..., Generator[FixtureValue]] ] # The type of FixtureDef.cached_result (type alias generic in fixture value). _FixtureCachedResult = Union[ @@ -891,9 +891,7 @@ def call_fixture_func( fixturefunc: _FixtureFunc[FixtureValue], request: FixtureRequest, kwargs ) -> FixtureValue: if inspect.isgeneratorfunction(fixturefunc): - fixturefunc = cast( - Callable[..., Generator[FixtureValue, None, None]], fixturefunc - ) + fixturefunc = cast(Callable[..., Generator[FixtureValue]], fixturefunc) generator = fixturefunc(**kwargs) try: fixture_result = next(generator) diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 46c456a5b6e..af072f0d1a4 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -10,6 +10,7 @@ from __future__ import annotations +from collections.abc import Callable from datetime import datetime from datetime import timezone import functools @@ -17,7 +18,6 @@ import platform import re from re import Match -from typing import Callable import xml.etree.ElementTree as ET from _pytest import nodes diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 1e18a60141d..ebd94c84c76 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -3,6 +3,7 @@ from __future__ import annotations import argparse +from collections.abc import Callable from collections.abc import Iterable from collections.abc import Iterator from collections.abc import Sequence @@ -15,7 +16,6 @@ from pathlib import Path import sys from typing import AbstractSet -from typing import Callable from typing import final from typing import Literal from typing import overload diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 09ef7d02cef..d1e0a49b62d 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -2,6 +2,7 @@ from __future__ import annotations import collections.abc +from collections.abc import Callable from collections.abc import Collection from collections.abc import Iterable from collections.abc import Iterator @@ -11,7 +12,6 @@ import dataclasses import inspect from typing import Any -from typing import Callable from typing import final from typing import NamedTuple from typing import overload diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index e84fb37c9d0..5b50fbc92cb 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -2,6 +2,7 @@ from __future__ import annotations import abc +from collections.abc import Callable from collections.abc import Iterable from collections.abc import Iterator from collections.abc import MutableMapping @@ -11,7 +12,6 @@ import pathlib from pathlib import Path from typing import Any -from typing import Callable from typing import cast from typing import NoReturn from typing import overload diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index ab39bac61b9..d792382a9c1 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -3,9 +3,9 @@ from __future__ import annotations +from collections.abc import Callable import sys from typing import Any -from typing import Callable from typing import cast from typing import NoReturn from typing import Protocol diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index f6392561951..55b27985d31 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -1,6 +1,7 @@ from __future__ import annotations import atexit +from collections.abc import Callable from collections.abc import Iterable from collections.abc import Iterator import contextlib @@ -28,7 +29,6 @@ import types from types import ModuleType from typing import Any -from typing import Callable from typing import TypeVar import uuid import warnings diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index d19151391b0..056be52a4ed 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -7,6 +7,7 @@ from __future__ import annotations import collections.abc +from collections.abc import Callable from collections.abc import Generator from collections.abc import Iterable from collections.abc import Sequence @@ -25,7 +26,6 @@ import sys import traceback from typing import Any -from typing import Callable from typing import Final from typing import final from typing import IO diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 153fbf8893b..3a42b43d0a1 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -6,6 +6,7 @@ import abc from collections import Counter from collections import defaultdict +from collections.abc import Callable from collections.abc import Generator from collections.abc import Iterable from collections.abc import Iterator @@ -22,7 +23,6 @@ from re import Pattern import types from typing import Any -from typing import Callable from typing import final from typing import Literal from typing import TYPE_CHECKING diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 30a630c42ff..aae0bd50ce0 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Callable from collections.abc import Collection from collections.abc import Mapping from collections.abc import Sequence @@ -13,7 +14,6 @@ from re import Pattern from types import TracebackType from typing import Any -from typing import Callable from typing import cast from typing import ContextManager from typing import final diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index fc26fcc78e4..b168bbe746d 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -3,6 +3,7 @@ from __future__ import annotations +from collections.abc import Callable from collections.abc import Generator from collections.abc import Iterator from pprint import pformat @@ -10,7 +11,6 @@ from re import Pattern from types import TracebackType from typing import Any -from typing import Callable from typing import final from typing import overload from typing import TYPE_CHECKING diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 0b60301bf5f..5189efce538 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -4,11 +4,11 @@ from __future__ import annotations import bdb +from collections.abc import Callable import dataclasses import os import sys import types -from typing import Callable from typing import cast from typing import final from typing import Generic diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index d2baee40d9c..a74f73bff17 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -8,6 +8,7 @@ import argparse from collections import Counter +from collections.abc import Callable from collections.abc import Generator from collections.abc import Mapping from collections.abc import Sequence @@ -20,7 +21,6 @@ import sys import textwrap from typing import Any -from typing import Callable from typing import ClassVar from typing import final from typing import Literal diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index 49560bf7d7f..4a76a9d9000 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -1,11 +1,11 @@ from __future__ import annotations +from collections.abc import Callable from collections.abc import Generator import threading import traceback from types import TracebackType from typing import Any -from typing import Callable from typing import TYPE_CHECKING import warnings diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 6d967b972ee..04d50b53090 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -3,6 +3,7 @@ from __future__ import annotations +from collections.abc import Callable from collections.abc import Generator from collections.abc import Iterable import inspect @@ -10,7 +11,6 @@ import traceback import types from typing import Any -from typing import Callable from typing import TYPE_CHECKING from typing import Union diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index 9ef583137e1..5796b37715d 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -1,11 +1,11 @@ from __future__ import annotations +from collections.abc import Callable from collections.abc import Generator import sys import traceback from types import TracebackType from typing import Any -from typing import Callable from typing import TYPE_CHECKING import warnings diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 4aa4876c711..d3ad09da871 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1,11 +1,11 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Callable import inspect from pathlib import Path import sys import textwrap -from typing import Callable from _pytest.doctest import _get_checker from _pytest.doctest import _is_main_py diff --git a/testing/test_mark_expression.py b/testing/test_mark_expression.py index a61a9f21560..884c4b5af88 100644 --- a/testing/test_mark_expression.py +++ b/testing/test_mark_expression.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Callable +from collections.abc import Callable from typing import cast from _pytest.mark import MarkMatcher diff --git a/testing/test_tmpdir.py b/testing/test_tmpdir.py index 865d8e0b05c..016588a143d 100644 --- a/testing/test_tmpdir.py +++ b/testing/test_tmpdir.py @@ -1,12 +1,12 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Callable import dataclasses import os from pathlib import Path import stat import sys -from typing import Callable from typing import cast import warnings From f57b26b76c064535f54f5d9cd612ae888254be8f Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 10 Oct 2024 18:22:48 +0200 Subject: [PATCH 0996/1271] Remove code that is impossible to reach on python 3.9+ --- src/_pytest/config/argparsing.py | 40 -------------------------------- testing/test_assertrewrite.py | 4 ---- 2 files changed, 44 deletions(-) diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 5a4e2e7993e..d535fe1096a 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -5,9 +5,7 @@ from collections.abc import Callable from collections.abc import Mapping from collections.abc import Sequence -from gettext import gettext import os -import sys from typing import Any from typing import cast from typing import final @@ -446,44 +444,6 @@ def parse_args( # type: ignore getattr(parsed, FILE_OR_DIR).extend(unrecognized) return parsed - if sys.version_info < (3, 9): # pragma: no cover - # Backport of https://github.com/python/cpython/pull/14316 so we can - # disable long --argument abbreviations without breaking short flags. - def _parse_optional( - self, arg_string: str - ) -> tuple[argparse.Action | None, str, str | None] | None: - if not arg_string: - return None - if arg_string[0] not in self.prefix_chars: - return None - if arg_string in self._option_string_actions: - action = self._option_string_actions[arg_string] - return action, arg_string, None - if len(arg_string) == 1: - return None - if "=" in arg_string: - option_string, explicit_arg = arg_string.split("=", 1) - if option_string in self._option_string_actions: - action = self._option_string_actions[option_string] - return action, option_string, explicit_arg - if self.allow_abbrev or not arg_string.startswith("--"): - option_tuples = self._get_option_tuples(arg_string) - if len(option_tuples) > 1: - msg = gettext( - "ambiguous option: %(option)s could match %(matches)s" - ) - options = ", ".join(option for _, option, _ in option_tuples) - self.error(msg % {"option": arg_string, "matches": options}) - elif len(option_tuples) == 1: - (option_tuple,) = option_tuples - return option_tuple - if self._negative_number_matcher.match(arg_string): - if not self._has_negative_number_optionals: - return None - if " " in arg_string: - return None - return None, arg_string, None - class DropShorterLongHelpFormatter(argparse.HelpFormatter): """Shorten help for long options that differ only in extra hyphens. diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 2a988149daf..eed59a2dce7 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1018,10 +1018,6 @@ def test_zipfile(self, pytester: Pytester) -> None: ) assert pytester.runpytest().ret == ExitCode.NO_TESTS_COLLECTED - @pytest.mark.skipif( - sys.version_info < (3, 9), - reason="importlib.resources.files was introduced in 3.9", - ) def test_load_resource_via_files_with_rewrite(self, pytester: Pytester) -> None: example = pytester.path.joinpath("demo") / "example" init = pytester.path.joinpath("demo") / "__init__.py" From 66fc31f05f02914c190fd9120653143f0bcb5105 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Nov 2024 22:03:44 +0100 Subject: [PATCH 0997/1271] Fix 'typing.AbstractSet' is deprecated, use 'collections.abc.Set' --- src/_pytest/assertion/util.py | 2 +- src/_pytest/fixtures.py | 2 +- src/_pytest/logging.py | 2 +- src/_pytest/main.py | 2 +- src/_pytest/mark/__init__.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 49e977171b9..0db846ce204 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -8,9 +8,9 @@ from collections.abc import Iterable from collections.abc import Mapping from collections.abc import Sequence +from collections.abc import Set as AbstractSet import os import pprint -from typing import AbstractSet from typing import Any from typing import Literal from typing import Protocol diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 80c4ec962b8..01707418755 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -12,6 +12,7 @@ from collections.abc import Mapping from collections.abc import MutableMapping from collections.abc import Sequence +from collections.abc import Set as AbstractSet import dataclasses import functools import inspect @@ -19,7 +20,6 @@ from pathlib import Path import sys import types -from typing import AbstractSet from typing import Any from typing import cast from typing import Final diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index 00645dae2da..ca5fbda6fcc 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -5,6 +5,7 @@ from collections.abc import Generator from collections.abc import Mapping +from collections.abc import Set as AbstractSet from contextlib import contextmanager from contextlib import nullcontext from datetime import datetime @@ -18,7 +19,6 @@ from pathlib import Path import re from types import TracebackType -from typing import AbstractSet from typing import final from typing import Generic from typing import Literal diff --git a/src/_pytest/main.py b/src/_pytest/main.py index ebd94c84c76..d7086537f39 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -7,6 +7,7 @@ from collections.abc import Iterable from collections.abc import Iterator from collections.abc import Sequence +from collections.abc import Set as AbstractSet import dataclasses import fnmatch import functools @@ -15,7 +16,6 @@ import os from pathlib import Path import sys -from typing import AbstractSet from typing import final from typing import Literal from typing import overload diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index c8c51d19aa0..efb966c09aa 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -5,8 +5,8 @@ import collections from collections.abc import Collection from collections.abc import Iterable +from collections.abc import Set as AbstractSet import dataclasses -from typing import AbstractSet from typing import Optional from typing import TYPE_CHECKING From e684e64dd04967c94d34b7cab651640512b67fa6 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Nov 2024 22:04:32 +0100 Subject: [PATCH 0998/1271] Fix 'typing.Type' is deprecated, use 'type' instead --- src/_pytest/config/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index fb012d081e1..6160f780b1b 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -32,7 +32,6 @@ from typing import final from typing import IO from typing import TextIO -from typing import Type from typing import TYPE_CHECKING import warnings From a6ef97b65bea694f179ed026e988cf7535ba8d2e Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Sun, 10 Nov 2024 22:05:05 +0100 Subject: [PATCH 0999/1271] Fix 'typing.ContextManager' is deprecated, use 'contextlib.AbstractContextManager' --- src/_pytest/python_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index aae0bd50ce0..fb00f1dd749 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -6,6 +6,7 @@ from collections.abc import Mapping from collections.abc import Sequence from collections.abc import Sized +from contextlib import AbstractContextManager from decimal import Decimal import math from numbers import Complex @@ -15,7 +16,6 @@ from types import TracebackType from typing import Any from typing import cast -from typing import ContextManager from typing import final from typing import overload from typing import TYPE_CHECKING @@ -978,7 +978,7 @@ def raises( @final -class RaisesContext(ContextManager[_pytest._code.ExceptionInfo[E]]): +class RaisesContext(AbstractContextManager[_pytest._code.ExceptionInfo[E]]): def __init__( self, expected_exception: type[E] | tuple[type[E], ...], From 1bacc000779e46e55925533eeb97465e8c857254 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 20 Nov 2024 22:24:45 +0100 Subject: [PATCH 1000/1271] [typing] Use the re namespace in 're' typing everywhere --- src/_pytest/_code/code.py | 9 ++++----- src/_pytest/doctest.py | 5 ++--- src/_pytest/junitxml.py | 3 +-- src/_pytest/python.py | 4 ++-- src/_pytest/python_api.py | 7 +++---- src/_pytest/recwarn.py | 11 ++++++----- 6 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 14ac545490f..b98ce013b6e 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -14,7 +14,6 @@ import os from pathlib import Path import re -from re import Pattern import sys import traceback from traceback import format_exception_only @@ -722,7 +721,7 @@ def _stringify_exception(self, exc: BaseException) -> str: ] ) - def match(self, regexp: str | Pattern[str]) -> Literal[True]: + def match(self, regexp: str | re.Pattern[str]) -> Literal[True]: """Check whether the regular expression `regexp` matches the string representation of the exception using :func:`python:re.search`. @@ -741,7 +740,7 @@ def _group_contains( self, exc_group: BaseExceptionGroup[BaseException], expected_exception: EXCEPTION_OR_MORE, - match: str | Pattern[str] | None, + match: str | re.Pattern[str] | None, target_depth: int | None = None, current_depth: int = 1, ) -> bool: @@ -771,7 +770,7 @@ def group_contains( self, expected_exception: EXCEPTION_OR_MORE, *, - match: str | Pattern[str] | None = None, + match: str | re.Pattern[str] | None = None, depth: int | None = None, ) -> bool: """Check whether a captured exception group contains a matching exception. @@ -780,7 +779,7 @@ def group_contains( The expected exception type, or a tuple if one of multiple possible exception types are expected. - :param str | Pattern[str] | None match: + :param str | re.Pattern[str] | None match: If specified, a string containing a regular expression, or a regular expression object, that is tested against the string representation of the exception and its `PEP-678 ` `__notes__` diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 94868d06106..598df84d70e 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -14,7 +14,7 @@ import os from pathlib import Path import platform -from re import Pattern +import re import sys import traceback import types @@ -593,7 +593,6 @@ def _from_module(self, module, object): def _init_checker_class() -> type[doctest.OutputChecker]: import doctest - import re class LiteralsOutputChecker(doctest.OutputChecker): # Based on doctest_nose_plugin.py from the nltk project @@ -636,7 +635,7 @@ def check_output(self, want: str, got: str, optionflags: int) -> bool: if not allow_unicode and not allow_bytes and not allow_number: return False - def remove_prefixes(regex: Pattern[str], txt: str) -> str: + def remove_prefixes(regex: re.Pattern[str], txt: str) -> str: return re.sub(regex, r"\1\2", txt) if allow_unicode: diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index af072f0d1a4..d129cd295e7 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -17,7 +17,6 @@ import os import platform import re -from re import Match import xml.etree.ElementTree as ET from _pytest import nodes @@ -48,7 +47,7 @@ def bin_xml_escape(arg: object) -> str: The idea is to escape visually for the user rather than for XML itself. """ - def repl(matchobj: Match[str]) -> str: + def repl(matchobj: re.Match[str]) -> str: i = ord(matchobj.group()) if i <= 0xFF: return f"#x{i:02X}" diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 3a42b43d0a1..f75bb5b432e 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -20,7 +20,7 @@ import itertools import os from pathlib import Path -from re import Pattern +import re import types from typing import Any from typing import final @@ -973,7 +973,7 @@ def _idval_from_value(self, val: object) -> str | None: return _ascii_escaped_by_config(val, self.config) elif val is None or isinstance(val, (float, int, bool, complex)): return str(val) - elif isinstance(val, Pattern): + elif isinstance(val, re.Pattern): return ascii_escaped(val.pattern) elif val is NOTSET: # Fallback to default. Note that NOTSET is an enum.Enum. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index fb00f1dd749..af13c3dc981 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -12,7 +12,6 @@ from numbers import Complex import pprint import re -from re import Pattern from types import TracebackType from typing import Any from typing import cast @@ -780,7 +779,7 @@ def _as_numpy_array(obj: object) -> ndarray | None: def raises( expected_exception: type[E] | tuple[type[E], ...], *, - match: str | Pattern[str] | None = ..., + match: str | re.Pattern[str] | None = ..., ) -> RaisesContext[E]: ... @@ -955,7 +954,7 @@ def raises( message = f"DID NOT RAISE {expected_exception}" if not args: - match: str | Pattern[str] | None = kwargs.pop("match", None) + match: str | re.Pattern[str] | None = kwargs.pop("match", None) if kwargs: msg = "Unexpected keyword arguments passed to pytest.raises: " msg += ", ".join(sorted(kwargs)) @@ -983,7 +982,7 @@ def __init__( self, expected_exception: type[E] | tuple[type[E], ...], message: str, - match_expr: str | Pattern[str] | None = None, + match_expr: str | re.Pattern[str] | None = None, ) -> None: self.expected_exception = expected_exception self.message = message diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index b168bbe746d..440e3efac8a 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -8,7 +8,6 @@ from collections.abc import Iterator from pprint import pformat import re -from re import Pattern from types import TracebackType from typing import Any from typing import final @@ -44,7 +43,9 @@ def recwarn() -> Generator[WarningsRecorder]: @overload -def deprecated_call(*, match: str | Pattern[str] | None = ...) -> WarningsRecorder: ... +def deprecated_call( + *, match: str | re.Pattern[str] | None = ... +) -> WarningsRecorder: ... @overload @@ -89,7 +90,7 @@ def deprecated_call( def warns( expected_warning: type[Warning] | tuple[type[Warning], ...] = ..., *, - match: str | Pattern[str] | None = ..., + match: str | re.Pattern[str] | None = ..., ) -> WarningsChecker: ... @@ -105,7 +106,7 @@ def warns( def warns( expected_warning: type[Warning] | tuple[type[Warning], ...] = Warning, *args: Any, - match: str | Pattern[str] | None = None, + match: str | re.Pattern[str] | None = None, **kwargs: Any, ) -> WarningsChecker | Any: r"""Assert that code raises a particular class of warning. @@ -258,7 +259,7 @@ class WarningsChecker(WarningsRecorder): def __init__( self, expected_warning: type[Warning] | tuple[type[Warning], ...] = Warning, - match_expr: str | Pattern[str] | None = None, + match_expr: str | re.Pattern[str] | None = None, *, _ispytest: bool = False, ) -> None: From 58e25811b6d8a481c15004c2f0c097db6b24d5ad Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 20 Nov 2024 22:29:13 +0100 Subject: [PATCH 1001/1271] [black] Fix the target-version configuration --- pyproject.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 6856e652829..c13da163259 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,9 +83,8 @@ scripts.pytest = "pytest:console_main" write_to = "src/_pytest/_version.py" [tool.black] -target-version = [ - 'py39', -] +# See https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#t-target-version +target-version = [ "py39", "py310", "py311", "py312", "py313" ] [tool.ruff] line-length = 88 From 10c0c6271604e339042bbf5dd4f271fe6bfd0f5b Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 28 Nov 2024 21:12:53 +0100 Subject: [PATCH 1002/1271] [ruff] Set the target version to python 3.9 --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index c13da163259..dce6a0870e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,6 +87,7 @@ write_to = "src/_pytest/_version.py" target-version = [ "py39", "py310", "py311", "py312", "py313" ] [tool.ruff] +target-version = "py39" line-length = 88 src = [ "src", From a16e8eac8c91b8d0f91c461a4de39adbf8a75b0f Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Fri, 29 Nov 2024 18:30:48 +0100 Subject: [PATCH 1003/1271] approx: use exact comparison for bool Fixes #9353 --- changelog/9353.bugfix.rst | 1 + src/_pytest/python_api.py | 44 +++++++++++++++++++++++---------------- testing/python/approx.py | 23 +++++++++++++++++++- 3 files changed, 49 insertions(+), 19 deletions(-) create mode 100644 changelog/9353.bugfix.rst diff --git a/changelog/9353.bugfix.rst b/changelog/9353.bugfix.rst new file mode 100644 index 00000000000..414f5a007b6 --- /dev/null +++ b/changelog/9353.bugfix.rst @@ -0,0 +1 @@ +:func:`pytest.approx` now uses strict equality when given booleans. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index af13c3dc981..4563b997246 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -259,19 +259,22 @@ def _repr_compare(self, other_side: Mapping[object, float]) -> list[str]: ): if approx_value != other_value: if approx_value.expected is not None and other_value is not None: - max_abs_diff = max( - max_abs_diff, abs(approx_value.expected - other_value) - ) - if approx_value.expected == 0.0: - max_rel_diff = math.inf - else: - max_rel_diff = max( - max_rel_diff, - abs( - (approx_value.expected - other_value) - / approx_value.expected - ), + try: + max_abs_diff = max( + max_abs_diff, abs(approx_value.expected - other_value) ) + if approx_value.expected == 0.0: + max_rel_diff = math.inf + else: + max_rel_diff = max( + max_rel_diff, + abs( + (approx_value.expected - other_value) + / approx_value.expected + ), + ) + except ZeroDivisionError: + pass different_ids.append(approx_key) message_data = [ @@ -395,8 +398,10 @@ def __repr__(self) -> str: # Don't show a tolerance for values that aren't compared using # tolerances, i.e. non-numerics and infinities. Need to call abs to # handle complex numbers, e.g. (inf + 1j). - if (not isinstance(self.expected, (Complex, Decimal))) or math.isinf( - abs(self.expected) + if ( + isinstance(self.expected, bool) + or (not isinstance(self.expected, (Complex, Decimal))) + or math.isinf(abs(self.expected) or isinstance(self.expected, bool)) ): return str(self.expected) @@ -428,14 +433,17 @@ def __eq__(self, actual) -> bool: # numpy<1.13. See #3748. return all(self.__eq__(a) for a in asarray.flat) - # Short-circuit exact equality. - if actual == self.expected: + # Short-circuit exact equality, except for bool + if isinstance(self.expected, bool) and not isinstance(actual, bool): + return False + elif actual == self.expected: return True # If either type is non-numeric, fall back to strict equality. # NB: we need Complex, rather than just Number, to ensure that __abs__, - # __sub__, and __float__ are defined. - if not ( + # __sub__, and __float__ are defined. Also, consider bool to be + # nonnumeric, even though it has the required arithmetic. + if isinstance(self.expected, bool) or not ( isinstance(self.expected, (Complex, Decimal)) and isinstance(actual, (Complex, Decimal)) ): diff --git a/testing/python/approx.py b/testing/python/approx.py index 21932059cc6..6de66d4f35e 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -90,13 +90,26 @@ def do_assert(lhs, rhs, expected_message, verbosity_level=0): return do_assert -SOME_FLOAT = r"[+-]?([0-9]*[.])?[0-9]+\s*" +SOME_FLOAT = r"[+-]?((?:([0-9]*[.])?[0-9]+(e-?[0-9]+)?)|inf|nan)\s*" SOME_INT = r"[0-9]+\s*" SOME_TOLERANCE = rf"({SOME_FLOAT}|[+-]?[0-9]+(\.[0-9]+)?[eE][+-]?[0-9]+\s*)" class TestApprox: def test_error_messages_native_dtypes(self, assert_approx_raises_regex): + # Treat bool exactly. + assert_approx_raises_regex( + {"a": 1.0, "b": True}, + {"a": 1.0, "b": False}, + [ + "", + " comparison failed. Mismatched elements: 1 / 2:", + f" Max absolute difference: {SOME_FLOAT}", + f" Max relative difference: {SOME_FLOAT}", + r" Index\s+\| Obtained\s+\| Expected", + r".*(True|False)\s+", + ], + ) assert_approx_raises_regex( 2.0, 1.0, @@ -596,6 +609,13 @@ def test_complex(self): assert approx(x, rel=5e-6, abs=0) == a assert approx(x, rel=5e-7, abs=0) != a + def test_expecting_bool(self) -> None: + assert True == approx(True) # noqa: E712 + assert False == approx(False) # noqa: E712 + assert True != approx(False) # noqa: E712 + assert True != approx(False, abs=2) # noqa: E712 + assert 1 != approx(True) + def test_list(self): actual = [1 + 1e-7, 2 + 1e-8] expected = [1, 2] @@ -661,6 +681,7 @@ def test_dict_wrong_len(self): def test_dict_nonnumeric(self): assert {"a": 1.0, "b": None} == pytest.approx({"a": 1.0, "b": None}) assert {"a": 1.0, "b": 1} != pytest.approx({"a": 1.0, "b": None}) + assert {"a": 1.0, "b": True} != pytest.approx({"a": 1.0, "b": False}, abs=2) def test_dict_vs_other(self): assert 1 != approx({"a": 0}) From d65d99177628b87a46cec85e5d83ae0ea9cbdb2a Mon Sep 17 00:00:00 2001 From: Marcelo Duarte Trevisani Date: Sat, 30 Nov 2024 12:31:52 +0000 Subject: [PATCH 1004/1271] approx: do not raise error in mixed sequence/collections Previously `approx` would show an internal error when passed a collection with numbers and non-numbers mixed: ``` E (pytest_assertion plugin: representation of details failed: /tmp/test_a/.venv/lib/python3.12/site-packages/_pytest/python_api.py:343: TypeError: unsupported operand type(s) for -: 'str' and 'str'. E Probably an object has a faulty __repr__.) ``` The problem was that it was unconditionally computing the diff for every element. This change introduces a try/except catch around the code related to computing the diff, and ignores it instead of letting the error be raised. Fixes #13010 Co-authored-by: Bruno Oliveira --- changelog/13010.improvement.rst | 1 + src/_pytest/python_api.py | 16 ++++++++++------ testing/python/approx.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) create mode 100644 changelog/13010.improvement.rst diff --git a/changelog/13010.improvement.rst b/changelog/13010.improvement.rst new file mode 100644 index 00000000000..d6b814f090e --- /dev/null +++ b/changelog/13010.improvement.rst @@ -0,0 +1 @@ +:func:`pytest.approx` now can compare collections that contain numbers and non-numbers mixed. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 4563b997246..cbb2ff2b80a 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -340,14 +340,18 @@ def _repr_compare(self, other_side: Sequence[float]) -> list[str]: zip(approx_side_as_map, other_side) ): if approx_value != other_value: - abs_diff = abs(approx_value.expected - other_value) - max_abs_diff = max(max_abs_diff, abs_diff) - if other_value == 0.0: - max_rel_diff = math.inf + try: + abs_diff = abs(approx_value.expected - other_value) + max_abs_diff = max(max_abs_diff, abs_diff) + # Ignore non-numbers for the diff calculations (#13012). + except TypeError: + pass else: - max_rel_diff = max(max_rel_diff, abs_diff / abs(other_value)) + if other_value == 0.0: + max_rel_diff = math.inf + else: + max_rel_diff = max(max_rel_diff, abs_diff / abs(other_value)) different_ids.append(i) - message_data = [ (str(i), str(other_side[i]), str(approx_side_as_map[i])) for i in different_ids diff --git a/testing/python/approx.py b/testing/python/approx.py index 6de66d4f35e..7eba4755c01 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -390,6 +390,37 @@ def test_bool(self): assert err.match(r"approx\(\) is not supported in a boolean context") + def test_mixed_sequence(self, assert_approx_raises_regex) -> None: + """Approx should work on sequences that also contain non-numbers (#13010).""" + assert_approx_raises_regex( + [1.1, 2, "word"], + [1.0, 2, "different"], + [ + "", + r" comparison failed. Mismatched elements: 2 / 3:", + rf" Max absolute difference: {SOME_FLOAT}", + rf" Max relative difference: {SOME_FLOAT}", + r" Index \| Obtained\s+\| Expected\s+", + r"\s*0\s*\|\s*1\.1\s*\|\s*1\.0\s*±\s*1\.0e\-06\s*", + r"\s*2\s*\|\s*word\s*\|\s*different\s*", + ], + verbosity_level=2, + ) + assert_approx_raises_regex( + [1.1, 2, "word"], + [1.0, 2, "word"], + [ + "", + r" comparison failed. Mismatched elements: 1 / 3:", + rf" Max absolute difference: {SOME_FLOAT}", + rf" Max relative difference: {SOME_FLOAT}", + r" Index \| Obtained\s+\| Expected\s+", + r"\s*0\s*\|\s*1\.1\s*\|\s*1\.0\s*±\s*1\.0e\-06\s*", + ], + verbosity_level=2, + ) + assert [1.1, 2, "word"] == pytest.approx([1.1, 2, "word"]) + def test_operator_overloading(self): assert 1 == approx(1, rel=1e-6, abs=1e-12) assert not (1 != approx(1, rel=1e-6, abs=1e-12)) From 10bcc70ad6f5eff8af023d662682e643f0dda4aa Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 29 Nov 2024 19:59:40 +0100 Subject: [PATCH 1005/1271] [pre-commit] Upgrade ruff to 0.8.1 --- .pre-commit-config.yaml | 2 +- pyproject.toml | 2 ++ src/_pytest/_code/__init__.py | 8 ++--- src/_pytest/_code/code.py | 10 +++---- src/_pytest/assertion/rewrite.py | 4 +-- src/_pytest/capture.py | 4 +-- src/_pytest/fixtures.py | 2 +- src/_pytest/mark/expression.py | 10 +++---- src/_pytest/mark/structures.py | 8 ++--- src/_pytest/nodes.py | 10 +++---- src/_pytest/python.py | 8 ++--- src/_pytest/runner.py | 2 +- src/_pytest/skipping.py | 2 +- src/pytest/__init__.py | 50 ++++++++++++++++---------------- testing/_py/test_local.py | 4 +-- 15 files changed, 61 insertions(+), 65 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb02fd0f00f..8a5418350d7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.7.4" + rev: "v0.8.1" hooks: - id: ruff args: ["--fix"] diff --git a/pyproject.toml b/pyproject.toml index dce6a0870e1..b10c1289b80 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -156,8 +156,10 @@ lint.ignore = [ "PLW0120", # remove the else and dedent its contents "PLW0603", # Using the global statement "PLW2901", # for loop variable overwritten by assignment target + "PYI063", # ruff ignore "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + "UP031", ] lint.per-file-ignores."src/_pytest/_py/**/*.py" = [ "B", diff --git a/src/_pytest/_code/__init__.py b/src/_pytest/_code/__init__.py index 0bfde42604d..7f67a2e3e0a 100644 --- a/src/_pytest/_code/__init__.py +++ b/src/_pytest/_code/__init__.py @@ -16,11 +16,11 @@ __all__ = [ "Code", "ExceptionInfo", - "filter_traceback", "Frame", - "getfslineno", - "getrawcode", + "Source", "Traceback", "TracebackEntry", - "Source", + "filter_traceback", + "getfslineno", + "getrawcode", ] diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index b98ce013b6e..bb09c01c11d 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -953,7 +953,7 @@ def repr_traceback_entry( if short: message = f"in {entry.name}" else: - message = excinfo and excinfo.typename or "" + message = (excinfo and excinfo.typename) or "" entry_path = entry.path path = self._makepath(entry_path) reprfileloc = ReprFileLocation(path, entry.lineno + 1, message) @@ -1182,10 +1182,8 @@ def toterminal(self, tw: TerminalWriter) -> None: entry.toterminal(tw) if i < len(self.reprentries) - 1: next_entry = self.reprentries[i + 1] - if ( - entry.style == "long" - or entry.style == "short" - and next_entry.style == "long" + if entry.style == "long" or ( + entry.style == "short" and next_entry.style == "long" ): tw.sep(self.entrysep) @@ -1369,7 +1367,7 @@ def getfslineno(obj: object) -> tuple[str | Path, int]: except TypeError: return "", -1 - fspath = fn and absolutepath(fn) or "" + fspath = (fn and absolutepath(fn)) or "" lineno = -1 if fspath: try: diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 93a08a4e69f..c414b30a4a8 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -53,7 +53,7 @@ class Sentinel: # pytest caches rewritten pycs in pycache dirs PYTEST_TAG = f"{sys.implementation.cache_tag}-pytest-{version}" -PYC_EXT = ".py" + (__debug__ and "c" or "o") +PYC_EXT = ".py" + ((__debug__ and "c") or "o") PYC_TAIL = "." + PYTEST_TAG + PYC_EXT # Special marker that denotes we have just left a scope definition @@ -481,7 +481,7 @@ def _should_repr_global_name(obj: object) -> bool: def _format_boolop(explanations: Iterable[str], is_or: bool) -> str: - explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")" + explanation = "(" + ((is_or and " or ") or " and ").join(explanations) + ")" return explanation.replace("%", "%%") diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 93a3b04182e..de2ee9c8dbd 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -360,7 +360,7 @@ def repr(self, class_name: str) -> str: return "<{} {} _old={} _state={!r} tmpfile={!r}>".format( class_name, self.name, - hasattr(self, "_old") and repr(self._old) or "", + (hasattr(self, "_old") and repr(self._old)) or "", self._state, self.tmpfile, ) @@ -369,7 +369,7 @@ def __repr__(self) -> str: return "<{} {} _old={} _state={!r} tmpfile={!r}>".format( self.__class__.__name__, self.name, - hasattr(self, "_old") and repr(self._old) or "", + (hasattr(self, "_old") and repr(self._old)) or "", self._state, self.tmpfile, ) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 01707418755..95fa1336169 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -305,7 +305,7 @@ class FuncFixtureInfo: these are not reflected here. """ - __slots__ = ("argnames", "initialnames", "names_closure", "name2fixturedefs") + __slots__ = ("argnames", "initialnames", "name2fixturedefs", "names_closure") # Fixture names that the item requests directly by function parameters. argnames: tuple[str, ...] diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index d0ab190e3b6..b71ed29c62f 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -58,7 +58,7 @@ class TokenType(enum.Enum): @dataclasses.dataclass(frozen=True) class Token: - __slots__ = ("type", "value", "pos") + __slots__ = ("pos", "type", "value") type: TokenType value: str pos: int @@ -80,7 +80,7 @@ def __str__(self) -> str: class Scanner: - __slots__ = ("tokens", "current") + __slots__ = ("current", "tokens") def __init__(self, input: str) -> None: self.tokens = self.lex(input) @@ -238,10 +238,8 @@ def single_kwarg(s: Scanner) -> ast.keyword: value: str | int | bool | None = value_token.value[1:-1] # strip quotes else: value_token = s.accept(TokenType.IDENT, reject=True) - if ( - (number := value_token.value).isdigit() - or number.startswith("-") - and number[1:].isdigit() + if (number := value_token.value).isdigit() or ( + number.startswith("-") and number[1:].isdigit() ): value = int(number) elif value_token.value in BUILTIN_MATCHERS: diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index d1e0a49b62d..e7e32555ba4 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -562,7 +562,7 @@ def __getattr__(self, name: str) -> MarkDecorator: @final class NodeKeywords(MutableMapping[str, Any]): - __slots__ = ("node", "parent", "_markers") + __slots__ = ("_markers", "node", "parent") def __init__(self, node: Node) -> None: self.node = node @@ -584,10 +584,8 @@ def __setitem__(self, key: str, value: Any) -> None: # below and use the collections.abc fallback, but that would be slow. def __contains__(self, key: object) -> bool: - return ( - key in self._markers - or self.parent is not None - and key in self.parent.keywords + return key in self._markers or ( + self.parent is not None and key in self.parent.keywords ) def update( # type: ignore[override] diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 5b50fbc92cb..0d1f3d2352b 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -143,14 +143,14 @@ class Node(abc.ABC, metaclass=NodeMeta): # Use __slots__ to make attribute access faster. # Note that __dict__ is still available. __slots__ = ( + "__dict__", + "_nodeid", + "_store", + "config", "name", "parent", - "config", - "session", "path", - "_nodeid", - "_store", - "__dict__", + "session", ) def __init__( diff --git a/src/_pytest/python.py b/src/_pytest/python.py index f75bb5b432e..0b33133c1f2 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -431,7 +431,7 @@ def _genfunctions(self, name: str, funcobj) -> Iterator[Function]: assert modulecol is not None module = modulecol.obj clscol = self.getparent(Class) - cls = clscol and clscol.obj or None + cls = (clscol and clscol.obj) or None definition = FunctionDefinition.from_parent(self, name=name, callobj=funcobj) fixtureinfo = definition._fixtureinfo @@ -848,12 +848,12 @@ class IdMaker: __slots__ = ( "argnames", - "parametersets", + "config", + "func_name", "idfn", "ids", - "config", "nodeid", - "func_name", + "parametersets", ) # The argnames of the parametrization. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 5189efce538..d2b7fda8c2a 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -533,7 +533,7 @@ def teardown_exact(self, nextitem: Item | None) -> None: When nextitem is None (meaning we're at the last item), the entire stack is torn down. """ - needed_collectors = nextitem and nextitem.listchain() or [] + needed_collectors = (nextitem and nextitem.listchain()) or [] exceptions: list[BaseException] = [] while self.stack: if list(self.stack.keys()) == needed_collectors[: len(self.stack)]: diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 8fa17a01eb0..d21be181955 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -196,7 +196,7 @@ def evaluate_skip_marks(item: Item) -> Skip | None: class Xfail: """The result of evaluate_xfail_marks().""" - __slots__ = ("reason", "run", "strict", "raises") + __slots__ = ("raises", "reason", "run", "strict") reason: str run: bool diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 5ab2a22b0c0..f0c3516f4cc 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -88,41 +88,27 @@ __all__ = [ - "__version__", - "approx", "Cache", "CallInfo", "CaptureFixture", "Class", - "cmdline", - "Collector", "CollectReport", + "Collector", "Config", - "console_main", - "deprecated_call", "Dir", "Directory", "DoctestItem", - "exit", "ExceptionInfo", "ExitCode", - "fail", "File", - "fixture", "FixtureDef", "FixtureLookupError", "FixtureRequest", - "freeze_includes", "Function", - "hookimpl", "HookRecorder", - "hookspec", - "importorskip", "Item", "LineMatcher", "LogCaptureFixture", - "main", - "mark", "Mark", "MarkDecorator", "MarkGenerator", @@ -131,7 +117,6 @@ "MonkeyPatch", "OptionGroup", "Package", - "param", "Parser", "PytestAssertRewriteWarning", "PytestCacheWarning", @@ -139,31 +124,46 @@ "PytestConfigWarning", "PytestDeprecationWarning", "PytestExperimentalApiWarning", - "PytestRemovedIn9Warning", - "Pytester", "PytestPluginManager", + "PytestRemovedIn9Warning", "PytestUnhandledThreadExceptionWarning", "PytestUnknownMarkWarning", "PytestUnraisableExceptionWarning", "PytestWarning", - "raises", + "Pytester", "RecordedHookCall", - "register_assert_rewrite", "RunResult", "Session", - "set_trace", - "skip", "Stash", "StashKey", - "version_tuple", - "TempdirFactory", "TempPathFactory", + "TempdirFactory", "TerminalReporter", - "Testdir", "TestReport", "TestShortLogReport", + "Testdir", "UsageError", "WarningsRecorder", + "__version__", + "approx", + "cmdline", + "console_main", + "deprecated_call", + "exit", + "fail", + "fixture", + "freeze_includes", + "hookimpl", + "hookspec", + "importorskip", + "main", + "mark", + "param", + "raises", + "register_assert_rewrite", + "set_trace", + "skip", + "version_tuple", "warns", "xfail", "yield_fixture", diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 21fbfb3e3ad..b6d49c5425e 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -855,7 +855,7 @@ def test_fnmatch_file_abspath(self, tmpdir): assert b.fnmatch(pattern) def test_sysfind(self): - name = sys.platform == "win32" and "cmd" or "test" + name = (sys.platform == "win32" and "cmd") or "test" x = local.sysfind(name) assert x.check(file=1) assert local.sysfind("jaksdkasldqwe") is None @@ -1250,7 +1250,7 @@ def test_owner_group_not_implemented(self, path1): def test_chmod_simple_int(self, path1): mode = path1.stat().mode # Ensure that we actually change the mode to something different. - path1.chmod(mode == 0 and 1 or 0) + path1.chmod((mode == 0 and 1) or 0) try: print(path1.stat().mode) print(mode) From 049bb29d8a7fce42bcb4825c23bacffb56b68e55 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 28 Nov 2024 22:17:12 +0100 Subject: [PATCH 1006/1271] [Fix PYI063] Use PEP 570 syntax for positional-only parameters --- pyproject.toml | 1 - .../dataclasses/test_compare_dataclasses_with_custom_eq.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b10c1289b80..c5833f73851 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -156,7 +156,6 @@ lint.ignore = [ "PLW0120", # remove the else and dedent its contents "PLW0603", # Using the global statement "PLW2901", # for loop variable overwritten by assignment target - "PYI063", # ruff ignore "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` "UP031", diff --git a/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py b/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py index b787cb39ee2..e25bebf74dd 100644 --- a/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py +++ b/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py @@ -10,7 +10,7 @@ class SimpleDataObject: field_a: int = field() field_b: str = field() - def __eq__(self, __o: object) -> bool: + def __eq__(self, __o: object, /) -> bool: return super().__eq__(__o) left = SimpleDataObject(1, "b") From 17c5bbbdaee125f7d574ae390d4807724efa871a Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 29 Nov 2024 20:30:17 +0100 Subject: [PATCH 1007/1271] [Fix UP031] Manually, keeping some required %r specifiers Co-authored-by: Bruno Oliveira --- bench/empty.py | 2 +- pyproject.toml | 1 - src/_pytest/_code/code.py | 9 ++------ src/_pytest/_io/pprint.py | 2 +- src/_pytest/_py/error.py | 2 +- src/_pytest/assertion/util.py | 9 +++----- src/_pytest/cacheprovider.py | 6 ++--- src/_pytest/compat.py | 4 ++-- src/_pytest/doctest.py | 2 +- src/_pytest/fixtures.py | 2 +- src/_pytest/main.py | 18 +++++++-------- src/_pytest/mark/structures.py | 10 ++------- src/_pytest/pytester.py | 6 +++-- src/_pytest/terminal.py | 22 +++++++++---------- testing/_py/test_local.py | 4 ++-- ...test_compare_dataclasses_with_custom_eq.py | 4 ++-- testing/python/metafunc.py | 7 +++--- testing/test_assertion.py | 7 +++--- testing/test_conftest.py | 4 ++-- testing/test_doctest.py | 2 +- testing/test_terminal.py | 2 +- 21 files changed, 53 insertions(+), 72 deletions(-) diff --git a/bench/empty.py b/bench/empty.py index 35abeef4140..346b79d5e33 100644 --- a/bench/empty.py +++ b/bench/empty.py @@ -2,4 +2,4 @@ for i in range(1000): - exec("def test_func_%d(): pass" % i) + exec(f"def test_func_{i}(): pass") diff --git a/pyproject.toml b/pyproject.toml index c5833f73851..dce6a0870e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -158,7 +158,6 @@ lint.ignore = [ "PLW2901", # for loop variable overwritten by assignment target # ruff ignore "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - "UP031", ] lint.per-file-ignores."src/_pytest/_py/**/*.py" = [ "B", diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index bb09c01c11d..bba8896076e 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -217,7 +217,7 @@ def relline(self) -> int: return self.lineno - self.frame.code.firstlineno def __repr__(self) -> str: - return "" % (self.frame.code.path, self.lineno + 1) + return f"" @property def statement(self) -> Source: @@ -303,12 +303,7 @@ def __str__(self) -> str: # This output does not quite match Python's repr for traceback entries, # but changing it to do so would break certain plugins. See # https://github.com/pytest-dev/pytest/pull/7535/ for details. - return " File %r:%d in %s\n %s\n" % ( - str(self.path), - self.lineno + 1, - name, - line, - ) + return f" File '{self.path}':{self.lineno+1} in {name}\n {line}\n" @property def name(self) -> str: diff --git a/src/_pytest/_io/pprint.py b/src/_pytest/_io/pprint.py index ca780c41344..28f06909206 100644 --- a/src/_pytest/_io/pprint.py +++ b/src/_pytest/_io/pprint.py @@ -540,7 +540,7 @@ def _pprint_deque( ) -> None: stream.write(object.__class__.__name__ + "(") if object.maxlen is not None: - stream.write("maxlen=%d, " % object.maxlen) + stream.write(f"maxlen={object.maxlen}, ") stream.write("[") self._format_items(object, stream, indent, allowance + 1, context, level) diff --git a/src/_pytest/_py/error.py b/src/_pytest/_py/error.py index 3a63304008a..de0c04a4838 100644 --- a/src/_pytest/_py/error.py +++ b/src/_pytest/_py/error.py @@ -69,7 +69,7 @@ def _geterrnoclass(self, eno: int) -> type[Error]: try: return self._errno2class[eno] except KeyError: - clsname = errno.errorcode.get(eno, "UnknownErrno%d" % (eno,)) + clsname = errno.errorcode.get(eno, f"UnknownErrno{eno}") errorcls = type( clsname, (Error,), diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 0db846ce204..3fe7eb9d862 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -406,8 +406,7 @@ def _compare_eq_sequence( ] else: explanation += [ - "%s contains %d more items, first extra item: %s" - % (dir_with_more, len_diff, highlighter(extra)) + f"{dir_with_more} contains {len_diff} more items, first extra item: {highlighter(extra)}" ] return explanation @@ -510,8 +509,7 @@ def _compare_eq_dict( len_extra_left = len(extra_left) if len_extra_left: explanation.append( - "Left contains %d more item%s:" - % (len_extra_left, "" if len_extra_left == 1 else "s") + f"Left contains {len_extra_left} more item{'' if len_extra_left == 1 else 's'}:" ) explanation.extend( highlighter(pprint.pformat({k: left[k] for k in extra_left})).splitlines() @@ -520,8 +518,7 @@ def _compare_eq_dict( len_extra_right = len(extra_right) if len_extra_right: explanation.append( - "Right contains %d more item%s:" - % (len_extra_right, "" if len_extra_right == 1 else "s") + f"Right contains {len_extra_right} more item{'' if len_extra_right == 1 else 's'}:" ) explanation.extend( highlighter(pprint.pformat({k: right[k] for k in extra_right})).splitlines() diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index bf643d6f4dc..facb98f09e0 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -388,8 +388,8 @@ def pytest_collection_modifyitems( if not previously_failed: # Running a subset of all tests with recorded failures # only outside of it. - self._report_status = "%d known failures not in selected tests" % ( - len(self.lastfailed), + self._report_status = ( + f"{len(self.lastfailed)} known failures not in selected tests" ) else: if self.config.getoption("lf"): @@ -622,5 +622,5 @@ def cacheshow(config: Config, session: Session) -> int: # print("%s/" % p.relative_to(basedir)) if p.is_file(): key = str(p.relative_to(basedir)) - tw.line(f"{key} is a file of length {p.stat().st_size:d}") + tw.line(f"{key} is a file of length {p.stat().st_size}") return 0 diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 2f7413d466a..1aa7495bddb 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -71,8 +71,8 @@ def getlocation(function, curdir: str | os.PathLike[str] | None = None) -> str: except ValueError: pass else: - return "%s:%d" % (relfn, lineno + 1) - return "%s:%d" % (fn, lineno + 1) + return f"{relfn}:{lineno+1}" + return f"{fn}:{lineno+1}" def num_mock_patch_args(function) -> int: diff --git a/src/_pytest/doctest.py b/src/_pytest/doctest.py index 598df84d70e..0dbef6056d7 100644 --- a/src/_pytest/doctest.py +++ b/src/_pytest/doctest.py @@ -353,7 +353,7 @@ def repr_failure( # type: ignore[override] # add line numbers to the left of the error message assert test.lineno is not None lines = [ - "%03d %s" % (i + test.lineno + 1, x) for (i, x) in enumerate(lines) + f"{i + test.lineno + 1:03d} {x}" for (i, x) in enumerate(lines) ] # trim docstring error lines to 10 lines = lines[max(example.lineno - 9, 0) : example.lineno + 1] diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 95fa1336169..76c4b919aff 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -884,7 +884,7 @@ def toterminal(self, tw: TerminalWriter) -> None: red=True, ) tw.line() - tw.line("%s:%d" % (os.fspath(self.filename), self.firstlineno + 1)) + tw.line(f"{os.fspath(self.filename)}:{self.firstlineno + 1}") def call_fixture_func( diff --git a/src/_pytest/main.py b/src/_pytest/main.py index d7086537f39..c97f746e1d6 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -349,8 +349,7 @@ def pytest_collection(session: Session) -> None: def pytest_runtestloop(session: Session) -> bool: if session.testsfailed and not session.config.option.continue_on_collection_errors: raise session.Interrupted( - "%d error%s during collection" - % (session.testsfailed, "s" if session.testsfailed != 1 else "") + f"{session.testsfailed} error{'s' if session.testsfailed != 1 else ''} during collection" ) if session.config.option.collectonly: @@ -585,13 +584,12 @@ def from_config(cls, config: Config) -> Session: return session def __repr__(self) -> str: - return "<%s %s exitstatus=%r testsfailed=%d testscollected=%d>" % ( - self.__class__.__name__, - self.name, - getattr(self, "exitstatus", ""), - self.testsfailed, - self.testscollected, - ) + return ( + f"<{self.__class__.__name__} {self.name} " + f"exitstatus=%r " + f"testsfailed={self.testsfailed} " + f"testscollected={self.testscollected}>" + ) % getattr(self, "exitstatus", "") @property def shouldstop(self) -> bool | str: @@ -654,7 +652,7 @@ def pytest_runtest_logreport(self, report: TestReport | CollectReport) -> None: self.testsfailed += 1 maxfail = self.config.getvalue("maxfail") if maxfail and self.testsfailed >= maxfail: - self.shouldfail = "stopping after %d failures" % (self.testsfailed) + self.shouldfail = f"stopping after {self.testsfailed} failures" pytest_collectreport = pytest_runtest_logreport diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index e7e32555ba4..ac64ef2d606 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -48,13 +48,7 @@ def get_empty_parameterset_mark( from ..nodes import Collector fs, lineno = getfslineno(func) - reason = "got empty parameter set %r, function %s at %s:%d" % ( - argnames, - func.__name__, - fs, - lineno, - ) - + reason = f"got empty parameter set {argnames!r}, function {func.__name__} at {fs}:{lineno}" requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION) if requested_mark in ("", None, "skip"): mark = MARK_GEN.skip(reason=reason) @@ -64,7 +58,7 @@ def get_empty_parameterset_mark( f_name = func.__name__ _, lineno = getfslineno(func) raise Collector.CollectError( - "Empty parameter set in '%s' at line %d" % (f_name, lineno + 1) + f"Empty parameter set in '{f_name}' at line {lineno + 1}" ) else: raise LookupError(requested_mark) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 056be52a4ed..412d850d2da 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -547,8 +547,10 @@ def __init__( def __repr__(self) -> str: return ( - "" - % (self.ret, len(self.stdout.lines), len(self.stderr.lines), self.duration) + f"" ) def parseoutcomes(self) -> dict[str, int]: diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index a74f73bff17..348a78af9f5 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -766,13 +766,13 @@ def report_collect(self, final: bool = False) -> None: str(self._numcollected) + " item" + ("" if self._numcollected == 1 else "s") ) if errors: - line += " / %d error%s" % (errors, "s" if errors != 1 else "") + line += f" / {errors} error{'s' if errors != 1 else ''}" if deselected: - line += " / %d deselected" % deselected + line += f" / {deselected} deselected" if skipped: - line += " / %d skipped" % skipped + line += f" / {skipped} skipped" if self._numcollected > selected: - line += " / %d selected" % selected + line += f" / {selected} selected" if self.isatty: self.rewrite(line, bold=True, erase=True) if final: @@ -862,7 +862,7 @@ def _printcollecteditems(self, items: Sequence[Item]) -> None: if test_cases_verbosity < -1: counts = Counter(item.nodeid.split("::", 1)[0] for item in items) for name, count in sorted(counts.items()): - self._tw.line("%s: %d" % (name, count)) + self._tw.line(f"{name}: {count}") else: for item in items: self._tw.line(item.nodeid) @@ -1254,11 +1254,9 @@ def show_skipped_folded(lines: list[str]) -> None: if reason.startswith(prefix): reason = reason[len(prefix) :] if lineno is not None: - lines.append( - "%s [%d] %s:%d: %s" % (markup_word, num, fspath, lineno, reason) - ) + lines.append(f"{markup_word} [{num}] {fspath}:{lineno}: {reason}") else: - lines.append("%s [%d] %s: %s" % (markup_word, num, fspath, reason)) + lines.append(f"{markup_word} [{num}] {fspath}: {reason}") def show_skipped_unfolded(lines: list[str]) -> None: skipped: list[CollectReport] = self.stats.get("skipped", []) @@ -1375,7 +1373,7 @@ def _build_normal_summary_stats_line( count = len(reports) color = _color_for_type.get(key, _color_for_type_default) markup = {color: True, "bold": color == main_color} - parts.append(("%d %s" % pluralize(count, key), markup)) + parts.append(("%d %s" % pluralize(count, key), markup)) # noqa: UP031 if not parts: parts = [("no tests ran", {_color_for_type_default: True})] @@ -1394,7 +1392,7 @@ def _build_collect_only_summary_stats_line( elif deselected == 0: main_color = "green" - collected_output = "%d %s collected" % pluralize(self._numcollected, "test") + collected_output = "%d %s collected" % pluralize(self._numcollected, "test") # noqa: UP031 parts = [(collected_output, {main_color: True})] else: all_tests_were_deselected = self._numcollected == deselected @@ -1410,7 +1408,7 @@ def _build_collect_only_summary_stats_line( if errors: main_color = _color_for_type["error"] - parts += [("%d %s" % pluralize(errors, "error"), {main_color: True})] + parts += [("%d %s" % pluralize(errors, "error"), {main_color: True})] # noqa: UP031 return parts, main_color diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index b6d49c5425e..cd8752fb79b 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -948,7 +948,7 @@ def test_make_numbered_dir(self, tmpdir): prefix="base.", rootdir=tmpdir, keep=2, lock_timeout=0 ) assert numdir.check() - assert numdir.basename == "base.%d" % i + assert numdir.basename == f"base.{i}" if i >= 1: assert numdir.new(ext=str(i - 1)).check() if i >= 2: @@ -993,7 +993,7 @@ def test_locked_make_numbered_dir(self, tmpdir): for i in range(10): numdir = local.make_numbered_dir(prefix="base2.", rootdir=tmpdir, keep=2) assert numdir.check() - assert numdir.basename == "base2.%d" % i + assert numdir.basename == f"base2.{i}" for j in range(i): assert numdir.new(ext=str(j)).check() diff --git a/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py b/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py index e25bebf74dd..5ae9a02f99b 100644 --- a/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py +++ b/testing/example_scripts/dataclasses/test_compare_dataclasses_with_custom_eq.py @@ -10,8 +10,8 @@ class SimpleDataObject: field_a: int = field() field_b: str = field() - def __eq__(self, __o: object, /) -> bool: - return super().__eq__(__o) + def __eq__(self, o: object, /) -> bool: + return super().__eq__(o) left = SimpleDataObject(1, "b") right = SimpleDataObject(1, "c") diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index df6dbaee0fd..4e7e441768c 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -1438,13 +1438,13 @@ def test_parametrize_scope_overrides( self, pytester: Pytester, scope: str, length: int ) -> None: pytester.makepyfile( - """ + f""" import pytest values = [] def pytest_generate_tests(metafunc): if "arg" in metafunc.fixturenames: metafunc.parametrize("arg", [1,2], indirect=True, - scope=%r) + scope={scope!r}) @pytest.fixture def arg(request): values.append(request.param) @@ -1454,9 +1454,8 @@ def test_hello(arg): def test_world(arg): assert arg in (1,2) def test_checklength(): - assert len(values) == %d + assert len(values) == {length} """ - % (scope, length) ) reprec = pytester.inline_run() reprec.assertoutcome(passed=5) diff --git a/testing/test_assertion.py b/testing/test_assertion.py index a14c4125cf6..a2e2304d342 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -1406,15 +1406,14 @@ def test_full_output_truncated(self, monkeypatch, pytester: Pytester) -> None: line_len = 100 expected_truncated_lines = 2 pytester.makepyfile( - r""" + rf""" def test_many_lines(): - a = list([str(i)[0] * %d for i in range(%d)]) + a = list([str(i)[0] * {line_len} for i in range({line_count})]) b = a[::2] a = '\n'.join(map(str, a)) b = '\n'.join(map(str, b)) assert a == b """ - % (line_len, line_count) ) monkeypatch.delenv("CI", raising=False) @@ -1424,7 +1423,7 @@ def test_many_lines(): [ "*+ 1*", "*+ 3*", - "*truncated (%d lines hidden)*use*-vv*" % expected_truncated_lines, + f"*truncated ({expected_truncated_lines} lines hidden)*use*-vv*", ] ) diff --git a/testing/test_conftest.py b/testing/test_conftest.py index bbb1d301ebe..bd083574ffc 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -699,9 +699,9 @@ def out_of_reach(): pass result = pytester.runpytest(*args) match = "" if passed: - match += "*%d passed*" % passed + match += f"*{passed} passed*" if error: - match += "*%d error*" % error + match += f"*{error} error*" result.stdout.fnmatch_lines(match) diff --git a/testing/test_doctest.py b/testing/test_doctest.py index d3ad09da871..1a852ebc82a 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -1328,7 +1328,7 @@ def test_bar(): params = ("--doctest-modules",) if enable_doctest else () passes = 3 if enable_doctest else 2 result = pytester.runpytest(*params) - result.stdout.fnmatch_lines(["*=== %d passed in *" % passes]) + result.stdout.fnmatch_lines([f"*=== {passes} passed in *"]) @pytest.mark.parametrize("scope", SCOPES) @pytest.mark.parametrize("autouse", [True, False]) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 872703900cd..6fa04be28b1 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -49,7 +49,7 @@ def __init__(self, verbosity=0): @property def args(self): values = [] - values.append("--verbosity=%d" % self.verbosity) + values.append(f"--verbosity={self.verbosity}") return values From 4b32e7cc33f2972417436fbc86d915944f6c906a Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sat, 30 Nov 2024 21:17:32 +0000 Subject: [PATCH 1008/1271] Enhancements to unraisable plugin (#12958) A number of `unraisable` plugin enhancements: * Set the unraisablehook as early as possible and unset it as late as possible, to collect the most possible unraisable exceptions (please let me know if there's an earlier or later hook I can use). * Call the garbage collector just before unsetting the unraisablehook, to collect any straggling exceptions * Collect multiple unraisable exceptions per test phase. * Report the tracemalloc allocation traceback, if available. * Avoid using a generator based hook to allow handling StopIteration in test failures * Report the unraisable exception as the cause of the PytestUnraisableExceptionWarning exception if raised. * Compute the repr of the unraisable.object in the unraisablehook so you get the latest information if available, and should help with resurrection of the object. Co-authored-by: Ran Benita Co-authored-by: Bruno Oliveira --- changelog/12958.improvement.rst | 9 ++ src/_pytest/tracemalloc.py | 24 +++ src/_pytest/unraisableexception.py | 222 ++++++++++++++++++---------- src/_pytest/warnings.py | 26 +--- testing/test_unraisableexception.py | 106 ++++++++++++- 5 files changed, 279 insertions(+), 108 deletions(-) create mode 100644 changelog/12958.improvement.rst create mode 100644 src/_pytest/tracemalloc.py diff --git a/changelog/12958.improvement.rst b/changelog/12958.improvement.rst new file mode 100644 index 00000000000..ee8dc8c0710 --- /dev/null +++ b/changelog/12958.improvement.rst @@ -0,0 +1,9 @@ +A number of :ref:`unraisable ` enhancements: + +* Set the unraisable hook as early as possible and unset it as late as possible, to collect the most possible number of unraisable exceptions. +* Call the garbage collector just before unsetting the unraisable hook, to collect any straggling exceptions. +* Collect multiple unraisable exceptions per test phase. +* Report the :mod:`tracemalloc` allocation traceback (if available). +* Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures. +* Report the unraisable exception as the cause of the :class:`pytest.PytestUnraisableExceptionWarning` exception if raised. +* Compute the ``repr`` of the unraisable object in the unraisable hook so you get the latest information if available, and should help with resurrection of the object. diff --git a/src/_pytest/tracemalloc.py b/src/_pytest/tracemalloc.py new file mode 100644 index 00000000000..5d0b19855c7 --- /dev/null +++ b/src/_pytest/tracemalloc.py @@ -0,0 +1,24 @@ +from __future__ import annotations + + +def tracemalloc_message(source: object) -> str: + if source is None: + return "" + + try: + import tracemalloc + except ImportError: + return "" + + tb = tracemalloc.get_object_traceback(source) + if tb is not None: + formatted_tb = "\n".join(tb.format()) + # Use a leading new line to better separate the (large) output + # from the traceback to the previous warning text. + return f"\nObject allocated at:\n{formatted_tb}" + # No need for a leading new line. + url = "https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings" + return ( + "Enable tracemalloc to get traceback where the object was allocated.\n" + f"See {url} for more info." + ) diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index 5796b37715d..2bd7f07e862 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -1,100 +1,158 @@ from __future__ import annotations +import collections from collections.abc import Callable -from collections.abc import Generator +import functools +import gc import sys import traceback -from types import TracebackType -from typing import Any +from typing import NamedTuple from typing import TYPE_CHECKING import warnings +from _pytest.config import Config +from _pytest.nodes import Item +from _pytest.stash import StashKey +from _pytest.tracemalloc import tracemalloc_message import pytest if TYPE_CHECKING: - from typing_extensions import Self - - -# Copied from cpython/Lib/test/support/__init__.py, with modifications. -class catch_unraisable_exception: - """Context manager catching unraisable exception using sys.unraisablehook. - - Storing the exception value (cm.unraisable.exc_value) creates a reference - cycle. The reference cycle is broken explicitly when the context manager - exits. - - Storing the object (cm.unraisable.object) can resurrect it if it is set to - an object which is being finalized. Exiting the context manager clears the - stored object. - - Usage: - with catch_unraisable_exception() as cm: - # code creating an "unraisable exception" - ... - # check the unraisable exception: use cm.unraisable - ... - # cm.unraisable attribute no longer exists at this point - # (to break a reference cycle) - """ - - def __init__(self) -> None: - self.unraisable: sys.UnraisableHookArgs | None = None - self._old_hook: Callable[[sys.UnraisableHookArgs], Any] | None = None - - def _hook(self, unraisable: sys.UnraisableHookArgs) -> None: - # Storing unraisable.object can resurrect an object which is being - # finalized. Storing unraisable.exc_value creates a reference cycle. - self.unraisable = unraisable - - def __enter__(self) -> Self: - self._old_hook = sys.unraisablehook - sys.unraisablehook = self._hook - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - assert self._old_hook is not None - sys.unraisablehook = self._old_hook - self._old_hook = None - del self.unraisable - - -def unraisable_exception_runtest_hook() -> Generator[None]: - with catch_unraisable_exception() as cm: - try: - yield - finally: - if cm.unraisable: - if cm.unraisable.err_msg is not None: - err_msg = cm.unraisable.err_msg - else: - err_msg = "Exception ignored in" - msg = f"{err_msg}: {cm.unraisable.object!r}\n\n" - msg += "".join( - traceback.format_exception( - cm.unraisable.exc_type, - cm.unraisable.exc_value, - cm.unraisable.exc_traceback, - ) - ) - warnings.warn(pytest.PytestUnraisableExceptionWarning(msg)) + pass + +if sys.version_info < (3, 11): + from exceptiongroup import ExceptionGroup + + +def gc_collect_harder() -> None: + # A single collection doesn't necessarily collect everything. + # Constant determined experimentally by the Trio project. + for _ in range(5): + gc.collect() -@pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_setup() -> Generator[None]: - yield from unraisable_exception_runtest_hook() +class UnraisableMeta(NamedTuple): + msg: str + cause_msg: str + exc_value: BaseException | None -@pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_call() -> Generator[None]: - yield from unraisable_exception_runtest_hook() +unraisable_exceptions: StashKey[collections.deque[UnraisableMeta | BaseException]] = ( + StashKey() +) -@pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_teardown() -> Generator[None]: - yield from unraisable_exception_runtest_hook() +def collect_unraisable(config: Config) -> None: + pop_unraisable = config.stash[unraisable_exceptions].pop + errors: list[pytest.PytestUnraisableExceptionWarning | RuntimeError] = [] + meta = None + hook_error = None + try: + while True: + try: + meta = pop_unraisable() + except IndexError: + break + + if isinstance(meta, BaseException): + hook_error = RuntimeError("Failed to process unraisable exception") + hook_error.__cause__ = meta + errors.append(hook_error) + continue + + msg = meta.msg + try: + warnings.warn(pytest.PytestUnraisableExceptionWarning(msg)) + except pytest.PytestUnraisableExceptionWarning as e: + # This except happens when the warning is treated as an error (e.g. `-Werror`). + if meta.exc_value is not None: + # Exceptions have a better way to show the traceback, but + # warnings do not, so hide the traceback from the msg and + # set the cause so the traceback shows up in the right place. + e.args = (meta.cause_msg,) + e.__cause__ = meta.exc_value + errors.append(e) + + if len(errors) == 1: + raise errors[0] + if errors: + raise ExceptionGroup("multiple unraisable exception warnings", errors) + finally: + del errors, meta, hook_error + + +def cleanup( + *, config: Config, prev_hook: Callable[[sys.UnraisableHookArgs], object] +) -> None: + try: + try: + gc_collect_harder() + collect_unraisable(config) + finally: + sys.unraisablehook = prev_hook + finally: + del config.stash[unraisable_exceptions] + + +def unraisable_hook( + unraisable: sys.UnraisableHookArgs, + /, + *, + append: Callable[[UnraisableMeta | BaseException], object], +) -> None: + try: + err_msg = ( + "Exception ignored in" if unraisable.err_msg is None else unraisable.err_msg + ) + summary = f"{err_msg}: {unraisable.object!r}" + traceback_message = "\n\n" + "".join( + traceback.format_exception( + unraisable.exc_type, + unraisable.exc_value, + unraisable.exc_traceback, + ) + ) + tracemalloc_tb = "\n" + tracemalloc_message(unraisable.object) + msg = summary + traceback_message + tracemalloc_tb + cause_msg = summary + tracemalloc_tb + + append( + UnraisableMeta( + # we need to compute these strings here as they might change after + # the unraisablehook finishes and before the unraisable object is + # collected by a hook + msg=msg, + cause_msg=cause_msg, + exc_value=unraisable.exc_value, + ) + ) + except BaseException as e: + append(e) + # Raising this will cause the exception to be logged twice, once in our + # collect_unraisable and once by the unraisablehook calling machinery + # which is fine - this should never happen anyway and if it does + # it should probably be reported as a pytest bug. + raise + + +def pytest_configure(config: Config) -> None: + prev_hook = sys.unraisablehook + deque: collections.deque[UnraisableMeta | BaseException] = collections.deque() + config.stash[unraisable_exceptions] = deque + config.add_cleanup(functools.partial(cleanup, config=config, prev_hook=prev_hook)) + sys.unraisablehook = functools.partial(unraisable_hook, append=deque.append) + + +@pytest.hookimpl(trylast=True) +def pytest_runtest_setup(item: Item) -> None: + collect_unraisable(item.config) + + +@pytest.hookimpl(trylast=True) +def pytest_runtest_call(item: Item) -> None: + collect_unraisable(item.config) + + +@pytest.hookimpl(trylast=True) +def pytest_runtest_teardown(item: Item) -> None: + collect_unraisable(item.config) diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index 87cdbda288f..64ea3ff222d 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -13,6 +13,7 @@ from _pytest.main import Session from _pytest.nodes import Item from _pytest.terminal import TerminalReporter +from _pytest.tracemalloc import tracemalloc_message import pytest @@ -76,32 +77,13 @@ def catch_warnings_for_item( def warning_record_to_str(warning_message: warnings.WarningMessage) -> str: """Convert a warnings.WarningMessage to a string.""" - warn_msg = warning_message.message - msg = warnings.formatwarning( - str(warn_msg), + return warnings.formatwarning( + str(warning_message.message), warning_message.category, warning_message.filename, warning_message.lineno, warning_message.line, - ) - if warning_message.source is not None: - try: - import tracemalloc - except ImportError: - pass - else: - tb = tracemalloc.get_object_traceback(warning_message.source) - if tb is not None: - formatted_tb = "\n".join(tb.format()) - # Use a leading new line to better separate the (large) output - # from the traceback to the previous warning text. - msg += f"\nObject allocated at:\n{formatted_tb}" - else: - # No need for a leading new line. - url = "https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings" - msg += "Enable tracemalloc to get traceback where the object was allocated.\n" - msg += f"See {url} for more info." - return msg + ) + tracemalloc_message(warning_message.source) @pytest.hookimpl(wrapper=True, tryfirst=True) diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index a15c754d067..70248e1c122 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -1,6 +1,8 @@ from __future__ import annotations +import gc import sys +from unittest import mock from _pytest.pytester import Pytester import pytest @@ -27,7 +29,7 @@ def test_2(): pass ) result = pytester.runpytest() assert result.ret == 0 - assert result.parseoutcomes() == {"passed": 2, "warnings": 1} + result.assert_outcomes(passed=2, warnings=1) result.stdout.fnmatch_lines( [ "*= warnings summary =*", @@ -37,6 +39,8 @@ def test_2(): pass " Traceback (most recent call last):", " ValueError: del is broken", " ", + " Enable tracemalloc to get traceback where the object was allocated.", + " See https* for more info.", " warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))", ] ) @@ -64,7 +68,7 @@ def test_2(): pass ) result = pytester.runpytest() assert result.ret == 0 - assert result.parseoutcomes() == {"passed": 2, "warnings": 1} + result.assert_outcomes(passed=2, warnings=1) result.stdout.fnmatch_lines( [ "*= warnings summary =*", @@ -74,6 +78,8 @@ def test_2(): pass " Traceback (most recent call last):", " ValueError: del is broken", " ", + " Enable tracemalloc to get traceback where the object was allocated.", + " See https* for more info.", " warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))", ] ) @@ -102,7 +108,7 @@ def test_2(): pass ) result = pytester.runpytest() assert result.ret == 0 - assert result.parseoutcomes() == {"passed": 2, "warnings": 1} + result.assert_outcomes(passed=2, warnings=1) result.stdout.fnmatch_lines( [ "*= warnings summary =*", @@ -112,6 +118,8 @@ def test_2(): pass " Traceback (most recent call last):", " ValueError: del is broken", " ", + " Enable tracemalloc to get traceback where the object was allocated.", + " See https* for more info.", " warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))", ] ) @@ -135,4 +143,94 @@ def test_2(): pass ) result = pytester.runpytest() assert result.ret == pytest.ExitCode.TESTS_FAILED - assert result.parseoutcomes() == {"passed": 1, "failed": 1} + result.assert_outcomes(passed=1, failed=1) + + +@pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning") +def test_unraisable_warning_multiple_errors(pytester: Pytester) -> None: + pytester.makepyfile( + test_it=f""" + class BrokenDel: + def __init__(self, msg: str): + self.msg = msg + + def __del__(self) -> None: + raise ValueError(self.msg) + + def test_it() -> None: + BrokenDel("del is broken 1") + BrokenDel("del is broken 2") + {"import gc; gc.collect()" * PYPY} + + def test_2(): pass + """ + ) + result = pytester.runpytest() + assert result.ret == pytest.ExitCode.TESTS_FAILED + result.assert_outcomes(passed=1, failed=1) + result.stdout.fnmatch_lines( + [ + " | *ExceptionGroup: multiple unraisable exception warnings (2 sub-exceptions)" + ] + ) + + +def test_unraisable_collection_failure(pytester: Pytester) -> None: + pytester.makepyfile( + test_it=f""" + class BrokenDel: + def __del__(self): + raise ValueError("del is broken") + + def test_it(): + obj = BrokenDel() + del obj + {"import gc; gc.collect()" * PYPY} + + def test_2(): pass + """ + ) + + class MyError(BaseException): + pass + + with mock.patch("traceback.format_exception", side_effect=MyError): + result = pytester.runpytest() + assert result.ret == 1 + result.assert_outcomes(passed=1, failed=1) + result.stdout.fnmatch_lines( + ["E RuntimeError: Failed to process unraisable exception"] + ) + + +def test_create_task_unraisable(pytester: Pytester) -> None: + # see: https://github.com/pytest-dev/pytest/issues/10404 + pytester.makepyfile( + test_it=""" + import pytest + + class BrokenDel: + def __init__(self): + self.self = self # make a reference cycle + + def __del__(self): + raise ValueError("del is broken") + + def test_it(): + BrokenDel() + """ + ) + + was_enabled = gc.isenabled() + gc.disable() + try: + result = pytester.runpytest() + finally: + if was_enabled: + gc.enable() + + # TODO: should be a test failure or error + assert result.ret == pytest.ExitCode.INTERNAL_ERROR + + result.assert_outcomes(passed=1) + result.stderr.fnmatch_lines("ValueError: del is broken") From 68b5938f057c5fc748e362befd18e3812b59b3e7 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 1 Dec 2024 00:30:58 +0000 Subject: [PATCH 1009/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 220 ++++++++++++++++++------------- 1 file changed, 130 insertions(+), 90 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 3ac9b0b4c13..62535d2d366 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.2) :pypi:`pytest-ai1899` pytest plugin for connecting to ai1899 smart system stack Mar 13, 2024 5 - Production/Stable N/A :pypi:`pytest-aio` Pytest plugin for testing async python code Jul 31, 2024 5 - Production/Stable pytest + :pypi:`pytest-aioboto3` Aioboto3 Pytest with Moto Nov 26, 2024 N/A N/A :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A :pypi:`pytest-aiogram` May 06, 2023 N/A N/A :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Sep 06, 2023 4 - Beta pytest >=6.1.0 @@ -150,14 +151,14 @@ This list contains 1546 plugins. :pypi:`pytest-bazel` A pytest runner with bazel support Sep 27, 2024 4 - Beta pytest :pypi:`pytest-bdd` BDD for pytest Nov 14, 2024 6 - Mature pytest>=7.0.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) - :pypi:`pytest-bdd-ng` BDD for pytest Oct 07, 2024 4 - Beta pytest>=5.0 - :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Aug 26, 2024 N/A pytest>=7.1.3 + :pypi:`pytest-bdd-ng` BDD for pytest Nov 26, 2024 4 - Beta pytest>=5.2 + :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 27, 2024 N/A pytest>=7.1.3 :pypi:`pytest-bdd-splinter` Common steps for pytest bdd and splinter integration Aug 12, 2019 5 - Production/Stable pytest (>=4.0.0) :pypi:`pytest-bdd-web` A simple plugin to use with pytest Jan 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Nov 18, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Nov 27, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -211,7 +212,7 @@ This list contains 1546 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest - :pypi:`pytest-case` A clean, modern, wrapper for pytest.mark.parametrize Nov 22, 2024 N/A pytest<9.0.0,>=8.3.3 + :pypi:`pytest-case` A clean, modern, wrapper for pytest.mark.parametrize Nov 25, 2024 N/A pytest<9.0.0,>=8.3.3 :pypi:`pytest-cases` Separate test code from test cases in pytest. Sep 26, 2024 5 - Production/Stable N/A :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) @@ -249,7 +250,7 @@ This list contains 1546 plugins. :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Nov 08, 2024 5 - Production/Stable N/A - :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Oct 08, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Nov 29, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Oct 23, 2024 N/A pytest>=3.9 @@ -429,7 +430,7 @@ This list contains 1546 plugins. :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) :pypi:`pytest-doctest-mkdocstrings` Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) Mar 02, 2024 N/A pytest - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Mar 10, 2024 5 - Production/Stable pytest >=4.6 + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Nov 25, 2024 5 - Production/Stable pytest>=4.6 :pypi:`pytest-documentary` A simple pytest plugin to generate test documentation Jul 11, 2024 N/A pytest :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 Dec 14, 2023 N/A N/A @@ -506,7 +507,7 @@ This list contains 1546 plugins. :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Nov 20, 2024 N/A pytest>=7 :pypi:`pytest-exasol-backend` Nov 22, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-extension` Oct 10, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-itde` Jul 01, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-itde` Nov 22, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Nov 22, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-slc` Nov 01, 2024 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 @@ -578,6 +579,7 @@ This list contains 1546 plugins. :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Nov 09, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-flake8-v2` pytest plugin to check FLAKE8 requirements Mar 01, 2022 5 - Production/Stable pytest (>=7.0) + :pypi:`pytest-flake-detection` Continuously runs your tests to detect flaky tests Nov 29, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-flakefinder` Runs tests multiple times to expose flakiness. Oct 26, 2022 4 - Beta pytest (>=2.7.1) :pypi:`pytest-flakes` pytest plugin to check source code with pyflakes Dec 02, 2021 5 - Production/Stable pytest (>=5) :pypi:`pytest-flaptastic` Flaptastic py.test plugin Mar 17, 2019 N/A N/A @@ -664,7 +666,7 @@ This list contains 1546 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 16, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Nov 29, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -684,12 +686,12 @@ This list contains 1546 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Sep 18, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Oct 21, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Nov 23, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Aug 10, 2024 N/A pytest<9.0.0,>=8.2.0 - :pypi:`pytest-httpx` Send responses to httpx. Nov 18, 2024 5 - Production/Stable pytest==8.* + :pypi:`pytest-httpx` Send responses to httpx. Nov 28, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A @@ -719,10 +721,10 @@ This list contains 1546 plugins. :pypi:`pytest-inline` A pytest plugin for writing inline tests Oct 24, 2024 4 - Beta pytest<9.0,>=7.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Oct 10, 2024 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 10, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Oct 29, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Nov 26, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A - :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Mar 02, 2024 N/A pytest + :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Nov 23, 2024 N/A pytest :pypi:`pytest-insper` Pytest plugin for courses at Insper Mar 21, 2024 N/A pytest :pypi:`pytest-insta` A practical snapshot testing plugin for pytest Feb 19, 2024 N/A pytest (>=7.2.0,<9.0.0) :pypi:`pytest-instafail` pytest plugin to show failures instantly Mar 31, 2023 4 - Beta pytest (>=5) @@ -738,7 +740,7 @@ This list contains 1546 plugins. :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipywidgets` Oct 28, 2024 N/A pytest - :pypi:`pytest-isolate` Feb 20, 2023 4 - Beta pytest + :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Nov 24, 2024 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Sep 18, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -805,7 +807,7 @@ This list contains 1546 plugins. :pypi:`pytest-line-profiler` Profile code executed by pytest Aug 10, 2023 4 - Beta pytest >=3.5.0 :pypi:`pytest-line-profiler-apn` Profile code executed by pytest Dec 05, 2022 N/A pytest (>=3.5.0) :pypi:`pytest-lisa` Pytest plugin for organizing tests. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-listener` A simple network listener Oct 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-listener` A simple network listener Nov 29, 2024 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. Nov 23, 2023 4 - Beta pytest >=6.1 :pypi:`pytest-live` Live results for pytest Mar 08, 2020 N/A pytest @@ -823,17 +825,17 @@ This list contains 1546 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logikal` Common testing environment Nov 09, 2024 5 - Production/Stable pytest==8.3.3 + :pypi:`pytest-logikal` Common testing environment Nov 27, 2024 5 - Production/Stable pytest==8.3.3 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Oct 17, 2024 5 - Production/Stable pytest - :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Sep 04, 2024 3 - Alpha pytest + :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 23, 2024 3 - Alpha pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Nov 13, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) - :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Oct 22, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Nov 28, 2024 N/A pytest>=7.0.0 :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Oct 30, 2024 4 - Beta pytest>=6.0 :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A @@ -864,7 +866,7 @@ This list contains 1546 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 Feb 12, 2024 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 Nov 04, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Nov 28, 2024 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) @@ -929,7 +931,7 @@ This list contains 1546 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Sep 06, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Nov 28, 2024 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Aug 05, 2024 N/A N/A @@ -960,7 +962,7 @@ This list contains 1546 plugins. :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 11, 2023 4 - Beta N/A :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Jun 05, 2024 3 - Alpha pytest>=4.6 - :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Oct 01, 2023 N/A pytest + :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Nov 22, 2024 N/A pytest :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Sep 05, 2024 5 - Production/Stable pytest>=5.0 :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest :pypi:`pytest-optional` include/exclude values of fixtures in pytest Oct 07, 2015 N/A N/A @@ -1024,9 +1026,9 @@ This list contains 1546 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Sep 06, 2024 N/A pytest<9.0.0,>=6.2.4 + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Nov 26, 2024 N/A pytest<9.0.0,>=6.2.4 :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Sep 28, 2024 N/A N/A - :pypi:`pytest-playwright-asyncio` Aug 29, 2023 N/A N/A + :pypi:`pytest-playwright-asyncio` A pytest wrapper with fixtures for Playwright to automate web browsers Nov 26, 2024 N/A pytest<9.0.0,>=6.2.4 :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A @@ -1047,6 +1049,7 @@ This list contains 1546 plugins. :pypi:`pytest-poo-fail` Visualize your failed tests with poo Feb 12, 2015 5 - Production/Stable N/A :pypi:`pytest-pook` Pytest plugin for pook Feb 15, 2024 4 - Beta pytest :pypi:`pytest-pop` A pytest plugin to help with testing pop projects May 09, 2023 5 - Production/Stable pytest + :pypi:`pytest-porcochu` Show surprise when tests are passing Nov 28, 2024 5 - Production/Stable N/A :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Sep 05, 2024 5 - Production/Stable pytest>=6.2 @@ -1060,7 +1063,7 @@ This list contains 1546 plugins. :pypi:`pytest-priority` pytest plugin for add priority for tests Aug 19, 2024 N/A pytest :pypi:`pytest-proceed` Oct 01, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) - :pypi:`pytest-profiling` Profiling plugin for py.test Oct 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-profiling` Profiling plugin for py.test Nov 29, 2024 5 - Production/Stable pytest :pypi:`pytest-progress` pytest plugin for instant test progress status Jun 18, 2024 5 - Production/Stable pytest>=2.7 :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest @@ -1083,7 +1086,7 @@ This list contains 1546 plugins. :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Oct 09, 2024 3 - Alpha pytest>=7.0 :pypi:`pytest-pylint` pytest plugin to check source code with pylint Oct 06, 2023 5 - Production/Stable pytest >=7.0 :pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A - :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Jul 23, 2024 N/A pytest + :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Nov 23, 2024 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) @@ -1133,7 +1136,7 @@ This list contains 1546 plugins. :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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-record-video` 用例执行过程中录制视频 Oct 31, 2024 N/A N/A - :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Jun 19, 2024 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Nov 27, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-redislite` Pytest plugin for testing code using Redis Apr 05, 2022 4 - Beta pytest :pypi:`pytest-redmine` Pytest plugin for redmine Mar 19, 2018 1 - Planning N/A :pypi:`pytest-ref` A plugin to store reference files to ease regression testing Nov 23, 2019 4 - Beta pytest (>=3.5.0) @@ -1152,7 +1155,7 @@ This list contains 1546 plugins. :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest :pypi:`pytest_repeater` py.test plugin for repeating single test multiple times. Feb 09, 2018 1 - Planning N/A - :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Sep 03, 2024 5 - Production/Stable pytest + :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Nov 29, 2024 5 - Production/Stable pytest :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest @@ -1171,6 +1174,7 @@ This list contains 1546 plugins. :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A :pypi:`pytest-requests-futures` Pytest Plugin to Mock Requests Futures Jul 06, 2022 5 - Production/Stable pytest + :pypi:`pytest-requirements` pytest plugin for using custom markers to relate tests to requirements and usecases Nov 29, 2024 N/A pytest :pypi:`pytest-requires` A pytest plugin to elegantly skip tests with optional requirements Dec 21, 2021 4 - Beta pytest (>=3.5.0) :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) @@ -1192,7 +1196,7 @@ This list contains 1546 plugins. :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments May 14, 2024 N/A pytest>=7.0.0 - :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Mar 25, 2023 N/A pytest (>=5.3) + :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Nov 24, 2024 N/A pytest>=5.3 :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-reverse` Pytest plugin to reverse test order. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) @@ -1229,7 +1233,7 @@ This list contains 1546 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 30, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1240,15 +1244,15 @@ This list contains 1546 plugins. :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 Feb 01, 2024 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 19, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Nov 30, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-send-email` Send pytest execution result email Sep 02, 2024 N/A pytest - :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Apr 25, 2024 N/A pytest + :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Nov 25, 2024 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A - :pypi:`pytest-server-fixtures` Extensible server fixtures for py.test Oct 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-server-fixtures` Extensible server fixtures for py.test Nov 29, 2024 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A :pypi:`pytest-servers` pytest servers Nov 14, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-service` Aug 06, 2024 5 - Production/Stable pytest>=6.0.0 @@ -1267,7 +1271,7 @@ This list contains 1546 plugins. :pypi:`pytest-sheraf` Versatile ZODB abstraction layer - pytest fixtures Feb 11, 2020 N/A pytest :pypi:`pytest-sherlock` pytest plugin help to find coupled tests Aug 14, 2023 5 - Production/Stable pytest >=3.5.1 :pypi:`pytest-shortcuts` Expand command-line shortcuts listed in pytest configuration Oct 29, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test Oct 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-shutil` A goodie-bag of unix shell and environment tools for py.test Nov 29, 2024 5 - Production/Stable pytest :pypi:`pytest-simbind` Pytest plugin to operate with objects generated by Simbind tool. Mar 28, 2024 N/A pytest>=7.0.0 :pypi:`pytest-simplehttpserver` Simple pytest fixture to spin up an HTTP server Jun 24, 2021 4 - Beta N/A :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A @@ -1286,7 +1290,7 @@ This list contains 1546 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A - :pypi:`pytest-smoke` pytest plugin for supporting smoke testing Nov 07, 2024 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-smoke` Pytest plugin for smoke testing Nov 27, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -1322,7 +1326,7 @@ This list contains 1546 plugins. :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 28, 2024 N/A pytest<8,>5.4.0 - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Sep 26, 2024 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Nov 24, 2024 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 @@ -1343,7 +1347,7 @@ This list contains 1546 plugins. :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A :pypi:`pytest-stf` pytest plugin for openSTF Sep 24, 2024 N/A pytest>=5.0 - :pypi:`pytest-stochastics` pytest plugin that allows selectively running tests several times and accepting \*some\* failures. Oct 31, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-stochastics` pytest plugin that allows selectively running tests several times and accepting \*some\* failures. Nov 30, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Sep 04, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) @@ -1468,6 +1472,7 @@ This list contains 1546 plugins. :pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A + :pypi:`pytest-tt-ddriven` A simple project that act as a placeholder for project name Nov 29, 2024 N/A N/A :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A @@ -1503,17 +1508,17 @@ This list contains 1546 plugins. :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 Nov 23, 2023 4 - Beta pytest - :pypi:`pytest-verbose-parametrize` More descriptive output for parametrized py.test tests Oct 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-verbose-parametrize` More descriptive output for parametrized py.test tests Nov 29, 2024 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 Oct 17, 2024 5 - Production/Stable pytest - :pypi:`pytest-visual` Nov 01, 2023 3 - Alpha pytest >=7.0.0 + :pypi:`pytest-virtualenv` Virtualenv fixture for py.test Nov 29, 2024 5 - Production/Stable pytest + :pypi:`pytest-visual` Nov 28, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-vnc` VNC client for Pytest Nov 06, 2023 N/A pytest :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest :pypi:`pytest-vtestify` A pytest plugin for visual assertion using SSIM and image comparison. Oct 10, 2024 N/A pytest :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) - :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Nov 22, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Nov 25, 2024 N/A pytest>=7.0.0 :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A :pypi:`pytest-vyper` Plugin for the vyper smart contract language. May 28, 2020 2 - Pre-Alpha N/A :pypi:`pytest-wa-e2e-plugin` Pytest plugin for testing whatsapp bots with end to end tests Feb 18, 2020 4 - Beta pytest (>=3.5.0) @@ -1528,7 +1533,7 @@ This list contains 1546 plugins. :pypi:`pytest-webstage` Test web apps with pytest Sep 20, 2024 N/A pytest<9.0,>=7.0 :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Oct 03, 2024 N/A pytest>=7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A - :pypi:`pytest-when` Utility which makes mocking more readable and controllable May 28, 2024 N/A pytest>=7.3.1 + :pypi:`pytest-when` Utility which makes mocking more readable and controllable Nov 29, 2024 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A :pypi:`pytest-wholenodeid` pytest addon for displaying the whole node id for failures Aug 26, 2015 4 - Beta pytest (>=2.0) :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A @@ -1711,6 +1716,13 @@ This list contains 1546 plugins. Pytest plugin for testing async python code + :pypi:`pytest-aioboto3` + *last release*: Nov 26, 2024, + *status*: N/A, + *requires*: N/A + + Aioboto3 Pytest with Moto + :pypi:`pytest-aiofiles` *last release*: May 14, 2017, *status*: 5 - Production/Stable, @@ -2398,14 +2410,14 @@ This list contains 1546 plugins. pytest plugin to display BDD info in HTML test report :pypi:`pytest-bdd-ng` - *last release*: Oct 07, 2024, + *last release*: Nov 26, 2024, *status*: 4 - Beta, - *requires*: pytest>=5.0 + *requires*: pytest>=5.2 BDD for pytest :pypi:`pytest-bdd-report` - *last release*: Aug 26, 2024, + *last release*: Nov 27, 2024, *status*: N/A, *requires*: pytest>=7.1.3 @@ -2447,7 +2459,7 @@ This list contains 1546 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Nov 18, 2024, + *last release*: Nov 27, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2825,7 +2837,7 @@ This list contains 1546 plugins. pytest plugin to capture all warnings and put them in one file of your choice :pypi:`pytest-case` - *last release*: Nov 22, 2024, + *last release*: Nov 25, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.3.3 @@ -3091,7 +3103,7 @@ This list contains 1546 plugins. A cleanup plugin for pytest :pypi:`pytest-clerk` - *last release*: Oct 08, 2024, + *last release*: Nov 29, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -4351,9 +4363,9 @@ This list contains 1546 plugins. Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) :pypi:`pytest-doctestplus` - *last release*: Mar 10, 2024, + *last release*: Nov 25, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=4.6 + *requires*: pytest>=4.6 Pytest plugin with advanced doctest features. @@ -4890,7 +4902,7 @@ This list contains 1546 plugins. :pypi:`pytest-exasol-itde` - *last release*: Jul 01, 2024, + *last release*: Nov 22, 2024, *status*: N/A, *requires*: pytest<9,>=7 @@ -5393,6 +5405,13 @@ This list contains 1546 plugins. pytest plugin to check FLAKE8 requirements + :pypi:`pytest-flake-detection` + *last release*: Nov 29, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + Continuously runs your tests to detect flaky tests + :pypi:`pytest-flakefinder` *last release*: Oct 26, 2022, *status*: 4 - Beta, @@ -5996,7 +6015,7 @@ This list contains 1546 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Nov 16, 2024, + *last release*: Nov 29, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6136,7 +6155,7 @@ This list contains 1546 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Oct 21, 2024, + *last release*: Nov 23, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -6171,7 +6190,7 @@ This list contains 1546 plugins. http_testing framework on top of pytest :pypi:`pytest-httpx` - *last release*: Nov 18, 2024, + *last release*: Nov 28, 2024, *status*: 5 - Production/Stable, *requires*: pytest==8.* @@ -6381,7 +6400,7 @@ This list contains 1546 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Oct 29, 2024, + *last release*: Nov 26, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6402,7 +6421,7 @@ This list contains 1546 plugins. A simple image diff plugin for pytest :pypi:`pytest-in-robotframework` - *last release*: Mar 02, 2024, + *last release*: Nov 23, 2024, *status*: N/A, *requires*: pytest @@ -6514,11 +6533,11 @@ This list contains 1546 plugins. :pypi:`pytest-isolate` - *last release*: Feb 20, 2023, + *last release*: Nov 24, 2024, *status*: 4 - Beta, *requires*: pytest - + Run pytest tests in isolated subprocesses :pypi:`pytest-isolate-mpi` *last release*: Sep 18, 2024, @@ -6983,7 +7002,7 @@ This list contains 1546 plugins. Pytest plugin for organizing tests. :pypi:`pytest-listener` - *last release*: Oct 17, 2024, + *last release*: Nov 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -7109,7 +7128,7 @@ This list contains 1546 plugins. :pypi:`pytest-logikal` - *last release*: Nov 09, 2024, + *last release*: Nov 27, 2024, *status*: 5 - Production/Stable, *requires*: pytest==8.3.3 @@ -7144,7 +7163,7 @@ This list contains 1546 plugins. pytest plugin for looping tests :pypi:`pytest-lsp` - *last release*: Sep 04, 2024, + *last release*: Nov 23, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -7179,7 +7198,7 @@ This list contains 1546 plugins. Test your markdown docs with pytest :pypi:`pytest-markdown-docs` - *last release*: Oct 22, 2024, + *last release*: Nov 28, 2024, *status*: N/A, *requires*: pytest>=7.0.0 @@ -7396,7 +7415,7 @@ This list contains 1546 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Nov 04, 2024, + *last release*: Nov 28, 2024, *status*: N/A, *requires*: pytest @@ -7851,7 +7870,7 @@ This list contains 1546 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Sep 06, 2024, + *last release*: Nov 28, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -8068,7 +8087,7 @@ This list contains 1546 plugins. Pytest plugin for detecting inadvertent open file handles :pypi:`pytest-opentelemetry` - *last release*: Oct 01, 2023, + *last release*: Nov 22, 2024, *status*: N/A, *requires*: pytest @@ -8516,7 +8535,7 @@ This list contains 1546 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Sep 06, 2024, + *last release*: Nov 26, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=6.2.4 @@ -8530,11 +8549,11 @@ This list contains 1546 plugins. ASYNC Pytest plugin for Playwright :pypi:`pytest-playwright-asyncio` - *last release*: Aug 29, 2023, + *last release*: Nov 26, 2024, *status*: N/A, - *requires*: N/A - + *requires*: pytest<9.0.0,>=6.2.4 + A pytest wrapper with fixtures for Playwright to automate web browsers :pypi:`pytest-playwright-enhanced` *last release*: Mar 24, 2024, @@ -8676,6 +8695,13 @@ This list contains 1546 plugins. A pytest plugin to help with testing pop projects + :pypi:`pytest-porcochu` + *last release*: Nov 28, 2024, + *status*: 5 - Production/Stable, + *requires*: N/A + + Show surprise when tests are passing + :pypi:`pytest-portion` *last release*: Jan 28, 2021, *status*: 4 - Beta, @@ -8768,7 +8794,7 @@ This list contains 1546 plugins. pytest plugin for configuration profiles :pypi:`pytest-profiling` - *last release*: Oct 17, 2024, + *last release*: Nov 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -8929,7 +8955,7 @@ This list contains 1546 plugins. Record PyMySQL queries and mock with the stored data. :pypi:`pytest-pyodide` - *last release*: Jul 23, 2024, + *last release*: Nov 23, 2024, *status*: N/A, *requires*: pytest @@ -9279,7 +9305,7 @@ This list contains 1546 plugins. 用例执行过程中录制视频 :pypi:`pytest-redis` - *last release*: Jun 19, 2024, + *last release*: Nov 27, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.2 @@ -9412,7 +9438,7 @@ This list contains 1546 plugins. py.test plugin for repeating single test multiple times. :pypi:`pytest-replay` - *last release*: Sep 03, 2024, + *last release*: Nov 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -9544,6 +9570,13 @@ This list contains 1546 plugins. Pytest Plugin to Mock Requests Futures + :pypi:`pytest-requirements` + *last release*: Nov 29, 2024, + *status*: N/A, + *requires*: pytest + + pytest plugin for using custom markers to relate tests to requirements and usecases + :pypi:`pytest-requires` *last release*: Dec 21, 2021, *status*: 4 - Beta, @@ -9692,9 +9725,9 @@ This list contains 1546 plugins. Adds the ability to retry flaky tests in CI environments :pypi:`pytest-retry-class` - *last release*: Mar 25, 2023, + *last release*: Nov 24, 2024, *status*: N/A, - *requires*: pytest (>=5.3) + *requires*: pytest>=5.3 A pytest plugin to rerun entire class on failure @@ -9951,7 +9984,7 @@ This list contains 1546 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Nov 19, 2024, + *last release*: Nov 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10028,7 +10061,7 @@ This list contains 1546 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Nov 19, 2024, + *last release*: Nov 30, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10063,7 +10096,7 @@ This list contains 1546 plugins. Send pytest execution result email :pypi:`pytest-sentry` - *last release*: Apr 25, 2024, + *last release*: Nov 25, 2024, *status*: N/A, *requires*: pytest @@ -10084,7 +10117,7 @@ This list contains 1546 plugins. test server exec cmd :pypi:`pytest-server-fixtures` - *last release*: Oct 17, 2024, + *last release*: Nov 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -10217,7 +10250,7 @@ This list contains 1546 plugins. Expand command-line shortcuts listed in pytest configuration :pypi:`pytest-shutil` - *last release*: Oct 17, 2024, + *last release*: Nov 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -10350,11 +10383,11 @@ This list contains 1546 plugins. Automated bad smell detection tool for Pytest :pypi:`pytest-smoke` - *last release*: Nov 07, 2024, + *last release*: Nov 27, 2024, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 - pytest plugin for supporting smoke testing + Pytest plugin for smoke testing :pypi:`pytest-smtp` *last release*: Feb 20, 2021, @@ -10602,7 +10635,7 @@ This list contains 1546 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Sep 26, 2024, + *last release*: Nov 24, 2024, *status*: N/A, *requires*: N/A @@ -10749,7 +10782,7 @@ This list contains 1546 plugins. pytest plugin for openSTF :pypi:`pytest-stochastics` - *last release*: Oct 31, 2024, + *last release*: Nov 30, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -11623,6 +11656,13 @@ This list contains 1546 plugins. Test Class Base + :pypi:`pytest-tt-ddriven` + *last release*: Nov 29, 2024, + *status*: N/A, + *requires*: N/A + + A simple project that act as a placeholder for project name + :pypi:`pytest-tui` *last release*: Dec 08, 2023, *status*: 4 - Beta, @@ -11869,7 +11909,7 @@ This list contains 1546 plugins. py.test fixture for creating a virtual environment :pypi:`pytest-verbose-parametrize` - *last release*: Oct 17, 2024, + *last release*: Nov 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -11883,16 +11923,16 @@ This list contains 1546 plugins. A simple pytest plugin that will shrink pytest output when specified, to fit vim quickfix window. :pypi:`pytest-virtualenv` - *last release*: Oct 17, 2024, + *last release*: Nov 29, 2024, *status*: 5 - Production/Stable, *requires*: pytest Virtualenv fixture for py.test :pypi:`pytest-visual` - *last release*: Nov 01, 2023, - *status*: 3 - Alpha, - *requires*: pytest >=7.0.0 + *last release*: Nov 28, 2024, + *status*: 4 - Beta, + *requires*: pytest>=7.0.0 @@ -11939,7 +11979,7 @@ This list contains 1546 plugins. pytest plugin for automatic recording of http stubbed tests :pypi:`pytest-vulture` - *last release*: Nov 22, 2024, + *last release*: Nov 25, 2024, *status*: N/A, *requires*: pytest>=7.0.0 @@ -12044,7 +12084,7 @@ This list contains 1546 plugins. Welian API Automation test framework pytest plugin :pypi:`pytest-when` - *last release*: May 28, 2024, + *last release*: Nov 29, 2024, *status*: N/A, *requires*: pytest>=7.3.1 From 9892455da544e1d444000b39214578facf95ca37 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 1 Dec 2024 07:52:29 -0300 Subject: [PATCH 1010/1271] Remove 'pip' command hint from release announcement While of course `pip` is still the most used tool to install packages, currently there are a lot of alternatives (`poetry`, `uv`, etc), so it feels a bit dated to suggest `pip install --upgrade` directly on the release announcement. Also, all the other release notes do not mention `pip` too, so it makes sense to remove it from the patch release announcement. --- scripts/release.patch.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/release.patch.rst b/scripts/release.patch.rst index 59fbe50ce0e..120cae51702 100644 --- a/scripts/release.patch.rst +++ b/scripts/release.patch.rst @@ -3,9 +3,7 @@ pytest-{version} pytest {version} has just been released to PyPI. -This is a bug-fix release, being a drop-in replacement. To upgrade:: - - pip install --upgrade pytest +This is a bug-fix release, being a drop-in replacement. The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. From b2dce69664759943b77ab0926ab5ab7f4f605136 Mon Sep 17 00:00:00 2001 From: Daara <3807987+daara-s@users.noreply.github.com> Date: Sun, 1 Dec 2024 11:08:33 +0000 Subject: [PATCH 1011/1271] Warn `pytest.mark.usefixtures()` is used without arguments (#13008) Closes #12426 Closes #12439 --------- Co-authored-by: Jiajun Xu Co-authored-by: Bruno Oliveira --- AUTHORS | 2 ++ changelog/12426.improvement.rst | 1 + src/_pytest/fixtures.py | 9 ++++++++- testing/plugins_integration/pytest.ini | 1 + testing/python/fixtures.py | 17 +++++++++++++++++ 5 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 changelog/12426.improvement.rst diff --git a/AUTHORS b/AUTHORS index 303d04133cb..6399461ee59 100644 --- a/AUTHORS +++ b/AUTHORS @@ -103,6 +103,7 @@ Cornelius Riemenschneider CrazyMerlyn Cristian Vera Cyrus Maden +Daara Shaw Damian Skrzypczak Daniel Grana Daniel Hahler @@ -209,6 +210,7 @@ Jeff Rackauckas Jeff Widman Jenni Rinker Jens Tröger +Jiajun Xu John Eddie Ayson John Litborn John Towler diff --git a/changelog/12426.improvement.rst b/changelog/12426.improvement.rst new file mode 100644 index 00000000000..0da1f838aea --- /dev/null +++ b/changelog/12426.improvement.rst @@ -0,0 +1 @@ +A warning is now issued when :ref:`pytest.mark.usefixtures ref` is used without specifying any fixtures. Previously, empty usefixtures markers were silently ignored. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 76c4b919aff..fc6541c1404 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -71,6 +71,7 @@ from _pytest.scope import HIGH_SCOPES from _pytest.scope import Scope from _pytest.warning_types import PytestRemovedIn9Warning +from _pytest.warning_types import PytestWarning if sys.version_info < (3, 11): @@ -1562,7 +1563,13 @@ def _getautousenames(self, node: nodes.Node) -> Iterator[str]: def _getusefixturesnames(self, node: nodes.Item) -> Iterator[str]: """Return the names of usefixtures fixtures applicable to node.""" - for mark in node.iter_markers(name="usefixtures"): + for marker_node, mark in node.iter_markers_with_node(name="usefixtures"): + if not mark.args: + marker_node.warn( + PytestWarning( + f"usefixtures() in {node.nodeid} without arguments has no effect" + ) + ) yield from mark.args def getfixtureclosure( diff --git a/testing/plugins_integration/pytest.ini b/testing/plugins_integration/pytest.ini index 3bacdef62ab..86058fbbac8 100644 --- a/testing/plugins_integration/pytest.ini +++ b/testing/plugins_integration/pytest.ini @@ -3,4 +3,5 @@ addopts = --strict-markers asyncio_mode = strict filterwarnings = error::pytest.PytestWarning + ignore:usefixtures.* without arguments has no effect:pytest.PytestWarning ignore:.*.fspath is deprecated and will be replaced by .*.path.*:pytest.PytestDeprecationWarning diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index c939b221f22..cac00ab5401 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1435,6 +1435,23 @@ def test_two(self): reprec = pytester.inline_run() reprec.assertoutcome(passed=2) + def test_empty_usefixtures_marker(self, pytester: Pytester) -> None: + """Empty usefixtures() marker issues a warning (#12439).""" + pytester.makepyfile( + """ + import pytest + + @pytest.mark.usefixtures() + def test_one(): + assert 1 == 1 + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + "*PytestWarning: usefixtures() in test_empty_usefixtures_marker.py::test_one" + " without arguments has no effect" + ) + def test_usefixtures_ini(self, pytester: Pytester) -> None: pytester.makeini( """ From df7bfde99bb998912159d274367b816fbfe5cfec Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 1 Dec 2024 08:11:21 -0300 Subject: [PATCH 1012/1271] Also mention to announce releases on BlueSky --- RELEASING.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASING.rst b/RELEASING.rst index 030a5c8652f..52910de0002 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -168,4 +168,4 @@ Both automatic and manual processes described above follow the same steps from t * python-announce-list@python.org (all releases) * testing-in-python@lists.idyll.org (only major/minor releases) - And announce it on `Twitter `_ with the ``#pytest`` hashtag. + And announce it on `Twitter `_ and `BlueSky `_ with the ``#pytest`` hashtag. From 6ccb5e75d6dd5494e6ef725cd7a41d3b81116585 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 1 Dec 2024 09:03:24 -0300 Subject: [PATCH 1013/1271] Fix collection and simplify tests We should not collect classes at the module level when the config is set. Doing so is not only the correct thing, as we will not collect the class, but also lets us avoid having the same logic at the Class collector (as it will not be collected at all now). --- src/_pytest/python.py | 21 +- testing/test_collect_imported_tests.py | 103 ++++++++ testing/test_collect_imports.py | 317 ------------------------- 3 files changed, 108 insertions(+), 333 deletions(-) create mode 100644 testing/test_collect_imported_tests.py delete mode 100644 testing/test_collect_imports.py diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 9c00252c5f8..6e7360c5b7d 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -405,6 +405,7 @@ def collect(self) -> Iterable[nodes.Item | nodes.Collector]: # __dict__ is definition ordered. seen: set[str] = set() dict_values: list[list[nodes.Item | nodes.Collector]] = [] + collect_imported_tests = self.session.config.getini("collect_imported_tests") ihook = self.ihook for dic in dicts: values: list[nodes.Item | nodes.Collector] = [] @@ -417,12 +418,10 @@ def collect(self) -> Iterable[nodes.Item | nodes.Collector]: continue seen.add(name) - if not self.session.config.getini("collect_imported_tests"): - # Do not collect imported functions - if inspect.isfunction(obj) and isinstance(self, Module): - fn_defined_at = obj.__module__ - in_module = self._getobj().__name__ - if fn_defined_at != in_module: + if not collect_imported_tests and isinstance(self, Module): + # Do not collect functions and classes from other modules. + if inspect.isfunction(obj) or inspect.isclass(obj): + if obj.__module__ != self._getobj().__name__: continue res = ihook.pytest_pycollect_makeitem( @@ -750,16 +749,6 @@ def newinstance(self): return self.obj() def collect(self) -> Iterable[nodes.Item | nodes.Collector]: - if not self.config.getini("collect_imported_tests"): - # This entire branch will discard (not collect) a class - # if it is imported (defined in a different module) - if isinstance(self, Class) and isinstance(self.parent, Module): - if inspect.isclass(self._getobj()): - class_defined_at = self._getobj().__module__ - in_module = self.parent._getobj().__name__ - if class_defined_at != in_module: - return [] - if not safe_getattr(self.obj, "__test__", True): return [] if hasinit(self.obj): diff --git a/testing/test_collect_imported_tests.py b/testing/test_collect_imported_tests.py new file mode 100644 index 00000000000..4b264ce6069 --- /dev/null +++ b/testing/test_collect_imported_tests.py @@ -0,0 +1,103 @@ +"""Tests for the `collect_imported_tests` configuration value.""" + +from __future__ import annotations + +import textwrap + +from _pytest.pytester import Pytester +import pytest + + +def setup_import_class_test(pytester: Pytester) -> None: + src_dir = pytester.mkdir("src") + tests_dir = pytester.mkdir("tests") + src_file = src_dir / "foo.py" + + src_file.write_text( + textwrap.dedent("""\ + class Testament: + def test_collections(self): + pass + + def test_testament(): pass + """), + encoding="utf-8", + ) + + test_file = tests_dir / "foo_test.py" + test_file.write_text( + textwrap.dedent("""\ + from foo import Testament, test_testament + + class TestDomain: + def test(self): + testament = Testament() + assert testament + """), + encoding="utf-8", + ) + + pytester.syspathinsert(src_dir) + + +def test_collect_imports_disabled(pytester: Pytester) -> None: + """ + When collect_imported_tests is disabled, only objects in the + test modules are collected as tests, so the imported names (`Testament` and `test_testament`) + are not collected. + """ + pytester.makeini( + """ + [pytest] + testpaths = "tests" + collect_imported_tests = false + """ + ) + + setup_import_class_test(pytester) + result = pytester.runpytest("-v") + result.stdout.fnmatch_lines( + [ + "tests/foo_test.py::TestDomain::test PASSED*", + ] + ) + + # Ensure that the hooks were only called for the collected item. + reprec = result.reprec # type:ignore[attr-defined] + reports = reprec.getreports("pytest_collectreport") + [modified] = reprec.getcalls("pytest_collection_modifyitems") + [item_collected] = reprec.getcalls("pytest_itemcollected") + + assert [x.nodeid for x in reports] == [ + "", + "tests/foo_test.py::TestDomain", + "tests/foo_test.py", + "tests", + ] + assert [x.nodeid for x in modified.items] == ["tests/foo_test.py::TestDomain::test"] + assert item_collected.item.nodeid == "tests/foo_test.py::TestDomain::test" + + +@pytest.mark.parametrize("configure_ini", [False, True]) +def test_collect_imports_enabled(pytester: Pytester, configure_ini: bool) -> None: + """ + When collect_imported_tests is enabled (the default), all names in the + test modules are collected as tests. + """ + if configure_ini: + pytester.makeini( + """ + [pytest] + collect_imported_tests = true + """ + ) + + setup_import_class_test(pytester) + result = pytester.runpytest("-v") + result.stdout.fnmatch_lines( + [ + "tests/foo_test.py::Testament::test_collections PASSED*", + "tests/foo_test.py::test_testament PASSED*", + "tests/foo_test.py::TestDomain::test PASSED*", + ] + ) diff --git a/testing/test_collect_imports.py b/testing/test_collect_imports.py deleted file mode 100644 index 1c56c9155e5..00000000000 --- a/testing/test_collect_imports.py +++ /dev/null @@ -1,317 +0,0 @@ -from __future__ import annotations - -import textwrap -from typing import Any - -from _pytest.fixtures import FixtureRequest -from _pytest.main import Session -from _pytest.pytester import Pytester -from _pytest.pytester import RecordedHookCall -from _pytest.pytester import RunResult -from _pytest.reports import CollectReport -import pytest - - -# Start of tests for classes - - -def run_import_class_test( - pytester: Pytester, passed: int = 0, errors: int = 0 -) -> RunResult: - src_dir = pytester.mkdir("src") - tests_dir = pytester.mkdir("tests") - src_file = src_dir / "foo.py" - - src_file.write_text( - textwrap.dedent("""\ - class Testament(object): - def __init__(self): - super().__init__() - self.collections = ["stamp", "coin"] - - def personal_property(self): - return [f"my {x} collection" for x in self.collections] - """), - encoding="utf-8", - ) - - test_file = tests_dir / "foo_test.py" - test_file.write_text( - textwrap.dedent("""\ - import sys - import os - - current_file = os.path.abspath(__file__) - current_dir = os.path.dirname(current_file) - parent_dir = os.path.abspath(os.path.join(current_dir, '..')) - sys.path.append(parent_dir) - - from src.foo import Testament - - class TestDomain: - def test_testament(self): - testament = Testament() - assert testament.personal_property() - """), - encoding="utf-8", - ) - - result = pytester.runpytest() - result.assert_outcomes(passed=passed, errors=errors) - return result - - -def test_collect_imports_disabled(pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - testpaths = "tests" - collect_imported_tests = false - """) - - run_import_class_test(pytester, passed=1) - - # Verify that the state of hooks - reprec = pytester.inline_run() - reports = reprec.getreports("pytest_collectreport") - modified = reprec.getcalls("pytest_collection_modifyitems") - items_collected = reprec.getcalls("pytest_itemcollected") - - assert len(reports) == 5 - assert len(modified) == 1 - assert len(items_collected) == 1 - for x in items_collected: - assert x.item._getobj().__name__ == "test_testament" - - -def test_collect_imports_default(pytester: Pytester) -> None: - run_import_class_test(pytester, errors=1) - - -def test_collect_imports_enabled(pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - collect_imported_tests = true - """) - - run_import_class_test(pytester, errors=1) - - -# End of tests for classes -################################# -# Start of tests for functions - - -def run_import_functions_test( - pytester: Pytester, passed: int, errors: int, failed: int -) -> RunResult: - # Note that these "tests" should _not_ be treated as tests if `collect_imported_tests = false` - # They are normal functions in that case, that happens to have test_* or *_test in the name. - # Thus should _not_ be collected! - pytester.makepyfile( - **{ - "src/foo.py": textwrap.dedent( - """\ - def test_function(): - some_random_computation = 5 - return some_random_computation - - def test_bar(): - pass - """ - ) - } - ) - - # Inferred from the comment above, this means that there is _only_ one actual test - # which should result in only 1 passing test being ran. - pytester.makepyfile( - **{ - "tests/foo_test.py": textwrap.dedent( - """\ - import sys - import os - - current_file = os.path.abspath(__file__) - current_dir = os.path.dirname(current_file) - parent_dir = os.path.abspath(os.path.join(current_dir, '..')) - sys.path.append(parent_dir) - - from src.foo import * - - class TestDomain: - def test_important(self): - res = test_function() - if res == 5: - pass - """ - ) - } - ) - - result = pytester.runpytest() - result.assert_outcomes(passed=passed, errors=errors, failed=failed) - return result - - -def test_collect_function_imports_enabled(pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - testpaths = "tests" - collect_imported_tests = true - """) - - run_import_functions_test(pytester, passed=2, errors=0, failed=1) - reprec = pytester.inline_run() - items_collected = reprec.getcalls("pytest_itemcollected") - # Recall that the default is `collect_imported_tests = true`. - # Which means that the normal functions are now interpreted as - # valid tests and `test_function()` will fail. - assert len(items_collected) == 3 - for x in items_collected: - assert x.item._getobj().__name__ in [ - "test_important", - "test_bar", - "test_function", - ] - - -def test_behaviour_without_testpaths_set_and_false(pytester: Pytester) -> None: - # Make sure `collect_imported_tests` has no dependence on `testpaths` - pytester.makeini(""" - [pytest] - collect_imported_tests = false - """) - - run_import_functions_test(pytester, passed=1, errors=0, failed=0) - reprec = pytester.inline_run() - items_collected = reprec.getcalls("pytest_itemcollected") - assert len(items_collected) == 1 - for x in items_collected: - assert x.item._getobj().__name__ == "test_important" - - -def test_behaviour_without_testpaths_set_and_true(pytester: Pytester) -> None: - # Make sure `collect_imported_tests` has no dependence on `testpaths` - pytester.makeini(""" - [pytest] - collect_imported_tests = true - """) - - run_import_functions_test(pytester, passed=2, errors=0, failed=1) - reprec = pytester.inline_run() - items_collected = reprec.getcalls("pytest_itemcollected") - assert len(items_collected) == 3 - - -class TestHookBehaviour: - collect_outcomes: dict[str, Any] = {} - - @pytest.mark.parametrize("step", [1, 2, 3]) - def test_hook_behaviour(self, pytester: Pytester, step: int) -> None: - if step == 1: - self._test_hook_default_behaviour(pytester) - elif step == 2: - self._test_hook_behaviour_when_collect_off(pytester) - elif step == 3: - self._test_hook_behaviour() - - @pytest.fixture(scope="class", autouse=True) - def setup_collect_outcomes(self, request: FixtureRequest) -> None: - request.cls.collect_outcomes = {} - - def _test_hook_default_behaviour(self, pytester: Pytester) -> None: - pytester.makepyfile( - **{ - "tests/foo_test.py": textwrap.dedent( - """\ - class TestDomain: - def test_important(self): - pass - """ - ) - } - ) - - result = pytester.runpytest() - result.assert_outcomes(passed=1) - reprec = pytester.inline_run() - reports = reprec.getreports("pytest_collectreport") - modified = reprec.getcalls("pytest_collection_modifyitems") - items_collected = reprec.getcalls("pytest_itemcollected") - - self.collect_outcomes["default"] = { - "result": result.parseoutcomes(), - "modified": modified, - "items_collected": items_collected, - "reports": reports, - } - - def _test_hook_behaviour_when_collect_off(self, pytester: Pytester) -> None: - pytester.makeini(""" - [pytest] - collect_imported_tests = false - """) - res = run_import_functions_test(pytester, passed=1, errors=0, failed=0) - reprec = pytester.inline_run() - reports = reprec.getreports("pytest_collectreport") - modified = reprec.getcalls("pytest_collection_modifyitems") - items_collected = reprec.getcalls("pytest_itemcollected") - - self.collect_outcomes["collect_off"] = { - "result": res.parseoutcomes(), - "modified": modified, - "items_collected": items_collected, - "reports": reports, - } - - def _test_hook_behaviour(self) -> None: - default = self.collect_outcomes["default"] - collect_off = self.collect_outcomes["collect_off"] - - # Check that the two tests above did indeed result in the same outcome. - assert default["result"] == collect_off["result"] - - assert len(default["modified"]) == len(collect_off["modified"]) == 1 - - def_modified_record: RecordedHookCall = default["modified"][0] - off_modified_record: RecordedHookCall = collect_off["modified"][0] - def_sess: Session = def_modified_record.__dict__["session"] - off_sess: Session = off_modified_record.__dict__["session"] - - assert def_sess.exitstatus == off_sess.exitstatus - assert def_sess.testsfailed == off_sess.testsfailed - assert def_sess.testscollected == off_sess.testscollected - - def_items = def_modified_record.__dict__["items"] - off_items = off_modified_record.__dict__["items"] - assert len(def_items) == len(off_items) == 1 - assert def_items[0].name == off_items[0].name - - assert ( - len(default["items_collected"]) == len(collect_off["items_collected"]) == 1 - ) - - # Check if the same tests got collected - def_items_record: RecordedHookCall = default["items_collected"][0] - off_items_record: RecordedHookCall = collect_off["items_collected"][0] - def_items = def_items_record.__dict__["item"] - off_items = off_items_record.__dict__["item"] - assert def_items.name == off_items.name - - def compare_report(r1: CollectReport, r2: CollectReport) -> None: - assert r1.result[0].name == r2.result[0].name - assert len(r1.result) == len(r2.result) - assert r1.outcome == r2.outcome - - # Function test_important - compare_report(default["reports"][1], collect_off["reports"][2]) - # Class TestDomain - compare_report(default["reports"][2], collect_off["reports"][3]) - # Module foo_test.py - compare_report(default["reports"][3], collect_off["reports"][4]) - - # + 1 since src dir is collected - assert len(default["reports"]) + 1 == len(collect_off["reports"]) - - # Two Dirs will be collected, src and test. - assert len(collect_off["reports"][5].result) == 2 From e2ec64e0374d31e64a59a2b12e4d35de062f07a2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 1 Dec 2024 09:24:40 -0300 Subject: [PATCH 1014/1271] Improve docs --- changelog/12749.feature.rst | 20 ++++++++++++++++++-- doc/en/reference/reference.rst | 22 +++++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/changelog/12749.feature.rst b/changelog/12749.feature.rst index cda0db6c930..c3b7ca5d321 100644 --- a/changelog/12749.feature.rst +++ b/changelog/12749.feature.rst @@ -1,5 +1,21 @@ -New :confval:`collect_imported_tests`: when enabled (the default) pytest will collect classes/functions in test modules even if they are imported from another file. +pytest traditionally collects classes/functions in the test module namespace even if they are imported from another file. -Setting this to False will make pytest collect classes/functions from test files only if they are defined in that file (as opposed to imported there). +For example: + +.. code-block:: python + + # contents of src/domain.py + class Testament: ... + + + # contents of tests/test_testament.py + from domain import Testament + + + def test_testament(): ... + +In this scenario with the default options, pytest will collect the class `Testament` from `tests/test_testament.py` because it starts with `Test`, even though in this case it is a production class being imported in the test module namespace. + +This behavior can now be prevented by setting the new :confval:`collect_imported_tests` configuration option to ``false``, which will make pytest collect classes/functions from test files **only** if they are defined in that file. -- by :user:`FreerGit` diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 53f9470f756..1e550a115c8 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1306,7 +1306,7 @@ passed multiple times. The expected format is ``name=value``. For example:: .. versionadded:: 8.4 Setting this to ``false`` will make pytest collect classes/functions from test - files only if they are defined in that file (as opposed to imported there). + files **only** if they are defined in that file (as opposed to imported there). .. code-block:: ini @@ -1315,6 +1315,26 @@ passed multiple times. The expected format is ``name=value``. For example:: Default: ``true`` + pytest traditionally collects classes/functions in the test module namespace even if they are imported from another file. + + For example: + + .. code-block:: python + + # contents of src/domain.py + class Testament: ... + + + # contents of tests/test_testament.py + from domain import Testament + + + def test_testament(): ... + + In this scenario, with the default options, pytest will collect the class `Testament` from `tests/test_testament.py` because it starts with `Test`, even though in this case it is a production class being imported in the test module namespace. + + Set ``collected_imported_tests`` to ``false`` in the configuration file prevents that. + .. confval:: consider_namespace_packages Controls if pytest should attempt to identify `namespace packages `__ From 43865ed1a9642596007c382d212da460e4cdfedb Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 1 Dec 2024 09:30:33 -0300 Subject: [PATCH 1015/1271] Pass tests directory explicitly --- testing/test_collect_imported_tests.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/testing/test_collect_imported_tests.py b/testing/test_collect_imported_tests.py index 4b264ce6069..158d9342b41 100644 --- a/testing/test_collect_imported_tests.py +++ b/testing/test_collect_imported_tests.py @@ -49,13 +49,12 @@ def test_collect_imports_disabled(pytester: Pytester) -> None: pytester.makeini( """ [pytest] - testpaths = "tests" collect_imported_tests = false """ ) setup_import_class_test(pytester) - result = pytester.runpytest("-v") + result = pytester.runpytest("-v", "tests") result.stdout.fnmatch_lines( [ "tests/foo_test.py::TestDomain::test PASSED*", @@ -93,7 +92,7 @@ def test_collect_imports_enabled(pytester: Pytester, configure_ini: bool) -> Non ) setup_import_class_test(pytester) - result = pytester.runpytest("-v") + result = pytester.runpytest("-v", "tests") result.stdout.fnmatch_lines( [ "tests/foo_test.py::Testament::test_collections PASSED*", From d2327d9deb4b6f54104039817540951b5deced7b Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 1 Dec 2024 09:31:11 -0300 Subject: [PATCH 1016/1271] Rename test helper --- testing/test_collect_imported_tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testing/test_collect_imported_tests.py b/testing/test_collect_imported_tests.py index 158d9342b41..28b92e17f6f 100644 --- a/testing/test_collect_imported_tests.py +++ b/testing/test_collect_imported_tests.py @@ -8,7 +8,7 @@ import pytest -def setup_import_class_test(pytester: Pytester) -> None: +def setup_files(pytester: Pytester) -> None: src_dir = pytester.mkdir("src") tests_dir = pytester.mkdir("tests") src_file = src_dir / "foo.py" @@ -53,7 +53,7 @@ def test_collect_imports_disabled(pytester: Pytester) -> None: """ ) - setup_import_class_test(pytester) + setup_files(pytester) result = pytester.runpytest("-v", "tests") result.stdout.fnmatch_lines( [ @@ -91,7 +91,7 @@ def test_collect_imports_enabled(pytester: Pytester, configure_ini: bool) -> Non """ ) - setup_import_class_test(pytester) + setup_files(pytester) result = pytester.runpytest("-v", "tests") result.stdout.fnmatch_lines( [ From ea1a79a93a353223cd8dcb039e45d10ae20bc168 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 4 Dec 2024 21:19:49 +0000 Subject: [PATCH 1017/1271] threadexception enhancements (#13016) --- changelog/13016.improvement.rst | 9 ++ src/_pytest/threadexception.py | 236 ++++++++++++++++++---------- src/_pytest/unraisableexception.py | 6 +- testing/test_threadexception.py | 131 ++++++++++++++- testing/test_unraisableexception.py | 36 +++++ 5 files changed, 328 insertions(+), 90 deletions(-) create mode 100644 changelog/13016.improvement.rst diff --git a/changelog/13016.improvement.rst b/changelog/13016.improvement.rst new file mode 100644 index 00000000000..22642fc6f4f --- /dev/null +++ b/changelog/13016.improvement.rst @@ -0,0 +1,9 @@ +A number of :ref:`threadexception ` enhancements: + +* Set the excepthook as early as possible and unset it as late as possible, to collect the most possible number of unhandled exceptions from threads. +* join threads for 1 second just before unsetting the excepthook, to collect any straggling exceptions +* Collect multiple thread exceptions per test phase. +* Report the :mod:`tracemalloc` allocation traceback (if available). +* Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures. +* Report the thread exception as the cause of the :class:`pytest.PytestUnhandledThreadExceptionWarning` exception if raised. +* Extract the ``name`` of the thread object in the excepthook which should help with resurrection of the thread. diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index 4a76a9d9000..38665d2731f 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -1,97 +1,167 @@ from __future__ import annotations +import collections from collections.abc import Callable -from collections.abc import Generator +import functools +import sys import threading +import time import traceback -from types import TracebackType -from typing import Any +from typing import NamedTuple from typing import TYPE_CHECKING import warnings +from _pytest.config import Config +from _pytest.nodes import Item +from _pytest.stash import StashKey +from _pytest.tracemalloc import tracemalloc_message import pytest if TYPE_CHECKING: - from typing_extensions import Self - - -# Copied from cpython/Lib/test/support/threading_helper.py, with modifications. -class catch_threading_exception: - """Context manager catching threading.Thread exception using - threading.excepthook. - - Storing exc_value using a custom hook can create a reference cycle. The - reference cycle is broken explicitly when the context manager exits. - - Storing thread using a custom hook can resurrect it if it is set to an - object which is being finalized. Exiting the context manager clears the - stored object. - - Usage: - with threading_helper.catch_threading_exception() as cm: - # code spawning a thread which raises an exception - ... - # check the thread exception: use cm.args - ... - # cm.args attribute no longer exists at this point - # (to break a reference cycle) - """ - - def __init__(self) -> None: - self.args: threading.ExceptHookArgs | None = None - self._old_hook: Callable[[threading.ExceptHookArgs], Any] | None = None - - def _hook(self, args: threading.ExceptHookArgs) -> None: - self.args = args - - def __enter__(self) -> Self: - self._old_hook = threading.excepthook - threading.excepthook = self._hook - return self - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> None: - assert self._old_hook is not None - threading.excepthook = self._old_hook - self._old_hook = None - del self.args - - -def thread_exception_runtest_hook() -> Generator[None]: - with catch_threading_exception() as cm: + pass + +if sys.version_info < (3, 11): + from exceptiongroup import ExceptionGroup + + +def join_threads() -> None: + start = time.monotonic() + current_thread = threading.current_thread() + # This function is executed right at the end of the pytest run, just + # before we return an exit code, which is where the interpreter joins + # any remaining non-daemonic threads anyway, so it's ok to join all the + # threads. However there might be threads that depend on some shutdown + # signal that happens after pytest finishes, so we want to limit the + # join time somewhat. A one second timeout seems reasonable. + timeout = 1 + for thread in threading.enumerate(): + if thread is not current_thread and not thread.daemon: + # TODO: raise an error/warning if there's dangling threads. + thread.join(timeout - (time.monotonic() - start)) + + +class ThreadExceptionMeta(NamedTuple): + msg: str + cause_msg: str + exc_value: BaseException | None + + +thread_exceptions: StashKey[collections.deque[ThreadExceptionMeta | BaseException]] = ( + StashKey() +) + + +def collect_thread_exception(config: Config) -> None: + pop_thread_exception = config.stash[thread_exceptions].pop + errors: list[pytest.PytestUnhandledThreadExceptionWarning | RuntimeError] = [] + meta = None + hook_error = None + try: + while True: + try: + meta = pop_thread_exception() + except IndexError: + break + + if isinstance(meta, BaseException): + hook_error = RuntimeError("Failed to process thread exception") + hook_error.__cause__ = meta + errors.append(hook_error) + continue + + msg = meta.msg + try: + warnings.warn(pytest.PytestUnhandledThreadExceptionWarning(msg)) + except pytest.PytestUnhandledThreadExceptionWarning as e: + # This except happens when the warning is treated as an error (e.g. `-Werror`). + if meta.exc_value is not None: + # Exceptions have a better way to show the traceback, but + # warnings do not, so hide the traceback from the msg and + # set the cause so the traceback shows up in the right place. + e.args = (meta.cause_msg,) + e.__cause__ = meta.exc_value + errors.append(e) + + if len(errors) == 1: + raise errors[0] + if errors: + raise ExceptionGroup("multiple thread exception warnings", errors) + finally: + del errors, meta, hook_error + + +def cleanup( + *, config: Config, prev_hook: Callable[[threading.ExceptHookArgs], object] +) -> None: + try: try: - yield + join_threads() + collect_thread_exception(config) finally: - if cm.args: - thread_name = ( - "" if cm.args.thread is None else cm.args.thread.name - ) - msg = f"Exception in thread {thread_name}\n\n" - msg += "".join( - traceback.format_exception( - cm.args.exc_type, - cm.args.exc_value, - cm.args.exc_traceback, - ) - ) - warnings.warn(pytest.PytestUnhandledThreadExceptionWarning(msg)) - - -@pytest.hookimpl(wrapper=True, trylast=True) -def pytest_runtest_setup() -> Generator[None]: - yield from thread_exception_runtest_hook() - - -@pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_call() -> Generator[None]: - yield from thread_exception_runtest_hook() - - -@pytest.hookimpl(wrapper=True, tryfirst=True) -def pytest_runtest_teardown() -> Generator[None]: - yield from thread_exception_runtest_hook() + threading.excepthook = prev_hook + finally: + del config.stash[thread_exceptions] + + +def thread_exception_hook( + args: threading.ExceptHookArgs, + /, + *, + append: Callable[[ThreadExceptionMeta | BaseException], object], +) -> None: + try: + # we need to compute these strings here as they might change after + # the excepthook finishes and before the metadata object is + # collected by a pytest hook + thread_name = "" if args.thread is None else args.thread.name + summary = f"Exception in thread {thread_name}" + traceback_message = "\n\n" + "".join( + traceback.format_exception( + args.exc_type, + args.exc_value, + args.exc_traceback, + ) + ) + tracemalloc_tb = "\n" + tracemalloc_message(args.thread) + msg = summary + traceback_message + tracemalloc_tb + cause_msg = summary + tracemalloc_tb + + append( + ThreadExceptionMeta( + # Compute these strings here as they might change later + msg=msg, + cause_msg=cause_msg, + exc_value=args.exc_value, + ) + ) + except BaseException as e: + append(e) + # Raising this will cause the exception to be logged twice, once in our + # collect_thread_exception and once by sys.excepthook + # which is fine - this should never happen anyway and if it does + # it should probably be reported as a pytest bug. + raise + + +def pytest_configure(config: Config) -> None: + prev_hook = threading.excepthook + deque: collections.deque[ThreadExceptionMeta | BaseException] = collections.deque() + config.stash[thread_exceptions] = deque + config.add_cleanup(functools.partial(cleanup, config=config, prev_hook=prev_hook)) + threading.excepthook = functools.partial(thread_exception_hook, append=deque.append) + + +@pytest.hookimpl(trylast=True) +def pytest_runtest_setup(item: Item) -> None: + collect_thread_exception(item.config) + + +@pytest.hookimpl(trylast=True) +def pytest_runtest_call(item: Item) -> None: + collect_thread_exception(item.config) + + +@pytest.hookimpl(trylast=True) +def pytest_runtest_teardown(item: Item) -> None: + collect_thread_exception(item.config) diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index 2bd7f07e862..7826aeccd12 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -101,6 +101,9 @@ def unraisable_hook( append: Callable[[UnraisableMeta | BaseException], object], ) -> None: try: + # we need to compute these strings here as they might change after + # the unraisablehook finishes and before the metadata object is + # collected by a pytest hook err_msg = ( "Exception ignored in" if unraisable.err_msg is None else unraisable.err_msg ) @@ -118,9 +121,6 @@ def unraisable_hook( append( UnraisableMeta( - # we need to compute these strings here as they might change after - # the unraisablehook finishes and before the unraisable object is - # collected by a hook msg=msg, cause_msg=cause_msg, exc_value=unraisable.exc_value, diff --git a/testing/test_threadexception.py b/testing/test_threadexception.py index abd30144914..6ee93ab9c22 100644 --- a/testing/test_threadexception.py +++ b/testing/test_threadexception.py @@ -23,7 +23,7 @@ def test_2(): pass ) result = pytester.runpytest() assert result.ret == 0 - assert result.parseoutcomes() == {"passed": 2, "warnings": 1} + result.assert_outcomes(passed=2, warnings=1) result.stdout.fnmatch_lines( [ "*= warnings summary =*", @@ -59,7 +59,7 @@ def test_2(): pass ) result = pytester.runpytest() assert result.ret == 0 - assert result.parseoutcomes() == {"passed": 2, "warnings": 1} + result.assert_outcomes(passed=2, warnings=1) result.stdout.fnmatch_lines( [ "*= warnings summary =*", @@ -96,7 +96,7 @@ def test_2(): pass ) result = pytester.runpytest() assert result.ret == 0 - assert result.parseoutcomes() == {"passed": 2, "warnings": 1} + result.assert_outcomes(passed=2, warnings=1) result.stdout.fnmatch_lines( [ "*= warnings summary =*", @@ -130,4 +130,127 @@ def test_2(): pass ) result = pytester.runpytest() assert result.ret == pytest.ExitCode.TESTS_FAILED - assert result.parseoutcomes() == {"passed": 1, "failed": 1} + result.assert_outcomes(passed=1, failed=1) + + +@pytest.mark.filterwarnings("error::pytest.PytestUnhandledThreadExceptionWarning") +def test_threadexception_warning_multiple_errors(pytester: Pytester) -> None: + pytester.makepyfile( + test_it=""" + import threading + + def test_it(): + def oops(): + raise ValueError("Oops") + + t = threading.Thread(target=oops, name="MyThread") + t.start() + t.join() + + t = threading.Thread(target=oops, name="MyThread2") + t.start() + t.join() + + def test_2(): pass + """ + ) + result = pytester.runpytest() + assert result.ret == pytest.ExitCode.TESTS_FAILED + result.assert_outcomes(passed=1, failed=1) + result.stdout.fnmatch_lines( + [" | *ExceptionGroup: multiple thread exception warnings (2 sub-exceptions)"] + ) + + +def test_unraisable_collection_failure(pytester: Pytester) -> None: + pytester.makepyfile( + test_it=""" + import threading + + class Thread(threading.Thread): + @property + def name(self): + raise RuntimeError("oops!") + + def test_it(): + def oops(): + raise ValueError("Oops") + + t = Thread(target=oops, name="MyThread") + t.start() + t.join() + + def test_2(): pass + """ + ) + + result = pytester.runpytest() + assert result.ret == 1 + result.assert_outcomes(passed=1, failed=1) + result.stdout.fnmatch_lines( + ["E RuntimeError: Failed to process thread exception"] + ) + + +def test_unhandled_thread_exception_after_teardown(pytester: Pytester) -> None: + pytester.makepyfile( + test_it=""" + import time + import threading + import pytest + + def thread(): + def oops(): + time.sleep(0.5) + raise ValueError("Oops") + + t = threading.Thread(target=oops, name="MyThread") + t.start() + + def test_it(request): + request.config.add_cleanup(thread) + """ + ) + + result = pytester.runpytest() + + # TODO: should be a test failure or error + assert result.ret == pytest.ExitCode.INTERNAL_ERROR + + result.assert_outcomes(passed=1) + result.stderr.fnmatch_lines("ValueError: Oops") + + +@pytest.mark.filterwarnings("error::pytest.PytestUnhandledThreadExceptionWarning") +def test_possibly_none_excinfo(pytester: Pytester) -> None: + pytester.makepyfile( + test_it=""" + import threading + import types + + def test_it(): + threading.excepthook( + types.SimpleNamespace( + exc_type=RuntimeError, + exc_value=None, + exc_traceback=None, + thread=None, + ) + ) + """ + ) + + result = pytester.runpytest() + + # TODO: should be a test failure or error + assert result.ret == pytest.ExitCode.TESTS_FAILED + + result.assert_outcomes(failed=1) + result.stdout.fnmatch_lines( + [ + "E pytest.PytestUnhandledThreadExceptionWarning:" + " Exception in thread ", + "E ", + "E NoneType: None", + ] + ) diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index 70248e1c122..5aa6aa773d9 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -234,3 +234,39 @@ def test_it(): result.assert_outcomes(passed=1) result.stderr.fnmatch_lines("ValueError: del is broken") + + +@pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning") +def test_possibly_none_excinfo(pytester: Pytester) -> None: + pytester.makepyfile( + test_it=""" + import sys + import types + + def test_it(): + sys.unraisablehook( + types.SimpleNamespace( + exc_type=RuntimeError, + exc_value=None, + exc_traceback=None, + err_msg=None, + object=None, + ) + ) + """ + ) + + result = pytester.runpytest() + + # TODO: should be a test failure or error + assert result.ret == pytest.ExitCode.TESTS_FAILED + + result.assert_outcomes(failed=1) + result.stdout.fnmatch_lines( + [ + "E pytest.PytestUnraisableExceptionWarning:" + " Exception ignored in: None", + "E ", + "E NoneType: None", + ] + ) From 80da4274398617274ff9e576339184ce77893d9b Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Thu, 5 Dec 2024 12:52:23 +0000 Subject: [PATCH 1018/1271] Remove thread join from threadexception plugin (#13027) As per review comment: https://github.com/pytest-dev/pytest/pull/13016#discussion_r1870340465. Closes #13028. --------- Co-authored-by: Bruno Oliveira --- changelog/13016.improvement.rst | 1 - src/_pytest/threadexception.py | 21 +++------------------ testing/test_threadexception.py | 3 +-- 3 files changed, 4 insertions(+), 21 deletions(-) diff --git a/changelog/13016.improvement.rst b/changelog/13016.improvement.rst index 22642fc6f4f..634672ab69b 100644 --- a/changelog/13016.improvement.rst +++ b/changelog/13016.improvement.rst @@ -1,7 +1,6 @@ A number of :ref:`threadexception ` enhancements: * Set the excepthook as early as possible and unset it as late as possible, to collect the most possible number of unhandled exceptions from threads. -* join threads for 1 second just before unsetting the excepthook, to collect any straggling exceptions * Collect multiple thread exceptions per test phase. * Report the :mod:`tracemalloc` allocation traceback (if available). * Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures. diff --git a/src/_pytest/threadexception.py b/src/_pytest/threadexception.py index 38665d2731f..eb57783be26 100644 --- a/src/_pytest/threadexception.py +++ b/src/_pytest/threadexception.py @@ -5,7 +5,6 @@ import functools import sys import threading -import time import traceback from typing import NamedTuple from typing import TYPE_CHECKING @@ -25,22 +24,6 @@ from exceptiongroup import ExceptionGroup -def join_threads() -> None: - start = time.monotonic() - current_thread = threading.current_thread() - # This function is executed right at the end of the pytest run, just - # before we return an exit code, which is where the interpreter joins - # any remaining non-daemonic threads anyway, so it's ok to join all the - # threads. However there might be threads that depend on some shutdown - # signal that happens after pytest finishes, so we want to limit the - # join time somewhat. A one second timeout seems reasonable. - timeout = 1 - for thread in threading.enumerate(): - if thread is not current_thread and not thread.daemon: - # TODO: raise an error/warning if there's dangling threads. - thread.join(timeout - (time.monotonic() - start)) - - class ThreadExceptionMeta(NamedTuple): msg: str cause_msg: str @@ -96,7 +79,9 @@ def cleanup( ) -> None: try: try: - join_threads() + # We don't join threads here, so exceptions raised from any + # threads still running by the time _threading_atexits joins them + # do not get captured (see #13027). collect_thread_exception(config) finally: threading.excepthook = prev_hook diff --git a/testing/test_threadexception.py b/testing/test_threadexception.py index 6ee93ab9c22..5dad07b8b85 100644 --- a/testing/test_threadexception.py +++ b/testing/test_threadexception.py @@ -195,17 +195,16 @@ def test_2(): pass def test_unhandled_thread_exception_after_teardown(pytester: Pytester) -> None: pytester.makepyfile( test_it=""" - import time import threading import pytest def thread(): def oops(): - time.sleep(0.5) raise ValueError("Oops") t = threading.Thread(target=oops, name="MyThread") t.start() + t.join() def test_it(request): request.config.add_cleanup(thread) From 9fc8a3ea74490c2801a111a76817bcd4a4030f6d Mon Sep 17 00:00:00 2001 From: Nathan Rousseau Date: Fri, 6 Dec 2024 20:35:35 +0100 Subject: [PATCH 1019/1271] Fix file name in comment of .git-blame-ignore-revs (closes #13033) (#13034) As explained in [issue 13033](https://github.com/pytest-dev/pytest/issues/13033), the file name on the comment explaining how to setup the *.git-blame-ignore-revs* file weren't up-to-date with the current name of the file. --- .git-blame-ignore-revs | 2 +- AUTHORS | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index d6aac5c425d..4f4cdb6c564 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -5,7 +5,7 @@ # # To "install" it: # -# git config --local blame.ignoreRevsFile .gitblameignore +# git config --local blame.ignoreRevsFile .git-blame-ignore-revs # run black 703e4b11ba76171eccd3f13e723c47b810ded7ef diff --git a/AUTHORS b/AUTHORS index 5c046ff5988..5aa9045208a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -305,6 +305,7 @@ Milan Lesnek Miro Hrončok mrbean-bremen Nathan Goldbaum +Nathan Rousseau Nathaniel Compton Nathaniel Waisbrot Nauman Ahmed From 44cb841e44d2aec29952f6aa586c2204cabe6b50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Dec 2024 20:37:30 +0100 Subject: [PATCH 1020/1271] build(deps): Bump django in /testing/plugins_integration (#13032) Bumps [django](https://github.com/django/django) from 5.1.3 to 5.1.4. - [Commits](https://github.com/django/django/compare/5.1.3...5.1.4) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index ec6b9418c93..a9b1e67ff7a 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[curio,trio]==4.6.2.post1 -django==5.1.3 +django==5.1.4 pytest-asyncio==0.24.0 pytest-bdd==8.0.0 pytest-cov==6.0.0 From ecde993e17efb3f34157642a111ba20f476aa80a Mon Sep 17 00:00:00 2001 From: Shaygan Hooshyari Date: Sat, 7 Dec 2024 12:51:26 +0100 Subject: [PATCH 1021/1271] fixtures: replace fixture representation with a class (#12473) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During the sprint we discussed fixing the above issue and thought maybe it's a better idea to add a better representation to fixtures. To do this without patching the object more, this PR refactors fixtures to have a class with attributes. The main rational behind that is: - Now we have a type for fixtures makes it easier to check for fixture types and no need to perform cast on objects. Removed monkey patching. - They are no longer functions that carry a class within them. - When you decorate a function with a fixture it's not possible to call it anymore. So it makes more sense for it to not be a function or method. Fixes #11525 --------- Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) Co-authored-by: Bruno Oliveira Co-authored-by: Ran Benita --- AUTHORS | 1 + changelog/11525.improvement.rst | 3 + doc/en/conf.py | 1 + src/_pytest/assertion/rewrite.py | 4 +- src/_pytest/compat.py | 48 +--------- src/_pytest/fixtures.py | 157 +++++++++++++++++-------------- testing/code/test_source.py | 12 +-- testing/python/fixtures.py | 72 ++++++++++++++ testing/test_assertrewrite.py | 17 ++++ testing/test_collection.py | 4 +- testing/test_compat.py | 17 ++-- 11 files changed, 203 insertions(+), 133 deletions(-) create mode 100644 changelog/11525.improvement.rst diff --git a/AUTHORS b/AUTHORS index 5aa9045208a..3419accfa6b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -393,6 +393,7 @@ Serhii Mozghovyi Seth Junot Shantanu Jain Sharad Nair +Shaygan Hooshyari Shubham Adep Simon Blanchard Simon Gomizelj diff --git a/changelog/11525.improvement.rst b/changelog/11525.improvement.rst new file mode 100644 index 00000000000..1935ce59343 --- /dev/null +++ b/changelog/11525.improvement.rst @@ -0,0 +1,3 @@ +Fixtures are now clearly represented in the output as a "fixture object", not as a normal function as before, making it easy for beginners to catch mistakes such as referencing a fixture declared in the same module but not requested in the test function. + +-- by :user:`the-compiler` and :user:`glyphack` diff --git a/doc/en/conf.py b/doc/en/conf.py index 9558a75f927..47fc70dce85 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -75,6 +75,7 @@ ("py:class", "_pytest._code.code.TerminalRepr"), ("py:class", "TerminalRepr"), ("py:class", "_pytest.fixtures.FixtureFunctionMarker"), + ("py:class", "_pytest.fixtures.FixtureFunctionDefinition"), ("py:class", "_pytest.logging.LogCaptureHandler"), ("py:class", "_pytest.mark.structures.ParameterSet"), # Intentionally undocumented/private diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index c414b30a4a8..41e3d271396 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -31,6 +31,7 @@ from _pytest._version import version from _pytest.assertion import util from _pytest.config import Config +from _pytest.fixtures import FixtureFunctionDefinition from _pytest.main import Session from _pytest.pathlib import absolutepath from _pytest.pathlib import fnmatch_ex @@ -472,7 +473,8 @@ def _format_assertmsg(obj: object) -> str: def _should_repr_global_name(obj: object) -> bool: if callable(obj): - return False + # For pytest fixtures the __repr__ method provides more information than the function name. + return isinstance(obj, FixtureFunctionDefinition) try: return not hasattr(obj, "__name__") diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 1aa7495bddb..053ef1fd1fd 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -4,7 +4,6 @@ from __future__ import annotations from collections.abc import Callable -import dataclasses import enum import functools import inspect @@ -205,59 +204,16 @@ def ascii_escaped(val: bytes | str) -> str: return ret.translate(_non_printable_ascii_translate_table) -@dataclasses.dataclass -class _PytestWrapper: - """Dummy wrapper around a function object for internal use only. - - Used to correctly unwrap the underlying function object when we are - creating fixtures, because we wrap the function object ourselves with a - decorator to issue warnings when the fixture function is called directly. - """ - - obj: Any - - def get_real_func(obj): """Get the real function object of the (possibly) wrapped object by - functools.wraps or functools.partial.""" - start_obj = obj - for i in range(100): - # __pytest_wrapped__ is set by @pytest.fixture when wrapping the fixture function - # to trigger a warning if it gets called directly instead of by pytest: we don't - # want to unwrap further than this otherwise we lose useful wrappings like @mock.patch (#3774) - new_obj = getattr(obj, "__pytest_wrapped__", None) - if isinstance(new_obj, _PytestWrapper): - obj = new_obj.obj - break - new_obj = getattr(obj, "__wrapped__", None) - if new_obj is None: - break - obj = new_obj - else: - from _pytest._io.saferepr import saferepr + :func:`functools.wraps`, or :func:`functools.partial`.""" + obj = inspect.unwrap(obj) - raise ValueError( - f"could not find real function of {saferepr(start_obj)}\nstopped at {saferepr(obj)}" - ) if isinstance(obj, functools.partial): obj = obj.func return obj -def get_real_method(obj, holder): - """Attempt to obtain the real function object that might be wrapping - ``obj``, while at the same time returning a bound method to ``holder`` if - the original object was a bound method.""" - try: - is_method = hasattr(obj, "__func__") - obj = get_real_func(obj) - except Exception: # pragma: no cover - return obj - if is_method and hasattr(obj, "__get__") and callable(obj.__get__): - obj = obj.__get__(holder) - return obj - - def getimfunc(func): try: return func.__func__ diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index fc6541c1404..8b79dbcb932 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -40,10 +40,8 @@ from _pytest._code.code import FormattedExcinfo from _pytest._code.code import TerminalRepr from _pytest._io import TerminalWriter -from _pytest.compat import _PytestWrapper from _pytest.compat import assert_never from _pytest.compat import get_real_func -from _pytest.compat import get_real_method from _pytest.compat import getfuncargnames from _pytest.compat import getimfunc from _pytest.compat import getlocation @@ -152,13 +150,12 @@ def get_scope_node(node: nodes.Node, scope: Scope) -> nodes.Node | None: assert_never(scope) +# TODO: Try to use FixtureFunctionDefinition instead of the marker def getfixturemarker(obj: object) -> FixtureFunctionMarker | None: - """Return fixturemarker or None if it doesn't exist or raised - exceptions.""" - return cast( - Optional[FixtureFunctionMarker], - safe_getattr(obj, "_pytestfixturefunction", None), - ) + """Return fixturemarker or None if it doesn't exist""" + if isinstance(obj, FixtureFunctionDefinition): + return obj._fixture_function_marker + return None # Algorithm for sorting on a per-parametrized resource setup basis. @@ -1181,31 +1178,6 @@ def pytest_fixture_setup( return result -def wrap_function_to_error_out_if_called_directly( - function: FixtureFunction, - fixture_marker: FixtureFunctionMarker, -) -> FixtureFunction: - """Wrap the given fixture function so we can raise an error about it being called directly, - instead of used as an argument in a test function.""" - name = fixture_marker.name or function.__name__ - message = ( - f'Fixture "{name}" called directly. Fixtures are not meant to be called directly,\n' - "but are created automatically when test functions request them as parameters.\n" - "See https://docs.pytest.org/en/stable/explanation/fixtures.html for more information about fixtures, and\n" - "https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly about how to update your code." - ) - - @functools.wraps(function) - def result(*args, **kwargs): - fail(message, pytrace=False) - - # Keep reference to the original function in our own custom attribute so we don't unwrap - # further than this point and lose useful wrappings like @mock.patch (#3774). - result.__pytest_wrapped__ = _PytestWrapper(function) # type: ignore[attr-defined] - - return cast(FixtureFunction, result) - - @final @dataclasses.dataclass(frozen=True) class FixtureFunctionMarker: @@ -1220,11 +1192,11 @@ class FixtureFunctionMarker: def __post_init__(self, _ispytest: bool) -> None: check_ispytest(_ispytest) - def __call__(self, function: FixtureFunction) -> FixtureFunction: + def __call__(self, function: FixtureFunction) -> FixtureFunctionDefinition: if inspect.isclass(function): raise ValueError("class fixtures not supported (maybe in the future)") - if getattr(function, "_pytestfixturefunction", False): + if isinstance(function, FixtureFunctionDefinition): raise ValueError( f"@pytest.fixture is being applied more than once to the same function {function.__name__!r}" ) @@ -1232,7 +1204,9 @@ def __call__(self, function: FixtureFunction) -> FixtureFunction: if hasattr(function, "pytestmark"): warnings.warn(MARKED_FIXTURE, stacklevel=2) - function = wrap_function_to_error_out_if_called_directly(function, self) + fixture_definition = FixtureFunctionDefinition( + function=function, fixture_function_marker=self, _ispytest=True + ) name = self.name or function.__name__ if name == "request": @@ -1242,21 +1216,68 @@ def __call__(self, function: FixtureFunction) -> FixtureFunction: pytrace=False, ) - # Type ignored because https://github.com/python/mypy/issues/2087. - function._pytestfixturefunction = self # type: ignore[attr-defined] - return function + return fixture_definition + + +# TODO: paramspec/return type annotation tracking and storing +class FixtureFunctionDefinition: + def __init__( + self, + *, + function: Callable[..., Any], + fixture_function_marker: FixtureFunctionMarker, + instance: object | None = None, + _ispytest: bool = False, + ) -> None: + check_ispytest(_ispytest) + self.name = fixture_function_marker.name or function.__name__ + # In order to show the function that this fixture contains in messages. + # Set the __name__ to be same as the function __name__ or the given fixture name. + self.__name__ = self.name + self._fixture_function_marker = fixture_function_marker + if instance is not None: + self._fixture_function = cast( + Callable[..., Any], function.__get__(instance) + ) + else: + self._fixture_function = function + functools.update_wrapper(self, function) + + def __repr__(self) -> str: + return f"" + + def __get__(self, instance, owner=None): + """Behave like a method if the function it was applied to was a method.""" + return FixtureFunctionDefinition( + function=self._fixture_function, + fixture_function_marker=self._fixture_function_marker, + instance=instance, + _ispytest=True, + ) + + def __call__(self, *args: Any, **kwds: Any) -> Any: + message = ( + f'Fixture "{self.name}" called directly. Fixtures are not meant to be called directly,\n' + "but are created automatically when test functions request them as parameters.\n" + "See https://docs.pytest.org/en/stable/explanation/fixtures.html for more information about fixtures, and\n" + "https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly" + ) + fail(message, pytrace=False) + + def _get_wrapped_function(self) -> Callable[..., Any]: + return self._fixture_function @overload def fixture( - fixture_function: FixtureFunction, + fixture_function: Callable[..., object], *, scope: _ScopeName | Callable[[str, Config], _ScopeName] = ..., params: Iterable[object] | None = ..., autouse: bool = ..., ids: Sequence[object | None] | Callable[[Any], object | None] | None = ..., name: str | None = ..., -) -> FixtureFunction: ... +) -> FixtureFunctionDefinition: ... @overload @@ -1279,7 +1300,7 @@ def fixture( autouse: bool = False, ids: Sequence[object | None] | Callable[[Any], object | None] | None = None, name: str | None = None, -) -> FixtureFunctionMarker | FixtureFunction: +) -> FixtureFunctionMarker | FixtureFunctionDefinition: """Decorator to mark a fixture factory function. This decorator can be used, with or without parameters, to define a @@ -1774,33 +1795,31 @@ def parsefactories( # The attribute can be an arbitrary descriptor, so the attribute # access below can raise. safe_getattr() ignores such exceptions. obj_ub = safe_getattr(holderobj_tp, name, None) - marker = getfixturemarker(obj_ub) - if not isinstance(marker, FixtureFunctionMarker): - # Magic globals with __getattr__ might have got us a wrong - # fixture attribute. - continue - - # OK we know it is a fixture -- now safe to look up on the _instance_. - obj = getattr(holderobj, name) - - if marker.name: - name = marker.name - - # During fixture definition we wrap the original fixture function - # to issue a warning if called directly, so here we unwrap it in - # order to not emit the warning when pytest itself calls the - # fixture function. - func = get_real_method(obj, holderobj) - - self._register_fixture( - name=name, - nodeid=nodeid, - func=func, - scope=marker.scope, - params=marker.params, - ids=marker.ids, - autouse=marker.autouse, - ) + if type(obj_ub) is FixtureFunctionDefinition: + marker = obj_ub._fixture_function_marker + if marker.name: + fixture_name = marker.name + else: + fixture_name = name + + # OK we know it is a fixture -- now safe to look up on the _instance_. + try: + obj = getattr(holderobj, name) + # if the fixture is named in the decorator we cannot find it in the module + except AttributeError: + obj = obj_ub + + func = obj._get_wrapped_function() + + self._register_fixture( + name=fixture_name, + nodeid=nodeid, + func=func, + scope=marker.scope, + params=marker.params, + ids=marker.ids, + autouse=marker.autouse, + ) def getfixturedefs( self, argname: str, node: nodes.Node diff --git a/testing/code/test_source.py b/testing/code/test_source.py index d78d9e7025a..843233fe21e 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -478,14 +478,14 @@ def deco_mark(): def deco_fixture(): assert False - src = inspect.getsource(deco_fixture) + src = inspect.getsource(deco_fixture._get_wrapped_function()) assert src == " @pytest.fixture\n def deco_fixture():\n assert False\n" - # currently Source does not unwrap decorators, testing the - # existing behavior here for explicitness, but perhaps we should revisit/change this - # in the future - assert str(Source(deco_fixture)).startswith("@functools.wraps(function)") + # Make sure the decorator is not a wrapped function + assert not str(Source(deco_fixture)).startswith("@functools.wraps(function)") assert ( - textwrap.indent(str(Source(get_real_func(deco_fixture))), " ") + "\n" == src + textwrap.indent(str(Source(deco_fixture._get_wrapped_function())), " ") + + "\n" + == src ) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index cac00ab5401..dc69781095b 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -1606,6 +1606,63 @@ def teardown_module(): result = pytester.runpytest() result.stdout.no_fnmatch_line("* ERROR at teardown *") + def test_unwrapping_pytest_fixture(self, pytester: Pytester) -> None: + """Ensure the unwrap method on `FixtureFunctionDefinition` correctly wraps and unwraps methods and functions""" + pytester.makepyfile( + """ + import pytest + import inspect + + class FixtureFunctionDefTestClass: + def __init__(self) -> None: + self.i = 10 + + @pytest.fixture + def fixture_function_def_test_method(self): + return self.i + + + @pytest.fixture + def fixture_function_def_test_func(): + return 9 + + + def test_get_wrapped_func_returns_method(): + obj = FixtureFunctionDefTestClass() + wrapped_function_result = ( + obj.fixture_function_def_test_method._get_wrapped_function() + ) + assert inspect.ismethod(wrapped_function_result) + assert wrapped_function_result() == 10 + + + def test_get_wrapped_func_returns_function(): + assert fixture_function_def_test_func._get_wrapped_function()() == 9 + """ + ) + result = pytester.runpytest() + result.assert_outcomes(passed=2) + + def test_fixture_wrapped_looks_liked_wrapped_function( + self, pytester: Pytester + ) -> None: + """Ensure that `FixtureFunctionDefinition` behaves like the function it wrapped.""" + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def fixture_function_def_test_func(): + return 9 + fixture_function_def_test_func.__doc__ = "documentation" + + def test_fixture_has_same_doc(): + assert fixture_function_def_test_func.__doc__ == "documentation" + """ + ) + result = pytester.runpytest() + result.assert_outcomes(passed=1) + class TestFixtureManagerParseFactories: @pytest.fixture @@ -4526,6 +4583,21 @@ def fixt(): ) +def test_fixture_class(pytester: Pytester) -> None: + """Check if an error is raised when using @pytest.fixture on a class.""" + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + class A: + pass + """ + ) + result = pytester.runpytest() + result.assert_outcomes(errors=1) + + def test_fixture_param_shadowing(pytester: Pytester) -> None: """Parametrized arguments would be shadowed if a fixture with the same name also exists (#5036)""" pytester.makepyfile( diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index eed59a2dce7..02d1c3e52ff 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -975,6 +975,23 @@ def __repr__(self): assert "UnicodeDecodeError" not in msg assert "UnicodeEncodeError" not in msg + def test_assert_fixture(self, pytester: Pytester) -> None: + pytester.makepyfile( + """\ + import pytest + @pytest.fixture + def fixt(): + return 42 + + def test_something(): # missing "fixt" argument + assert fixt == 42 + """ + ) + result = pytester.runpytest() + result.stdout.fnmatch_lines( + ["*assert )> == 42*"] + ) + class TestRewriteOnImport: def test_pycache_is_a_file(self, pytester: Pytester) -> None: diff --git a/testing/test_collection.py b/testing/test_collection.py index 7d28610e015..ccd57eeef43 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1284,7 +1284,7 @@ def test_1(): """ ) result = pytester.runpytest() - result.stdout.fnmatch_lines(["*1 passed in*"]) + result.assert_outcomes(passed=1) assert result.ret == 0 @@ -1348,7 +1348,7 @@ def test_collect_pyargs_with_testpaths( with monkeypatch.context() as mp: mp.chdir(root) result = pytester.runpytest_subprocess() - result.stdout.fnmatch_lines(["*1 passed in*"]) + result.assert_outcomes(passed=1) def test_initial_conftests_with_testpaths(pytester: Pytester) -> None: diff --git a/testing/test_compat.py b/testing/test_compat.py index 86868858956..3722bfcfb40 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -7,7 +7,6 @@ from functools import wraps from typing import TYPE_CHECKING -from _pytest.compat import _PytestWrapper from _pytest.compat import assert_never from _pytest.compat import get_real_func from _pytest.compat import safe_getattr @@ -38,10 +37,7 @@ def __getattr__(self, attr): with pytest.raises( ValueError, - match=( - "could not find real function of \n" - "stopped at " - ), + match=("wrapper loop when unwrapping "), ): get_real_func(evil) @@ -65,10 +61,13 @@ def func(): wrapped_func2 = decorator(decorator(wrapped_func)) assert get_real_func(wrapped_func2) is func - # special case for __pytest_wrapped__ attribute: used to obtain the function up until the point - # a function was wrapped by pytest itself - wrapped_func2.__pytest_wrapped__ = _PytestWrapper(wrapped_func) - assert get_real_func(wrapped_func2) is wrapped_func + # obtain the function up until the point a function was wrapped by pytest itself + @pytest.fixture + def wrapped_func3(): + pass # pragma: no cover + + wrapped_func4 = decorator(wrapped_func3) + assert get_real_func(wrapped_func4) is wrapped_func3._get_wrapped_function() def test_get_real_func_partial() -> None: From 8cff12865691b14b4bce70e0e304524619be385d Mon Sep 17 00:00:00 2001 From: dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com> Date: Sat, 7 Dec 2024 21:41:54 +0800 Subject: [PATCH 1022/1271] fix `AttributeError` crash when using `--import-mode=importlib` (#13029) Only parent modules with the `__path__` attribute can be used by the `find_spec` function, and most of the standard library does not meet this condition. Fixes #13026 . --- changelog/13026.bugfix.rst | 1 + src/_pytest/pathlib.py | 5 ++++- testing/test_pathlib.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 changelog/13026.bugfix.rst diff --git a/changelog/13026.bugfix.rst b/changelog/13026.bugfix.rst new file mode 100644 index 00000000000..d10edbd111a --- /dev/null +++ b/changelog/13026.bugfix.rst @@ -0,0 +1 @@ +Fixed :class:`AttributeError` crash when using ``--import-mode=importlib`` when top-level directory same name as another module of the standard library. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 55b27985d31..7c368e0dcd0 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -668,7 +668,10 @@ def _import_module_using_spec( parent_module: ModuleType | None = None if parent_module_name: parent_module = sys.modules.get(parent_module_name) - if parent_module is None: + # If the parent_module lacks the `__path__` attribute, AttributeError when finding a submodule's spec, + # requiring re-import according to the path. + need_reimport = not hasattr(parent_module, "__path__") + if parent_module is None or need_reimport: # Get parent_location based on location, get parent_path based on path. if module_path.name == "__init__.py": # If the current module is in a package, diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 436a6b9cae3..a21d1edf970 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -922,6 +922,37 @@ def test_my_test(): result = pytester.runpytest("--import-mode=importlib") result.stdout.fnmatch_lines("* 1 passed *") + @pytest.mark.parametrize("name", ["code", "time", "math"]) + def test_importlib_same_name_as_stl( + self, pytester, ns_param: bool, tmp_path: Path, name: str + ): + """Import a namespace package with the same name as the standard library (#13026).""" + file_path = pytester.path / f"{name}/foo/test_demo.py" + file_path.parent.mkdir(parents=True) + file_path.write_text( + dedent( + """ + def test_demo(): + pass + """ + ), + encoding="utf-8", + ) + + # unit test + __import__(name) # import standard library + + import_path( # import user files + file_path, + mode=ImportMode.importlib, + root=pytester.path, + consider_namespace_packages=ns_param, + ) + + # E2E test + result = pytester.runpytest("--import-mode=importlib") + result.stdout.fnmatch_lines("* 1 passed *") + def create_installed_doctests_and_tests_dir( self, path: Path, monkeypatch: MonkeyPatch ) -> tuple[Path, Path, Path]: From eacc65654b4a626d1543760b354bca773d2cca93 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 8 Dec 2024 06:08:15 +0000 Subject: [PATCH 1023/1271] [automated] Update plugin list (#13040) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 156 ++++++++++++++++++------------- 1 file changed, 90 insertions(+), 66 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 62535d2d366..f0e209008c6 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 :pypi:`pytest-bazel` A pytest runner with bazel support Sep 27, 2024 4 - Beta pytest - :pypi:`pytest-bdd` BDD for pytest Nov 14, 2024 6 - Mature pytest>=7.0.0 + :pypi:`pytest-bdd` BDD for pytest Dec 05, 2024 6 - Mature pytest>=7.0.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Nov 26, 2024 4 - Beta pytest>=5.2 :pypi:`pytest-bdd-report` A pytest-bdd plugin for generating useful and informative BDD test reports Nov 27, 2024 N/A pytest>=7.1.3 @@ -158,7 +158,7 @@ This list contains 1551 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Nov 27, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Dec 06, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -268,7 +268,7 @@ This list contains 1551 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Oct 29, 2024 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Dec 06, 2024 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -284,7 +284,7 @@ This list contains 1551 plugins. :pypi:`pytest-confluence-report` Package stands for pytest plugin to upload results into Confluence page. Apr 17, 2022 N/A N/A :pypi:`pytest-console-scripts` Pytest plugin for testing console scripts May 31, 2023 4 - Beta pytest (>=4.0.0) :pypi:`pytest-consul` pytest plugin with fixtures for testing consul aware apps Nov 24, 2018 3 - Alpha pytest - :pypi:`pytest-container` Pytest fixtures for writing container based tests Apr 10, 2024 4 - Beta pytest>=3.10 + :pypi:`pytest-container` Pytest fixtures for writing container based tests Dec 04, 2024 4 - Beta pytest>=3.10 :pypi:`pytest-contextfixture` Define pytest fixtures as context managers. Mar 12, 2013 4 - Beta N/A :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-continuous` A pytest plugin to run tests continuously until failure or interruption. Apr 23, 2024 N/A N/A @@ -360,7 +360,7 @@ This list contains 1551 plugins. :pypi:`pytest-dependency` Manage dependencies of tests Dec 31, 2023 4 - Beta N/A :pypi:`pytest-depends` Tests that depend on other tests Apr 05, 2020 5 - Production/Stable pytest (>=3) :pypi:`pytest-deprecate` Mark tests as testing a deprecated feature with a warning note. Jul 01, 2019 N/A N/A - :pypi:`pytest-deprecator` A simple plugin to use with pytest Nov 14, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-deprecator` A simple plugin to use with pytest Dec 02, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-describe` Describe-style plugin for pytest Feb 10, 2024 5 - Production/Stable pytest <9,>=4.6 :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest :pypi:`pytest-deselect-if` A plugin to deselect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 @@ -463,21 +463,21 @@ This list contains 1551 plugins. :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Nov 17, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest - :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Mar 15, 2024 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Dec 03, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-elasticsearch-test` Elasticsearch fixtures and fixture factories for Pytest. Aug 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jul 25, 2024 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 14, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Nov 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Nov 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Nov 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Nov 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Nov 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Nov 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Nov 14, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Nov 14, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Dec 02, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Dec 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Dec 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Dec 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Dec 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Dec 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Dec 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Dec 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Dec 02, 2024 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) @@ -531,6 +531,7 @@ This list contains 1551 plugins. :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest + :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI Dec 03, 2024 N/A pytest<8.0.0,>=7.2.1 :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) @@ -567,6 +568,7 @@ This list contains 1551 plugins. :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Feb 22, 2024 4 - Beta pytest >=3.5.0 :pypi:`pytest-fixture-config` Fixture configuration utils for py.test Oct 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-fixture-forms` A pytest plugin for creating fixtures that holds different forms between tests. Dec 06, 2024 N/A pytest<9.0.0,>=7.0.0 :pypi:`pytest-fixture-maker` Pytest plugin to load fixtures from YAML files Sep 21, 2021 N/A N/A :pypi:`pytest-fixture-marker` A pytest plugin to add markers based on fixtures used. Oct 11, 2020 5 - Production/Stable N/A :pypi:`pytest-fixture-order` pytest plugin to control fixture evaluation order May 16, 2022 5 - Production/Stable pytest (>=3.0) @@ -590,7 +592,7 @@ This list contains 1551 plugins. :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Aug 14, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-fly` pytest observer Apr 14, 2024 3 - Alpha pytest + :pypi:`pytest-fly` pytest observer Dec 03, 2024 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) @@ -617,12 +619,12 @@ This list contains 1551 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Nov 14, 2024 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Dec 06, 2024 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-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 19, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Dec 05, 2024 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -666,7 +668,7 @@ This list contains 1551 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 29, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Dec 07, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -734,14 +736,14 @@ This list contains 1551 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Nov 19, 2024 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Jun 27, 2024 5 - Production/Stable pytest<7.2.0,>=6 + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Dec 02, 2024 5 - Production/Stable pytest<9.0.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Oct 28, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Dec 04, 2024 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Nov 24, 2024 4 - Beta pytest - :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Sep 18, 2024 4 - Beta pytest>=5 + :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Dec 05, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A :pypi:`pytest-item-dict` Get a hierarchical dict of session.items Nov 14, 2024 4 - Beta pytest>=8.3.0 @@ -1166,7 +1168,7 @@ This list contains 1551 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Oct 31, 2024 N/A pytest>=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Dec 04, 2024 N/A pytest>=3.8.0 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A :pypi:`pytest-req` pytest requests plugin Aug 31, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.2 @@ -1198,6 +1200,7 @@ This list contains 1551 plugins. :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments May 14, 2024 N/A pytest>=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Nov 24, 2024 N/A pytest>=5.3 :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A + :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Dec 03, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-reverse` Pytest plugin to reverse test order. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest @@ -1233,7 +1236,7 @@ This list contains 1551 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Nov 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 06, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1244,7 +1247,7 @@ This list contains 1551 plugins. :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 Feb 01, 2024 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 30, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Dec 06, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1347,7 +1350,7 @@ This list contains 1551 plugins. :pypi:`pytest-steps` Create step-wise / incremental tests in pytest. Sep 23, 2021 5 - Production/Stable N/A :pypi:`pytest-stepwise` Run a test suite one failing test at a time. Dec 01, 2015 4 - Beta N/A :pypi:`pytest-stf` pytest plugin for openSTF Sep 24, 2024 N/A pytest>=5.0 - :pypi:`pytest-stochastics` pytest plugin that allows selectively running tests several times and accepting \*some\* failures. Nov 30, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-stochastics` pytest plugin that allows selectively running tests several times and accepting \*some\* failures. Dec 01, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Sep 04, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) @@ -1359,7 +1362,7 @@ This list contains 1551 plugins. :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 Jul 24, 2024 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 Jul 17, 2024 4 - Beta pytest>=7.0 + :pypi:`pytest-subtests` unittest subTest() support and subtests fixture Dec 07, 2024 4 - Beta pytest>=7.4 :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Feb 01, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A @@ -1396,6 +1399,7 @@ This list contains 1551 plugins. :pypi:`pytest-testinfra` Test infrastructures May 26, 2024 5 - Production/Stable pytest>=6 :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-testit-parametrize` A pytest plugin for uploading parameterized tests parameters into TMS TestIT Dec 04, 2024 4 - Beta pytest>=8.3.3 :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 Feb 27, 2024 4 - Beta pytest <9,>=5 :pypi:`pytest-testmon-dev` selects tests affected by changed files and methods Mar 30, 2023 4 - Beta pytest (<8,>=5) @@ -1472,7 +1476,6 @@ This list contains 1551 plugins. :pypi:`pytest-tspwplib` A simple plugin to use with tspwplib Jan 08, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A - :pypi:`pytest-tt-ddriven` A simple project that act as a placeholder for project name Nov 29, 2024 N/A N/A :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A @@ -2396,7 +2399,7 @@ This list contains 1551 plugins. A pytest runner with bazel support :pypi:`pytest-bdd` - *last release*: Nov 14, 2024, + *last release*: Dec 05, 2024, *status*: 6 - Mature, *requires*: pytest>=7.0.0 @@ -2459,7 +2462,7 @@ This list contains 1551 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Nov 27, 2024, + *last release*: Dec 06, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3229,7 +3232,7 @@ This list contains 1551 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Oct 29, 2024, + *last release*: Dec 06, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3341,7 +3344,7 @@ This list contains 1551 plugins. pytest plugin with fixtures for testing consul aware apps :pypi:`pytest-container` - *last release*: Apr 10, 2024, + *last release*: Dec 04, 2024, *status*: 4 - Beta, *requires*: pytest>=3.10 @@ -3873,7 +3876,7 @@ This list contains 1551 plugins. Mark tests as testing a deprecated feature with a warning note. :pypi:`pytest-deprecator` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -4594,9 +4597,9 @@ This list contains 1551 plugins. Pytest plugin to select test using Ekstazi algorithm :pypi:`pytest-elasticsearch` - *last release*: Mar 15, 2024, + *last release*: Dec 03, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=7.0 + *requires*: pytest>=7.0 Elasticsearch fixtures and fixture factories for Pytest. @@ -4636,63 +4639,63 @@ This list contains 1551 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Nov 14, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -5069,6 +5072,13 @@ This list contains 1551 plugins. Additional pytest markers to dynamically enable/disable tests viia CLI flags + :pypi:`pytest-f3ts` + *last release*: Dec 03, 2024, + *status*: N/A, + *requires*: pytest<8.0.0,>=7.2.1 + + Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI + :pypi:`pytest-fabric` *last release*: Sep 12, 2018, *status*: 5 - Production/Stable, @@ -5321,6 +5331,13 @@ This list contains 1551 plugins. Fixture configuration utils for py.test + :pypi:`pytest-fixture-forms` + *last release*: Dec 06, 2024, + *status*: N/A, + *requires*: pytest<9.0.0,>=7.0.0 + + A pytest plugin for creating fixtures that holds different forms between tests. + :pypi:`pytest-fixture-maker` *last release*: Sep 21, 2021, *status*: N/A, @@ -5483,7 +5500,7 @@ This list contains 1551 plugins. A pytest plugin in order to provide logs via fluentbit :pypi:`pytest-fly` - *last release*: Apr 14, 2024, + *last release*: Dec 03, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -5672,7 +5689,7 @@ This list contains 1551 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Nov 14, 2024, + *last release*: Dec 06, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -5707,7 +5724,7 @@ This list contains 1551 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Nov 19, 2024, + *last release*: Dec 05, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -6015,7 +6032,7 @@ This list contains 1551 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Nov 29, 2024, + *last release*: Dec 07, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6491,9 +6508,9 @@ This list contains 1551 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Jun 27, 2024, + *last release*: Dec 02, 2024, *status*: 5 - Production/Stable, - *requires*: pytest<7.2.0,>=6 + *requires*: pytest<9.0.0,>=6 Pytest fixtures for Invenio. @@ -6526,7 +6543,7 @@ This list contains 1551 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Oct 28, 2024, + *last release*: Dec 04, 2024, *status*: N/A, *requires*: pytest @@ -6540,7 +6557,7 @@ This list contains 1551 plugins. Run pytest tests in isolated subprocesses :pypi:`pytest-isolate-mpi` - *last release*: Sep 18, 2024, + *last release*: Dec 05, 2024, *status*: 4 - Beta, *requires*: pytest>=5 @@ -9515,7 +9532,7 @@ This list contains 1551 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Oct 31, 2024, + *last release*: Dec 04, 2024, *status*: N/A, *requires*: pytest>=3.8.0 @@ -9738,6 +9755,13 @@ This list contains 1551 plugins. + :pypi:`pytest-revealtype-injector` + *last release*: Dec 03, 2024, + *status*: 4 - Beta, + *requires*: pytest>=7.0 + + Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. + :pypi:`pytest-reverse` *last release*: Oct 25, 2024, *status*: 5 - Production/Stable, @@ -9984,7 +10008,7 @@ This list contains 1551 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Nov 30, 2024, + *last release*: Dec 06, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10061,7 +10085,7 @@ This list contains 1551 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Nov 30, 2024, + *last release*: Dec 06, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10782,7 +10806,7 @@ This list contains 1551 plugins. pytest plugin for openSTF :pypi:`pytest-stochastics` - *last release*: Nov 30, 2024, + *last release*: Dec 01, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -10866,9 +10890,9 @@ This list contains 1551 plugins. A hack to explicitly set up and tear down fixtures. :pypi:`pytest-subtests` - *last release*: Jul 17, 2024, + *last release*: Dec 07, 2024, *status*: 4 - Beta, - *requires*: pytest>=7.0 + *requires*: pytest>=7.4 unittest subTest() support and subtests fixture @@ -11124,6 +11148,13 @@ This list contains 1551 plugins. Test infrastructures + :pypi:`pytest-testit-parametrize` + *last release*: Dec 04, 2024, + *status*: 4 - Beta, + *requires*: pytest>=8.3.3 + + A pytest plugin for uploading parameterized tests parameters into TMS TestIT + :pypi:`pytest-testlink-adaptor` *last release*: Dec 20, 2018, *status*: 4 - Beta, @@ -11656,13 +11687,6 @@ This list contains 1551 plugins. Test Class Base - :pypi:`pytest-tt-ddriven` - *last release*: Nov 29, 2024, - *status*: N/A, - *requires*: N/A - - A simple project that act as a placeholder for project name - :pypi:`pytest-tui` *last release*: Dec 08, 2023, *status*: 4 - Beta, From ebba6fdec6efa30d1d2256109448b705877f01bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:19:39 +0100 Subject: [PATCH 1024/1271] build(deps): Bump twisted in /testing/plugins_integration (#13043) Bumps [twisted](https://github.com/twisted/twisted) from 24.10.0 to 24.11.0. - [Release notes](https://github.com/twisted/twisted/releases) - [Changelog](https://github.com/twisted/twisted/blob/trunk/NEWS.rst) - [Commits](https://github.com/twisted/twisted/compare/twisted-24.10.0...twisted-24.11.0) --- updated-dependencies: - dependency-name: twisted dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index a9b1e67ff7a..b0c9774dd35 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -11,5 +11,5 @@ pytest-rerunfailures==15.0 pytest-sugar==1.0.0 pytest-trio==0.8.0 pytest-twisted==1.14.3 -twisted==24.10.0 +twisted==24.11.0 pytest-xvfb==3.0.0 From 0285c96337ec4ac64a338fbb81e14420ff676694 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 07:20:12 +0100 Subject: [PATCH 1025/1271] build(deps): Bump anyio[curio,trio] in /testing/plugins_integration (#13042) Bumps [anyio[curio,trio]](https://github.com/agronholm/anyio) from 4.6.2.post1 to 4.7.0. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.6.2.post1...4.7.0) --- updated-dependencies: - dependency-name: anyio[curio,trio] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index b0c9774dd35..92935a2a72f 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==4.6.2.post1 +anyio[curio,trio]==4.7.0 django==5.1.4 pytest-asyncio==0.24.0 pytest-bdd==8.0.0 From cb66eeef46511d855b689e587a31faae92e24ccc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 06:57:17 +0000 Subject: [PATCH 1026/1271] build(deps): Bump pytest-bdd in /testing/plugins_integration (#13041) Bumps [pytest-bdd](https://github.com/pytest-dev/pytest-bdd) from 8.0.0 to 8.1.0. - [Changelog](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-bdd/compare/8.0.0...8.1.0) --- updated-dependencies: - dependency-name: pytest-bdd dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 92935a2a72f..4abe0bd6deb 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,7 +1,7 @@ anyio[curio,trio]==4.7.0 django==5.1.4 pytest-asyncio==0.24.0 -pytest-bdd==8.0.0 +pytest-bdd==8.1.0 pytest-cov==6.0.0 pytest-django==4.9.0 pytest-flakes==4.0.5 From 949c7711b3e22ab94110f1ae4fc307cda2f9e379 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 07:32:48 +0100 Subject: [PATCH 1027/1271] [pre-commit.ci] pre-commit autoupdate (#13048) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.1 → v0.8.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.1...v0.8.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8a5418350d7..d73ac5baee0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.8.1" + rev: "v0.8.2" hooks: - id: ruff args: ["--fix"] From 28e1e25a6782513db8a2963bd5ed5a9d66682f86 Mon Sep 17 00:00:00 2001 From: dongfangtianyu <7629022+dongfangtianyu@users.noreply.github.com> Date: Thu, 12 Dec 2024 22:47:05 +0800 Subject: [PATCH 1028/1271] Fix `ImportError` crash when using `--import-mode=importlib` (#13053) Regression in #12716 In short: `PathFinder.find_spec` received the argument `/cow/moo` but loaded `/cow/moo/moo.py` instead. **Trigger conditions:** 1. `/cow/moo/moo.py` exists (a file and directory with the same name). 2. `/cow/moo/test_moo.py` exists (test case resides in the directory). When pytest loads test files in `importlib` mode, it continues recursive loading upward: - When loading `cow.moo`, it should return a namespace but unexpectedly returns a module. - When loading `cow.moo.moo`, it should return a module but unexpectedly returns a namespace. **Complete example:** [[GitHub repository](https://github.com/dongfangtianyu/pytest_importlib_issue)](https://github.com/dongfangtianyu/pytest_importlib_issue) - `main.py`: Reproduces the error. - `debug.py`: Demonstrates the behavior of `PathFinder.find_spec`. **Context:** https://github.com/pytest-dev/pytest/issues/12592#issuecomment-2512039696 https://github.com/pytest-dev/pytest/issues/12592#issuecomment-2515100428 --------- Co-authored-by: Bruno Oliveira --- changelog/13053.bugfix.rst | 1 + src/_pytest/pathlib.py | 13 ++++++++++--- testing/test_pathlib.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 changelog/13053.bugfix.rst diff --git a/changelog/13053.bugfix.rst b/changelog/13053.bugfix.rst new file mode 100644 index 00000000000..b6744331394 --- /dev/null +++ b/changelog/13053.bugfix.rst @@ -0,0 +1 @@ +Fixed a regression in pytest 8.3.4 where, when using ``--import-mode=importlib``, a directory containing py file with the same name would cause an ``ImportError`` diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 7c368e0dcd0..25dc69b6349 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -694,9 +694,16 @@ def _import_module_using_spec( # Checking with sys.meta_path first in case one of its hooks can import this module, # such as our own assertion-rewrite hook. for meta_importer in sys.meta_path: - spec = meta_importer.find_spec( - module_name, [str(module_location), str(module_path)] - ) + module_name_of_meta = getattr(meta_importer.__class__, "__module__", "") + if module_name_of_meta == "_pytest.assertion.rewrite" and module_path.is_file(): + # Import modules in subdirectories by module_path + # to ensure assertion rewrites are not missed (#12659). + find_spec_path = [str(module_location), str(module_path)] + else: + find_spec_path = [str(module_location)] + + spec = meta_importer.find_spec(module_name, find_spec_path) + if spec_matches_module_path(spec, module_path): break else: diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index a21d1edf970..5a13cd5a400 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -1498,6 +1498,34 @@ def test(): ] ) + def test_ns_multiple_levels_import_error( + self, + tmp_path: Path, + pytester: Pytester, + ) -> None: + # Trigger condition 1: ns and file with the same name + file = pytester.path / "cow/moo/moo.py" + file.parent.mkdir(parents=True) + file.write_text("data=123", encoding="utf-8") + + # Trigger condition 2: tests are located in ns + tests = pytester.path / "cow/moo/test_moo.py" + + tests.write_text( + dedent( + """ + from cow.moo.moo import data + + def test_moo(): + print(data) + """ + ), + encoding="utf-8", + ) + + result = pytester.runpytest("--import-mode=importlib") + assert result.ret == ExitCode.OK + @pytest.mark.parametrize("import_mode", ["prepend", "append", "importlib"]) def test_incorrect_namespace_package( self, From 495459dc880d1cb47cec30ae8a8be7111b3d9916 Mon Sep 17 00:00:00 2001 From: eitanwass Date: Mon, 2 Dec 2024 21:52:06 +0200 Subject: [PATCH 1029/1271] Fix parametrized mark over staticmethod decorator --- AUTHORS | 1 + changelog/12863.bugfix.rst | 1 + pyproject.toml | 2 +- src/_pytest/mark/structures.py | 6 +++++- testing/test_mark.py | 17 +++++++++++++++++ 5 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 changelog/12863.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 3419accfa6b..9629e00bcfb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -150,6 +150,7 @@ Eric Yuan Erik Aronesty Erik Hasse Erik M. Bray +Ethan Wass Evan Kepner Evgeny Seliverstov Fabian Sturm diff --git a/changelog/12863.bugfix.rst b/changelog/12863.bugfix.rst new file mode 100644 index 00000000000..03b0c873ba3 --- /dev/null +++ b/changelog/12863.bugfix.rst @@ -0,0 +1 @@ +Fix :func:`pytest.mark.parametrize` marker placed above `@staticmethod` diff --git a/pyproject.toml b/pyproject.toml index dce6a0870e1..0a695e0247e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -334,7 +334,7 @@ disable = [ [tool.codespell] ignore-words-list = "afile,asend,asser,assertio,feld,hove,ned,noes,notin,paramete,parth,socio-economic,tesults,varius,wil" -skip = "*/plugin_list.rst" +skip = "AUTHORS,*/plugin_list.rst" write-changes = true [tool.check-wheel-contents] diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index ac64ef2d606..c07116655a8 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -350,7 +350,11 @@ def __call__(self, *args: object, **kwargs: object): func = args[0] is_class = inspect.isclass(func) if len(args) == 1 and (istestfunc(func) or is_class): - store_mark(func, self.mark, stacklevel=3) + if isinstance(func, staticmethod): + # If the marker decorates a staticmethod, store on the test func + store_mark(func.__func__, self.mark, stacklevel=3) + else: + store_mark(func, self.mark, stacklevel=3) return func return self.with_args(*args, **kwargs) diff --git a/testing/test_mark.py b/testing/test_mark.py index 89eef7920cf..9e9f87d5d31 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1226,3 +1226,20 @@ def test_attrs(self): ) result = pytester.runpytest(foo) result.assert_outcomes(passed=1) + + +# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/12863") +def test_mark_parametrize_over_staticmethod(pytester: Pytester) -> None: + foo = pytester.makepyfile( + """ + import pytest + + class TestClass: + @pytest.mark.parametrize("value", [1, 2]) + @staticmethod + def test_foo(value: int): + assert value in [1, 2] + """ + ) + result = pytester.runpytest(foo) + result.assert_outcomes(passed=2) From ec34f1c5b7a0878ce6cee1bdceab1e689f82a78e Mon Sep 17 00:00:00 2001 From: eitanwass Date: Tue, 3 Dec 2024 22:22:39 +0200 Subject: [PATCH 1030/1271] Fix compatibility with python pre-3.10 --- src/_pytest/mark/structures.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index c07116655a8..05208cf9b53 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -349,12 +349,9 @@ def __call__(self, *args: object, **kwargs: object): if args and not kwargs: func = args[0] is_class = inspect.isclass(func) - if len(args) == 1 and (istestfunc(func) or is_class): - if isinstance(func, staticmethod): - # If the marker decorates a staticmethod, store on the test func - store_mark(func.__func__, self.mark, stacklevel=3) - else: - store_mark(func, self.mark, stacklevel=3) + marking_func = func.__func__ if isinstance(func, staticmethod) else func + if len(args) == 1 and (istestfunc(marking_func) or is_class): + store_mark(marking_func, self.mark, stacklevel=3) return func return self.with_args(*args, **kwargs) From 27d1a2f7da5f642aca4a73ecd4662936e4b7ea28 Mon Sep 17 00:00:00 2001 From: eitanwass Date: Wed, 4 Dec 2024 19:37:29 +0200 Subject: [PATCH 1031/1271] Get any contained func when marking --- changelog/12863.bugfix.rst | 2 +- src/_pytest/mark/structures.py | 2 +- testing/test_mark.py | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/changelog/12863.bugfix.rst b/changelog/12863.bugfix.rst index 03b0c873ba3..ad4c6dbf4a3 100644 --- a/changelog/12863.bugfix.rst +++ b/changelog/12863.bugfix.rst @@ -1 +1 @@ -Fix :func:`pytest.mark.parametrize` marker placed above `@staticmethod` +Fix :func:`pytest.mark.parametrize ` marker placed above `@staticmethod` diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 05208cf9b53..bbdd4838610 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -349,7 +349,7 @@ def __call__(self, *args: object, **kwargs: object): if args and not kwargs: func = args[0] is_class = inspect.isclass(func) - marking_func = func.__func__ if isinstance(func, staticmethod) else func + marking_func = getattr(func, "__func__", func) if len(args) == 1 and (istestfunc(marking_func) or is_class): store_mark(marking_func, self.mark, stacklevel=3) return func diff --git a/testing/test_mark.py b/testing/test_mark.py index 9e9f87d5d31..dd132920217 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1235,11 +1235,16 @@ def test_mark_parametrize_over_staticmethod(pytester: Pytester) -> None: import pytest class TestClass: + @pytest.mark.parametrize("value", [1, 2]) + @classmethod + def test_classmethod_wrapper(cls, value: int): + assert value in [1, 2] + @pytest.mark.parametrize("value", [1, 2]) @staticmethod - def test_foo(value: int): + def test_staticmethod_wrapper(value: int): assert value in [1, 2] """ ) result = pytester.runpytest(foo) - result.assert_outcomes(passed=2) + result.assert_outcomes(passed=4) From ec60713bfe223931abe7c049326e2d30d9efb21d Mon Sep 17 00:00:00 2001 From: eitanwass Date: Thu, 5 Dec 2024 19:05:42 +0200 Subject: [PATCH 1032/1271] Additional sanity tests, and fixes --- changelog/12863.bugfix.rst | 2 +- testing/test_mark.py | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/changelog/12863.bugfix.rst b/changelog/12863.bugfix.rst index ad4c6dbf4a3..97a26464bf3 100644 --- a/changelog/12863.bugfix.rst +++ b/changelog/12863.bugfix.rst @@ -1 +1 @@ -Fix :func:`pytest.mark.parametrize ` marker placed above `@staticmethod` +Fix :ref:`pytest.mark.parametrize ` marker placed above `@staticmethod` diff --git a/testing/test_mark.py b/testing/test_mark.py index dd132920217..c8109ae3a6c 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1230,7 +1230,11 @@ def test_attrs(self): # @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/12863") def test_mark_parametrize_over_staticmethod(pytester: Pytester) -> None: - foo = pytester.makepyfile( + """Check that applying marks works as intended on classmethods and staticmethods. + + Regression test for #12863. + """ + pytester.makepyfile( """ import pytest @@ -1240,11 +1244,21 @@ class TestClass: def test_classmethod_wrapper(cls, value: int): assert value in [1, 2] + @classmethod + @pytest.mark.parametrize("value", [1, 2]) + def test_classmethod_wrapper_on_top(cls, value: int): + assert value in [1, 2] + @pytest.mark.parametrize("value", [1, 2]) @staticmethod def test_staticmethod_wrapper(value: int): assert value in [1, 2] + + @staticmethod + @pytest.mark.parametrize("value", [1, 2]) + def test_staticmethod_wrapper_on_top(value: int): + assert value in [1, 2] """ ) - result = pytester.runpytest(foo) - result.assert_outcomes(passed=4) + result = pytester.runpytest() + result.assert_outcomes(passed=8) From 37cf65912906b7402dbc7134ba4344f36243b931 Mon Sep 17 00:00:00 2001 From: eitanwass Date: Fri, 6 Dec 2024 08:38:44 +0200 Subject: [PATCH 1033/1271] More explicit edgecase of decorators --- changelog/12863.bugfix.rst | 2 +- src/_pytest/mark/structures.py | 10 +++++++--- testing/test_mark.py | 1 - 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/changelog/12863.bugfix.rst b/changelog/12863.bugfix.rst index 97a26464bf3..0b1c397a08e 100644 --- a/changelog/12863.bugfix.rst +++ b/changelog/12863.bugfix.rst @@ -1 +1 @@ -Fix :ref:`pytest.mark.parametrize ` marker placed above `@staticmethod` +Fix applying markers, including :ref:`pytest.mark.parametrize ` when placed above `@staticmethod` or `@classmethod`. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index bbdd4838610..624b37cab94 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -349,9 +349,13 @@ def __call__(self, *args: object, **kwargs: object): if args and not kwargs: func = args[0] is_class = inspect.isclass(func) - marking_func = getattr(func, "__func__", func) - if len(args) == 1 and (istestfunc(marking_func) or is_class): - store_mark(marking_func, self.mark, stacklevel=3) + # For staticmethods/classmethods, the marks are eventually fetched from the + # function object, not the descriptor, so unwrap. + unwrapped_func = func + if isinstance(func, (staticmethod, classmethod)): + unwrapped_func = func.__func__ + if len(args) == 1 and (istestfunc(unwrapped_func) or is_class): + store_mark(unwrapped_func, self.mark, stacklevel=3) return func return self.with_args(*args, **kwargs) diff --git a/testing/test_mark.py b/testing/test_mark.py index c8109ae3a6c..60ee795cf43 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1228,7 +1228,6 @@ def test_attrs(self): result.assert_outcomes(passed=1) -# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/12863") def test_mark_parametrize_over_staticmethod(pytester: Pytester) -> None: """Check that applying marks works as intended on classmethods and staticmethods. From dd9b603f48a5294a46228d7f9b51de56aea97ef8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 15 Dec 2024 02:51:34 +0000 Subject: [PATCH 1034/1271] [automated] Update plugin list (#13060) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 158 +++++++++++++++++++------------ 1 file changed, 99 insertions(+), 59 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index f0e209008c6..63d91b6eb53 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.3 - :pypi:`logassert` Simple but powerful assertion and verification of logged lines. Nov 08, 2024 5 - Production/Stable N/A + :pypi:`logassert` Simple but powerful assertion and verification of logged lines. Dec 09, 2024 5 - Production/Stable N/A :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A - :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Sep 09, 2024 N/A pytest>=7 + :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 08, 2024 N/A pytest>=7 :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Nov 08, 2023 N/A pytest >=5.4.0 :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) @@ -78,7 +78,7 @@ This list contains 1554 plugins. :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) :pypi:`pytest-annotated` Pytest plugin to allow use of Annotated in tests to resolve fixtures Sep 30, 2024 N/A pytest>=8.3.3 - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Sep 11, 2024 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Dec 12, 2024 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -115,7 +115,7 @@ This list contains 1554 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Aug 22, 2024 4 - Beta pytest<9,>=8.2 + :pypi:`pytest-asyncio` Pytest support for asyncio Dec 13, 2024 4 - Beta pytest<9,>=8.2 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -132,7 +132,6 @@ This list contains 1554 plugins. :pypi:`pytest-automock` Pytest plugin for automatical mocks creation May 16, 2023 N/A pytest ; extra == 'dev' :pypi:`pytest-auto-parametrize` pytest plugin: avoid repeating arguments in parametrize Oct 02, 2016 3 - Alpha N/A :pypi:`pytest-autotest` This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. Aug 25, 2021 N/A pytest - :pypi:`pytest-aux` all moved into module FUNCS_AUXt Oct 25, 2024 N/A N/A :pypi:`pytest-aviator` Aviator's Flakybot pytest plugin that automatically reruns flaky tests. Nov 04, 2022 4 - Beta pytest :pypi:`pytest-avoidance` Makes pytest skip tests that don not need rerunning May 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A @@ -158,7 +157,7 @@ This list contains 1554 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Dec 06, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Dec 09, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -264,11 +263,11 @@ This list contains 1554 plugins. :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A - :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Aug 21, 2024 4 - Beta pytest>=4.6.0 + :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Dec 11, 2024 4 - Beta pytest>=4.6.0 :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Dec 06, 2024 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Dec 09, 2024 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -412,7 +411,7 @@ This list contains 1554 plugins. :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) - :pypi:`pytest-docker-compose-v2` Manages Docker containers during your integration tests Feb 28, 2024 4 - Beta pytest<8,>=7.2.2 + :pypi:`pytest-docker-compose-v2` Manages Docker containers during your integration tests Dec 11, 2024 4 - Beta pytest>=7.2.2 :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) :pypi:`pytest-docker-fixtures` pytest docker fixtures Apr 03, 2024 3 - Alpha N/A :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Aug 12, 2024 4 - Beta pytest @@ -531,7 +530,7 @@ This list contains 1554 plugins. :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest - :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI Dec 03, 2024 N/A pytest<8.0.0,>=7.2.1 + :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI Dec 11, 2024 N/A pytest<8.0.0,>=7.2.1 :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) @@ -604,12 +603,12 @@ This list contains 1554 plugins. :pypi:`pytest-freethreaded` pytest plugin for running parallel tests Oct 03, 2024 5 - Production/Stable pytest :pypi:`pytest-freezeblaster` Wrap tests with fixtures in freeze_time Jul 10, 2024 N/A pytest>=6.2.5 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) - :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Jun 21, 2023 N/A pytest >= 3.6 + :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Dec 12, 2024 N/A pytest>=3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Nov 16, 2024 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Dec 12, 2024 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A @@ -619,7 +618,7 @@ This list contains 1554 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Dec 06, 2024 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Dec 12, 2024 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest @@ -668,7 +667,7 @@ This list contains 1554 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Dec 07, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Dec 14, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -717,13 +716,14 @@ This list contains 1554 plugins. :pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A + :pypi:`pytest-infrahouse` A set of fixtures to use with pytest Dec 12, 2024 4 - Beta pytest~=8.3 :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-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-inline` A pytest plugin for writing inline tests Oct 24, 2024 4 - Beta pytest<9.0,>=7.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Oct 10, 2024 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 10, 2024 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Nov 26, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Dec 13, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Nov 23, 2024 N/A pytest @@ -777,7 +777,7 @@ This list contains 1554 plugins. :pypi:`pytest-kasima` Display horizontal lines above and below the captured standard output for easy viewing. Jan 26, 2023 5 - Production/Stable pytest (>=7.2.1,<8.0.0) :pypi:`pytest-keep-together` Pytest plugin to customize test ordering by running all 'related' tests together Dec 07, 2022 5 - Production/Stable pytest :pypi:`pytest-kexi` Apr 29, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Sep 05, 2024 N/A pytest>=8.0.2 + :pypi:`pytest-keyring` A Pytest plugin to access the system's keyring to provide credentials for tests Dec 08, 2024 N/A pytest>=8.0.2 :pypi:`pytest-kind` Kubernetes test support with KIND for pytest Nov 30, 2022 5 - Production/Stable N/A :pypi:`pytest-kivy` Kivy GUI tests fixtures using pytest Jul 06, 2021 4 - Beta pytest (>=3.6) :pypi:`pytest-knows` A pytest plugin that can automaticly skip test case based on dependence info calculated by trace Aug 22, 2014 N/A N/A @@ -863,6 +863,7 @@ This list contains 1554 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Dec 11, 2024 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -919,7 +920,7 @@ This list contains 1554 plugins. :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-runner` Run the mypy static type checker as a pytest test case Apr 23, 2024 N/A pytest>=8.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 - :pypi:`pytest-mysql` MySQL process and client fixtures for pytest May 23, 2024 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Dec 10, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-ndb` pytest notebook debugger Apr 28, 2024 N/A pytest :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) @@ -987,6 +988,7 @@ This list contains 1554 plugins. :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A + :pypi:`pytest-parametrization-annotation` A pytest library for parametrizing tests using type hints. Dec 10, 2024 5 - Production/Stable pytest>=7 :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Nov 10, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Oct 22, 2024 5 - Production/Stable pytest @@ -1070,7 +1072,7 @@ This list contains 1554 plugins. :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest :pypi:`pytest-prosper` Test helpers for Prosper projects Sep 24, 2018 N/A N/A - :pypi:`pytest-prysk` Pytest plugin for prysk Mar 12, 2024 4 - Beta pytest (>=7.3.2) + :pypi:`pytest-prysk` Pytest plugin for prysk Dec 10, 2024 4 - Beta pytest>=7.3.2 :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-psqlgraph` pytest plugin for testing applications that use psqlgraph Oct 19, 2021 4 - Beta pytest (>=6.0) :pypi:`pytest-pt` pytest plugin to use \*.pt files as tests Sep 22, 2024 5 - Production/Stable pytest @@ -1163,6 +1165,7 @@ This list contains 1554 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Dec 14, 2024 N/A pytest>=7.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1195,14 +1198,15 @@ This list contains 1554 plugins. :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Oct 24, 2024 5 - Production/Stable pytest :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 + :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 14, 2024 N/A pytest>=8.3.4 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments May 14, 2024 N/A pytest>=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Nov 24, 2024 N/A pytest>=5.3 :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A - :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Dec 03, 2024 4 - Beta pytest>=7.0 + :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Dec 14, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-reverse` Pytest plugin to reverse test order. Oct 25, 2024 5 - Production/Stable pytest - :pypi:`pytest-rich` Leverage rich for richer test session output Mar 03, 2022 4 - Beta pytest (>=7.0) + :pypi:`pytest-rich` Leverage rich for richer test session output Dec 12, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest :pypi:`pytest-rich-reporter` A pytest plugin using Rich for beautiful test result formatting. Feb 17, 2022 1 - Planning pytest (>=5.0.0) :pypi:`pytest-richtrace` A pytest plugin that displays the names and information of the pytest hook functions as they are executed. Jun 20, 2023 N/A N/A @@ -1236,7 +1240,7 @@ This list contains 1554 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 06, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 13, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1247,7 +1251,7 @@ This list contains 1554 plugins. :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 Feb 01, 2024 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. Dec 06, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Dec 13, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -1293,7 +1297,7 @@ This list contains 1554 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A - :pypi:`pytest-smoke` Pytest plugin for smoke testing Nov 27, 2024 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-smoke` Pytest plugin for smoke testing Dec 13, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -1362,7 +1366,7 @@ This list contains 1554 plugins. :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 Jul 24, 2024 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 Dec 07, 2024 4 - Beta pytest>=7.4 + :pypi:`pytest-subtests` unittest subTest() support and subtests fixture Dec 10, 2024 4 - Beta pytest>=7.4 :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) :pypi:`pytest-sugar` pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly). Feb 01, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-suitemanager` A simple plugin to use with pytest Apr 28, 2023 4 - Beta N/A @@ -1379,6 +1383,7 @@ This list contains 1554 plugins. :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Jul 15, 2023 5 - Production/Stable pytest (>=3.0) :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) + :pypi:`pytest-taskgraph` Add your description here Dec 12, 2024 N/A pytest :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A @@ -1601,7 +1606,7 @@ This list contains 1554 plugins. Python Testing for Databricks :pypi:`logassert` - *last release*: Nov 08, 2024, + *last release*: Dec 09, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -1636,7 +1641,7 @@ This list contains 1554 plugins. A contextmanager pytest fixture for handling multiple mock abstracts :pypi:`pytest-accept` - *last release*: Sep 09, 2024, + *last release*: Dec 08, 2024, *status*: N/A, *requires*: pytest>=7 @@ -1902,7 +1907,7 @@ This list contains 1554 plugins. Pytest plugin to allow use of Annotated in tests to resolve fixtures :pypi:`pytest-ansible` - *last release*: Sep 11, 2024, + *last release*: Dec 12, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2161,7 +2166,7 @@ This list contains 1554 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Aug 22, 2024, + *last release*: Dec 13, 2024, *status*: 4 - Beta, *requires*: pytest<9,>=8.2 @@ -2279,13 +2284,6 @@ This list contains 1554 plugins. This fixture provides a configured "driver" for Android Automated Testing, using uiautomator2. - :pypi:`pytest-aux` - *last release*: Oct 25, 2024, - *status*: N/A, - *requires*: N/A - - all moved into module FUNCS_AUXt - :pypi:`pytest-aviator` *last release*: Nov 04, 2022, *status*: 4 - Beta, @@ -2462,7 +2460,7 @@ This list contains 1554 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Dec 06, 2024, + *last release*: Dec 09, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3204,7 +3202,7 @@ This list contains 1554 plugins. pytest plugin to add source code sanity checks (pep8 and friends) :pypi:`pytest-codecov` - *last release*: Aug 21, 2024, + *last release*: Dec 11, 2024, *status*: 4 - Beta, *requires*: pytest>=4.6.0 @@ -3232,7 +3230,7 @@ This list contains 1554 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Dec 06, 2024, + *last release*: Dec 09, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -4240,9 +4238,9 @@ This list contains 1554 plugins. Manages Docker containers during your integration tests :pypi:`pytest-docker-compose-v2` - *last release*: Feb 28, 2024, + *last release*: Dec 11, 2024, *status*: 4 - Beta, - *requires*: pytest<8,>=7.2.2 + *requires*: pytest>=7.2.2 Manages Docker containers during your integration tests @@ -5073,7 +5071,7 @@ This list contains 1554 plugins. Additional pytest markers to dynamically enable/disable tests viia CLI flags :pypi:`pytest-f3ts` - *last release*: Dec 03, 2024, + *last release*: Dec 11, 2024, *status*: N/A, *requires*: pytest<8.0.0,>=7.2.1 @@ -5584,9 +5582,9 @@ This list contains 1554 plugins. Wrap tests with fixtures in freeze_time :pypi:`pytest-freezer` - *last release*: Jun 21, 2023, + *last release*: Dec 12, 2024, *status*: N/A, - *requires*: pytest >= 3.6 + *requires*: pytest>=3.6 Pytest plugin providing a fixture interface for spulec/freezegun @@ -5619,7 +5617,7 @@ This list contains 1554 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Nov 16, 2024, + *last release*: Dec 12, 2024, *status*: N/A, *requires*: pytest @@ -5689,7 +5687,7 @@ This list contains 1554 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Dec 06, 2024, + *last release*: Dec 12, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -6032,7 +6030,7 @@ This list contains 1554 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Dec 07, 2024, + *last release*: Dec 14, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6374,6 +6372,13 @@ This list contains 1554 plugins. display more node ininformation. + :pypi:`pytest-infrahouse` + *last release*: Dec 12, 2024, + *status*: 4 - Beta, + *requires*: pytest~=8.3 + + A set of fixtures to use with pytest + :pypi:`pytest-infrastructure` *last release*: Apr 12, 2020, *status*: 4 - Beta, @@ -6417,7 +6422,7 @@ This list contains 1554 plugins. Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Nov 26, 2024, + *last release*: Dec 13, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -6795,7 +6800,7 @@ This list contains 1554 plugins. :pypi:`pytest-keyring` - *last release*: Sep 05, 2024, + *last release*: Dec 08, 2024, *status*: N/A, *requires*: pytest>=8.0.2 @@ -7396,6 +7401,13 @@ This list contains 1554 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals + :pypi:`pytest-mergify` + *last release*: Dec 11, 2024, + *status*: N/A, + *requires*: N/A + + Pytest plugin for Mergify + :pypi:`pytest-mesh` *last release*: Aug 05, 2022, *status*: N/A, @@ -7789,7 +7801,7 @@ This list contains 1554 plugins. Pytest plugin to check mypy output. :pypi:`pytest-mysql` - *last release*: May 23, 2024, + *last release*: Dec 10, 2024, *status*: 5 - Production/Stable, *requires*: pytest>=6.2 @@ -8264,6 +8276,13 @@ This list contains 1554 plugins. Simpler PyTest parametrization + :pypi:`pytest-parametrization-annotation` + *last release*: Dec 10, 2024, + *status*: 5 - Production/Stable, + *requires*: pytest>=7 + + A pytest library for parametrizing tests using type hints. + :pypi:`pytest-parametrize` *last release*: Nov 10, 2024, *status*: 5 - Production/Stable, @@ -8846,9 +8865,9 @@ This list contains 1554 plugins. Test helpers for Prosper projects :pypi:`pytest-prysk` - *last release*: Mar 12, 2024, + *last release*: Dec 10, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.3.2) + *requires*: pytest>=7.3.2 Pytest plugin for prysk @@ -9496,6 +9515,13 @@ This list contains 1554 plugins. A basic HTML report for pytest using Jinja2 template engine. + :pypi:`pytest-report-extras` + *last release*: Dec 14, 2024, + *status*: N/A, + *requires*: pytest>=7.0.0 + + Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. + :pypi:`pytest-reportinfra` *last release*: Aug 11, 2019, *status*: 3 - Alpha, @@ -9720,6 +9746,13 @@ This list contains 1554 plugins. + :pypi:`pytest-result-sender-lj` + *last release*: Dec 14, 2024, + *status*: N/A, + *requires*: pytest>=8.3.4 + + Default template for PDM package + :pypi:`pytest-resume` *last release*: Apr 22, 2023, *status*: 4 - Beta, @@ -9756,7 +9789,7 @@ This list contains 1554 plugins. :pypi:`pytest-revealtype-injector` - *last release*: Dec 03, 2024, + *last release*: Dec 14, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0 @@ -9770,9 +9803,9 @@ This list contains 1554 plugins. Pytest plugin to reverse test order. :pypi:`pytest-rich` - *last release*: Mar 03, 2022, + *last release*: Dec 12, 2024, *status*: 4 - Beta, - *requires*: pytest (>=7.0) + *requires*: pytest>=7.0 Leverage rich for richer test session output @@ -10008,7 +10041,7 @@ This list contains 1554 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Dec 06, 2024, + *last release*: Dec 13, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10085,7 +10118,7 @@ This list contains 1554 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Dec 06, 2024, + *last release*: Dec 13, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10407,7 +10440,7 @@ This list contains 1554 plugins. Automated bad smell detection tool for Pytest :pypi:`pytest-smoke` - *last release*: Nov 27, 2024, + *last release*: Dec 13, 2024, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 @@ -10890,7 +10923,7 @@ This list contains 1554 plugins. A hack to explicitly set up and tear down fixtures. :pypi:`pytest-subtests` - *last release*: Dec 07, 2024, + *last release*: Dec 10, 2024, *status*: 4 - Beta, *requires*: pytest>=7.4 @@ -11008,6 +11041,13 @@ This list contains 1554 plugins. Pytest plugin for remote target orchestration. + :pypi:`pytest-taskgraph` + *last release*: Dec 12, 2024, + *status*: N/A, + *requires*: pytest + + Add your description here + :pypi:`pytest-tblineinfo` *last release*: Dec 01, 2015, *status*: 3 - Alpha, From 1d4f7309651fc62420a6f8a0ea6d3601e04ce110 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 03:36:19 +0000 Subject: [PATCH 1035/1271] build(deps): Bump hynek/build-and-inspect-python-package Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.10.0 to 2.11.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.10.0...v2.11.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3d3cb7534a4..b111be9a572 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.10.0 + uses: hynek/build-and-inspect-python-package@v2.11.0 with: attest-build-provenance-github: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 30536706afb..4058716b47d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.10.0 + uses: hynek/build-and-inspect-python-package@v2.11.0 build: needs: [package] From 4da57defe06274fa73d9312ce49c242f704e4f25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 03:36:21 +0000 Subject: [PATCH 1036/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.12.2 to 1.12.3 Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.2 to 1.12.3. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.2...v1.12.3) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3d3cb7534a4..c1f7013240a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -54,7 +54,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.2 + uses: pypa/gh-action-pypi-publish@v1.12.3 with: attestations: true From ee8f98d2f976a1df17093eab12e00f0f3c4bee29 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 16 Dec 2024 07:48:05 +0200 Subject: [PATCH 1037/1271] ci: harden github actions according to "zizmor" recommendations (#13062) Fix all issues reported by zizmor 0.9.2 running locally. See: https://woodruffw.github.io/zizmor/ --- .github/workflows/deploy.yml | 12 +++++++++--- .github/workflows/prepare-release-pr.yml | 11 +++++++++-- .github/workflows/update-plugin-list.yml | 6 ++++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 53a0ad4c2af..32d55361e54 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -46,6 +46,8 @@ jobs: contents: write steps: - uses: actions/checkout@v4 + with: + persist-credentials: true - name: Download Package uses: actions/download-artifact@v4 @@ -59,11 +61,13 @@ jobs: attestations: true - name: Push tag + env: + VERSION: ${{ github.event.inputs.version }} run: | git config user.name "pytest bot" git config user.email "pytestbot@gmail.com" - git tag --annotate --message=v${{ github.event.inputs.version }} ${{ github.event.inputs.version }} ${{ github.sha }} - git push origin ${{ github.event.inputs.version }} + git tag --annotate --message=v"$VERSION" "$VERSION" ${{ github.sha }} + git push origin "$VERSION" release-notes: @@ -98,9 +102,11 @@ jobs: pip install --upgrade tox - name: Generate release notes + env: + VERSION: ${{ github.event.inputs.version }} run: | sudo apt-get install pandoc - tox -e generate-gh-release-notes -- ${{ github.event.inputs.version }} scripts/latest-release-notes.md + tox -e generate-gh-release-notes -- "$VERSION" scripts/latest-release-notes.md - name: Publish GitHub Release uses: softprops/action-gh-release@v2 diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index f46b5cecda5..b803ba8517b 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -30,6 +30,7 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + persist-credentials: false - name: Set up Python uses: actions/setup-python@v5 @@ -43,10 +44,16 @@ jobs: - name: Prepare release PR (minor/patch release) if: github.event.inputs.major == 'no' + env: + BRANCH: ${{ github.event.inputs.branch }} + PRERELEASE: ${{ github.event.inputs.prerelease }} run: | - tox -e prepare-release-pr -- ${{ github.event.inputs.branch }} ${{ github.token }} --prerelease='${{ github.event.inputs.prerelease }}' + tox -e prepare-release-pr -- "$BRANCH" ${{ github.token }} --prerelease="$PRERELEASE" - name: Prepare release PR (major release) if: github.event.inputs.major == 'yes' + env: + BRANCH: ${{ github.event.inputs.branch }} + PRERELEASE: ${{ github.event.inputs.prerelease }} run: | - tox -e prepare-release-pr -- ${{ github.event.inputs.branch }} ${{ github.token }} --major --prerelease='${{ github.event.inputs.prerelease }}' + tox -e prepare-release-pr -- "$BRANCH" ${{ github.token }} --major --prerelease="$PRERELEASE" diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 0c76b91843c..ce3e9fd5230 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -23,12 +23,14 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + persist-credentials: false - name: Setup Python uses: actions/setup-python@v5 with: python-version: "3.11" cache: pip + - name: requests-cache uses: actions/cache@v4 with: @@ -41,7 +43,6 @@ jobs: python -m pip install --upgrade pip pip install packaging requests tabulate[widechars] tqdm requests-cache platformdirs - - name: Update Plugin List run: python scripts/update-plugin-list.py @@ -61,8 +62,9 @@ jobs: - name: Instruct the maintainers to trigger CI by undrafting the PR env: GITHUB_TOKEN: ${{ github.token }} + PULL_REQUEST_NUMBER: ${{ steps.pr.outputs.pull-request-number }} run: >- gh pr comment --body 'Please mark the PR as ready for review to trigger PR checks.' --repo '${{ github.repository }}' - '${{ steps.pr.outputs.pull-request-number }}' + "$PULL_REQUEST_NUMBER" From 9b92c41bc6b83c18509b6e86cbf69daeb003bf7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 07:23:31 +0100 Subject: [PATCH 1038/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#13065) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.24.0 to 0.25.0. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.24.0...v0.25.0) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 4abe0bd6deb..74be0367cdc 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[curio,trio]==4.7.0 django==5.1.4 -pytest-asyncio==0.24.0 +pytest-asyncio==0.25.0 pytest-bdd==8.1.0 pytest-cov==6.0.0 pytest-django==4.9.0 From 6b3dadc9cce0d63e62dd72193d7ef8a7ae8dd38b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 16 Dec 2024 13:21:31 +0200 Subject: [PATCH 1039/1271] pre-commit: add zizmor hook Ensure we don't regress. --- .pre-commit-config.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d73ac5baee0..8937a1ff9ac 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,6 +11,10 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml +- repo: https://github.com/woodruffw/zizmor-pre-commit + rev: v0.9.2 + hooks: + - id: zizmor - repo: https://github.com/adamchainz/blacken-docs rev: 1.19.1 hooks: From b39b871e79868fd1966d181dfc9c115caabc1ec5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 07:04:38 +0100 Subject: [PATCH 1040/1271] [pre-commit.ci] pre-commit autoupdate (#13071) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.2 → v0.8.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.2...v0.8.3) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8937a1ff9ac..d7a4efabe98 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.8.2" + rev: "v0.8.3" hooks: - id: ruff args: ["--fix"] From 868e1d225e443984a6aa29cfde2d1231eb03ed41 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 18 Dec 2024 11:09:33 +0000 Subject: [PATCH 1041/1271] apply warnings filter as soon as possible, and remove it as late as possible (#13057) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 1 + changelog/10404.bugfix.rst | 7 ++ pyproject.toml | 3 + src/_pytest/config/__init__.py | 8 +- src/_pytest/pytester.py | 4 +- src/_pytest/warning_types.py | 7 ++ src/_pytest/warnings.py | 59 ++++++++----- src/pytest/__init__.py | 2 + testing/test_unraisableexception.py | 124 ++++++++++++++++++++++++++-- 9 files changed, 181 insertions(+), 34 deletions(-) create mode 100644 changelog/10404.bugfix.rst diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4058716b47d..5814c81fb30 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -123,6 +123,7 @@ jobs: python: "3.9" os: ubuntu-latest tox_env: "py39-lsof-numpy-pexpect" + use_coverage: true - name: "ubuntu-py39-pluggy" python: "3.9" diff --git a/changelog/10404.bugfix.rst b/changelog/10404.bugfix.rst new file mode 100644 index 00000000000..4c98ea03d64 --- /dev/null +++ b/changelog/10404.bugfix.rst @@ -0,0 +1,7 @@ +Apply filterwarnings from config/cli as soon as possible, and revert them as late as possible +so that warnings as errors are collected throughout the pytest run and before the +unraisable and threadexcept hooks are removed. + +This allows very late warnings and unraisable/threadexcept exceptions to fail the test suite. + +This also changes the warning that the lsof plugin issues from PytestWarning to the new warning PytestFDWarning so it can be more easily filtered. diff --git a/pyproject.toml b/pyproject.toml index 0a695e0247e..df633e0a092 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -403,6 +403,9 @@ filterwarnings = [ "ignore:VendorImporter\\.find_spec\\(\\) not found; falling back to find_module\\(\\):ImportWarning", # https://github.com/pytest-dev/execnet/pull/127 "ignore:isSet\\(\\) is deprecated, use is_set\\(\\) instead:DeprecationWarning", + # https://github.com/pytest-dev/pytest/issues/2366 + # https://github.com/pytest-dev/pytest/pull/13057 + "default::pytest.PytestFDWarning", ] pytester_example_dir = "testing/example_scripts" markers = [ diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 6160f780b1b..0161f5952b8 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -264,11 +264,11 @@ def directory_arg(path: str, optname: str) -> str: "setuponly", "setupplan", "stepwise", + "unraisableexception", + "threadexception", "warnings", "logging", "reports", - "unraisableexception", - "threadexception", "faulthandler", ) @@ -1112,9 +1112,7 @@ def add_cleanup(self, func: Callable[[], None]) -> None: def _do_configure(self) -> None: assert not self._configured self._configured = True - with warnings.catch_warnings(): - warnings.simplefilter("default") - self.hook.pytest_configure.call_historic(kwargs=dict(config=self)) + self.hook.pytest_configure.call_historic(kwargs=dict(config=self)) def _ensure_unconfigure(self) -> None: try: diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 412d850d2da..59839562031 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -65,7 +65,7 @@ from _pytest.reports import CollectReport from _pytest.reports import TestReport from _pytest.tmpdir import TempPathFactory -from _pytest.warning_types import PytestWarning +from _pytest.warning_types import PytestFDWarning if TYPE_CHECKING: @@ -188,7 +188,7 @@ def pytest_runtest_protocol(self, item: Item) -> Generator[None, object, object] "*** function {}:{}: {} ".format(*item.location), "See issue #2366", ] - item.warn(PytestWarning("\n".join(error))) + item.warn(PytestFDWarning("\n".join(error))) # used at least by pytest-xdist plugin diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index b8e9998cd2e..8c9ff2d9a36 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -123,6 +123,13 @@ def format(self, **kwargs: Any) -> _W: return self.category(self.template.format(**kwargs)) +@final +class PytestFDWarning(PytestWarning): + """When the lsof plugin finds leaked fds.""" + + __module__ = "pytest" + + def warn_explicit_for(method: FunctionType, message: PytestWarning) -> None: """ Issue the warning :param:`message` for the definition of the given :param:`method` diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index 64ea3ff222d..806681a5020 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -3,6 +3,7 @@ from collections.abc import Generator from contextlib import contextmanager +from contextlib import ExitStack import sys from typing import Literal import warnings @@ -17,20 +18,14 @@ import pytest -def pytest_configure(config: Config) -> None: - config.addinivalue_line( - "markers", - "filterwarnings(warning): add a warning filter to the given test. " - "see https://docs.pytest.org/en/stable/how-to/capture-warnings.html#pytest-mark-filterwarnings ", - ) - - @contextmanager def catch_warnings_for_item( config: Config, ihook, when: Literal["config", "collect", "runtest"], item: Item | None, + *, + record: bool = True, ) -> Generator[None]: """Context manager that catches warnings generated in the contained execution block. @@ -40,10 +35,7 @@ def catch_warnings_for_item( """ config_filters = config.getini("filterwarnings") cmdline_filters = config.known_args_namespace.pythonwarnings or [] - with warnings.catch_warnings(record=True) as log: - # mypy can't infer that record=True means log is not None; help it. - assert log is not None - + with warnings.catch_warnings(record=record) as log: if not sys.warnoptions: # If user is not explicitly configuring warning filters, show deprecation warnings by default (#2908). warnings.filterwarnings("always", category=DeprecationWarning) @@ -64,15 +56,19 @@ def catch_warnings_for_item( try: yield finally: - for warning_message in log: - ihook.pytest_warning_recorded.call_historic( - kwargs=dict( - warning_message=warning_message, - nodeid=nodeid, - when=when, - location=None, + if record: + # mypy can't infer that record=True means log is not None; help it. + assert log is not None + + for warning_message in log: + ihook.pytest_warning_recorded.call_historic( + kwargs=dict( + warning_message=warning_message, + nodeid=nodeid, + when=when, + location=None, + ) ) - ) def warning_record_to_str(warning_message: warnings.WarningMessage) -> str: @@ -131,3 +127,26 @@ def pytest_load_initial_conftests( config=early_config, ihook=early_config.hook, when="config", item=None ): return (yield) + + +def pytest_configure(config: Config) -> None: + with ExitStack() as stack: + stack.enter_context( + catch_warnings_for_item( + config=config, + ihook=config.hook, + when="config", + item=None, + # this disables recording because the terminalreporter has + # finished by the time it comes to reporting logged warnings + # from the end of config cleanup. So for now, this is only + # useful for setting a warning filter with an 'error' action. + record=False, + ) + ) + config.addinivalue_line( + "markers", + "filterwarnings(warning): add a warning filter to the given test. " + "see https://docs.pytest.org/en/stable/how-to/capture-warnings.html#pytest-mark-filterwarnings ", + ) + config.add_cleanup(stack.pop_all().close) diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index f0c3516f4cc..70096d6593e 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -77,6 +77,7 @@ from _pytest.warning_types import PytestConfigWarning from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestExperimentalApiWarning +from _pytest.warning_types import PytestFDWarning from _pytest.warning_types import PytestRemovedIn9Warning from _pytest.warning_types import PytestUnhandledThreadExceptionWarning from _pytest.warning_types import PytestUnknownMarkWarning @@ -124,6 +125,7 @@ "PytestConfigWarning", "PytestDeprecationWarning", "PytestExperimentalApiWarning", + "PytestFDWarning", "PytestPluginManager", "PytestRemovedIn9Warning", "PytestUnhandledThreadExceptionWarning", diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index 5aa6aa773d9..3f191073e2b 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -1,5 +1,7 @@ from __future__ import annotations +from collections.abc import Generator +import contextlib import gc import sys from unittest import mock @@ -203,7 +205,25 @@ class MyError(BaseException): ) -def test_create_task_unraisable(pytester: Pytester) -> None: +def _set_gc_state(enabled: bool) -> bool: + was_enabled = gc.isenabled() + if enabled: + gc.enable() + else: + gc.disable() + return was_enabled + + +@contextlib.contextmanager +def _disable_gc() -> Generator[None]: + was_enabled = _set_gc_state(enabled=False) + try: + yield + finally: + _set_gc_state(enabled=was_enabled) + + +def test_refcycle_unraisable(pytester: Pytester) -> None: # see: https://github.com/pytest-dev/pytest/issues/10404 pytester.makepyfile( test_it=""" @@ -221,13 +241,8 @@ def test_it(): """ ) - was_enabled = gc.isenabled() - gc.disable() - try: + with _disable_gc(): result = pytester.runpytest() - finally: - if was_enabled: - gc.enable() # TODO: should be a test failure or error assert result.ret == pytest.ExitCode.INTERNAL_ERROR @@ -236,6 +251,101 @@ def test_it(): result.stderr.fnmatch_lines("ValueError: del is broken") +@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") +def test_refcycle_unraisable_warning_filter(pytester: Pytester) -> None: + # note that the host pytest warning filter is disabled and the pytester + # warning filter applies during config teardown of unraisablehook. + # see: https://github.com/pytest-dev/pytest/issues/10404 + pytester.makepyfile( + test_it=""" + import pytest + + class BrokenDel: + def __init__(self): + self.self = self # make a reference cycle + + def __del__(self): + raise ValueError("del is broken") + + def test_it(): + BrokenDel() + """ + ) + + with _disable_gc(): + result = pytester.runpytest("-Werror") + + # TODO: should be a test failure or error + assert result.ret == pytest.ExitCode.INTERNAL_ERROR + + result.assert_outcomes(passed=1) + result.stderr.fnmatch_lines("ValueError: del is broken") + + +@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") +def test_create_task_raises_unraisable_warning_filter(pytester: Pytester) -> None: + # note that the host pytest warning filter is disabled and the pytester + # warning filter applies during config teardown of unraisablehook. + # see: https://github.com/pytest-dev/pytest/issues/10404 + # This is a dupe of the above test, but using the exact reproducer from + # the issue + pytester.makepyfile( + test_it=""" + import asyncio + import pytest + + async def my_task(): + pass + + def test_scheduler_must_be_created_within_running_loop() -> None: + with pytest.raises(RuntimeError) as _: + asyncio.create_task(my_task()) + """ + ) + + with _disable_gc(): + result = pytester.runpytest("-Werror") + + # TODO: should be a test failure or error + assert result.ret == pytest.ExitCode.INTERNAL_ERROR + + result.assert_outcomes(passed=1) + result.stderr.fnmatch_lines("RuntimeWarning: coroutine 'my_task' was never awaited") + + +def test_refcycle_unraisable_warning_filter_default(pytester: Pytester) -> None: + # note this time we use a default warning filter for pytester + # and run it in a subprocess, because the warning can only go to the + # sys.stdout rather than the terminal reporter, which has already + # finished. + # see: https://github.com/pytest-dev/pytest/pull/13057#discussion_r1888396126 + pytester.makepyfile( + test_it=""" + import pytest + + class BrokenDel: + def __init__(self): + self.self = self # make a reference cycle + + def __del__(self): + raise ValueError("del is broken") + + def test_it(): + BrokenDel() + """ + ) + + with _disable_gc(): + result = pytester.runpytest_subprocess("-Wdefault") + + assert result.ret == pytest.ExitCode.OK + + # TODO: should be warnings=1, but the outcome has already come out + # by the time the warning triggers + result.assert_outcomes(passed=1) + result.stderr.fnmatch_lines("ValueError: del is broken") + + @pytest.mark.filterwarnings("error::pytest.PytestUnraisableExceptionWarning") def test_possibly_none_excinfo(pytester: Pytester) -> None: pytester.makepyfile( From 7d585acd1123a6bf6df6ff3279757bb5a69a9417 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Sat, 21 Dec 2024 14:28:17 +0100 Subject: [PATCH 1042/1271] fix #13031: use the concrete id NOTSET for the empty parameter list (#13073) * fix #13031: use the concrete id NOTSET for the empty parameter list stand-in this ensures we dont invoke idfunc with the internal NOTSET enum token * Apply suggestions from code review Co-authored-by: Bruno Oliveira --------- Co-authored-by: Bruno Oliveira --- changelog/13031.improvement.rst | 1 + src/_pytest/mark/structures.py | 12 +++++++----- testing/test_mark.py | 26 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 changelog/13031.improvement.rst diff --git a/changelog/13031.improvement.rst b/changelog/13031.improvement.rst new file mode 100644 index 00000000000..c6c64c4673a --- /dev/null +++ b/changelog/13031.improvement.rst @@ -0,0 +1 @@ +An empty parameter set as in ``pytest.mark.parametrize([], ids=idfunc)`` will no longer trigger a call to ``idfunc`` with internal objects. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 624b37cab94..1a0b3c5b5b8 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -47,18 +47,18 @@ def get_empty_parameterset_mark( ) -> MarkDecorator: from ..nodes import Collector + argslisting = ", ".join(argnames) + fs, lineno = getfslineno(func) - reason = f"got empty parameter set {argnames!r}, function {func.__name__} at {fs}:{lineno}" + reason = f"got empty parameter set for ({argslisting})" requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION) if requested_mark in ("", None, "skip"): mark = MARK_GEN.skip(reason=reason) elif requested_mark == "xfail": mark = MARK_GEN.xfail(reason=reason, run=False) elif requested_mark == "fail_at_collect": - f_name = func.__name__ - _, lineno = getfslineno(func) raise Collector.CollectError( - f"Empty parameter set in '{f_name}' at line {lineno + 1}" + f"Empty parameter set in '{func.__name__}' at line {lineno + 1}" ) else: raise LookupError(requested_mark) @@ -181,7 +181,9 @@ def _for_parametrize( # parameter set with NOTSET values, with the "empty parameter set" mark applied to it. mark = get_empty_parameterset_mark(config, argnames, func) parameters.append( - ParameterSet(values=(NOTSET,) * len(argnames), marks=[mark], id=None) + ParameterSet( + values=(NOTSET,) * len(argnames), marks=[mark], id="NOTSET" + ) ) return argnames, parameters diff --git a/testing/test_mark.py b/testing/test_mark.py index 60ee795cf43..7b76acf9990 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1048,6 +1048,32 @@ def test(): assert result.ret == ExitCode.INTERRUPTED +def test_paramset_empty_no_idfunc( + pytester: Pytester, monkeypatch: pytest.MonkeyPatch +) -> None: + """An empty parameter set should not call the user provided id function (#13031).""" + p1 = pytester.makepyfile( + """ + import pytest + + def idfunc(value): + raise ValueError() + @pytest.mark.parametrize("param", [], ids=idfunc) + def test(param): + pass + """ + ) + result = pytester.runpytest(p1, "-v", "-rs") + result.stdout.fnmatch_lines( + [ + "* collected 1 item", + "test_paramset_empty_no_idfunc* SKIPPED *", + "SKIPPED [1] test_paramset_empty_no_idfunc.py:5: got empty parameter set for (param)", + "*= 1 skipped in *", + ] + ) + + def test_parameterset_for_parametrize_bad_markname(pytester: Pytester) -> None: with pytest.raises(pytest.UsageError): test_parameterset_for_parametrize_marks(pytester, "bad") From 24e84f08f43216f95620135305cbebe9f646e433 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 22 Dec 2024 08:34:13 +0100 Subject: [PATCH 1043/1271] [automated] Update plugin list (#13080) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 88 ++++++++++++++++---------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 63d91b6eb53..ddda5448232 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -157,7 +157,7 @@ This list contains 1559 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Dec 09, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Dec 16, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -168,7 +168,7 @@ This list contains 1559 plugins. :pypi:`pytest-bigchaindb` A BigchainDB plugin for pytest. Jan 24, 2022 4 - Beta N/A :pypi:`pytest-bigquery-mock` Provides a mock fixture for python bigquery client Dec 28, 2022 N/A pytest (>=5.0) :pypi:`pytest-bisect-tests` Find tests leaking state and affecting other Jun 09, 2024 N/A N/A - :pypi:`pytest-black` A pytest plugin to enable format checking with black Oct 05, 2020 4 - Beta N/A + :pypi:`pytest-black` A pytest plugin to enable format checking with black Dec 15, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-black-multipy` Allow '--black' on older Pythons Jan 14, 2021 5 - Production/Stable pytest (!=3.7.3,>=3.5) ; extra == 'testing' :pypi:`pytest-black-ng` A pytest plugin to enable format checking with black Oct 20, 2022 4 - Beta pytest (>=7.0.0) :pypi:`pytest-blame` A pytest plugin helps developers to debug by providing useful commits history. May 04, 2019 N/A pytest (>=4.4.0) @@ -667,7 +667,7 @@ This list contains 1559 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Dec 14, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Dec 21, 2024 3 - Alpha pytest==8.3.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` Sep 23, 2024 N/A N/A @@ -691,7 +691,7 @@ This list contains 1559 plugins. :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A - :pypi:`pytest-httptesting` http_testing framework on top of pytest Aug 10, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-httptesting` http_testing framework on top of pytest Dec 19, 2024 N/A pytest>=8.2.0 :pypi:`pytest-httpx` Send responses to httpx. Nov 28, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) :pypi:`pytest-httpx-recorder` Recorder feature based on pytest_httpx, like recorder feature in responses. Jan 04, 2024 5 - Production/Stable pytest @@ -716,7 +716,7 @@ This list contains 1559 plugins. :pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A - :pypi:`pytest-infrahouse` A set of fixtures to use with pytest Dec 12, 2024 4 - Beta pytest~=8.3 + :pypi:`pytest-infrahouse` A set of fixtures to use with pytest Dec 19, 2024 4 - Beta pytest~=8.3 :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-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 @@ -741,7 +741,7 @@ This list contains 1559 plugins. :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Dec 04, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Dec 19, 2024 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Nov 24, 2024 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Dec 05, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) @@ -819,7 +819,7 @@ This list contains 1559 plugins. :pypi:`pytest-localstack` Pytest plugin for AWS integration tests Jun 07, 2023 4 - Beta pytest (>=6.0.0,<7.0.0) :pypi:`pytest-lock` pytest-lock is a pytest plugin that allows you to "lock" the results of unit tests, storing them in a local cache. This is particularly useful for tests that are resource-intensive or don't need to be run every time. When the tests are run subsequently, pytest-lock will compare the current results with the locked results and issue a warning if there are any discrepancies. Feb 03, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-lockable` lockable resource plugin for pytest Jan 24, 2024 5 - Production/Stable pytest - :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Oct 29, 2021 N/A pytest (>=5.4) + :pypi:`pytest-locker` Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed Dec 20, 2024 N/A pytest>=5.4 :pypi:`pytest-log` print log Aug 15, 2021 N/A pytest (>=3.8) :pypi:`pytest-logbook` py.test plugin to capture logbook log messages Nov 23, 2015 5 - Production/Stable pytest (>=2.8) :pypi:`pytest-logdog` Pytest plugin to test logging Jun 15, 2021 1 - Planning pytest (>=6.2.0) @@ -863,7 +863,7 @@ This list contains 1559 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Dec 11, 2024 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Dec 20, 2024 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -1058,7 +1058,7 @@ This list contains 1559 plugins. :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Sep 05, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) - :pypi:`pytest-powerpack` A plugin containing extra batteries for pytest Oct 01, 2024 N/A pytest<9.0.0,>=8.1.1 + :pypi:`pytest-powerpack` A plugin containing extra batteries for pytest Dec 17, 2024 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) @@ -1136,7 +1136,7 @@ This list contains 1559 plugins. :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jun 07, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A - :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jun 27, 2024 N/A N/A + :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Dec 19, 2024 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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-record-video` 用例执行过程中录制视频 Oct 31, 2024 N/A N/A @@ -1147,7 +1147,7 @@ This list contains 1559 plugins. :pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest - :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Aug 31, 2023 5 - Production/Stable pytest >=6.2.0 + :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Dec 17, 2024 5 - Production/Stable pytest>=6.2.0 :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Nov 12, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relative-path` Handle relative path in pytest options or ini configs Aug 30, 2024 N/A pytest @@ -1165,7 +1165,7 @@ This list contains 1559 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Dec 14, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. Dec 15, 2024 N/A pytest>=7.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1188,7 +1188,7 @@ This list contains 1559 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Nov 20, 2024 5 - Production/Stable pytest!=8.2.2,>=7.4 :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. Jul 23, 2024 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Jul 16, 2024 N/A pytest~=7.0 + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Dec 16, 2024 N/A pytest~=7.0 :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 @@ -1198,13 +1198,13 @@ This list contains 1559 plugins. :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Oct 24, 2024 5 - Production/Stable pytest :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 - :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 14, 2024 N/A pytest>=8.3.4 + :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 17, 2024 N/A pytest>=8.3.4 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments May 14, 2024 N/A pytest>=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Nov 24, 2024 N/A pytest>=5.3 :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A - :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Dec 14, 2024 4 - Beta pytest>=7.0 + :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Dec 19, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-reverse` Pytest plugin to reverse test order. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Dec 12, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest @@ -1240,7 +1240,7 @@ This list contains 1559 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 13, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 15, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1251,10 +1251,10 @@ This list contains 1559 plugins. :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 Feb 01, 2024 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. Dec 13, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Dec 15, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Apr 05, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 :pypi:`pytest-send-email` Send pytest execution result email Sep 02, 2024 N/A pytest :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Nov 25, 2024 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A @@ -1569,7 +1569,7 @@ This list contains 1559 plugins. :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-xstress` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 :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, 2024 4 - Beta pytest>=7.2.2 + :pypi:`pytest-xvirt` A pytest plugin to virtualize test. For example to transparently running them on a remote box. Dec 15, 2024 4 - Beta pytest>=7.2.2 :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 with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Nov 20, 2024 N/A pytest~=8.2.2 :pypi:`pytest-yamltree` Create or check file/directory trees described by YAML Mar 02, 2020 4 - Beta pytest (>=3.1.1) @@ -2460,7 +2460,7 @@ This list contains 1559 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Dec 09, 2024, + *last release*: Dec 16, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -2537,9 +2537,9 @@ This list contains 1559 plugins. Find tests leaking state and affecting other :pypi:`pytest-black` - *last release*: Oct 05, 2020, + *last release*: Dec 15, 2024, *status*: 4 - Beta, - *requires*: N/A + *requires*: pytest>=7.0.0 A pytest plugin to enable format checking with black @@ -6030,7 +6030,7 @@ This list contains 1559 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Dec 14, 2024, + *last release*: Dec 21, 2024, *status*: 3 - Alpha, *requires*: pytest==8.3.3 @@ -6198,9 +6198,9 @@ This list contains 1559 plugins. pytest-httpserver is a httpserver for pytest :pypi:`pytest-httptesting` - *last release*: Aug 10, 2024, + *last release*: Dec 19, 2024, *status*: N/A, - *requires*: pytest<9.0.0,>=8.2.0 + *requires*: pytest>=8.2.0 http_testing framework on top of pytest @@ -6373,7 +6373,7 @@ This list contains 1559 plugins. display more node ininformation. :pypi:`pytest-infrahouse` - *last release*: Dec 12, 2024, + *last release*: Dec 19, 2024, *status*: 4 - Beta, *requires*: pytest~=8.3 @@ -6548,7 +6548,7 @@ This list contains 1559 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Dec 04, 2024, + *last release*: Dec 19, 2024, *status*: N/A, *requires*: pytest @@ -7094,9 +7094,9 @@ This list contains 1559 plugins. lockable resource plugin for pytest :pypi:`pytest-locker` - *last release*: Oct 29, 2021, + *last release*: Dec 20, 2024, *status*: N/A, - *requires*: pytest (>=5.4) + *requires*: pytest>=5.4 Used to lock object during testing. Essentially changing assertions from being hard coded to asserting that nothing changed @@ -7402,7 +7402,7 @@ This list contains 1559 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Dec 11, 2024, + *last release*: Dec 20, 2024, *status*: N/A, *requires*: N/A @@ -8767,7 +8767,7 @@ This list contains 1559 plugins. pytest plugin with powerful fixtures :pypi:`pytest-powerpack` - *last release*: Oct 01, 2024, + *last release*: Dec 17, 2024, *status*: N/A, *requires*: pytest<9.0.0,>=8.1.1 @@ -9313,7 +9313,7 @@ This list contains 1559 plugins. Pytest fixtures for REANA. :pypi:`pytest-recorder` - *last release*: Jun 27, 2024, + *last release*: Dec 19, 2024, *status*: N/A, *requires*: N/A @@ -9390,9 +9390,9 @@ This list contains 1559 plugins. Management of Pytest dependencies via regex patterns :pypi:`pytest-regressions` - *last release*: Aug 31, 2023, + *last release*: Dec 17, 2024, *status*: 5 - Production/Stable, - *requires*: pytest >=6.2.0 + *requires*: pytest>=6.2.0 Easy to use fixtures to write regression tests. @@ -9516,11 +9516,11 @@ This list contains 1559 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Dec 14, 2024, + *last release*: Dec 15, 2024, *status*: N/A, *requires*: pytest>=7.0.0 - Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. + Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. :pypi:`pytest-reportinfra` *last release*: Aug 11, 2019, @@ -9677,7 +9677,7 @@ This list contains 1559 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Jul 16, 2024, + *last release*: Dec 16, 2024, *status*: N/A, *requires*: pytest~=7.0 @@ -9747,7 +9747,7 @@ This list contains 1559 plugins. :pypi:`pytest-result-sender-lj` - *last release*: Dec 14, 2024, + *last release*: Dec 17, 2024, *status*: N/A, *requires*: pytest>=8.3.4 @@ -9789,7 +9789,7 @@ This list contains 1559 plugins. :pypi:`pytest-revealtype-injector` - *last release*: Dec 14, 2024, + *last release*: Dec 19, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0 @@ -10041,7 +10041,7 @@ This list contains 1559 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Dec 13, 2024, + *last release*: Dec 15, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10118,7 +10118,7 @@ This list contains 1559 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Dec 13, 2024, + *last release*: Dec 15, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10139,9 +10139,9 @@ This list contains 1559 plugins. A pytest package implementing perceptualdiff for Selenium tests. :pypi:`pytest-selfie` - *last release*: Apr 05, 2024, + *last release*: Dec 16, 2024, *status*: N/A, - *requires*: pytest<9.0.0,>=8.0.0 + *requires*: pytest>=8.0.0 A pytest plugin for selfie snapshot testing. @@ -12344,7 +12344,7 @@ This list contains 1559 plugins. A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. :pypi:`pytest-xvirt` - *last release*: Oct 01, 2024, + *last release*: Dec 15, 2024, *status*: 4 - Beta, *requires*: pytest>=7.2.2 From 9c02a3f6ed59215a06fb146ccb573182e9481e06 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 29 Dec 2024 06:33:15 +0000 Subject: [PATCH 1044/1271] [automated] Update plugin list (#13088) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 90 +++++++++++++++++++------------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index ddda5448232..6b2a1898203 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.2.0,<8.0.0) :pypi:`pytest-aiomoto` pytest-aiomoto Jun 24, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-aioresponses` py.test integration for aioresponses Jul 29, 2021 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest May 01, 2023 5 - Production/Stable pytest>=6.1.0 + :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest Dec 26, 2024 5 - Production/Stable pytest>=8.3.4 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 29, 2024 N/A pytest>=6.0 @@ -116,12 +116,14 @@ This list contains 1559 plugins. :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Dec 13, 2024 4 - Beta pytest<9,>=8.2 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Dec 26, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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进行自定义 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-atstack` A simple plugin to use with pytest Dec 28, 2024 4 - Beta pytest>=6.2.0 :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-attributes` A plugin that allows users to add attributes to their tests. These attributes can then be referenced by fixtures or the test itself. Jun 24, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A @@ -157,7 +159,7 @@ This list contains 1559 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Dec 16, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Dec 23, 2024 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -362,7 +364,7 @@ This list contains 1559 plugins. :pypi:`pytest-deprecator` A simple plugin to use with pytest Dec 02, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-describe` Describe-style plugin for pytest Feb 10, 2024 5 - Production/Stable pytest <9,>=4.6 :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest - :pypi:`pytest-deselect-if` A plugin to deselect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-deselect-if` A plugin to deselect pytests tests rather than using skipif Dec 26, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-devpi-server` DevPI server fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-dhos` Common fixtures for pytest in DHOS services and libraries Sep 07, 2022 N/A N/A :pypi:`pytest-diamond` pytest plugin for diamond Aug 31, 2015 4 - Beta N/A @@ -623,7 +625,7 @@ This list contains 1559 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Dec 05, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Dec 23, 2024 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -667,7 +669,7 @@ This list contains 1559 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Dec 21, 2024 3 - Alpha pytest==8.3.3 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Dec 26, 2024 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -863,7 +865,7 @@ This list contains 1559 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Dec 20, 2024 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Dec 27, 2024 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -916,7 +918,7 @@ This list contains 1559 plugins. :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" - :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Mar 31, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Dec 21, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 :pypi:`pytest-mypy-runner` Run the mypy static type checker as a pytest test case Apr 23, 2024 N/A pytest>=8.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 @@ -991,7 +993,7 @@ This list contains 1559 plugins. :pypi:`pytest-parametrization-annotation` A pytest library for parametrizing tests using type hints. Dec 10, 2024 5 - Production/Stable pytest>=7 :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Nov 10, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 :pypi:`pytest-parametrize-cases` A more user-friendly way to write parametrized tests. Mar 13, 2022 N/A pytest (>=6.1.2) - :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Oct 22, 2024 5 - Production/Stable pytest + :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Dec 21, 2024 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest :pypi:`pytest_param_files` Create pytest parametrize decorators from external files. Jul 29, 2023 N/A pytest :pypi:`pytest-params` Simplified pytest test case parameters. Aug 05, 2024 N/A pytest>=7.0.0 @@ -1133,7 +1135,7 @@ This list contains 1559 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jun 07, 2024 4 - Beta pytest>=7.4.3 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Dec 23, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Dec 19, 2024 N/A N/A @@ -1165,7 +1167,7 @@ This list contains 1559 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. Dec 15, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. Dec 28, 2024 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1187,7 +1189,7 @@ This list contains 1559 plugins. :pypi:`pytest-rerunclassfailures` pytest rerun class failures plugin Apr 24, 2024 5 - Production/Stable pytest>=7.2 :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Nov 20, 2024 5 - Production/Stable pytest!=8.2.2,>=7.4 :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. Jul 23, 2024 4 - Beta pytest + :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Dec 22, 2024 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Dec 16, 2024 N/A pytest~=7.0 :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) @@ -1240,7 +1242,7 @@ This list contains 1559 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 15, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 25, 2024 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1251,7 +1253,7 @@ This list contains 1559 plugins. :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 Feb 01, 2024 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. Dec 15, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Dec 25, 2024 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1406,7 +1408,7 @@ This list contains 1559 plugins. :pypi:`pytest-testinfra-winrm-transport` Test infrastructures Sep 21, 2023 5 - Production/Stable N/A :pypi:`pytest-testit-parametrize` A pytest plugin for uploading parameterized tests parameters into TMS TestIT Dec 04, 2024 4 - Beta pytest>=8.3.3 :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 Feb 27, 2024 4 - Beta pytest <9,>=5 + :pypi:`pytest-testmon` selects tests affected by changed files and methods Dec 22, 2024 4 - Beta pytest<9,>=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) @@ -1495,7 +1497,7 @@ This list contains 1559 plugins. :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest :pypi:`pytest-ui-failed-screenshot` UI自动测试失败时自动截图,并将截图加入到测试报告中 Dec 06, 2022 N/A N/A :pypi:`pytest-ui-failed-screenshot-allure` UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 Dec 06, 2022 N/A N/A - :pypi:`pytest-uncollect-if` A plugin to uncollect pytests tests rather than using skipif Mar 24, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-uncollect-if` A plugin to uncollect pytests tests rather than using skipif Dec 26, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unflakable` Unflakable plugin for PyTest Apr 30, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-unique` Pytest fixture to generate unique values. Oct 21, 2024 N/A pytest<8.0.0,>=7.4.2 @@ -1539,7 +1541,7 @@ This list contains 1559 plugins. :pypi:`pytest-web3-data` A pytest plugin to fetch test data from IPFS HTTP gateways during pytest execution. Oct 04, 2023 4 - Beta pytest :pypi:`pytest-webdriver` Selenium webdriver fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-webstage` Test web apps with pytest Sep 20, 2024 N/A pytest<9.0,>=7.0 - :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Oct 03, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-webtest-extras` Pytest plugin to enhance pytest-html and allure reports of webtest projects by adding screenshots, comments and webpage sources. Dec 28, 2024 N/A pytest>=7.0.0 :pypi:`pytest-wetest` Welian API Automation test framework pytest plugin Nov 10, 2018 4 - Beta N/A :pypi:`pytest-when` Utility which makes mocking more readable and controllable Nov 29, 2024 N/A pytest>=7.3.1 :pypi:`pytest-whirlwind` Testing Tornado. Jun 12, 2020 N/A N/A @@ -1774,9 +1776,9 @@ This list contains 1559 plugins. py.test integration for aioresponses :pypi:`pytest-aioworkers` - *last release*: May 01, 2023, + *last release*: Dec 26, 2024, *status*: 5 - Production/Stable, - *requires*: pytest>=6.1.0 + *requires*: pytest>=8.3.4 A plugin to test aioworkers project with pytest @@ -2172,6 +2174,13 @@ This list contains 1559 plugins. Pytest support for asyncio + :pypi:`pytest-asyncio-concurrent` + *last release*: Dec 26, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + Pytest plugin to execute python async tests concurrently. + :pypi:`pytest-asyncio-cooperative` *last release*: Jul 04, 2024, *status*: N/A, @@ -2214,6 +2223,13 @@ This list contains 1559 plugins. Skip rest of tests if previous test failed. + :pypi:`pytest-atstack` + *last release*: Dec 28, 2024, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A simple plugin to use with pytest + :pypi:`pytest-attrib` *last release*: May 24, 2016, *status*: 4 - Beta, @@ -2460,7 +2476,7 @@ This list contains 1559 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Dec 16, 2024, + *last release*: Dec 23, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -3895,7 +3911,7 @@ This list contains 1559 plugins. plugin for rich text descriptions :pypi:`pytest-deselect-if` - *last release*: Mar 24, 2024, + *last release*: Dec 26, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -5722,7 +5738,7 @@ This list contains 1559 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Dec 05, 2024, + *last release*: Dec 23, 2024, *status*: N/A, *requires*: pytest>=3.6 @@ -6030,9 +6046,9 @@ This list contains 1559 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Dec 21, 2024, + *last release*: Dec 26, 2024, *status*: 3 - Alpha, - *requires*: pytest==8.3.3 + *requires*: pytest==8.3.4 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -7402,7 +7418,7 @@ This list contains 1559 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Dec 20, 2024, + *last release*: Dec 27, 2024, *status*: N/A, *requires*: N/A @@ -7773,7 +7789,7 @@ This list contains 1559 plugins. Mypy static type checker plugin for Pytest :pypi:`pytest-mypy-plugins` - *last release*: Mar 31, 2024, + *last release*: Dec 21, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -8298,7 +8314,7 @@ This list contains 1559 plugins. A more user-friendly way to write parametrized tests. :pypi:`pytest-parametrized` - *last release*: Oct 22, 2024, + *last release*: Dec 21, 2024, *status*: 5 - Production/Stable, *requires*: pytest @@ -9292,7 +9308,7 @@ This list contains 1559 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-ranking` - *last release*: Jun 07, 2024, + *last release*: Dec 23, 2024, *status*: 4 - Beta, *requires*: pytest>=7.4.3 @@ -9516,9 +9532,9 @@ This list contains 1559 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Dec 15, 2024, + *last release*: Dec 28, 2024, *status*: N/A, - *requires*: pytest>=7.0.0 + *requires*: pytest>=8.0.0 Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. @@ -9670,7 +9686,7 @@ This list contains 1559 plugins. pytest plugin to re-run tests to eliminate flaky failures :pypi:`pytest-reserial` - *last release*: Jul 23, 2024, + *last release*: Dec 22, 2024, *status*: 4 - Beta, *requires*: pytest @@ -10041,7 +10057,7 @@ This list contains 1559 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Dec 15, 2024, + *last release*: Dec 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -10118,7 +10134,7 @@ This list contains 1559 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Dec 15, 2024, + *last release*: Dec 25, 2024, *status*: 5 - Production/Stable, *requires*: N/A @@ -11203,9 +11219,9 @@ This list contains 1559 plugins. pytest reporting plugin for testlink :pypi:`pytest-testmon` - *last release*: Feb 27, 2024, + *last release*: Dec 22, 2024, *status*: 4 - Beta, - *requires*: pytest <9,>=5 + *requires*: pytest<9,>=5 selects tests affected by changed files and methods @@ -11826,7 +11842,7 @@ This list contains 1559 plugins. UI自动测试失败时自动截图,并将截图加入到Allure测试报告中 :pypi:`pytest-uncollect-if` - *last release*: Mar 24, 2024, + *last release*: Dec 26, 2024, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -12134,7 +12150,7 @@ This list contains 1559 plugins. Test web apps with pytest :pypi:`pytest-webtest-extras` - *last release*: Oct 03, 2024, + *last release*: Dec 28, 2024, *status*: N/A, *requires*: pytest>=7.0.0 From f2c3237f51518715db455b33d53bc1fa3c831a04 Mon Sep 17 00:00:00 2001 From: "Jason N. White" Date: Wed, 1 Jan 2025 03:58:27 -0500 Subject: [PATCH 1045/1271] Update LICENSE, fix license year (#13097) Signed-off-by: JasonnnW3000 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index c3f1657fce9..b591972a049 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2004 Holger Krekel and others +Copyright (c) 2025 Holger Krekel and others Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in From 0d90a31d4a647fa7ba0d53a05b9266c2d4aaa05a Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 1 Jan 2025 16:40:40 +0100 Subject: [PATCH 1046/1271] Revert "Update LICENSE, fix license year (#13097)" This reverts commit f2c3237f51518715db455b33d53bc1fa3c831a04. --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index b591972a049..c3f1657fce9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2025 Holger Krekel and others +Copyright (c) 2004 Holger Krekel and others Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in From 7e5c1b631df47629b62171f856bdcd1c684eae81 Mon Sep 17 00:00:00 2001 From: Julian Valentin <128477611+JulianJvn@users.noreply.github.com> Date: Thu, 2 Jan 2025 08:31:08 +0100 Subject: [PATCH 1047/1271] Fix -vv overriding --durations-min (#12938) --- AUTHORS | 1 + changelog/12938.bugfix.rst | 1 + src/_pytest/runner.py | 14 +++++++++--- testing/acceptance_test.py | 44 ++++++++++++++++++++++++-------------- 4 files changed, 41 insertions(+), 19 deletions(-) create mode 100644 changelog/12938.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 9629e00bcfb..f9bade5f0fa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -225,6 +225,7 @@ Joseph Hunkeler Joseph Sawaya Josh Karpel Joshua Bronson +Julian Valentin Jurko Gospodnetić Justice Ndou Justyna Janczyszyn diff --git a/changelog/12938.bugfix.rst b/changelog/12938.bugfix.rst new file mode 100644 index 00000000000..d54d73bdbf5 --- /dev/null +++ b/changelog/12938.bugfix.rst @@ -0,0 +1 @@ +Fixed ``--durations-min`` argument not respected if ``-vv`` is used. diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index d2b7fda8c2a..973892f2c92 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -61,7 +61,7 @@ def pytest_addoption(parser: Parser) -> None: "--durations-min", action="store", type=float, - default=0.005, + default=None, metavar="N", help="Minimal duration in seconds for inclusion in slowest list. " "Default: 0.005.", @@ -74,6 +74,8 @@ def pytest_terminal_summary(terminalreporter: TerminalReporter) -> None: verbose = terminalreporter.config.get_verbosity() if durations is None: return + if durations_min is None: + durations_min = 0.005 if verbose < 2 else 0.0 tr = terminalreporter dlist = [] for replist in tr.stats.values(): @@ -90,10 +92,16 @@ def pytest_terminal_summary(terminalreporter: TerminalReporter) -> None: dlist = dlist[:durations] for i, rep in enumerate(dlist): - if verbose < 2 and rep.duration < durations_min: + if rep.duration < durations_min: tr.write_line("") tr.write_line( - f"({len(dlist) - i} durations < {durations_min:g}s hidden. Use -vv to show these durations.)" + f"({len(dlist) - i} durations < {durations_min:g}s hidden." + + ( + " Use -vv to show these durations." + if terminalreporter.config.option.durations_min is None + else "" + ) + + ")" ) break tr.write_line(f"{rep.duration:02.2f}s {rep.when:<8} {rep.nodeid}") diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index ba1f86f02d9..a42940c9f6a 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs from __future__ import annotations +from collections.abc import Sequence import dataclasses import importlib.metadata import os @@ -970,28 +971,39 @@ def test_calls_showall(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=0") assert result.ret == 0 - - tested = "3" - for x in tested: - for y in ("call",): # 'setup', 'call', 'teardown': - for line in result.stdout.lines: - if (f"test_{x}") in line and y in line: - break - else: - raise AssertionError(f"not found {x} {y}") + print(result.stdout) + TestDurations.check_tests_in_output(result.stdout.lines, "23") def test_calls_showall_verbose(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=0", "-vv") assert result.ret == 0 + TestDurations.check_tests_in_output(result.stdout.lines, "123") - for x in "123": - for y in ("call",): # 'setup', 'call', 'teardown': - for line in result.stdout.lines: - if (f"test_{x}") in line and y in line: - break - else: - raise AssertionError(f"not found {x} {y}") + def test_calls_showall_durationsmin(self, pytester: Pytester, mock_timing) -> None: + pytester.makepyfile(self.source) + result = pytester.runpytest_inprocess("--durations=0", "--durations-min=0.015") + assert result.ret == 0 + TestDurations.check_tests_in_output(result.stdout.lines, "3") + + def test_calls_showall_durationsmin_verbose( + self, pytester: Pytester, mock_timing + ) -> None: + pytester.makepyfile(self.source) + result = pytester.runpytest_inprocess( + "--durations=0", "--durations-min=0.015", "-vv" + ) + assert result.ret == 0 + TestDurations.check_tests_in_output(result.stdout.lines, "3") + + @staticmethod + def check_tests_in_output(lines: Sequence[str], expected_test_numbers: str) -> None: + found_test_numbers = "".join( + test_number + for test_number in "123" + if any(f"test_{test_number}" in line and " call " in line for line in lines) + ) + assert found_test_numbers == expected_test_numbers def test_with_deselected(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) From 30e7ad9aed0989a1047f1beeec198ba12eda51a4 Mon Sep 17 00:00:00 2001 From: Julian Valentin <128477611+JulianJvn@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:39:52 +0100 Subject: [PATCH 1048/1271] Remove leftover debug print in acceptance_test --- testing/acceptance_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index a42940c9f6a..4fed0f015d1 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -971,7 +971,6 @@ def test_calls_showall(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=0") assert result.ret == 0 - print(result.stdout) TestDurations.check_tests_in_output(result.stdout.lines, "23") def test_calls_showall_verbose(self, pytester: Pytester, mock_timing) -> None: From 61b4f7a157cab3da8e444bd3b5c81a9413a39b7b Mon Sep 17 00:00:00 2001 From: Julian Valentin <128477611+JulianJvn@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:39:52 +0100 Subject: [PATCH 1049/1271] Clarify --durations-min default in help text --- src/_pytest/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 973892f2c92..98090f3b4c6 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -64,7 +64,7 @@ def pytest_addoption(parser: Parser) -> None: default=None, metavar="N", help="Minimal duration in seconds for inclusion in slowest list. " - "Default: 0.005.", + "Default: 0.005 (or 0.0 if -vv is given).", ) From a811765b21bc428273fc054f553d8be5b19da2b0 Mon Sep 17 00:00:00 2001 From: Julian Valentin <128477611+JulianJvn@users.noreply.github.com> Date: Thu, 2 Jan 2025 18:39:52 +0100 Subject: [PATCH 1050/1271] Simplify message formatting --- src/_pytest/runner.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index 98090f3b4c6..f0543289267 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -94,15 +94,11 @@ def pytest_terminal_summary(terminalreporter: TerminalReporter) -> None: for i, rep in enumerate(dlist): if rep.duration < durations_min: tr.write_line("") - tr.write_line( - f"({len(dlist) - i} durations < {durations_min:g}s hidden." - + ( - " Use -vv to show these durations." - if terminalreporter.config.option.durations_min is None - else "" - ) - + ")" - ) + message = f"({len(dlist) - i} durations < {durations_min:g}s hidden." + if terminalreporter.config.option.durations_min is None: + message += " Use -vv to show these durations." + message += ")" + tr.write_line(message) break tr.write_line(f"{rep.duration:02.2f}s {rep.when:<8} {rep.nodeid}") From 6f98c96cbf80756b1b360dc5f4860ac7d7dc9427 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Sun, 5 Jan 2025 00:26:35 +0000 Subject: [PATCH 1051/1271] [automated] Update plugin list --- doc/en/reference/plugin_list.rst | 120 ++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 40 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6b2a1898203..2ccaa87b5e6 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.1.0 :pypi:`pytest-aiohttp-client` Pytest \`client\` fixture for the Aiohttp Jan 10, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-aiomoto` pytest-aiomoto Jun 24, 2023 N/A pytest (>=7.0,<8.0) - :pypi:`pytest-aioresponses` py.test integration for aioresponses Jul 29, 2021 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-aioresponses` py.test integration for aioresponses Jan 02, 2025 4 - Beta pytest>=3.5.0 :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest Dec 26, 2024 5 - Production/Stable pytest>=8.3.4 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A @@ -115,15 +115,15 @@ This list contains 1561 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Dec 13, 2024 4 - Beta pytest<9,>=8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Dec 26, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Jan 02, 2025 4 - Beta pytest<9,>=8.2 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Jan 03, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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进行自定义 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-atstack` A simple plugin to use with pytest Dec 28, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-atstack` A simple plugin to use with pytest Jan 02, 2025 4 - Beta pytest>=6.2.0 :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-attributes` A plugin that allows users to add attributes to their tests. These attributes can then be referenced by fixtures or the test itself. Jun 24, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-austin` Austin plugin for pytest Oct 11, 2020 4 - Beta N/A @@ -218,6 +218,7 @@ This list contains 1561 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A + :pypi:`pytest-cdist` Add your description here Dec 31, 2024 N/A pytest>=7 :pypi:`pytest-celery` Pytest plugin for Celery Sep 20, 2024 4 - Beta N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A @@ -553,7 +554,7 @@ This list contains 1561 plugins. :pypi:`pytest-fastest` Use SCM and coverage to run only needed tests Oct 04, 2023 4 - Beta pytest (>=4.4) :pypi:`pytest-fast-first` Pytest plugin that runs fast tests first Jan 19, 2023 3 - Alpha pytest :pypi:`pytest-faulthandler` py.test plugin that activates the fault handler module for tests (dummy package) Jul 04, 2019 6 - Mature pytest (>=5.0) - :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Oct 17, 2024 N/A N/A + :pypi:`pytest-fauna` A collection of helpful test fixtures for Fauna DB. Jan 03, 2025 N/A N/A :pypi:`pytest-fauxfactory` Integration of fauxfactory into pytest. Dec 06, 2017 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-figleaf` py.test figleaf coverage plugin Jan 18, 2010 5 - Production/Stable N/A :pypi:`pytest-file` Pytest File Mar 18, 2024 1 - Planning N/A @@ -669,7 +670,7 @@ This list contains 1561 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Dec 26, 2024 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jan 04, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -689,7 +690,7 @@ This list contains 1561 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Sep 18, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Nov 23, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Dec 29, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A @@ -708,7 +709,7 @@ This list contains 1561 plugins. :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 20, 2024 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-diff` Dec 31, 2024 3 - Alpha pytest :pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Jul 01, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-import-check` pytest plugin to check whether Python modules can be imported Jul 19, 2024 3 - Alpha pytest>=8.1 :pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A @@ -771,6 +772,7 @@ This list contains 1561 plugins. :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Jul 21, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-junit-xray-xml` Export test results in an augmented JUnit format for usage with Xray () Jan 01, 2025 4 - Beta pytest :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest :pypi:`pytest-kafka` Zookeeper, Kafka server, and Kafka consumer fixtures for Pytest Aug 14, 2024 N/A pytest @@ -829,6 +831,7 @@ This list contains 1561 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) + :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Jan 03, 2025 3 - Alpha pytest :pypi:`pytest-logikal` Common testing environment Nov 27, 2024 5 - Production/Stable pytest==8.3.3 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 @@ -858,7 +861,7 @@ This list contains 1561 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. May 18, 2024 4 - Beta pytest!=6.0.0,<9,>=3.3.2 + :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. Jan 02, 2025 4 - Beta pytest!=6.0.0,<9,>=3.3.2 :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Oct 08, 2024 N/A pytest>=7.4.3 :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A @@ -898,6 +901,7 @@ This list contains 1561 plugins. :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Mar 13, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A + :pypi:`pytest-mongodb-ry` pytest plugin for MongoDB Dec 31, 2024 N/A N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A @@ -1013,7 +1017,7 @@ This list contains 1561 plugins. :pypi:`pytest-percents` Mar 16, 2024 N/A N/A :pypi:`pytest-perf` Run performance tests against the mainline code. May 20, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) - :pypi:`pytest-performancetotal` A performance plugin for pytest Mar 19, 2024 4 - Beta N/A + :pypi:`pytest-performancetotal` A performance plugin for pytest Dec 31, 2024 5 - Production/Stable N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Aug 21, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 @@ -1060,7 +1064,7 @@ This list contains 1561 plugins. :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Sep 05, 2024 5 - Production/Stable pytest>=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) - :pypi:`pytest-powerpack` A plugin containing extra batteries for pytest Dec 17, 2024 N/A pytest<9.0.0,>=8.1.1 + :pypi:`pytest-powerpack` A plugin containing extra batteries for pytest Jan 04, 2025 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) @@ -1167,7 +1171,7 @@ This list contains 1561 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. Dec 28, 2024 N/A pytest>=8.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. Jan 04, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1263,7 +1267,7 @@ This list contains 1561 plugins. :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixtures for py.test Nov 29, 2024 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Nov 14, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-servers` pytest servers Dec 29, 2024 3 - Alpha pytest>=6.2 :pypi:`pytest-service` Aug 06, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest @@ -1299,7 +1303,7 @@ This list contains 1561 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A - :pypi:`pytest-smoke` Pytest plugin for smoke testing Dec 13, 2024 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-smoke` Pytest plugin for smoke testing Dec 30, 2024 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -1335,7 +1339,7 @@ This list contains 1561 plugins. :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 28, 2024 N/A pytest<8,>5.4.0 - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Nov 24, 2024 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jan 03, 2025 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 @@ -1366,7 +1370,7 @@ This list contains 1561 plugins. :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 Jul 24, 2024 5 - Production/Stable pytest>=4.0.0 + :pypi:`pytest-subprocess` A plugin to fake subprocess for pytest Jan 04, 2025 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 Dec 10, 2024 4 - Beta pytest>=7.4 :pypi:`pytest-subunit` pytest-subunit is a plugin for py.test which outputs testsresult in subunit format. Sep 17, 2023 N/A pytest (>=2.3) @@ -1500,7 +1504,7 @@ This list contains 1561 plugins. :pypi:`pytest-uncollect-if` A plugin to uncollect pytests tests rather than using skipif Dec 26, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unflakable` Unflakable plugin for PyTest Apr 30, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) - :pypi:`pytest-unique` Pytest fixture to generate unique values. Oct 21, 2024 N/A pytest<8.0.0,>=7.4.2 + :pypi:`pytest-unique` Pytest fixture to generate unique values. Jan 03, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) :pypi:`pytest-unmagic` Pytest fixtures with conventional import semantics Oct 22, 2024 5 - Production/Stable pytest :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A @@ -1556,6 +1560,7 @@ This list contains 1561 plugins. :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Jan 04, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 14, 2024 4 - Beta pytest>=8.2.1 @@ -1573,7 +1578,7 @@ This list contains 1561 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. Dec 15, 2024 4 - Beta pytest>=7.2.2 :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 with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Nov 20, 2024 N/A pytest~=8.2.2 + :pypi:`pytest-yaml-sanmu` Pytest plugin for generating test cases with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Jan 03, 2025 N/A pytest>=8.2.2 :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) @@ -1769,9 +1774,9 @@ This list contains 1561 plugins. pytest-aiomoto :pypi:`pytest-aioresponses` - *last release*: Jul 29, 2021, + *last release*: Jan 02, 2025, *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *requires*: pytest>=3.5.0 py.test integration for aioresponses @@ -2168,14 +2173,14 @@ This list contains 1561 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Dec 13, 2024, + *last release*: Jan 02, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=8.2 Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Dec 26, 2024, + *last release*: Jan 03, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2224,7 +2229,7 @@ This list contains 1561 plugins. Skip rest of tests if previous test failed. :pypi:`pytest-atstack` - *last release*: Dec 28, 2024, + *last release*: Jan 02, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2888,6 +2893,13 @@ This list contains 1561 plugins. Pytest plugin with server for catching HTTP requests. + :pypi:`pytest-cdist` + *last release*: Dec 31, 2024, + *status*: N/A, + *requires*: pytest>=7 + + Add your description here + :pypi:`pytest-celery` *last release*: Sep 20, 2024, *status*: 4 - Beta, @@ -5234,7 +5246,7 @@ This list contains 1561 plugins. py.test plugin that activates the fault handler module for tests (dummy package) :pypi:`pytest-fauna` - *last release*: Oct 17, 2024, + *last release*: Jan 03, 2025, *status*: N/A, *requires*: N/A @@ -6046,7 +6058,7 @@ This list contains 1561 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Dec 26, 2024, + *last release*: Jan 04, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6186,7 +6198,7 @@ This list contains 1561 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Nov 23, 2024, + *last release*: Dec 29, 2024, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -6319,7 +6331,7 @@ This list contains 1561 plugins. A pytest plugin to ignore test results. :pypi:`pytest-image-diff` - *last release*: Mar 09, 2023, + *last release*: Dec 31, 2024, *status*: 3 - Alpha, *requires*: pytest @@ -6759,6 +6771,13 @@ This list contains 1561 plugins. pytest plugin supporting json test report output + :pypi:`pytest-junit-xray-xml` + *last release*: Jan 01, 2025, + *status*: 4 - Beta, + *requires*: pytest + + Export test results in an augmented JUnit format for usage with Xray () + :pypi:`pytest-jupyter` *last release*: Apr 04, 2024, *status*: 4 - Beta, @@ -7165,6 +7184,13 @@ This list contains 1561 plugins. + :pypi:`pytest-logging-strict` + *last release*: Jan 03, 2025, + *status*: 3 - Alpha, + *requires*: pytest + + pytest fixture logging configured from packaged YAML + :pypi:`pytest-logikal` *last release*: Nov 27, 2024, *status*: 5 - Production/Stable, @@ -7369,7 +7395,7 @@ This list contains 1561 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: May 18, 2024, + *last release*: Jan 02, 2025, *status*: 4 - Beta, *requires*: pytest!=6.0.0,<9,>=3.3.2 @@ -7648,6 +7674,13 @@ This list contains 1561 plugins. pytest plugin for MongoDB fixtures + :pypi:`pytest-mongodb-ry` + *last release*: Dec 31, 2024, + *status*: N/A, + *requires*: N/A + + pytest plugin for MongoDB + :pypi:`pytest-monitor` *last release*: Jun 25, 2023, *status*: 5 - Production/Stable, @@ -8454,8 +8487,8 @@ This list contains 1561 plugins. A simple plugin to ensure the execution of critical sections of code has not been impacted :pypi:`pytest-performancetotal` - *last release*: Mar 19, 2024, - *status*: 4 - Beta, + *last release*: Dec 31, 2024, + *status*: 5 - Production/Stable, *requires*: N/A A performance plugin for pytest @@ -8783,7 +8816,7 @@ This list contains 1561 plugins. pytest plugin with powerful fixtures :pypi:`pytest-powerpack` - *last release*: Dec 17, 2024, + *last release*: Jan 04, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=8.1.1 @@ -9532,7 +9565,7 @@ This list contains 1561 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Dec 28, 2024, + *last release*: Jan 04, 2025, *status*: N/A, *requires*: pytest>=8.0.0 @@ -10204,7 +10237,7 @@ This list contains 1561 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Nov 14, 2024, + *last release*: Dec 29, 2024, *status*: 3 - Alpha, *requires*: pytest>=6.2 @@ -10456,7 +10489,7 @@ This list contains 1561 plugins. Automated bad smell detection tool for Pytest :pypi:`pytest-smoke` - *last release*: Dec 13, 2024, + *last release*: Dec 30, 2024, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 @@ -10708,7 +10741,7 @@ This list contains 1561 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Nov 24, 2024, + *last release*: Jan 03, 2025, *status*: N/A, *requires*: N/A @@ -10925,7 +10958,7 @@ This list contains 1561 plugins. Run pytest in a subinterpreter :pypi:`pytest-subprocess` - *last release*: Jul 24, 2024, + *last release*: Jan 04, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=4.0.0 @@ -11863,7 +11896,7 @@ This list contains 1561 plugins. Plugin for py.test set a different exit code on uncaught exceptions :pypi:`pytest-unique` - *last release*: Oct 21, 2024, + *last release*: Jan 03, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.2 @@ -12254,6 +12287,13 @@ This list contains 1561 plugins. A pytest plugin to list worker statistics after a xdist run. + :pypi:`pytest-xdocker` + *last release*: Jan 04, 2025, + *status*: N/A, + *requires*: pytest<8.0.0,>=7.4.2 + + Pytest fixture to run docker across test runs. + :pypi:`pytest-xfaillist` *last release*: Sep 17, 2021, *status*: N/A, @@ -12374,9 +12414,9 @@ This list contains 1561 plugins. This plugin is used to load yaml output to your test using pytest framework. :pypi:`pytest-yaml-sanmu` - *last release*: Nov 20, 2024, + *last release*: Jan 03, 2025, *status*: N/A, - *requires*: pytest~=8.2.2 + *requires*: pytest>=8.2.2 Pytest plugin for generating test cases with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. From 071bfb3d04408d2ccb9c7966347eda061b3a8762 Mon Sep 17 00:00:00 2001 From: Julian Valentin <128477611+JulianJvn@users.noreply.github.com> Date: Tue, 7 Jan 2025 08:39:40 +0100 Subject: [PATCH 1052/1271] Supply test numbers instead of string Use `endswith()` because the code would break for `number_of_tests >= 10` (as `test_10` also contains `test_1`). --- testing/acceptance_test.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 4fed0f015d1..06b97c34707 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -971,19 +971,19 @@ def test_calls_showall(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=0") assert result.ret == 0 - TestDurations.check_tests_in_output(result.stdout.lines, "23") + TestDurations.check_tests_in_output(result.stdout.lines, 2, 3) def test_calls_showall_verbose(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=0", "-vv") assert result.ret == 0 - TestDurations.check_tests_in_output(result.stdout.lines, "123") + TestDurations.check_tests_in_output(result.stdout.lines, 1, 2, 3) def test_calls_showall_durationsmin(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) result = pytester.runpytest_inprocess("--durations=0", "--durations-min=0.015") assert result.ret == 0 - TestDurations.check_tests_in_output(result.stdout.lines, "3") + TestDurations.check_tests_in_output(result.stdout.lines, 3) def test_calls_showall_durationsmin_verbose( self, pytester: Pytester, mock_timing @@ -993,16 +993,22 @@ def test_calls_showall_durationsmin_verbose( "--durations=0", "--durations-min=0.015", "-vv" ) assert result.ret == 0 - TestDurations.check_tests_in_output(result.stdout.lines, "3") + TestDurations.check_tests_in_output(result.stdout.lines, 3) @staticmethod - def check_tests_in_output(lines: Sequence[str], expected_test_numbers: str) -> None: - found_test_numbers = "".join( + def check_tests_in_output( + lines: Sequence[str], *expected_test_numbers: int + ) -> None: + number_of_tests = 3 + found_test_numbers = set( test_number - for test_number in "123" - if any(f"test_{test_number}" in line and " call " in line for line in lines) + for test_number in range(1, number_of_tests + 1) + if any( + line.endswith(f"test_{test_number}") and " call " in line + for line in lines + ) ) - assert found_test_numbers == expected_test_numbers + assert found_test_numbers == set(expected_test_numbers) def test_with_deselected(self, pytester: Pytester, mock_timing) -> None: pytester.makepyfile(self.source) From 0d077e640cb7d347f63c44026659b2ec46ab3e59 Mon Sep 17 00:00:00 2001 From: Julian Valentin <128477611+JulianJvn@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:22:27 +0100 Subject: [PATCH 1053/1271] Move number_of_tests to parameters --- testing/acceptance_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 06b97c34707..ffd1dcce219 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -997,9 +997,8 @@ def test_calls_showall_durationsmin_verbose( @staticmethod def check_tests_in_output( - lines: Sequence[str], *expected_test_numbers: int + lines: Sequence[str], *expected_test_numbers: int, number_of_tests: int = 3 ) -> None: - number_of_tests = 3 found_test_numbers = set( test_number for test_number in range(1, number_of_tests + 1) From 888cf3fd76adf5a9bfabc04736b96f9be3f55dbc Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 7 Jan 2025 11:25:55 +0100 Subject: [PATCH 1054/1271] Fix selftests with Pygments >= 2.19.0 With Pygments 2.19, the Python lexer now emits Text.Whitespace (rather than Text) tokens after "def", which get highlighted as "bright black". See https://github.com/pygments/pygments/issues/1905 Fixes #13112 --- changelog/13112.contrib.rst | 1 + testing/conftest.py | 8 ++++++++ testing/test_terminal.py | 10 +++++----- 3 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 changelog/13112.contrib.rst diff --git a/changelog/13112.contrib.rst b/changelog/13112.contrib.rst new file mode 100644 index 00000000000..5e59a736edb --- /dev/null +++ b/changelog/13112.contrib.rst @@ -0,0 +1 @@ +Fixed selftest failures in ``test_terminal.py`` with Pygments >= 2.19.0 diff --git a/testing/conftest.py b/testing/conftest.py index 110ad0d9b35..c9ffd33835b 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -2,10 +2,14 @@ from __future__ import annotations from collections.abc import Generator +import importlib.metadata import dataclasses import re import sys +import pygments +from packaging.version import Version + from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester import pytest @@ -168,6 +172,9 @@ def color_mapping(): Used by tests which check the actual colors output by pytest. """ + # https://github.com/pygments/pygments/commit/d24e272894a56a98b1b718d9ac5fabc20124882a + pygments_version = Version(importlib.metadata.version("pygments")) + pygments_has_kwspace_hl = pygments_version >= Version("2.19") class ColorMapping: COLORS = { @@ -180,6 +187,7 @@ class ColorMapping: "bold": "\x1b[1m", "reset": "\x1b[0m", "kw": "\x1b[94m", + "kwspace": "\x1b[90m \x1b[39;49;00m" if pygments_has_kwspace_hl else " ", "hl-reset": "\x1b[39;49;00m", "function": "\x1b[92m", "number": "\x1b[94m", diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 6fa04be28b1..32206364125 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -1294,13 +1294,13 @@ def test_this(): "=*= FAILURES =*=", "{red}{bold}_*_ test_this _*_{reset}", "", - " {reset}{kw}def{hl-reset} {function}test_this{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}test_this{hl-reset}():{endline}", "> fail(){endline}", "", "{bold}{red}test_color_yes.py{reset}:5: ", "_ _ * _ _*", "", - " {reset}{kw}def{hl-reset} {function}fail{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}fail{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}0{hl-reset}{endline}", "{bold}{red}E assert 0{reset}", "", @@ -2580,7 +2580,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}test_foo{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}1{hl-reset} == {number}10{hl-reset}{endline}", "{bold}{red}E assert 1 == 10{reset}", ] @@ -2602,7 +2602,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}test_foo{hl-reset}():{endline}", " {print}print{hl-reset}({str}'''{hl-reset}{str}{hl-reset}", "> {str} {hl-reset}{str}'''{hl-reset}); {kw}assert{hl-reset} {number}0{hl-reset}{endline}", "{bold}{red}E assert 0{reset}", @@ -2625,7 +2625,7 @@ def test_foo(): result.stdout.fnmatch_lines( color_mapping.format_for_fnmatch( [ - " {reset}{kw}def{hl-reset} {function}test_foo{hl-reset}():{endline}", + " {reset}{kw}def{hl-reset}{kwspace}{function}test_foo{hl-reset}():{endline}", "> {kw}assert{hl-reset} {number}1{hl-reset} == {number}10{hl-reset}{endline}", "{bold}{red}E assert 1 == 10{reset}", ] From ecf05486c8e72b7e49e547bf1124ddd02f7aacb3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:02:19 +0000 Subject: [PATCH 1055/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- testing/conftest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/testing/conftest.py b/testing/conftest.py index c9ffd33835b..45a47cbdbaa 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -2,12 +2,11 @@ from __future__ import annotations from collections.abc import Generator -import importlib.metadata import dataclasses +import importlib.metadata import re import sys -import pygments from packaging.version import Version from _pytest.monkeypatch import MonkeyPatch From 3214263b2f0d17b265c40cf5f87d70357b9a219d Mon Sep 17 00:00:00 2001 From: delta87 <124760624+delta87@users.noreply.github.com> Date: Thu, 9 Jan 2025 00:27:22 +0330 Subject: [PATCH 1056/1271] Fix crash when directory is removed during collection (#13086) Fixes #13083 --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/13083.bugfix.rst | 1 + src/_pytest/pathlib.py | 13 ++++++++++--- testing/test_pathlib.py | 24 ++++++++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 changelog/13083.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 9629e00bcfb..826556f1464 100644 --- a/AUTHORS +++ b/AUTHORS @@ -360,6 +360,7 @@ Ran Benita Raphael Castaneda Raphael Pierzina Rafal Semik +Reza Mousavi Raquel Alegre Ravi Chandra Reagan Lee diff --git a/changelog/13083.bugfix.rst b/changelog/13083.bugfix.rst new file mode 100644 index 00000000000..fc4564755ba --- /dev/null +++ b/changelog/13083.bugfix.rst @@ -0,0 +1 @@ +Fixed issue where pytest could crash if one of the collected directories got removed during collection. diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 25dc69b6349..7c06e2df962 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -955,17 +955,24 @@ def scandir( The returned entries are sorted according to the given key. The default is to sort by name. + If the directory does not exist, return an empty list. """ entries = [] - with os.scandir(path) as s: - # Skip entries with symlink loops and other brokenness, so the caller - # doesn't have to deal with it. + # Attempt to create a scandir iterator for the given path. + try: + scandir_iter = os.scandir(path) + except FileNotFoundError: + # If the directory does not exist, return an empty list. + return [] + # Use the scandir iterator in a context manager to ensure it is properly closed. + with scandir_iter as s: for entry in s: try: entry.is_file() except OSError as err: if _ignore_error(err): continue + # Reraise non-ignorable errors to avoid hiding issues. raise entries.append(entry) entries.sort(key=sort_key) # type: ignore[arg-type] diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 5a13cd5a400..65a4117812f 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -38,6 +38,7 @@ from _pytest.pathlib import resolve_package_path from _pytest.pathlib import resolve_pkg_root_and_module_name from _pytest.pathlib import safe_exists +from _pytest.pathlib import scandir from _pytest.pathlib import spec_matches_module_path from _pytest.pathlib import symlink_or_skip from _pytest.pathlib import visit @@ -569,6 +570,29 @@ def test_samefile_false_negatives(tmp_path: Path, monkeypatch: MonkeyPatch) -> N assert getattr(module, "foo")() == 42 +def test_scandir_with_non_existent_directory() -> None: + # Test with a directory that does not exist + non_existent_dir = "path_to_non_existent_dir" + result = scandir(non_existent_dir) + # Assert that the result is an empty list + assert result == [] + + +def test_scandir_handles_os_error() -> None: + # Create a mock entry that will raise an OSError when is_file is called + mock_entry = unittest.mock.MagicMock() + mock_entry.is_file.side_effect = OSError("some permission error") + # Mock os.scandir to return an iterator with our mock entry + with unittest.mock.patch("os.scandir") as mock_scandir: + mock_scandir.return_value.__enter__.return_value = [mock_entry] + # Call the scandir function with a path + # We expect an OSError to be raised here + with pytest.raises(OSError, match="some permission error"): + scandir("/fake/path") + # Verify that the is_file method was called on the mock entry + mock_entry.is_file.assert_called_once() + + class TestImportLibMode: def test_importmode_importlib_with_dataclass( self, tmp_path: Path, ns_param: bool From 2931fdb4227f2683d1ad6e6088bc8b839ada2c86 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Jan 2025 08:36:57 +0000 Subject: [PATCH 1057/1271] build(deps): Bump anyio[trio] from 4.7.0 to 4.8.0 in /testing/plugins_integration (#13109) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Pierre Sassoulas Co-authored-by: Thomas Grainger --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 74be0367cdc..d508bc525c1 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[curio,trio]==4.7.0 +anyio[trio]==4.8.0 django==5.1.4 pytest-asyncio==0.25.0 pytest-bdd==8.1.0 From 7307a62ff4e92dc2694d5d924d875c10d329fd80 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 25 Dec 2024 20:45:51 +0100 Subject: [PATCH 1058/1271] [mypy] Fixes 'Enum members must be left unannotated' --- src/_pytest/scope.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_pytest/scope.py b/src/_pytest/scope.py index 976a3ba242e..2b007e87893 100644 --- a/src/_pytest/scope.py +++ b/src/_pytest/scope.py @@ -33,11 +33,11 @@ class Scope(Enum): """ # Scopes need to be listed from lower to higher. - Function: _ScopeName = "function" - Class: _ScopeName = "class" - Module: _ScopeName = "module" - Package: _ScopeName = "package" - Session: _ScopeName = "session" + Function = "function" + Class = "class" + Module = "module" + Package = "package" + Session = "session" def next_lower(self) -> Scope: """Return the next lower scope.""" From f48a469eedf08f83355bd2d7f56784f0b72aead0 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 25 Dec 2024 20:56:30 +0100 Subject: [PATCH 1059/1271] [style] fix shadowed import name 'errno' from outer scope --- src/_pytest/_py/error.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/_pytest/_py/error.py b/src/_pytest/_py/error.py index de0c04a4838..8b7f63d6925 100644 --- a/src/_pytest/_py/error.py +++ b/src/_pytest/_py/error.py @@ -90,15 +90,14 @@ def checked_call( except OSError as value: if not hasattr(value, "errno"): raise - errno = value.errno if sys.platform == "win32": try: - cls = self._geterrnoclass(_winerrnomap[errno]) + cls = self._geterrnoclass(_winerrnomap[value.errno]) except KeyError: raise value else: # we are not on Windows, or we got a proper OSError - cls = self._geterrnoclass(errno) + cls = self._geterrnoclass(value.errno) raise cls(f"{func.__name__}{args!r}") From 0ca9eecf2ceafc259d4d0c393750273ba981b6f5 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 25 Dec 2024 21:27:47 +0100 Subject: [PATCH 1060/1271] [mypy] noqa false positive in NamespaceLoader --- src/_pytest/pathlib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/pathlib.py b/src/_pytest/pathlib.py index 7c06e2df962..b69e85404e7 100644 --- a/src/_pytest/pathlib.py +++ b/src/_pytest/pathlib.py @@ -711,7 +711,7 @@ def _import_module_using_spec( if module_path.is_dir(): # The `spec_from_file_location` matches a loader based on the file extension by default. # For a namespace package, need to manually specify a loader. - loader = NamespaceLoader(name, module_path, PathFinder()) + loader = NamespaceLoader(name, module_path, PathFinder()) # type: ignore[arg-type] spec = importlib.util.spec_from_file_location( module_name, str(module_path), loader=loader From b509fce545623a26dcd90a906694a38c11825861 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Wed, 25 Dec 2024 21:28:46 +0100 Subject: [PATCH 1061/1271] [mypy] Proper typing of mixed type string wrapper --- testing/io/test_terminalwriter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testing/io/test_terminalwriter.py b/testing/io/test_terminalwriter.py index f14e884b1f0..1f38d6f15d9 100644 --- a/testing/io/test_terminalwriter.py +++ b/testing/io/test_terminalwriter.py @@ -3,6 +3,7 @@ from collections.abc import Generator import io +from io import StringIO import os from pathlib import Path import re @@ -68,6 +69,7 @@ def test_terminalwriter_not_unicode() -> None: class TestTerminalWriter: @pytest.fixture(params=["path", "stringio"]) def tw(self, request, tmp_path: Path) -> Generator[terminalwriter.TerminalWriter]: + f: io.TextIOWrapper | StringIO if request.param == "path": p = tmp_path.joinpath("tmpfile") f = open(str(p), "w+", encoding="utf8") From 86464b4c3bb668f5df8e26bd56f5e8207d9e490a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 7 Jan 2025 00:27:33 +0000 Subject: [PATCH 1062/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.8.3 → v0.8.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.8.3...v0.8.6) - [github.com/woodruffw/zizmor-pre-commit: v0.9.2 → v1.0.0](https://github.com/woodruffw/zizmor-pre-commit/compare/v0.9.2...v1.0.0) - [github.com/pre-commit/mirrors-mypy: v1.13.0 → v1.14.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.13.0...v1.14.1) - [github.com/asottile/pyupgrade: v3.19.0 → v3.19.1](https://github.com/asottile/pyupgrade/compare/v3.19.0...v3.19.1) --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d7a4efabe98..06ced48d531 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.8.3" + rev: "v0.8.6" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v0.9.2 + rev: v1.0.1 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs @@ -32,7 +32,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.13.0 + rev: v1.14.1 hooks: - id: mypy files: ^(src/|testing/|scripts/) @@ -54,7 +54,7 @@ repos: # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version additional_dependencies: ["tox>=4.9"] - repo: https://github.com/asottile/pyupgrade - rev: v3.19.0 + rev: v3.19.1 hooks: - id: pyupgrade args: From 3432c20d18d3b0c6b6b4264c1e7299212e59414c Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 9 Jan 2025 15:07:36 +0100 Subject: [PATCH 1063/1271] [mypy] Fix "ErrorMaker._geterrnoclass" got "Optional[int] expected int --- src/_pytest/_py/error.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/_pytest/_py/error.py b/src/_pytest/_py/error.py index 8b7f63d6925..1c7984f5a8f 100644 --- a/src/_pytest/_py/error.py +++ b/src/_pytest/_py/error.py @@ -97,7 +97,14 @@ def checked_call( raise value else: # we are not on Windows, or we got a proper OSError - cls = self._geterrnoclass(value.errno) + if value.errno is None: + cls = type( + "UnknownErrnoNone", + (Error,), + {"__module__": "py.error", "__doc__": None}, + ) + else: + cls = self._geterrnoclass(value.errno) raise cls(f"{func.__name__}{args!r}") From 475b9c708ea83156bc4a65b377ea175659f31002 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 9 Jan 2025 22:24:07 +0100 Subject: [PATCH 1064/1271] [pre-commit] Upgrade ruff to 0.9.0 / 2025's style --- .pre-commit-config.yaml | 2 +- doc/en/example/assertion/failure_demo.py | 6 +- scripts/prepare-release-pr.py | 2 +- scripts/update-plugin-list.py | 4 +- src/_pytest/_code/code.py | 28 ++++---- src/_pytest/cacheprovider.py | 3 +- src/_pytest/capture.py | 16 ++--- src/_pytest/compat.py | 4 +- src/_pytest/config/__init__.py | 12 ++-- src/_pytest/fixtures.py | 10 +-- src/_pytest/python.py | 6 +- src/_pytest/python_api.py | 5 +- src/_pytest/reports.py | 6 +- testing/_py/test_local.py | 6 +- testing/test_junitxml.py | 90 ++++++++++++------------ testing/test_terminal.py | 4 +- 16 files changed, 103 insertions(+), 101 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 06ced48d531..0533a404c3d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.8.6" + rev: "v0.9.0" hooks: - id: ruff args: ["--fix"] diff --git a/doc/en/example/assertion/failure_demo.py b/doc/en/example/assertion/failure_demo.py index dd1485b0b21..16a578fda12 100644 --- a/doc/en/example/assertion/failure_demo.py +++ b/doc/en/example/assertion/failure_demo.py @@ -267,9 +267,9 @@ class A: a = 1 b = 2 - assert ( - A.a == b - ), "A.a appears not to be b\nor does not appear to be b\none of those" + assert A.a == b, ( + "A.a appears not to be b\nor does not appear to be b\none of those" + ) def test_custom_repr(self): class JSON: diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index 49cb2110639..49f8f8c431d 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -163,7 +163,7 @@ def find_next_version( last_version = valid_versions[-1] if is_major: - return f"{last_version[0]+1}.0.0{prerelease}" + return f"{last_version[0] + 1}.0.0{prerelease}" elif is_feature_release: return f"{last_version[0]}.{last_version[1] + 1}.0{prerelease}" else: diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 693a25a00cc..347952cc7e4 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -176,7 +176,7 @@ def version_sort_key(version_string: str) -> Any: ) last_release = release_date.strftime("%b %d, %Y") break - name = f':pypi:`{info["name"]}`' + name = f":pypi:`{info['name']}`" summary = "" if info["summary"]: summary = escape_rst(info["summary"].replace("\n", "")) @@ -194,7 +194,7 @@ def plugin_definitions(plugins: Iterable[PluginInfo]) -> Iterator[str]: for plugin in plugins: yield dedent( f""" - {plugin['name']} + {plugin["name"]} *last release*: {plugin["last_release"]}, *status*: {plugin["status"]}, *requires*: {plugin["requires"]} diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index bba8896076e..5be200df9de 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -217,7 +217,7 @@ def relline(self) -> int: return self.lineno - self.frame.code.firstlineno def __repr__(self) -> str: - return f"" + return f"" @property def statement(self) -> Source: @@ -303,7 +303,7 @@ def __str__(self) -> str: # This output does not quite match Python's repr for traceback entries, # but changing it to do so would break certain plugins. See # https://github.com/pytest-dev/pytest/pull/7535/ for details. - return f" File '{self.path}':{self.lineno+1} in {name}\n {line}\n" + return f" File '{self.path}':{self.lineno + 1} in {name}\n {line}\n" @property def name(self) -> str: @@ -527,33 +527,33 @@ def fill_unfilled(self, exc_info: tuple[type[E], E, TracebackType]) -> None: @property def type(self) -> type[E]: """The exception class.""" - assert ( - self._excinfo is not None - ), ".type can only be used after the context manager exits" + assert self._excinfo is not None, ( + ".type can only be used after the context manager exits" + ) return self._excinfo[0] @property def value(self) -> E: """The exception value.""" - assert ( - self._excinfo is not None - ), ".value can only be used after the context manager exits" + assert self._excinfo is not None, ( + ".value can only be used after the context manager exits" + ) return self._excinfo[1] @property def tb(self) -> TracebackType: """The exception raw traceback.""" - assert ( - self._excinfo is not None - ), ".tb can only be used after the context manager exits" + assert self._excinfo is not None, ( + ".tb can only be used after the context manager exits" + ) return self._excinfo[2] @property def typename(self) -> str: """The type name of the exception.""" - assert ( - self._excinfo is not None - ), ".typename can only be used after the context manager exits" + assert self._excinfo is not None, ( + ".typename can only be used after the context manager exits" + ) return self.type.__name__ @property diff --git a/src/_pytest/cacheprovider.py b/src/_pytest/cacheprovider.py index facb98f09e0..dea60109b51 100755 --- a/src/_pytest/cacheprovider.py +++ b/src/_pytest/cacheprovider.py @@ -482,8 +482,7 @@ def pytest_addoption(parser: Parser) -> None: "--last-failed", action="store_true", dest="lf", - help="Rerun only the tests that failed " - "at the last run (or all if none failed)", + help="Rerun only the tests that failed at the last run (or all if none failed)", ) group.addoption( "--ff", diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index de2ee9c8dbd..5c21590c937 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -375,10 +375,10 @@ def __repr__(self) -> str: ) def _assert_state(self, op: str, states: tuple[str, ...]) -> None: - assert ( - self._state in states - ), "cannot {} in state {!r}: expected one of {}".format( - op, self._state, ", ".join(states) + assert self._state in states, ( + "cannot {} in state {!r}: expected one of {}".format( + op, self._state, ", ".join(states) + ) ) def start(self) -> None: @@ -492,10 +492,10 @@ def __repr__(self) -> str: ) def _assert_state(self, op: str, states: tuple[str, ...]) -> None: - assert ( - self._state in states - ), "cannot {} in state {!r}: expected one of {}".format( - op, self._state, ", ".join(states) + assert self._state in states, ( + "cannot {} in state {!r}: expected one of {}".format( + op, self._state, ", ".join(states) + ) ) def start(self) -> None: diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 053ef1fd1fd..2cbb17eca38 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -70,8 +70,8 @@ def getlocation(function, curdir: str | os.PathLike[str] | None = None) -> str: except ValueError: pass else: - return f"{relfn}:{lineno+1}" - return f"{fn}:{lineno+1}" + return f"{relfn}:{lineno + 1}" + return f"{fn}:{lineno + 1}" def num_mock_patch_args(function) -> int: diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 0161f5952b8..3db5e3da983 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -838,9 +838,9 @@ def import_plugin(self, modname: str, consider_entry_points: bool = False) -> No # "terminal" or "capture". Those plugins are registered under their # basename for historic purposes but must be imported with the # _pytest prefix. - assert isinstance( - modname, str - ), f"module name as text required, got {modname!r}" + assert isinstance(modname, str), ( + f"module name as text required, got {modname!r}" + ) if self.is_blocked(modname) or self.get_plugin(modname) is not None: return @@ -1503,9 +1503,9 @@ def _get_unknown_ini_keys(self) -> list[str]: def parse(self, args: list[str], addopts: bool = True) -> None: # Parse given cmdline arguments into this config object. - assert ( - self.args == [] - ), "can only parse cmdline args at most once per Config object" + assert self.args == [], ( + "can only parse cmdline args at most once per Config object" + ) self.hook.pytest_addhooks.call_historic( kwargs=dict(pluginmanager=self.pluginmanager) ) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 8b79dbcb932..dcd06c3b40a 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -746,7 +746,9 @@ def node(self): if node is None and scope is Scope.Class: # Fallback to function item itself. node = self._pyfuncitem - assert node, f'Could not obtain a node for scope "{scope}" for function {self._pyfuncitem!r}' + assert node, ( + f'Could not obtain a node for scope "{scope}" for function {self._pyfuncitem!r}' + ) return node def _check_scope( @@ -808,9 +810,9 @@ def formatrepr(self) -> FixtureLookupErrorRepr: # new cases it might break. # Add the assert to make it clearer to developer that this will fail, otherwise # it crashes because `fspath` does not get set due to `stack` being empty. - assert ( - self.msg is None or self.fixturestack - ), "formatrepr assumptions broken, rewrite it to handle it" + assert self.msg is None or self.fixturestack, ( + "formatrepr assumptions broken, rewrite it to handle it" + ) if msg is not None: # The last fixture raise an error, let's present # it at the requesting side. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 85e3cb0ae71..ef8a5f02b53 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -914,9 +914,9 @@ def make_unique_parameterset_ids(self) -> list[str]: new_id = f"{id}{suffix}{id_suffixes[id]}" resolved_ids[index] = new_id id_suffixes[id] += 1 - assert len(resolved_ids) == len( - set(resolved_ids) - ), f"Internal error: {resolved_ids=}" + assert len(resolved_ids) == len(set(resolved_ids)), ( + f"Internal error: {resolved_ids=}" + ) return resolved_ids def _resolve_ids(self) -> Iterable[str]: diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index cbb2ff2b80a..25cf9f04d61 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -241,7 +241,7 @@ class ApproxMapping(ApproxBase): with numeric values (the keys can be anything).""" def __repr__(self) -> str: - return f"approx({({k: self._approx_scalar(v) for k, v in self.expected.items()})!r})" + return f"approx({ ({k: self._approx_scalar(v) for k, v in self.expected.items()})!r})" def _repr_compare(self, other_side: Mapping[object, float]) -> list[str]: import math @@ -867,7 +867,8 @@ def raises( Given that ``pytest.raises`` matches subclasses, be wary of using it to match :class:`Exception` like this:: - with pytest.raises(Exception): # Careful, this will catch ANY exception raised. + # Careful, this will catch ANY exception raised. + with pytest.raises(Exception): some_function() Because :class:`Exception` is the base class of almost all exceptions, it is easy for this to hide diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 4d926ef6c9e..746512285b4 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -361,9 +361,9 @@ def from_item_and_call(cls, item: Item, call: CallInfo[None]) -> TestReport: elif isinstance(excinfo.value, skip.Exception): outcome = "skipped" r = excinfo._getreprcrash() - assert ( - r is not None - ), "There should always be a traceback entry for skipping a test." + assert r is not None, ( + "There should always be a traceback entry for skipping a test." + ) if excinfo.value._use_item_location: path, line = item.reportinfo()[:2] assert line is not None diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index cd8752fb79b..71594d10903 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -555,9 +555,9 @@ def batch_make_numbered_dirs(rootdir, repeats): file_ = dir_.join("foo") file_.write_text(f"{i}", encoding="utf-8") actual = int(file_.read_text(encoding="utf-8")) - assert ( - actual == i - ), f"int(file_.read_text(encoding='utf-8')) is {actual} instead of {i}" + assert actual == i, ( + f"int(file_.read_text(encoding='utf-8')) is {actual} instead of {i}" + ) dir_.join(".lock").remove(ignore_errors=True) return True diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index fd1fecb54f1..5de0e6a5d7a 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -541,28 +541,28 @@ def test_fail(): systemout_xml = systemout.toxml() assert systemout.tag == "system-out", "Expected tag: system-out" assert "info msg" not in systemout_xml, "INFO message found in system-out" - assert ( - "hello-stdout" in systemout_xml - ), "Missing 'hello-stdout' in system-out" + assert "hello-stdout" in systemout_xml, ( + "Missing 'hello-stdout' in system-out" + ) if junit_logging in ["system-err", "out-err", "all"]: systemerr = tnode.find_first_by_tag("system-err") systemerr_xml = systemerr.toxml() assert systemerr.tag == "system-err", "Expected tag: system-err" assert "info msg" not in systemerr_xml, "INFO message found in system-err" - assert ( - "hello-stderr" in systemerr_xml - ), "Missing 'hello-stderr' in system-err" - assert ( - "warning msg" not in systemerr_xml - ), "WARN message found in system-err" + assert "hello-stderr" in systemerr_xml, ( + "Missing 'hello-stderr' in system-err" + ) + assert "warning msg" not in systemerr_xml, ( + "WARN message found in system-err" + ) if junit_logging == "no": assert not tnode.find_by_tag("log"), "Found unexpected content: log" - assert not tnode.find_by_tag( - "system-out" - ), "Found unexpected content: system-out" - assert not tnode.find_by_tag( - "system-err" - ), "Found unexpected content: system-err" + assert not tnode.find_by_tag("system-out"), ( + "Found unexpected content: system-out" + ) + assert not tnode.find_by_tag("system-err"), ( + "Found unexpected content: system-err" + ) @parametrize_families def test_failure_verbose_message( @@ -807,14 +807,14 @@ def test_pass(): node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": - assert not node.find_by_tag( - "system-out" - ), "system-out should not be generated" + assert not node.find_by_tag("system-out"), ( + "system-out should not be generated" + ) if junit_logging == "system-out": systemout = pnode.find_first_by_tag("system-out") - assert ( - "hello-stdout" in systemout.toxml() - ), "'hello-stdout' should be in system-out" + assert "hello-stdout" in systemout.toxml(), ( + "'hello-stdout' should be in system-out" + ) @pytest.mark.parametrize("junit_logging", ["no", "system-err"]) def test_pass_captures_stderr( @@ -831,14 +831,14 @@ def test_pass(): node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": - assert not node.find_by_tag( - "system-err" - ), "system-err should not be generated" + assert not node.find_by_tag("system-err"), ( + "system-err should not be generated" + ) if junit_logging == "system-err": systemerr = pnode.find_first_by_tag("system-err") - assert ( - "hello-stderr" in systemerr.toxml() - ), "'hello-stderr' should be in system-err" + assert "hello-stderr" in systemerr.toxml(), ( + "'hello-stderr' should be in system-err" + ) @pytest.mark.parametrize("junit_logging", ["no", "system-out"]) def test_setup_error_captures_stdout( @@ -860,14 +860,14 @@ def test_function(arg): node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": - assert not node.find_by_tag( - "system-out" - ), "system-out should not be generated" + assert not node.find_by_tag("system-out"), ( + "system-out should not be generated" + ) if junit_logging == "system-out": systemout = pnode.find_first_by_tag("system-out") - assert ( - "hello-stdout" in systemout.toxml() - ), "'hello-stdout' should be in system-out" + assert "hello-stdout" in systemout.toxml(), ( + "'hello-stdout' should be in system-out" + ) @pytest.mark.parametrize("junit_logging", ["no", "system-err"]) def test_setup_error_captures_stderr( @@ -890,14 +890,14 @@ def test_function(arg): node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": - assert not node.find_by_tag( - "system-err" - ), "system-err should not be generated" + assert not node.find_by_tag("system-err"), ( + "system-err should not be generated" + ) if junit_logging == "system-err": systemerr = pnode.find_first_by_tag("system-err") - assert ( - "hello-stderr" in systemerr.toxml() - ), "'hello-stderr' should be in system-err" + assert "hello-stderr" in systemerr.toxml(), ( + "'hello-stderr' should be in system-err" + ) @pytest.mark.parametrize("junit_logging", ["no", "system-out"]) def test_avoid_double_stdout( @@ -921,9 +921,9 @@ def test_function(arg): node = dom.find_first_by_tag("testsuite") pnode = node.find_first_by_tag("testcase") if junit_logging == "no": - assert not node.find_by_tag( - "system-out" - ), "system-out should not be generated" + assert not node.find_by_tag("system-out"), ( + "system-out should not be generated" + ) if junit_logging == "system-out": systemout = pnode.find_first_by_tag("system-out") assert "hello-stdout call" in systemout.toxml() @@ -1544,9 +1544,9 @@ class Report(BaseReport): test_case = minidom.parse(str(path)).getElementsByTagName("testcase")[0] - assert ( - test_case.getAttribute("url") == test_url - ), "The URL did not get written to the xml" + assert test_case.getAttribute("url") == test_url, ( + "The URL did not get written to the xml" + ) @parametrize_families diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 32206364125..402e1f8dba3 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -336,7 +336,7 @@ def test_report_teststatus_explicit_markup( pytester.makeconftest( f""" def pytest_report_teststatus(report): - return {category !r}, 'F', ('FOO', {{'red': True}}) + return {category!r}, 'F', ('FOO', {{'red': True}}) """ ) pytester.makepyfile( @@ -1187,7 +1187,7 @@ def test(param): @pytest.mark.parametrize( ("use_ci", "expected_message"), ( - (True, f"- AssertionError: {'this_failed'*100}"), + (True, f"- AssertionError: {'this_failed' * 100}"), (False, "- AssertionError: this_failedt..."), ), ids=("on CI", "not on CI"), From 8826bb822fe01ca2ef36cf16ca5792628df7fe18 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Thu, 9 Jan 2025 22:26:25 +0100 Subject: [PATCH 1065/1271] [style] Use '<' or '>=' for 'sys.version_info' comparisons --- testing/_py/test_local.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 71594d10903..461b0b599c1 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -18,7 +18,7 @@ @contextlib.contextmanager def ignore_encoding_warning(): with warnings.catch_warnings(): - if sys.version_info > (3, 10): + if sys.version_info >= (3, 10): warnings.simplefilter("ignore", EncodingWarning) # noqa: F821 yield From 05538acf906d6f6e0f75d1d0e2e2052e933761de Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 11 Jan 2025 16:45:01 +0100 Subject: [PATCH 1066/1271] Update links to microblogging pages (#13123) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update links to microblogging pages * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Apply suggestions from code review Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- RELEASING.rst | 6 +++++- doc/en/contact.rst | 7 +++++++ pyproject.toml | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/RELEASING.rst b/RELEASING.rst index 52910de0002..7ef907f2296 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -168,4 +168,8 @@ Both automatic and manual processes described above follow the same steps from t * python-announce-list@python.org (all releases) * testing-in-python@lists.idyll.org (only major/minor releases) - And announce it on `Twitter `_ and `BlueSky `_ with the ``#pytest`` hashtag. + And announce it with the ``#pytest`` hashtag on: + + * `Bluesky `_ + * `Fosstodon `_ + * `Twitter/X `_ diff --git a/doc/en/contact.rst b/doc/en/contact.rst index d650a7efbab..cd34f548e99 100644 --- a/doc/en/contact.rst +++ b/doc/en/contact.rst @@ -24,6 +24,13 @@ Chat `_) - ``#pytest`` `on Matrix `_. +Microblogging +------------- + +- Bluesky: `@pytest.org `_ +- Mastodon: `@pytest@fosstodon.org `_ +- Twitter/X: `@pytestdotorg `_ + Mail ---- diff --git a/pyproject.toml b/pyproject.toml index df633e0a092..3c3c04d2d5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,10 +64,11 @@ optional-dependencies.dev = [ "xmlschema", ] urls.Changelog = "https://docs.pytest.org/en/stable/changelog.html" +urls.Contact = "https://docs.pytest.org/en/stable/contact.html" +urls.Funding = "https://docs.pytest.org/en/stable/sponsor.html" urls.Homepage = "https://docs.pytest.org/en/latest/" urls.Source = "https://github.com/pytest-dev/pytest" urls.Tracker = "https://github.com/pytest-dev/pytest/issues" -urls.Twitter = "https://twitter.com/pytestdotorg" scripts."py.test" = "pytest:console_main" scripts.pytest = "pytest:console_main" From 7d721d2b9338bea0c1c52e8e441a42d336a69cef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 11 Jan 2025 22:18:11 +0100 Subject: [PATCH 1067/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#13121) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.25.0 to 0.25.2. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.25.0...v0.25.2) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d508bc525c1..aa35aeebcd2 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[trio]==4.8.0 django==5.1.4 -pytest-asyncio==0.25.0 +pytest-asyncio==0.25.2 pytest-bdd==8.1.0 pytest-cov==6.0.0 pytest-django==4.9.0 From 477e9283aabc93f8d3ad34ff0b98f68b5a432aa8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 12 Jan 2025 08:58:31 -0300 Subject: [PATCH 1068/1271] [automated] Update plugin list (#13128) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 124 ++++++++++++++++++------------- 1 file changed, 74 insertions(+), 50 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 2ccaa87b5e6..752bc869deb 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Jan 03, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio` Pytest support for asyncio Jan 08, 2025 4 - Beta pytest<9,>=8.2 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Jan 09, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -159,7 +159,7 @@ This list contains 1566 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Dec 23, 2024 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jan 09, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -218,7 +218,7 @@ This list contains 1566 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-cdist` Add your description here Dec 31, 2024 N/A pytest>=7 + :pypi:`pytest-cdist` A pytest plugin to split your test suite into multiple parts Jan 07, 2025 N/A pytest>=7 :pypi:`pytest-celery` Pytest plugin for Celery Sep 20, 2024 4 - Beta N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A @@ -270,7 +270,7 @@ This list contains 1566 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Dec 09, 2024 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jan 09, 2025 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -321,6 +321,7 @@ This list contains 1566 plugins. :pypi:`pytest-custom-outputs` A plugin that allows users to create and use custom outputs instead of the standard Pass and Fail. Also allows users to retrieve test results in fixtures. Jul 10, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-custom-report` Configure the symbols displayed for test outcomes Jan 30, 2019 N/A pytest :pypi:`pytest-custom-scheduling` Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report Mar 01, 2021 N/A N/A + :pypi:`pytest-custom-timeout` Use custom logic when a test times out. Based on pytest-timeout. Jan 08, 2025 4 - Beta pytest>=8.0.0 :pypi:`pytest-cython` A plugin for testing Cython extension modules Apr 05, 2024 5 - Production/Stable pytest>=8 :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 @@ -398,7 +399,7 @@ This list contains 1566 plugins. :pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4) :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Aug 27, 2023 5 - Production/Stable N/A :pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A - :pypi:`pytest-django-liveserver-ssl` Jan 20, 2022 3 - Alpha N/A + :pypi:`pytest-django-liveserver-ssl` Jan 09, 2025 3 - Alpha N/A :pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A :pypi:`pytest-django-ordering` A pytest plugin for preserving the order in which Django runs tests. Jul 25, 2019 5 - Production/Stable pytest (>=2.3.0) :pypi:`pytest-django-queries` Generate performance reports from your django database performance tests. Mar 01, 2021 N/A N/A @@ -500,6 +501,7 @@ This list contains 1566 plugins. :pypi:`pytest-eradicate` pytest plugin to check for commented out code Sep 08, 2020 N/A pytest (>=2.4.2) :pypi:`pytest_erp` py.test plugin to send test info to report portal dynamically Jan 13, 2015 N/A N/A :pypi:`pytest-error-for-skips` Pytest plugin to treat skipped tests a test failure Dec 19, 2019 4 - Beta pytest (>=4.6) + :pypi:`pytest-errxfail` pytest plugin to mark a test as xfailed if it fails with the specified error message in the captured output Jan 06, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) @@ -615,18 +617,18 @@ This list contains 1566 plugins. :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A - :pypi:`pytest-fzf` fzf-based test selector for pytest Jul 03, 2024 4 - Beta pytest>=6.0.0 + :pypi:`pytest-fzf` fzf-based test selector for pytest Jan 06, 2025 4 - Beta pytest>=6.0.0 :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Aug 18, 2024 N/A pytest>=7.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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Dec 12, 2024 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jan 10, 2025 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-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. Dec 23, 2024 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jan 08, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -670,7 +672,7 @@ This list contains 1566 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Jan 04, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jan 10, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -690,7 +692,7 @@ This list contains 1566 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Sep 18, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Dec 29, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 11, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A @@ -901,7 +903,8 @@ This list contains 1566 plugins. :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Mar 13, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A - :pypi:`pytest-mongodb-ry` pytest plugin for MongoDB Dec 31, 2024 N/A N/A + :pypi:`pytest-mongodb-nono` pytest plugin for MongoDB Jan 07, 2025 N/A N/A + :pypi:`pytest-mongodb-ry` pytest plugin for MongoDB Jan 10, 2025 N/A N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A @@ -913,7 +916,7 @@ This list contains 1566 plugins. :pypi:`pytest-mpiexec` pytest plugin for running individual tests with mpiexec Jul 29, 2024 3 - Alpha pytest :pypi:`pytest-mpl` pytest plugin to help with testing figures output from Matplotlib Feb 14, 2024 4 - Beta pytest :pypi:`pytest-mproc` low-startup-overhead, scalable, distributed-testing pytest plugin Nov 15, 2022 4 - Beta pytest (>=6) - :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Oct 19, 2024 4 - Beta pytest<9; extra == "test" + :pypi:`pytest-mqtt` pytest-mqtt supports testing systems based on MQTT Jan 07, 2025 5 - Production/Stable pytest<9; extra == "test" :pypi:`pytest-multihost` Utility for writing multi-host tests for pytest Apr 07, 2020 4 - Beta N/A :pypi:`pytest-multilog` Multi-process logs handling and other helpers for pytest Jan 17, 2023 N/A pytest :pypi:`pytest-multithreading` a pytest plugin for th and concurrent testing Aug 05, 2024 N/A N/A @@ -931,7 +934,7 @@ This list contains 1566 plugins. :pypi:`pytest-needle` pytest plugin for visual testing websites using selenium Dec 10, 2018 4 - Beta pytest (<5.0.0,>=3.0.0) :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) :pypi:`pytest-neos` Pytest plugin for neos Sep 10, 2024 5 - Production/Stable pytest<8.0,>=7.2; extra == "dev" - :pypi:`pytest-netconf` A pytest plugin that provides a mock NETCONF (RFC6241/RFC6242) server for local testing. Aug 08, 2024 N/A N/A + :pypi:`pytest-netconf` A pytest plugin that provides a mock NETCONF (RFC6241/RFC6242) server for local testing. Jan 06, 2025 N/A N/A :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jul 05, 2024 N/A pytest<7.3,>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest @@ -1017,7 +1020,7 @@ This list contains 1566 plugins. :pypi:`pytest-percents` Mar 16, 2024 N/A N/A :pypi:`pytest-perf` Run performance tests against the mainline code. May 20, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) - :pypi:`pytest-performancetotal` A performance plugin for pytest Dec 31, 2024 5 - Production/Stable N/A + :pypi:`pytest-performancetotal` A performance plugin for pytest Jan 07, 2025 5 - Production/Stable N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Aug 21, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 @@ -1115,7 +1118,7 @@ This list contains 1566 plugins. :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-qanova` A pytest plugin to collect test information Sep 05, 2024 3 - Alpha pytest - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Nov 18, 2024 5 - Production/Stable pytest<9.0.0,>=7.2.2 + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Jan 08, 2025 5 - Production/Stable pytest<9.0.0,>=7.2.2 :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 14, 2024 5 - Production/Stable pytest>=6.0 @@ -1142,7 +1145,7 @@ This list contains 1566 plugins. :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Dec 23, 2024 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A - :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Dec 19, 2024 N/A N/A + :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jan 09, 2025 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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-record-video` 用例执行过程中录制视频 Oct 31, 2024 N/A N/A @@ -1153,7 +1156,7 @@ This list contains 1566 plugins. :pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest - :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Dec 17, 2024 5 - Production/Stable pytest>=6.2.0 + :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 10, 2025 5 - Production/Stable pytest>=6.2.0 :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Nov 12, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relative-path` Handle relative path in pytest options or ini configs Aug 30, 2024 N/A pytest @@ -1171,7 +1174,7 @@ This list contains 1566 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. Jan 04, 2025 N/A pytest>=8.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Jan 09, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1230,7 +1233,7 @@ This list contains 1566 plugins. :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 21, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A - :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Nov 13, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Jan 06, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 @@ -1246,7 +1249,7 @@ This list contains 1566 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Dec 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 10, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1257,7 +1260,7 @@ This list contains 1566 plugins. :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 Feb 01, 2024 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. Dec 25, 2024 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jan 10, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1303,7 +1306,7 @@ This list contains 1566 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A - :pypi:`pytest-smoke` Pytest plugin for smoke testing Dec 30, 2024 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-smoke` Pytest plugin for smoke testing Jan 10, 2025 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -2173,14 +2176,14 @@ This list contains 1566 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jan 02, 2025, + *last release*: Jan 08, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=8.2 Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Jan 03, 2025, + *last release*: Jan 09, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2481,7 +2484,7 @@ This list contains 1566 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Dec 23, 2024, + *last release*: Jan 09, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -2894,11 +2897,11 @@ This list contains 1566 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-cdist` - *last release*: Dec 31, 2024, + *last release*: Jan 07, 2025, *status*: N/A, *requires*: pytest>=7 - Add your description here + A pytest plugin to split your test suite into multiple parts :pypi:`pytest-celery` *last release*: Sep 20, 2024, @@ -3258,7 +3261,7 @@ This list contains 1566 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Dec 09, 2024, + *last release*: Jan 09, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3614,6 +3617,13 @@ This list contains 1566 plugins. Custom grouping for pytest-xdist, rename test cases name and test cases nodeid, support allure report + :pypi:`pytest-custom-timeout` + *last release*: Jan 08, 2025, + *status*: 4 - Beta, + *requires*: pytest>=8.0.0 + + Use custom logic when a test times out. Based on pytest-timeout. + :pypi:`pytest-cython` *last release*: Apr 05, 2024, *status*: 5 - Production/Stable, @@ -4154,7 +4164,7 @@ This list contains 1566 plugins. The bare minimum to integrate py.test with Django. :pypi:`pytest-django-liveserver-ssl` - *last release*: Jan 20, 2022, + *last release*: Jan 09, 2025, *status*: 3 - Alpha, *requires*: N/A @@ -4867,6 +4877,13 @@ This list contains 1566 plugins. Pytest plugin to treat skipped tests a test failure + :pypi:`pytest-errxfail` + *last release*: Jan 06, 2025, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + pytest plugin to mark a test as xfailed if it fails with the specified error message in the captured output + :pypi:`pytest-eth` *last release*: Aug 14, 2020, *status*: 1 - Planning, @@ -5673,7 +5690,7 @@ This list contains 1566 plugins. :pypi:`pytest-fzf` - *last release*: Jul 03, 2024, + *last release*: Jan 06, 2025, *status*: 4 - Beta, *requires*: pytest>=6.0.0 @@ -5715,7 +5732,7 @@ This list contains 1566 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Dec 12, 2024, + *last release*: Jan 10, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -5750,7 +5767,7 @@ This list contains 1566 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Dec 23, 2024, + *last release*: Jan 08, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6058,7 +6075,7 @@ This list contains 1566 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jan 04, 2025, + *last release*: Jan 10, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6198,7 +6215,7 @@ This list contains 1566 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Dec 29, 2024, + *last release*: Jan 11, 2025, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -7674,8 +7691,15 @@ This list contains 1566 plugins. pytest plugin for MongoDB fixtures + :pypi:`pytest-mongodb-nono` + *last release*: Jan 07, 2025, + *status*: N/A, + *requires*: N/A + + pytest plugin for MongoDB + :pypi:`pytest-mongodb-ry` - *last release*: Dec 31, 2024, + *last release*: Jan 10, 2025, *status*: N/A, *requires*: N/A @@ -7759,8 +7783,8 @@ This list contains 1566 plugins. low-startup-overhead, scalable, distributed-testing pytest plugin :pypi:`pytest-mqtt` - *last release*: Oct 19, 2024, - *status*: 4 - Beta, + *last release*: Jan 07, 2025, + *status*: 5 - Production/Stable, *requires*: pytest<9; extra == "test" pytest-mqtt supports testing systems based on MQTT @@ -7885,7 +7909,7 @@ This list contains 1566 plugins. Pytest plugin for neos :pypi:`pytest-netconf` - *last release*: Aug 08, 2024, + *last release*: Jan 06, 2025, *status*: N/A, *requires*: N/A @@ -8487,7 +8511,7 @@ This list contains 1566 plugins. A simple plugin to ensure the execution of critical sections of code has not been impacted :pypi:`pytest-performancetotal` - *last release*: Dec 31, 2024, + *last release*: Jan 07, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -9173,7 +9197,7 @@ This list contains 1566 plugins. A pytest plugin to collect test information :pypi:`pytest-qaseio` - *last release*: Nov 18, 2024, + *last release*: Jan 08, 2025, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=7.2.2 @@ -9362,7 +9386,7 @@ This list contains 1566 plugins. Pytest fixtures for REANA. :pypi:`pytest-recorder` - *last release*: Dec 19, 2024, + *last release*: Jan 09, 2025, *status*: N/A, *requires*: N/A @@ -9439,7 +9463,7 @@ This list contains 1566 plugins. Management of Pytest dependencies via regex patterns :pypi:`pytest-regressions` - *last release*: Dec 17, 2024, + *last release*: Jan 10, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6.2.0 @@ -9565,11 +9589,11 @@ This list contains 1566 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Jan 04, 2025, + *last release*: Jan 09, 2025, *status*: N/A, *requires*: pytest>=8.0.0 - Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots and webpage sources. + Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. :pypi:`pytest-reportinfra` *last release*: Aug 11, 2019, @@ -9978,7 +10002,7 @@ This list contains 1566 plugins. implement a --failed option for pytest :pypi:`pytest-run-parallel` - *last release*: Nov 13, 2024, + *last release*: Jan 06, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -10090,7 +10114,7 @@ This list contains 1566 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Dec 25, 2024, + *last release*: Jan 10, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10167,7 +10191,7 @@ This list contains 1566 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Dec 25, 2024, + *last release*: Jan 10, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10489,7 +10513,7 @@ This list contains 1566 plugins. Automated bad smell detection tool for Pytest :pypi:`pytest-smoke` - *last release*: Dec 30, 2024, + *last release*: Jan 10, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 From 517b0066b903e9688beab3377a3bd2439175797f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 06:40:40 -0300 Subject: [PATCH 1069/1271] [pre-commit.ci] pre-commit autoupdate (#13130) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.0 → v0.9.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.0...v0.9.1) - [github.com/woodruffw/zizmor-pre-commit: v1.0.1 → v1.1.1](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.0.1...v1.1.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0533a404c3d..45af5f7f9b9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.0" + rev: "v0.9.1" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.0.1 + rev: v1.1.1 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs From 43064f5b61815496afa52a802ee6809fee0c06e2 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 10 Jan 2025 12:34:52 -0300 Subject: [PATCH 1070/1271] Improve stepwise to not forget failed tests Now `--stepwise` will remember the last failed test, even if the previous pytest invocations did not pass `--stepwise`. Previously it would always clear the cache if not active, which hinders certain interactive workflows, which is the prime use cases for the flag. --- changelog/13122.improvement.rst | 11 ++++++++++ src/_pytest/stepwise.py | 2 -- testing/test_cacheprovider.py | 4 ++-- testing/test_stepwise.py | 38 +++++++++++++++++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 changelog/13122.improvement.rst diff --git a/changelog/13122.improvement.rst b/changelog/13122.improvement.rst new file mode 100644 index 00000000000..d7372380e81 --- /dev/null +++ b/changelog/13122.improvement.rst @@ -0,0 +1,11 @@ +Improve the ``--stepwise`` flag to not forget the last failed test in case pytest is executed later without the flag. + +This enables the following workflow: + +1. Execute pytest with ``--stepwise``, pytest then stops at the first failing test; +2. User iteratively updates the code and runs the test in isolation, without the ``--stepwise`` flag + (for example in an IDE), until it is fixed. +3. At this point, the user can execute pytest with ``--stepwise`` again and pytest will continue from the previously + failed test, and if it passes, continue with the next tests. + +Previously, at step 3, pytest would start from the beginning, forgetting the failed tests. diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index c7860808c35..82d1fe3aee5 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -47,8 +47,6 @@ def pytest_sessionfinish(session: Session) -> None: # Do not update cache if this process is a xdist worker to prevent # race conditions (#10641). return - # Clear the list of failing tests if the plugin is not active. - session.config.cache.set(STEPWISE_CACHE_DIR, []) class StepwisePlugin: diff --git a/testing/test_cacheprovider.py b/testing/test_cacheprovider.py index 1ba4659d84e..ca417e86ee5 100644 --- a/testing/test_cacheprovider.py +++ b/testing/test_cacheprovider.py @@ -104,7 +104,7 @@ def test_cache_failure_warns( pytester.makepyfile("def test_error(): raise Exception") result = pytester.runpytest() assert result.ret == 1 - # warnings from nodeids, lastfailed, and stepwise + # warnings from nodeids and lastfailed result.stdout.fnmatch_lines( [ # Validate location/stacklevel of warning from cacheprovider. @@ -113,7 +113,7 @@ def test_cache_failure_warns( " */cacheprovider.py:*: PytestCacheWarning: could not create cache path " f"{unwritable_cache_dir}/v/cache/nodeids: *", ' config.cache.set("cache/nodeids", sorted(self.cached_nodeids))', - "*1 failed, 3 warnings in*", + "*1 failed, 2 warnings in*", ] ) diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index affdb73375e..02239e8b5f1 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -358,3 +358,41 @@ def test_one(): with stepwise_cache_file.open(encoding="utf-8") as file_handle: observed_value = file_handle.readlines() assert [expected_value] == observed_value + + +def test_do_not_clear_cache_if_disabled(pytester: Pytester) -> None: + """ + If pytest is run without --step-wise, do not clear the stepwise cache. + + Keeping the cache around is important for this workflow: + + 1. Run tests with --stepwise + 2. Stop at the failing test, and iterate over it changing the code and running it in isolation + (in the IDE for example). + 3. Run tests with --stepwise again - at this point we expect to start from the failing test, which should now pass, + and continue with the next tests. + """ + pytester.makepyfile( + """ + def test_1(): + pass + def test_2(): + assert False + def test_3(): + pass + """ + ) + result = pytester.runpytest("--stepwise") + result.stdout.fnmatch_lines( + ["*::test_2 - assert False*", "*failed, continuing from this test next run*"] + ) + + # Run a specific test without passing `--stepwise`. + result = pytester.runpytest("-k", "test_1") + result.stdout.fnmatch_lines(["*1 passed*"]) + + # Running with `--stepwise` should continue from the last failing test. + result = pytester.runpytest("--stepwise") + result.stdout.fnmatch_lines( + ["*::test_2 - assert False*", "*failed, continuing from this test next run*"] + ) From 40b38f97c977e51f165aa32ccfe95ec3a0e5f8c8 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 10 Jan 2025 13:48:29 -0300 Subject: [PATCH 1071/1271] Add --stepwise-reset to restart the stepwise workflow --- changelog/13122.improvement.rst | 4 +++- src/_pytest/stepwise.py | 16 +++++++++++++++- testing/test_stepwise.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/changelog/13122.improvement.rst b/changelog/13122.improvement.rst index d7372380e81..808e19dcc00 100644 --- a/changelog/13122.improvement.rst +++ b/changelog/13122.improvement.rst @@ -1,4 +1,4 @@ -Improve the ``--stepwise`` flag to not forget the last failed test in case pytest is executed later without the flag. +Improve the ``--stepwise``/``--sw`` flag to not forget the last failed test in case pytest is executed later without the flag. This enables the following workflow: @@ -9,3 +9,5 @@ This enables the following workflow: failed test, and if it passes, continue with the next tests. Previously, at step 3, pytest would start from the beginning, forgetting the failed tests. + +Also added the new ``--stepwise-reset``/``--sw-reset``, allowing the user to explicitly reset the stepwise state and restart the workflow from the beginning. diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index 82d1fe3aee5..28db3bfc6e2 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -30,11 +30,23 @@ def pytest_addoption(parser: Parser) -> None: help="Ignore the first failing test but stop on the next failing test. " "Implicitly enables --stepwise.", ) + group.addoption( + "--sw-reset", + "--stepwise-reset", + action="store_true", + default=False, + dest="stepwise_reset", + help="Resets stepwise state, restarting the stepwise workflow. " + "Implicitly enables --stepwise.", + ) def pytest_configure(config: Config) -> None: + # --stepwise-skip implies stepwise. if config.option.stepwise_skip: - # allow --stepwise-skip to work on its own merits. + config.option.stepwise = True + # --stepwise-clear implies stepwise. + if config.option.stepwise_reset: config.option.stepwise = True if config.getoption("stepwise"): config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin") @@ -58,6 +70,8 @@ def __init__(self, config: Config) -> None: self.cache: Cache = config.cache self.lastfailed: str | None = self.cache.get(STEPWISE_CACHE_DIR, None) self.skip: bool = config.getoption("stepwise_skip") + if config.getoption("stepwise_reset"): + self.lastfailed = None def pytest_sessionstart(self, session: Session) -> None: self.session = session diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index 02239e8b5f1..4d3d1e91b7f 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -396,3 +396,34 @@ def test_3(): result.stdout.fnmatch_lines( ["*::test_2 - assert False*", "*failed, continuing from this test next run*"] ) + + +def test_stepwise_reset(pytester: Pytester) -> None: + pytester.makepyfile( + """ + def test_1(): + pass + def test_2(): + assert False + def test_3(): + pass + """ + ) + result = pytester.runpytest("--stepwise", "-v") + result.stdout.fnmatch_lines( + [ + "*::test_1 *PASSED*", + "*::test_2 *FAILED*", + "*failed, continuing from this test next run*", + ] + ) + + # Running with --stepwise-reset restarts the stepwise workflow. + result = pytester.runpytest("-v", "--stepwise-reset") + result.stdout.fnmatch_lines( + [ + "*::test_1 *PASSED*", + "*::test_2 *FAILED*", + "*failed, continuing from this test next run*", + ] + ) From 18378585628247d92e668c05b2a1254a544d7d7c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 10 Jan 2025 19:37:06 -0300 Subject: [PATCH 1072/1271] Tweak changelog --- changelog/13122.improvement.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/changelog/13122.improvement.rst b/changelog/13122.improvement.rst index 808e19dcc00..4079696d676 100644 --- a/changelog/13122.improvement.rst +++ b/changelog/13122.improvement.rst @@ -3,11 +3,9 @@ Improve the ``--stepwise``/``--sw`` flag to not forget the last failed test in c This enables the following workflow: 1. Execute pytest with ``--stepwise``, pytest then stops at the first failing test; -2. User iteratively updates the code and runs the test in isolation, without the ``--stepwise`` flag - (for example in an IDE), until it is fixed. -3. At this point, the user can execute pytest with ``--stepwise`` again and pytest will continue from the previously - failed test, and if it passes, continue with the next tests. +2. Iteratively update the code and run the test in isolation, without the ``--stepwise`` flag (for example in an IDE), until it is fixed. +3. Execute pytest with ``--stepwise`` again and pytest will continue from the previously failed test, and if it passes, continue on to the next tests. -Previously, at step 3, pytest would start from the beginning, forgetting the failed tests. +Previously, at step 3, pytest would start from the beginning, forgetting the previously failed test. Also added the new ``--stepwise-reset``/``--sw-reset``, allowing the user to explicitly reset the stepwise state and restart the workflow from the beginning. From b6f1dadeb201677bd08601283649c9dcc5491895 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 10 Jan 2025 19:44:26 -0300 Subject: [PATCH 1073/1271] Tighten test --- testing/test_stepwise.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index 4d3d1e91b7f..dbf49f73535 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -384,7 +384,11 @@ def test_3(): ) result = pytester.runpytest("--stepwise") result.stdout.fnmatch_lines( - ["*::test_2 - assert False*", "*failed, continuing from this test next run*"] + [ + "*::test_2 - assert False*", + "*failed, continuing from this test next run*", + "=* 1 failed, 1 passed in *", + ] ) # Run a specific test without passing `--stepwise`. @@ -394,7 +398,12 @@ def test_3(): # Running with `--stepwise` should continue from the last failing test. result = pytester.runpytest("--stepwise") result.stdout.fnmatch_lines( - ["*::test_2 - assert False*", "*failed, continuing from this test next run*"] + [ + "stepwise: skipping 1 already passed items.", + "*::test_2 - assert False*", + "*failed, continuing from this test next run*", + "=* 1 failed, 1 deselected in *", + ] ) From 0c30a580606f6984897bd84f6b940e1a025f29bd Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 12 Jan 2025 10:12:16 -0300 Subject: [PATCH 1074/1271] Show cache information and reset cache if test count changes --- changelog/13122.improvement.rst | 18 ++-- src/_pytest/stepwise.py | 113 ++++++++++++++++++++----- testing/test_stepwise.py | 145 +++++++++++++++++++++++++++----- 3 files changed, 231 insertions(+), 45 deletions(-) diff --git a/changelog/13122.improvement.rst b/changelog/13122.improvement.rst index 4079696d676..c302713b320 100644 --- a/changelog/13122.improvement.rst +++ b/changelog/13122.improvement.rst @@ -1,11 +1,15 @@ -Improve the ``--stepwise``/``--sw`` flag to not forget the last failed test in case pytest is executed later without the flag. +The ``--stepwise`` mode received a number of improvements: -This enables the following workflow: +* It no longer forgets the last failed test in case pytest is executed later without the flag. -1. Execute pytest with ``--stepwise``, pytest then stops at the first failing test; -2. Iteratively update the code and run the test in isolation, without the ``--stepwise`` flag (for example in an IDE), until it is fixed. -3. Execute pytest with ``--stepwise`` again and pytest will continue from the previously failed test, and if it passes, continue on to the next tests. + This enables the following workflow: -Previously, at step 3, pytest would start from the beginning, forgetting the previously failed test. + 1. Execute pytest with ``--stepwise``, pytest then stops at the first failing test; + 2. Iteratively update the code and run the test in isolation, without the ``--stepwise`` flag (for example in an IDE), until it is fixed. + 3. Execute pytest with ``--stepwise`` again and pytest will continue from the previously failed test, and if it passes, continue on to the next tests. -Also added the new ``--stepwise-reset``/``--sw-reset``, allowing the user to explicitly reset the stepwise state and restart the workflow from the beginning. + Previously, at step 3, pytest would start from the beginning, forgetting the previously failed test. + + This change however might cause issues if the ``--stepwise`` mode is used far apart in time, as the state might get stale, so the internal state will be reset automatically in case the test suite changes (for now only the number of tests are considered for this, we might change/improve this on the future). + +* New ``--stepwise-reset``/``--sw-reset`` flag, allowing the user to explicitly reset the stepwise state and restart the workflow from the beginning. diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index 28db3bfc6e2..7ee869bcef8 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -1,5 +1,10 @@ from __future__ import annotations +import dataclasses +from datetime import datetime +from typing import Any +from typing import TYPE_CHECKING + from _pytest import nodes from _pytest.cacheprovider import Cache from _pytest.config import Config @@ -8,7 +13,12 @@ from _pytest.reports import TestReport -STEPWISE_CACHE_DIR = "cache/stepwise" +if TYPE_CHECKING: + from typing import ClassVar + + from typing_extensions import Self + +STEPWISE_CACHE_DIR = "cache/stepwise2" def pytest_addoption(parser: Parser) -> None: @@ -61,17 +71,63 @@ def pytest_sessionfinish(session: Session) -> None: return +@dataclasses.dataclass +class StepwiseCacheInfo: + # The nodeid of the last failed test. + last_failed: str | None + + # The number of tests in the last time --stepwise was run. + # We use this information as a simple way to invalidate the cache information, avoiding + # confusing behavior in case the cache is stale. + last_test_count: int | None + + # The date when the cache was last updated, for information purposes only. + last_cache_date_str: str + + _DATE_FORMAT: ClassVar[str] = "%Y-%m-%d %H:%M:%S" + + @property + def last_cache_date(self) -> datetime: + return datetime.strptime(self.last_cache_date_str, self._DATE_FORMAT) + + @classmethod + def empty(cls) -> Self: + return cls( + last_failed=None, + last_test_count=None, + last_cache_date_str=datetime.now().strftime(cls._DATE_FORMAT), + ) + + def update_date_to_now(self) -> None: + self.last_cache_date_str = datetime.now().strftime(self._DATE_FORMAT) + + class StepwisePlugin: def __init__(self, config: Config) -> None: self.config = config self.session: Session | None = None - self.report_status = "" + self.report_status: list[str] = [] assert config.cache is not None self.cache: Cache = config.cache - self.lastfailed: str | None = self.cache.get(STEPWISE_CACHE_DIR, None) self.skip: bool = config.getoption("stepwise_skip") - if config.getoption("stepwise_reset"): - self.lastfailed = None + self.reset: bool = config.getoption("stepwise_reset") + self.cached_info = self._load_cached_info() + + def _load_cached_info(self) -> StepwiseCacheInfo: + cached_dict: dict[str, Any] | None = self.cache.get(STEPWISE_CACHE_DIR, None) + if cached_dict: + try: + return StepwiseCacheInfo( + cached_dict["last_failed"], + cached_dict["last_test_count"], + cached_dict["last_cache_date_str"], + ) + except Exception as e: + error = f"{type(e).__name__}: {e}" + self.report_status.append(f"error reading cache, discarding ({error})") + + # Cache not found or error during load, return a new cache. + return StepwiseCacheInfo.empty() def pytest_sessionstart(self, session: Session) -> None: self.session = session @@ -79,23 +135,41 @@ def pytest_sessionstart(self, session: Session) -> None: def pytest_collection_modifyitems( self, config: Config, items: list[nodes.Item] ) -> None: - if not self.lastfailed: - self.report_status = "no previously failed tests, not skipping." + last_test_count = self.cached_info.last_test_count + self.cached_info.last_test_count = len(items) + + if self.reset: + self.report_status.append("resetting state, not skipping.") + self.cached_info.last_failed = None + return + + if not self.cached_info.last_failed: + self.report_status.append("no previously failed tests, not skipping.") + return + + if last_test_count is not None and last_test_count != len(items): + self.report_status.append( + f"test count changed, not skipping (now {len(items)} tests, previously {last_test_count})." + ) + self.cached_info.last_failed = None return - # check all item nodes until we find a match on last failed + # Check all item nodes until we find a match on last failed. failed_index = None for index, item in enumerate(items): - if item.nodeid == self.lastfailed: + if item.nodeid == self.cached_info.last_failed: failed_index = index break # If the previously failed test was not found among the test items, # do not skip any tests. if failed_index is None: - self.report_status = "previously failed test not found, not skipping." + self.report_status.append("previously failed test not found, not skipping.") else: - self.report_status = f"skipping {failed_index} already passed items." + self.report_status.append( + f"skipping {failed_index} already passed items (cache from {self.cached_info.last_cache_date}," + f" use --sw-reset to discard)." + ) deselected = items[:failed_index] del items[:failed_index] config.hook.pytest_deselected(items=deselected) @@ -105,13 +179,13 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: if self.skip: # Remove test from the failed ones (if it exists) and unset the skip option # to make sure the following tests will not be skipped. - if report.nodeid == self.lastfailed: - self.lastfailed = None + if report.nodeid == self.cached_info.last_failed: + self.cached_info.last_failed = None self.skip = False else: # Mark test as the last failing and interrupt the test session. - self.lastfailed = report.nodeid + self.cached_info.last_failed = report.nodeid assert self.session is not None self.session.shouldstop = ( "Test failed, continuing from this test next run." @@ -121,12 +195,12 @@ def pytest_runtest_logreport(self, report: TestReport) -> None: # If the test was actually run and did pass. if report.when == "call": # Remove test from the failed ones, if exists. - if report.nodeid == self.lastfailed: - self.lastfailed = None + if report.nodeid == self.cached_info.last_failed: + self.cached_info.last_failed = None - def pytest_report_collectionfinish(self) -> str | None: + def pytest_report_collectionfinish(self) -> list[str] | None: if self.config.get_verbosity() >= 0 and self.report_status: - return f"stepwise: {self.report_status}" + return [f"stepwise: {x}" for x in self.report_status] return None def pytest_sessionfinish(self) -> None: @@ -134,4 +208,5 @@ def pytest_sessionfinish(self) -> None: # Do not update cache if this process is a xdist worker to prevent # race conditions (#10641). return - self.cache.set(STEPWISE_CACHE_DIR, self.lastfailed) + self.cached_info.update_date_to_now() + self.cache.set(STEPWISE_CACHE_DIR, dataclasses.asdict(self.cached_info)) diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index dbf49f73535..8e040cca28e 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -1,6 +1,8 @@ -# mypy: allow-untyped-defs +# mypy: disallow-untyped-defs from __future__ import annotations +from collections.abc import Sequence +import json from pathlib import Path from _pytest.cacheprovider import Cache @@ -84,7 +86,7 @@ def broken_pytester(pytester: Pytester) -> Pytester: return pytester -def _strip_resource_warnings(lines): +def _strip_resource_warnings(lines: Sequence[str]) -> Sequence[str]: # Strip unreliable ResourceWarnings, so no-output assertions on stderr can work. # (https://github.com/pytest-dev/pytest/issues/5088) return [ @@ -114,7 +116,10 @@ def test_data(expected): result.stdout.fnmatch_lines(["stepwise: no previously failed tests, not skipping."]) result = pytester.runpytest("-v", "--stepwise") result.stdout.fnmatch_lines( - ["stepwise: skipping 4 already passed items.", "*1 failed, 4 deselected*"] + [ + "stepwise: skipping 4 already passed items (cache from *, use --sw-reset to discard).", + "*1 failed, 4 deselected*", + ] ) @@ -360,9 +365,9 @@ def test_one(): assert [expected_value] == observed_value -def test_do_not_clear_cache_if_disabled(pytester: Pytester) -> None: +def test_do_not_reset_cache_if_disabled(pytester: Pytester) -> None: """ - If pytest is run without --step-wise, do not clear the stepwise cache. + If pytest is run without --stepwise, do not clear the stepwise cache. Keeping the cache around is important for this workflow: @@ -374,12 +379,9 @@ def test_do_not_clear_cache_if_disabled(pytester: Pytester) -> None: """ pytester.makepyfile( """ - def test_1(): - pass - def test_2(): - assert False - def test_3(): - pass + def test_1(): pass + def test_2(): assert False + def test_3(): pass """ ) result = pytester.runpytest("--stepwise") @@ -399,7 +401,7 @@ def test_3(): result = pytester.runpytest("--stepwise") result.stdout.fnmatch_lines( [ - "stepwise: skipping 1 already passed items.", + "stepwise: skipping 1 already passed items (cache from *, use --sw-reset to discard).", "*::test_2 - assert False*", "*failed, continuing from this test next run*", "=* 1 failed, 1 deselected in *", @@ -407,23 +409,32 @@ def test_3(): ) -def test_stepwise_reset(pytester: Pytester) -> None: +def test_reset(pytester: Pytester) -> None: pytester.makepyfile( """ - def test_1(): - pass - def test_2(): - assert False - def test_3(): - pass + def test_1(): pass + def test_2(): assert False + def test_3(): pass """ ) result = pytester.runpytest("--stepwise", "-v") result.stdout.fnmatch_lines( [ + "stepwise: no previously failed tests, not skipping.", "*::test_1 *PASSED*", "*::test_2 *FAILED*", "*failed, continuing from this test next run*", + "* 1 failed, 1 passed in *", + ] + ) + + result = pytester.runpytest("--stepwise", "-v") + result.stdout.fnmatch_lines( + [ + "stepwise: skipping 1 already passed items (cache from *, use --sw-reset to discard).", + "*::test_2 *FAILED*", + "*failed, continuing from this test next run*", + "* 1 failed, 1 deselected in *", ] ) @@ -431,8 +442,104 @@ def test_3(): result = pytester.runpytest("-v", "--stepwise-reset") result.stdout.fnmatch_lines( [ + "stepwise: resetting state, not skipping.", "*::test_1 *PASSED*", "*::test_2 *FAILED*", "*failed, continuing from this test next run*", + "* 1 failed, 1 passed in *", + ] + ) + + +def test_change_test_count(pytester: Pytester) -> None: + # Run initially with 3 tests. + pytester.makepyfile( + """ + def test_1(): pass + def test_2(): assert False + def test_3(): pass + """ + ) + result = pytester.runpytest("--stepwise", "-v") + result.stdout.fnmatch_lines( + [ + "stepwise: no previously failed tests, not skipping.", + "*::test_1 *PASSED*", + "*::test_2 *FAILED*", + "*failed, continuing from this test next run*", + "* 1 failed, 1 passed in *", + ] + ) + + # Change the number of tests, which invalidates the test cache. + pytester.makepyfile( + """ + def test_1(): pass + def test_2(): assert False + def test_3(): pass + def test_4(): pass + """ + ) + result = pytester.runpytest("--stepwise", "-v") + result.stdout.fnmatch_lines( + [ + "stepwise: test count changed, not skipping (now 4 tests, previously 3).", + "*::test_1 *PASSED*", + "*::test_2 *FAILED*", + "*failed, continuing from this test next run*", + "* 1 failed, 1 passed in *", + ] + ) + + # Fix the failing test and run again. + pytester.makepyfile( + """ + def test_1(): pass + def test_2(): pass + def test_3(): pass + def test_4(): pass + """ + ) + result = pytester.runpytest("--stepwise", "-v") + result.stdout.fnmatch_lines( + [ + "stepwise: skipping 1 already passed items (cache from *, use --sw-reset to discard).", + "*::test_2 *PASSED*", + "*::test_3 *PASSED*", + "*::test_4 *PASSED*", + "* 3 passed, 1 deselected in *", + ] + ) + + +def test_cache_error(pytester: Pytester) -> None: + pytester.makepyfile( + """ + def test_1(): pass + """ + ) + # Run stepwise normally to generate the cache information. + result = pytester.runpytest("--stepwise", "-v") + result.stdout.fnmatch_lines( + [ + "stepwise: no previously failed tests, not skipping.", + "*::test_1 *PASSED*", + "* 1 passed in *", + ] + ) + + # Corrupt the cache. + cache_file = pytester.path / f".pytest_cache/v/{STEPWISE_CACHE_DIR}" + assert cache_file.is_file() + cache_file.write_text(json.dumps({"invalid": True}), encoding="UTF-8") + + # Check we run as if the cache did not exist, but also show an error message. + result = pytester.runpytest("--stepwise", "-v") + result.stdout.fnmatch_lines( + [ + "stepwise: error reading cache, discarding (KeyError: *", + "stepwise: no previously failed tests, not skipping.", + "*::test_1 *PASSED*", + "* 1 passed in *", ] ) From 1f7a1517dbcf381980e2ca1839209e0ca21a595d Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 13 Jan 2025 12:59:43 -0300 Subject: [PATCH 1075/1271] Code review requests --- src/_pytest/stepwise.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index 7ee869bcef8..c25f260a1ca 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -14,11 +14,9 @@ if TYPE_CHECKING: - from typing import ClassVar - from typing_extensions import Self -STEPWISE_CACHE_DIR = "cache/stepwise2" +STEPWISE_CACHE_DIR = "cache/stepwise" def pytest_addoption(parser: Parser) -> None: @@ -52,11 +50,8 @@ def pytest_addoption(parser: Parser) -> None: def pytest_configure(config: Config) -> None: - # --stepwise-skip implies stepwise. - if config.option.stepwise_skip: - config.option.stepwise = True - # --stepwise-clear implies stepwise. - if config.option.stepwise_reset: + # --stepwise-skip/--stepwise-reset implies stepwise. + if config.option.stepwise_skip or config.option.stepwise_reset: config.option.stepwise = True if config.getoption("stepwise"): config.pluginmanager.register(StepwisePlugin(config), "stepwiseplugin") @@ -84,22 +79,20 @@ class StepwiseCacheInfo: # The date when the cache was last updated, for information purposes only. last_cache_date_str: str - _DATE_FORMAT: ClassVar[str] = "%Y-%m-%d %H:%M:%S" - @property def last_cache_date(self) -> datetime: - return datetime.strptime(self.last_cache_date_str, self._DATE_FORMAT) + return datetime.fromisoformat(self.last_cache_date_str) @classmethod def empty(cls) -> Self: return cls( last_failed=None, last_test_count=None, - last_cache_date_str=datetime.now().strftime(cls._DATE_FORMAT), + last_cache_date_str=datetime.now().isoformat(), ) def update_date_to_now(self) -> None: - self.last_cache_date_str = datetime.now().strftime(self._DATE_FORMAT) + self.last_cache_date_str = datetime.now().isoformat() class StepwisePlugin: @@ -122,7 +115,7 @@ def _load_cached_info(self) -> StepwiseCacheInfo: cached_dict["last_test_count"], cached_dict["last_cache_date_str"], ) - except Exception as e: + except (KeyError, TypeError) as e: error = f"{type(e).__name__}: {e}" self.report_status.append(f"error reading cache, discarding ({error})") From 2fcaa79358ae781ae68cc3a335f93aff7c80d521 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 15 Jan 2025 14:48:06 -0300 Subject: [PATCH 1076/1271] Show cache age instead of update date --- src/_pytest/stepwise.py | 6 +++++- testing/test_stepwise.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/_pytest/stepwise.py b/src/_pytest/stepwise.py index c25f260a1ca..8901540eb59 100644 --- a/src/_pytest/stepwise.py +++ b/src/_pytest/stepwise.py @@ -2,6 +2,7 @@ import dataclasses from datetime import datetime +from datetime import timedelta from typing import Any from typing import TYPE_CHECKING @@ -159,8 +160,11 @@ def pytest_collection_modifyitems( if failed_index is None: self.report_status.append("previously failed test not found, not skipping.") else: + cache_age = datetime.now() - self.cached_info.last_cache_date + # Round up to avoid showing microseconds. + cache_age = timedelta(seconds=int(cache_age.total_seconds())) self.report_status.append( - f"skipping {failed_index} already passed items (cache from {self.cached_info.last_cache_date}," + f"skipping {failed_index} already passed items (cache from {cache_age} ago," f" use --sw-reset to discard)." ) deselected = items[:failed_index] diff --git a/testing/test_stepwise.py b/testing/test_stepwise.py index 8e040cca28e..d2ad3bae500 100644 --- a/testing/test_stepwise.py +++ b/testing/test_stepwise.py @@ -117,7 +117,7 @@ def test_data(expected): result = pytester.runpytest("-v", "--stepwise") result.stdout.fnmatch_lines( [ - "stepwise: skipping 4 already passed items (cache from *, use --sw-reset to discard).", + "stepwise: skipping 4 already passed items (cache from * ago, use --sw-reset to discard).", "*1 failed, 4 deselected*", ] ) From f93da9228d16fdbc619a775c5d2e2ffa761e2cac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 07:04:23 +0100 Subject: [PATCH 1077/1271] build(deps): Bump django in /testing/plugins_integration (#13146) Bumps [django](https://github.com/django/django) from 5.1.4 to 5.1.5. - [Commits](https://github.com/django/django/compare/5.1.4...5.1.5) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index aa35aeebcd2..4c3c66636ba 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[trio]==4.8.0 -django==5.1.4 +django==5.1.5 pytest-asyncio==0.25.2 pytest-bdd==8.1.0 pytest-cov==6.0.0 From 1ba36bc940f5570046ae2c4bec71102e9028ed90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 12:24:50 -0300 Subject: [PATCH 1078/1271] build(deps): Bump peter-evans/create-pull-request from 7.0.5 to 7.0.6 (#13147) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.5 to 7.0.6. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/5e914681df9dc83aa4e4905692ca88beb2f9e91f...67ccf781d68cd99b580ae25a5c18a1cc84ffff1f) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index ce3e9fd5230..a4eeb4b0a36 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -48,7 +48,7 @@ jobs: - name: Create Pull Request id: pr - uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f + uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 195f7e1bd22e0c1dc99da8d3ba6e5ab3d7627b3b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 12:25:15 -0300 Subject: [PATCH 1079/1271] [automated] Update plugin list (#13143) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 104 +++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 32 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 752bc869deb..e575d58ac7f 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7 :pypi:`pytest-adaptavist` pytest plugin for generating test execution results within Jira Test Management (tm4j) Oct 13, 2022 N/A pytest (>=5.4.0) - :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Nov 08, 2023 N/A pytest >=5.4.0 + :pypi:`pytest-adaptavist-fixed` pytest plugin for generating test execution results within Jira Test Management (tm4j) Jan 17, 2025 N/A pytest>=5.4.0 :pypi:`pytest-addons-test` 用于测试pytest的插件 Aug 02, 2021 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-adf` Pytest plugin for writing Azure Data Factory integration tests May 10, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-adf-azure-identity` Pytest plugin for writing Azure Data Factory integration tests Mar 06, 2021 4 - Beta pytest (>=3.5.0) @@ -52,7 +52,7 @@ This list contains 1569 plugins. :pypi:`pytest-aggreport` pytest plugin for pytest-repeat that generate aggregate report of the same test cases with additional statistics details. Mar 07, 2021 4 - Beta pytest (>=6.2.2) :pypi:`pytest-ai1899` pytest plugin for connecting to ai1899 smart system stack Mar 13, 2024 5 - Production/Stable N/A :pypi:`pytest-aio` Pytest plugin for testing async python code Jul 31, 2024 5 - Production/Stable pytest - :pypi:`pytest-aioboto3` Aioboto3 Pytest with Moto Nov 26, 2024 N/A N/A + :pypi:`pytest-aioboto3` Aioboto3 Pytest with Moto Jan 17, 2025 N/A N/A :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A :pypi:`pytest-aiogram` May 06, 2023 N/A N/A :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Sep 06, 2023 4 - Beta pytest >=6.1.0 @@ -116,7 +116,7 @@ This list contains 1569 plugins. :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Jan 08, 2025 4 - Beta pytest<9,>=8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Jan 09, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Jan 17, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -159,7 +159,7 @@ This list contains 1569 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jan 09, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jan 16, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -505,6 +505,7 @@ This list contains 1569 plugins. :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) + :pypi:`pytest-evals` A pytest plugin for running and analyzing LLM evaluation tests Jan 16, 2025 N/A pytest>=7.0.0 :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A @@ -522,6 +523,7 @@ This list contains 1569 plugins. :pypi:`pytest-exit-code` A pytest plugin that overrides the built-in exit codes to retain more information about the test results. May 06, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-expect` py.test plugin to store test expectations and mark tests based on them Apr 21, 2016 4 - Beta N/A :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) + :pypi:`pytest-expected` Record and play back your expectations Jan 14, 2025 N/A pytest :pypi:`pytest-expecter` Better testing with expecter and pytest. Sep 18, 2022 5 - Production/Stable N/A :pypi:`pytest-expectr` This plugin is used to expect multiple assert using pytest framework. Oct 05, 2018 N/A pytest (>=2.4.2) :pypi:`pytest-expect-test` A fixture to support expect tests in pytest Apr 10, 2023 4 - Beta pytest (>=3.5.0) @@ -623,7 +625,7 @@ This list contains 1569 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jan 10, 2025 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jan 13, 2025 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest @@ -635,7 +637,7 @@ This list contains 1569 plugins. :pypi:`pytest-git-diff` Pytest plugin that allows the user to select the tests affected by a range of git commits Apr 02, 2024 N/A N/A :pypi:`pytest-git-fixtures` Pytest fixtures for testing with git. Mar 11, 2021 4 - Beta pytest :pypi:`pytest-github` Plugin for py.test that associates tests with github issues using a marker. Mar 07, 2019 5 - Production/Stable N/A - :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions May 04, 2023 5 - Production/Stable pytest (>=4.0.0) + :pypi:`pytest-github-actions-annotate-failures` pytest plugin to annotate failed tests with a workflow command for GitHub Actions Jan 17, 2025 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-github-report` Generate a GitHub report using pytest in GitHub Workflows Jun 03, 2022 4 - Beta N/A :pypi:`pytest-gitignore` py.test plugin to ignore the same files as git Jul 17, 2015 4 - Beta N/A :pypi:`pytest-gitlab` Pytest Plugin for Gitlab Oct 16, 2024 N/A N/A @@ -727,7 +729,7 @@ This list contains 1569 plugins. :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-inline` A pytest plugin for writing inline tests Oct 24, 2024 4 - Beta pytest<9.0,>=7.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Oct 10, 2024 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Oct 10, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package Jan 17, 2025 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Dec 13, 2024 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A @@ -747,7 +749,7 @@ This list contains 1569 plugins. :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipywidgets` Dec 19, 2024 N/A pytest - :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Nov 24, 2024 4 - Beta pytest + :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Dec 05, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -834,7 +836,7 @@ This list contains 1569 plugins. :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Jan 03, 2025 3 - Alpha pytest - :pypi:`pytest-logikal` Common testing environment Nov 27, 2024 5 - Production/Stable pytest==8.3.3 + :pypi:`pytest-logikal` Common testing environment Jan 18, 2025 5 - Production/Stable pytest==8.3.4 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" @@ -904,7 +906,7 @@ This list contains 1569 plugins. :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Mar 13, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A :pypi:`pytest-mongodb-nono` pytest plugin for MongoDB Jan 07, 2025 N/A N/A - :pypi:`pytest-mongodb-ry` pytest plugin for MongoDB Jan 10, 2025 N/A N/A + :pypi:`pytest-mongodb-ry` pytest plugin for MongoDB Jan 13, 2025 N/A N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A @@ -1027,6 +1029,7 @@ This list contains 1569 plugins. :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-picked` Run the tests related to the changed files Nov 06, 2024 N/A pytest>=3.7.0 + :pypi:`pytest-pickle-cache` A pytest plugin for caching test results using pickle. Jan 18, 2025 N/A pytest>=7 :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) :pypi:`pytest-pikachu` Show surprise when tests are passing Aug 05, 2021 5 - Production/Stable pytest :pypi:`pytest-pilot` Slice in your test base thanks to powerful markers. Oct 09, 2020 5 - Production/Stable N/A @@ -1142,7 +1145,7 @@ This list contains 1569 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Dec 23, 2024 4 - Beta pytest>=7.4.3 + :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jan 14, 2025 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jan 09, 2025 N/A N/A @@ -1249,7 +1252,7 @@ This list contains 1569 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 10, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 14, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1260,7 +1263,7 @@ This list contains 1569 plugins. :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 Feb 01, 2024 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. Jan 10, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jan 14, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1317,6 +1320,7 @@ This list contains 1569 plugins. :pypi:`pytest-snapshot` A plugin for snapshot testing with pytest. Apr 23, 2022 4 - Beta pytest (>=3.0.0) :pypi:`pytest-snapshot-with-message-generator` A plugin for snapshot testing with pytest. Jul 25, 2023 4 - Beta pytest (>=3.0.0) :pypi:`pytest-snmpserver` May 12, 2021 N/A N/A + :pypi:`pytest-snob` A pytest plugin that only selects meaningful python tests to run. Jan 12, 2025 N/A pytest :pypi:`pytest-snowflake-bdd` Setup test data and run tests on snowflake in BDD style! Jan 05, 2022 4 - Beta pytest (>=6.2.0) :pypi:`pytest-socket` Pytest Plugin to disable socket calls during tests Jan 28, 2024 4 - Beta pytest (>=6.2.5) :pypi:`pytest-sofaepione` Test the installation of SOFA and the SofaEpione plugin. Aug 17, 2022 N/A N/A @@ -1557,13 +1561,14 @@ This list contains 1569 plugins. :pypi:`pytest-winnotify` Windows tray notifications for py.test results. Apr 22, 2016 N/A N/A :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-workaround-12888` forces an import of readline early in the process to work around pytest bug #12888 Jan 15, 2025 N/A N/A :pypi:`pytest-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Mar 18, 2024 5 - Production/Stable pytest >=7.0.0 :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Apr 28, 2024 5 - Production/Stable pytest>=7.0.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) :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 - :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Jan 04, 2025 N/A pytest<8.0.0,>=7.4.2 + :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Jan 15, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 14, 2024 4 - Beta pytest>=8.2.1 @@ -1665,9 +1670,9 @@ This list contains 1569 plugins. pytest plugin for generating test execution results within Jira Test Management (tm4j) :pypi:`pytest-adaptavist-fixed` - *last release*: Nov 08, 2023, + *last release*: Jan 17, 2025, *status*: N/A, - *requires*: pytest >=5.4.0 + *requires*: pytest>=5.4.0 pytest plugin for generating test execution results within Jira Test Management (tm4j) @@ -1735,7 +1740,7 @@ This list contains 1569 plugins. Pytest plugin for testing async python code :pypi:`pytest-aioboto3` - *last release*: Nov 26, 2024, + *last release*: Jan 17, 2025, *status*: N/A, *requires*: N/A @@ -2183,7 +2188,7 @@ This list contains 1569 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Jan 09, 2025, + *last release*: Jan 17, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2484,7 +2489,7 @@ This list contains 1569 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jan 09, 2025, + *last release*: Jan 16, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -4905,6 +4910,13 @@ This list contains 1569 plugins. Pytest Plugin for BDD + :pypi:`pytest-evals` + *last release*: Jan 16, 2025, + *status*: N/A, + *requires*: pytest>=7.0.0 + + A pytest plugin for running and analyzing LLM evaluation tests + :pypi:`pytest-eventlet` *last release*: Oct 04, 2021, *status*: N/A, @@ -5024,6 +5036,13 @@ This list contains 1569 plugins. A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one + :pypi:`pytest-expected` + *last release*: Jan 14, 2025, + *status*: N/A, + *requires*: pytest + + Record and play back your expectations + :pypi:`pytest-expecter` *last release*: Sep 18, 2022, *status*: 5 - Production/Stable, @@ -5732,7 +5751,7 @@ This list contains 1569 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Jan 10, 2025, + *last release*: Jan 13, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -5816,9 +5835,9 @@ This list contains 1569 plugins. Plugin for py.test that associates tests with github issues using a marker. :pypi:`pytest-github-actions-annotate-failures` - *last release*: May 04, 2023, + *last release*: Jan 17, 2025, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.0.0) + *requires*: pytest>=6.0.0 pytest plugin to annotate failed tests with a workflow command for GitHub Actions @@ -6460,7 +6479,7 @@ This list contains 1569 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Oct 10, 2024, + *last release*: Jan 17, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -6600,7 +6619,7 @@ This list contains 1569 plugins. :pypi:`pytest-isolate` - *last release*: Nov 24, 2024, + *last release*: Jan 16, 2025, *status*: 4 - Beta, *requires*: pytest @@ -7209,9 +7228,9 @@ This list contains 1569 plugins. pytest fixture logging configured from packaged YAML :pypi:`pytest-logikal` - *last release*: Nov 27, 2024, + *last release*: Jan 18, 2025, *status*: 5 - Production/Stable, - *requires*: pytest==8.3.3 + *requires*: pytest==8.3.4 Common testing environment @@ -7699,7 +7718,7 @@ This list contains 1569 plugins. pytest plugin for MongoDB :pypi:`pytest-mongodb-ry` - *last release*: Jan 10, 2025, + *last release*: Jan 13, 2025, *status*: N/A, *requires*: N/A @@ -8559,6 +8578,13 @@ This list contains 1569 plugins. Run the tests related to the changed files + :pypi:`pytest-pickle-cache` + *last release*: Jan 18, 2025, + *status*: N/A, + *requires*: pytest>=7 + + A pytest plugin for caching test results using pickle. + :pypi:`pytest-pigeonhole` *last release*: Jun 25, 2018, *status*: 5 - Production/Stable, @@ -9365,7 +9391,7 @@ This list contains 1569 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-ranking` - *last release*: Dec 23, 2024, + *last release*: Jan 14, 2025, *status*: 4 - Beta, *requires*: pytest>=7.4.3 @@ -10114,7 +10140,7 @@ This list contains 1569 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jan 10, 2025, + *last release*: Jan 14, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10191,7 +10217,7 @@ This list contains 1569 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jan 10, 2025, + *last release*: Jan 14, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10589,6 +10615,13 @@ This list contains 1569 plugins. + :pypi:`pytest-snob` + *last release*: Jan 12, 2025, + *status*: N/A, + *requires*: pytest + + A pytest plugin that only selects meaningful python tests to run. + :pypi:`pytest-snowflake-bdd` *last release*: Jan 05, 2022, *status*: 4 - Beta, @@ -12269,6 +12302,13 @@ This list contains 1569 plugins. pytest with docker helpers. + :pypi:`pytest-workaround-12888` + *last release*: Jan 15, 2025, + *status*: N/A, + *requires*: N/A + + forces an import of readline early in the process to work around pytest bug #12888 + :pypi:`pytest-workflow` *last release*: Mar 18, 2024, *status*: 5 - Production/Stable, @@ -12312,7 +12352,7 @@ This list contains 1569 plugins. A pytest plugin to list worker statistics after a xdist run. :pypi:`pytest-xdocker` - *last release*: Jan 04, 2025, + *last release*: Jan 15, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.2 From b89c1ce279b6dd7083a5e3795979683de269190f Mon Sep 17 00:00:00 2001 From: Emil Hjelm Date: Mon, 20 Jan 2025 16:27:21 +0100 Subject: [PATCH 1080/1271] Add confval ``console_output_style`` option ``times`` (#13126) Fixes #13125 --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/13125.feature.rst | 1 + doc/en/reference/reference.rst | 1 + src/_pytest/terminal.py | 70 +++++++++++++++++-- testing/test_terminal.py | 118 +++++++++++++++++++++++++++++++++ 5 files changed, 184 insertions(+), 7 deletions(-) create mode 100644 changelog/13125.feature.rst diff --git a/AUTHORS b/AUTHORS index ef36a4251b1..8a1a7d183a3 100644 --- a/AUTHORS +++ b/AUTHORS @@ -142,6 +142,7 @@ Eero Vaher Eli Boyarski Elizaveta Shashkova Éloi Rivard +Emil Hjelm Endre Galaczi Eric Hunsberger Eric Liu diff --git a/changelog/13125.feature.rst b/changelog/13125.feature.rst new file mode 100644 index 00000000000..0c7d66c1169 --- /dev/null +++ b/changelog/13125.feature.rst @@ -0,0 +1 @@ +:confval:`console_output_style` now supports ``times`` to show execution time of each test. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 26572174ad4..809e97b4747 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1355,6 +1355,7 @@ passed multiple times. The expected format is ``name=value``. For example:: * ``progress``: like classic pytest output, but with a progress indicator. * ``progress-even-when-capture-no``: allows the use of the progress indicator even when ``capture=no``. * ``count``: like progress, but shows progress as the number of tests completed instead of a percent. + * ``times``: show tests duration. The default is ``progress``, but you can fallback to ``classic`` if you prefer or the new mode is causing unexpected problems: diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 348a78af9f5..1d58bb9c8e8 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -382,12 +382,15 @@ def __init__(self, config: Config, file: TextIO | None = None) -> None: self.hasmarkup = self._tw.hasmarkup self.isatty = file.isatty() self._progress_nodeids_reported: set[str] = set() + self._timing_nodeids_reported: set[str] = set() self._show_progress_info = self._determine_show_progress_info() self._collect_report_last_write: float | None = None self._already_displayed_warnings: int | None = None self._keyboardinterrupt_memo: ExceptionRepr | None = None - def _determine_show_progress_info(self) -> Literal["progress", "count", False]: + def _determine_show_progress_info( + self, + ) -> Literal["progress", "count", "times", False]: """Return whether we should display progress information based on the current config.""" # do not show progress if we are not capturing output (#3038) unless explicitly # overridden by progress-even-when-capture-no @@ -405,6 +408,8 @@ def _determine_show_progress_info(self) -> Literal["progress", "count", False]: return "progress" elif cfg == "count": return "count" + elif cfg == "times": + return "times" else: return False @@ -692,12 +697,38 @@ def _get_progress_information_message(self) -> str: format_string = f" [{counter_format}/{{}}]" return format_string.format(progress, collected) return f" [ {collected} / {collected} ]" - else: - if collected: - return ( - f" [{len(self._progress_nodeids_reported) * 100 // collected:3d}%]" - ) - return " [100%]" + if self._show_progress_info == "times": + if not collected: + return "" + all_reports = ( + self._get_reports_to_display("passed") + + self._get_reports_to_display("xpassed") + + self._get_reports_to_display("failed") + + self._get_reports_to_display("xfailed") + + self._get_reports_to_display("skipped") + + self._get_reports_to_display("error") + + self._get_reports_to_display("") + ) + current_location = all_reports[-1].location[0] + not_reported = [ + r for r in all_reports if r.nodeid not in self._timing_nodeids_reported + ] + tests_in_module = sum( + i.location[0] == current_location for i in self._session.items + ) + tests_completed = sum( + r.when == "setup" + for r in not_reported + if r.location[0] == current_location + ) + last_in_module = tests_completed == tests_in_module + if self.showlongtestinfo or last_in_module: + self._timing_nodeids_reported.update(r.nodeid for r in not_reported) + return format_node_duration(sum(r.duration for r in not_reported)) + return "" + if collected: + return f" [{len(self._progress_nodeids_reported) * 100 // collected:3d}%]" + return " [100%]" def _write_progress_information_if_past_edge(self) -> None: w = self._width_of_current_line @@ -705,6 +736,8 @@ def _write_progress_information_if_past_edge(self) -> None: assert self._session num_tests = self._session.testscollected progress_length = len(f" [{num_tests}/{num_tests}]") + elif self._show_progress_info == "times": + progress_length = len(" 99h 59m") else: progress_length = len(" [100%]") past_edge = w + progress_length + 1 >= self._screen_width @@ -1554,6 +1587,29 @@ def format_session_duration(seconds: float) -> str: return f"{seconds:.2f}s ({dt})" +def format_node_duration(seconds: float) -> str: + """Format the given seconds in a human readable manner to show in the test progress.""" + # The formatting is designed to be compact and readable, with at most 7 characters + # for durations below 100 hours. + if seconds < 0.00001: + return f" {seconds * 1000000:.3f}us" + if seconds < 0.0001: + return f" {seconds * 1000000:.2f}us" + if seconds < 0.001: + return f" {seconds * 1000000:.1f}us" + if seconds < 0.01: + return f" {seconds * 1000:.3f}ms" + if seconds < 0.1: + return f" {seconds * 1000:.2f}ms" + if seconds < 1: + return f" {seconds * 1000:.1f}ms" + if seconds < 60: + return f" {seconds:.3f}s" + if seconds < 3600: + return f" {seconds // 60:.0f}m {seconds % 60:.0f}s" + return f" {seconds // 3600:.0f}h {(seconds % 3600) // 60:.0f}m" + + def _get_raw_skip_reason(report: TestReport) -> str: """Get the reason string of a skip/xfail/xpass test report. diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 402e1f8dba3..84c92753546 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2073,6 +2073,21 @@ def test_foobar(i): pass """, ) + @pytest.fixture + def more_tests_files(self, pytester: Pytester) -> None: + pytester.makepyfile( + test_bar=""" + import pytest + @pytest.mark.parametrize('i', range(30)) + def test_bar(i): pass + """, + test_foo=""" + import pytest + @pytest.mark.parametrize('i', range(5)) + def test_foo(i): pass + """, + ) + def test_zero_tests_collected(self, pytester: Pytester) -> None: """Some plugins (testmon for example) might issue pytest_runtest_logreport without any tests being actually collected (#2971).""" @@ -2169,6 +2184,52 @@ def test_count(self, many_tests_files, pytester: Pytester) -> None: ] ) + def test_times(self, many_tests_files, pytester: Pytester) -> None: + pytester.makeini( + """ + [pytest] + console_output_style = times + """ + ) + output = pytester.runpytest() + output.stdout.re_match_lines( + [ + r"test_bar.py \.{10} \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$", + r"test_foo.py \.{5} \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$", + r"test_foobar.py \.{5} \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$", + ] + ) + + def test_times_multiline( + self, more_tests_files, monkeypatch, pytester: Pytester + ) -> None: + monkeypatch.setenv("COLUMNS", "40") + pytester.makeini( + """ + [pytest] + console_output_style = times + """ + ) + output = pytester.runpytest() + output.stdout.re_match_lines( + [ + r"test_bar.py ...................", + r"........... \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$", + r"test_foo.py \.{5} \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$", + ], + consecutive=True, + ) + + def test_times_none_collected(self, pytester: Pytester) -> None: + pytester.makeini( + """ + [pytest] + console_output_style = times + """ + ) + output = pytester.runpytest() + assert output.ret == ExitCode.NO_TESTS_COLLECTED + def test_verbose(self, many_tests_files, pytester: Pytester) -> None: output = pytester.runpytest("-v") output.stdout.re_match_lines( @@ -2195,6 +2256,22 @@ def test_verbose_count(self, many_tests_files, pytester: Pytester) -> None: ] ) + def test_verbose_times(self, many_tests_files, pytester: Pytester) -> None: + pytester.makeini( + """ + [pytest] + console_output_style = times + """ + ) + output = pytester.runpytest("-v") + output.stdout.re_match_lines( + [ + r"test_bar.py::test_bar\[0\] PASSED \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$", + r"test_foo.py::test_foo\[4\] PASSED \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$", + r"test_foobar.py::test_foobar\[4\] PASSED \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$", + ] + ) + def test_xdist_normal( self, many_tests_files, pytester: Pytester, monkeypatch ) -> None: @@ -2247,6 +2324,26 @@ def test_xdist_verbose( ] ) + def test_xdist_times( + self, many_tests_files, pytester: Pytester, monkeypatch + ) -> None: + pytest.importorskip("xdist") + monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False) + pytester.makeini( + """ + [pytest] + console_output_style = times + """ + ) + output = pytester.runpytest("-n2", "-v") + output.stdout.re_match_lines_random( + [ + r"\[gw\d\] \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2} PASSED test_bar.py::test_bar\[1\]", + r"\[gw\d\] \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2} PASSED test_foo.py::test_foo\[1\]", + r"\[gw\d\] \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2} PASSED test_foobar.py::test_foobar\[1\]", + ] + ) + def test_capture_no(self, many_tests_files, pytester: Pytester) -> None: output = pytester.runpytest("-s") output.stdout.re_match_lines( @@ -2537,6 +2634,27 @@ def test_format_session_duration(seconds, expected): assert format_session_duration(seconds) == expected +@pytest.mark.parametrize( + "seconds, expected", + [ + (3600 * 100 - 60, " 99h 59m"), + (31 * 60 - 1, " 30m 59s"), + (10.1236, " 10.124s"), + (9.1236, " 9.124s"), + (0.1236, " 123.6ms"), + (0.01236, " 12.36ms"), + (0.001236, " 1.236ms"), + (0.0001236, " 123.6us"), + (0.00001236, " 12.36us"), + (0.000001236, " 1.236us"), + ], +) +def test_format_node_duration(seconds: float, expected: str) -> None: + from _pytest.terminal import format_node_duration + + assert format_node_duration(seconds) == expected + + def test_collecterror(pytester: Pytester) -> None: p1 = pytester.makepyfile("raise SyntaxError()") result = pytester.runpytest("-ra", str(p1)) From d6ab675a08c89606bfdc172eb410a4cdb56a5e60 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 21 Jan 2025 05:04:10 +0100 Subject: [PATCH 1081/1271] [pre-commit.ci] pre-commit autoupdate (#13151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.1 → v0.9.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.1...v0.9.2) - [github.com/woodruffw/zizmor-pre-commit: v1.1.1 → v1.2.2](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.1.1...v1.2.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 45af5f7f9b9..763d09eab7a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.1" + rev: "v0.9.2" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.1.1 + rev: v1.2.2 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs From 4a6a512443e5e1aaed0b5bb0cc82adb2c09d4b66 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 21 Jan 2025 08:02:56 -0300 Subject: [PATCH 1082/1271] Fix example in pytest_collection_modifyitems (#13152) Ref #13149 --- src/_pytest/hookspec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/hookspec.py b/src/_pytest/hookspec.py index 8b20061d6f0..12653ea11fe 100644 --- a/src/_pytest/hookspec.py +++ b/src/_pytest/hookspec.py @@ -277,7 +277,7 @@ def pytest_collection_modifyitems( When items are deselected (filtered out from ``items``), the hook :hook:`pytest_deselected` must be called explicitly with the deselected items to properly notify other plugins, - e.g. with ``config.hook.pytest_deselected(deselected_items)``. + e.g. with ``config.hook.pytest_deselected(items=deselected_items)``. :param session: The pytest session object. :param config: The pytest config object. From 2f1c143b17edab8e1525d553e0757a5fc27bb068 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 21 Jan 2025 10:32:01 -0300 Subject: [PATCH 1083/1271] Fix internal mypy error on Windows (#13153) When running `pre-commit` on Windows, I get the error below: ``` src\_pytest\_py\error.py:95: error: Invalid index type "Optional[int]" for "dict[int, int]"; expected type "int" [index] Found 1 error in 1 file (checked 234 source files) ``` Ignore the error because we do catch the `KeyError` anyway. --- src/_pytest/_py/error.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_pytest/_py/error.py b/src/_pytest/_py/error.py index 1c7984f5a8f..dace23764ff 100644 --- a/src/_pytest/_py/error.py +++ b/src/_pytest/_py/error.py @@ -92,7 +92,9 @@ def checked_call( raise if sys.platform == "win32": try: - cls = self._geterrnoclass(_winerrnomap[value.errno]) + # error: Invalid index type "Optional[int]" for "dict[int, int]"; expected type "int" [index] + # OK to ignore because we catch the KeyError below. + cls = self._geterrnoclass(_winerrnomap[value.errno]) # type:ignore[index] except KeyError: raise value else: From ecff0babe9449e9c89118b9f24bc28251e1634c4 Mon Sep 17 00:00:00 2001 From: Tobias Alex-Petersen Date: Fri, 24 Jan 2025 02:39:17 +0100 Subject: [PATCH 1084/1271] Accept generic ExceptionGroups for raises (#13134) * Accept generic ExceptionGroups for raises Closes #13115 * Fix review suggestions * Add extra test, changelog improvement * Minor suggested refactor of if clause (review comment) --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/13115.improvement.rst | 8 ++++++ src/_pytest/python_api.py | 47 +++++++++++++++++++++++++++++---- testing/code/test_excinfo.py | 34 ++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 5 deletions(-) create mode 100644 changelog/13115.improvement.rst diff --git a/AUTHORS b/AUTHORS index 8a1a7d183a3..8600735c8b5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -435,6 +435,7 @@ Tim Hoffmann Tim Strazny TJ Bruno Tobias Diez +Tobias Petersen Tom Dalton Tom Viner Tomáš Gavenčiak diff --git a/changelog/13115.improvement.rst b/changelog/13115.improvement.rst new file mode 100644 index 00000000000..9ac45820917 --- /dev/null +++ b/changelog/13115.improvement.rst @@ -0,0 +1,8 @@ +Allows supplying ``ExceptionGroup[Exception]`` and ``BaseExceptionGroup[BaseException]`` to ``pytest.raises`` to keep full typing on :class:`ExceptionInfo `: + +.. code-block:: python + + with pytest.raises(ExceptionGroup[Exception]) as exc_info: + some_function() + +Parametrizing with other exception types remains an error - we do not check the types of child exceptions and thus do not permit code that might look like we do. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 25cf9f04d61..ddbf9b87251 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -12,10 +12,13 @@ from numbers import Complex import pprint import re +import sys from types import TracebackType from typing import Any from typing import cast from typing import final +from typing import get_args +from typing import get_origin from typing import overload from typing import TYPE_CHECKING from typing import TypeVar @@ -24,6 +27,10 @@ from _pytest.outcomes import fail +if sys.version_info < (3, 11): + from exceptiongroup import BaseExceptionGroup + from exceptiongroup import ExceptionGroup + if TYPE_CHECKING: from numpy import ndarray @@ -954,15 +961,45 @@ def raises( f"Raising exceptions is already understood as failing the test, so you don't need " f"any special code to say 'this should never raise an exception'." ) + + expected_exceptions: tuple[type[E], ...] + origin_exc: type[E] | None = get_origin(expected_exception) if isinstance(expected_exception, type): - expected_exceptions: tuple[type[E], ...] = (expected_exception,) + expected_exceptions = (expected_exception,) + elif origin_exc and issubclass(origin_exc, BaseExceptionGroup): + expected_exceptions = (cast(type[E], expected_exception),) else: expected_exceptions = expected_exception - for exc in expected_exceptions: - if not isinstance(exc, type) or not issubclass(exc, BaseException): + + def validate_exc(exc: type[E]) -> type[E]: + __tracebackhide__ = True + origin_exc: type[E] | None = get_origin(exc) + if origin_exc and issubclass(origin_exc, BaseExceptionGroup): + exc_type = get_args(exc)[0] + if ( + issubclass(origin_exc, ExceptionGroup) and exc_type in (Exception, Any) + ) or ( + issubclass(origin_exc, BaseExceptionGroup) + and exc_type in (BaseException, Any) + ): + return cast(type[E], origin_exc) + else: + raise ValueError( + f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` " + f"are accepted as generic types but got `{exc}`. " + f"As `raises` will catch all instances of the specified group regardless of the " + f"generic argument specific nested exceptions has to be checked " + f"with `ExceptionInfo.group_contains()`" + ) + + elif not isinstance(exc, type) or not issubclass(exc, BaseException): msg = "expected exception must be a BaseException type, not {}" # type: ignore[unreachable] not_a = exc.__name__ if isinstance(exc, type) else type(exc).__name__ raise TypeError(msg.format(not_a)) + else: + return exc + + expected_exceptions = tuple(validate_exc(exc) for exc in expected_exceptions) message = f"DID NOT RAISE {expected_exception}" @@ -973,14 +1010,14 @@ def raises( msg += ", ".join(sorted(kwargs)) msg += "\nUse context-manager form instead?" raise TypeError(msg) - return RaisesContext(expected_exception, message, match) + return RaisesContext(expected_exceptions, message, match) else: func = args[0] if not callable(func): raise TypeError(f"{func!r} object (type: {type(func)}) must be callable") try: func(*args[1:], **kwargs) - except expected_exception as e: + except expected_exceptions as e: return _pytest._code.ExceptionInfo.from_exception(e) fail(message) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 22e695977e1..2e1d4bdf6dc 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -31,6 +31,7 @@ from _pytest._code.code import TracebackStyle if sys.version_info < (3, 11): + from exceptiongroup import BaseExceptionGroup from exceptiongroup import ExceptionGroup @@ -453,6 +454,39 @@ def test_division_zero(): result.stdout.re_match_lines([r".*__tracebackhide__ = True.*", *match]) +def test_raises_accepts_generic_group() -> None: + with pytest.raises(ExceptionGroup[Exception]) as exc_info: + raise ExceptionGroup("", [RuntimeError()]) + assert exc_info.group_contains(RuntimeError) + + +def test_raises_accepts_generic_base_group() -> None: + with pytest.raises(BaseExceptionGroup[BaseException]) as exc_info: + raise ExceptionGroup("", [RuntimeError()]) + assert exc_info.group_contains(RuntimeError) + + +def test_raises_rejects_specific_generic_group() -> None: + with pytest.raises(ValueError): + pytest.raises(ExceptionGroup[RuntimeError]) + + +def test_raises_accepts_generic_group_in_tuple() -> None: + with pytest.raises((ValueError, ExceptionGroup[Exception])) as exc_info: + raise ExceptionGroup("", [RuntimeError()]) + assert exc_info.group_contains(RuntimeError) + + +def test_raises_exception_escapes_generic_group() -> None: + try: + with pytest.raises(ExceptionGroup[Exception]): + raise ValueError("my value error") + except ValueError as e: + assert str(e) == "my value error" + else: + pytest.fail("Expected ValueError to be raised") + + class TestGroupContains: def test_contains_exception_type(self) -> None: exc_group = ExceptionGroup("", [RuntimeError()]) From 6c9939b08b23b29da93854b4412ae4e5a17faaf1 Mon Sep 17 00:00:00 2001 From: Kenny Y <24802984+kenny-y-dev@users.noreply.github.com> Date: Sun, 15 Dec 2024 09:41:27 -0500 Subject: [PATCH 1085/1271] Add --force-short-summary option This option allows the users to always see the "short test summary" section regardless of the verbosity level. Fix #12713 --- changelog/12713.feature.rst | 3 +++ src/_pytest/terminal.py | 11 ++++++++++- testing/test_terminal.py | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 changelog/12713.feature.rst diff --git a/changelog/12713.feature.rst b/changelog/12713.feature.rst new file mode 100644 index 00000000000..90867b87eae --- /dev/null +++ b/changelog/12713.feature.rst @@ -0,0 +1,3 @@ +New `--force-short-summary` option to force condensed summary output regardless of verbosity level. + +This lets users still see condensed summary output of failures for quick reference in log files from job outputs, being especially useful if non-condensed output is very verbose. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 1d58bb9c8e8..b2cdda37507 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -161,6 +161,13 @@ def pytest_addoption(parser: Parser) -> None: default=True, help="Do not fold skipped tests in short summary.", ) + group._addoption( + "--force-short-summary", + action="store_true", + dest="force_short_summary", + default=False, + help="Force condensed summary output regardless of verbosity level.", + ) group._addoption( "-q", "--quiet", @@ -1500,7 +1507,9 @@ def _get_line_with_reprcrash_message( except AttributeError: pass else: - if running_on_ci() or config.option.verbose >= 2: + if ( + running_on_ci() or config.option.verbose >= 2 + ) and not config.option.force_short_summary: msg = f" - {msg}" else: available_width = tw.fullwidth - line_width diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 84c92753546..b8242ec1b21 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2617,6 +2617,23 @@ def test(): ) +def test_force_short_summary(monkeypatch: MonkeyPatch, pytester: Pytester) -> None: + monkeypatch.setattr(_pytest.terminal, "running_on_ci", lambda: False) + + pytester.makepyfile( + """ + def test(): + assert "a\\n" * 10 == "" + """ + ) + + result = pytester.runpytest("-vv", "--force-short-summary") + assert result.ret == 1 + result.stdout.fnmatch_lines( + ["*short test summary info*", "*AssertionError: assert 'a\\na\\na\\na..."] + ) + + @pytest.mark.parametrize( "seconds, expected", [ From d471aef98473523f400f092071dadc7f745c7196 Mon Sep 17 00:00:00 2001 From: Kenny Y <24802984+kenny-y-dev@users.noreply.github.com> Date: Sun, 26 Jan 2025 09:20:04 -0300 Subject: [PATCH 1086/1271] Fix sequences being shortened even with `-vv` verbosity. Fix #11777 --- changelog/11777.bugfix.rst | 1 + src/_pytest/assertion/rewrite.py | 3 +++ testing/test_terminal.py | 29 +++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 changelog/11777.bugfix.rst diff --git a/changelog/11777.bugfix.rst b/changelog/11777.bugfix.rst new file mode 100644 index 00000000000..3f1ffc27a68 --- /dev/null +++ b/changelog/11777.bugfix.rst @@ -0,0 +1 @@ +Fixed issue where sequences were still being shortened even with ``-vv`` verbosity. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 41e3d271396..2e606d1903a 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -28,6 +28,7 @@ from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE from _pytest._io.saferepr import saferepr +from _pytest._io.saferepr import saferepr_unlimited from _pytest._version import version from _pytest.assertion import util from _pytest.config import Config @@ -433,6 +434,8 @@ def _saferepr(obj: object) -> str: return obj.__name__ maxsize = _get_maxsize_for_saferepr(util._config) + if not maxsize: + return saferepr_unlimited(obj).replace("\n", "\\n") return saferepr(obj, maxsize=maxsize).replace("\n", "\\n") diff --git a/testing/test_terminal.py b/testing/test_terminal.py index b8242ec1b21..42638f2edd7 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -2617,6 +2617,35 @@ def test(): ) +def test_full_sequence_print_with_vv( + monkeypatch: MonkeyPatch, pytester: Pytester +) -> None: + """Do not truncate sequences in summaries with -vv (#11777).""" + monkeypatch.setattr(_pytest.terminal, "running_on_ci", lambda: False) + + pytester.makepyfile( + """ + def test_len_list(): + l = list(range(10)) + assert len(l) == 9 + + def test_len_dict(): + d = dict(zip(range(10), range(10))) + assert len(d) == 9 + """ + ) + + result = pytester.runpytest("-vv") + assert result.ret == 1 + result.stdout.fnmatch_lines( + [ + "*short test summary info*", + f"*{list(range(10))}*", + f"*{dict(zip(range(10), range(10)))}*", + ] + ) + + def test_force_short_summary(monkeypatch: MonkeyPatch, pytester: Pytester) -> None: monkeypatch.setattr(_pytest.terminal, "running_on_ci", lambda: False) From a0e3a49f194175bec96a551791b2b02b23e06a09 Mon Sep 17 00:00:00 2001 From: Ammar Askar Date: Sun, 26 Jan 2025 23:15:14 -0500 Subject: [PATCH 1087/1271] Add basic implementation of PEP657 style expression markers in tracebacks (#13102) * Add very basic implementation of PEP657 style line markers in tracebacks * Version guard the py3.11 attributes * Change version guard to make mypy happy. Also, stop using private traceback function * Version guard unit test * Fix repr cycle test * Add changelog entry * Add pragma no cover for branch where column info is missing --- AUTHORS | 1 + changelog/10224.improvement.rst | 18 +++++ src/_pytest/_code/code.py | 121 +++++++++++++++++++++++++++++++- src/_pytest/_code/source.py | 10 +++ testing/code/test_excinfo.py | 110 ++++++++++++++++++++++------- 5 files changed, 234 insertions(+), 26 deletions(-) create mode 100644 changelog/10224.improvement.rst diff --git a/AUTHORS b/AUTHORS index 8600735c8b5..e670571566a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -24,6 +24,7 @@ Alice Purcell Allan Feldman Aly Sivji Amir Elkess +Ammar Askar Anatoly Bubenkoff Anders Hovmöller Andras Mitzki diff --git a/changelog/10224.improvement.rst b/changelog/10224.improvement.rst new file mode 100644 index 00000000000..93afe9e2c1e --- /dev/null +++ b/changelog/10224.improvement.rst @@ -0,0 +1,18 @@ +pytest's ``short`` and ``long`` traceback styles (:ref:`how-to-modifying-python-tb-printing`) +now have partial :pep:`657` support and will show specific code segments in the +traceback. + +.. code-block:: pytest + + ================================= FAILURES ================================= + _______________________ test_gets_correct_tracebacks _______________________ + + test_tracebacks.py:12: in test_gets_correct_tracebacks + assert manhattan_distance(p1, p2) == 1 + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + test_tracebacks.py:6: in manhattan_distance + return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y) + ^^^^^^^^^ + E AttributeError: 'NoneType' object has no attribute 'x' + +-- by :user:`ammaraskar` diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 5be200df9de..f812f0633c8 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -208,6 +208,45 @@ def with_repr_style( def lineno(self) -> int: return self._rawentry.tb_lineno - 1 + def get_python_framesummary(self) -> traceback.FrameSummary: + # Python's built-in traceback module implements all the nitty gritty + # details to get column numbers of out frames. + stack_summary = traceback.extract_tb(self._rawentry, limit=1) + return stack_summary[0] + + # Column and end line numbers introduced in python 3.11 + if sys.version_info < (3, 11): + + @property + def end_lineno_relative(self) -> int | None: + return None + + @property + def colno(self) -> int | None: + return None + + @property + def end_colno(self) -> int | None: + return None + else: + + @property + def end_lineno_relative(self) -> int | None: + frame_summary = self.get_python_framesummary() + if frame_summary.end_lineno is None: # pragma: no cover + return None + return frame_summary.end_lineno - 1 - self.frame.code.firstlineno + + @property + def colno(self) -> int | None: + """Starting byte offset of the expression in the traceback entry.""" + return self.get_python_framesummary().colno + + @property + def end_colno(self) -> int | None: + """Ending byte offset of the expression in the traceback entry.""" + return self.get_python_framesummary().end_colno + @property def frame(self) -> Frame: return Frame(self._rawentry.tb_frame) @@ -856,6 +895,9 @@ def get_source( line_index: int = -1, excinfo: ExceptionInfo[BaseException] | None = None, short: bool = False, + end_line_index: int | None = None, + colno: int | None = None, + end_colno: int | None = None, ) -> list[str]: """Return formatted and marked up source lines.""" lines = [] @@ -869,10 +911,30 @@ def get_source( space_prefix = " " if short: lines.append(space_prefix + source.lines[line_index].strip()) + lines.extend( + self.get_highlight_arrows_for_line( + raw_line=source.raw_lines[line_index], + line=source.lines[line_index].strip(), + lineno=line_index, + end_lineno=end_line_index, + colno=colno, + end_colno=end_colno, + ) + ) else: for line in source.lines[:line_index]: lines.append(space_prefix + line) lines.append(self.flow_marker + " " + source.lines[line_index]) + lines.extend( + self.get_highlight_arrows_for_line( + raw_line=source.raw_lines[line_index], + line=source.lines[line_index], + lineno=line_index, + end_lineno=end_line_index, + colno=colno, + end_colno=end_colno, + ) + ) for line in source.lines[line_index + 1 :]: lines.append(space_prefix + line) if excinfo is not None: @@ -880,6 +942,43 @@ def get_source( lines.extend(self.get_exconly(excinfo, indent=indent, markall=True)) return lines + def get_highlight_arrows_for_line( + self, + line: str, + raw_line: str, + lineno: int | None, + end_lineno: int | None, + colno: int | None, + end_colno: int | None, + ) -> list[str]: + """Return characters highlighting a source line. + + Example with colno and end_colno pointing to the bar expression: + "foo() + bar()" + returns " ^^^^^" + """ + if lineno != end_lineno: + # Don't handle expressions that span multiple lines. + return [] + if colno is None or end_colno is None: + # Can't do anything without column information. + return [] + + num_stripped_chars = len(raw_line) - len(line) + + start_char_offset = _byte_offset_to_character_offset(raw_line, colno) + end_char_offset = _byte_offset_to_character_offset(raw_line, end_colno) + num_carets = end_char_offset - start_char_offset + # If the highlight would span the whole line, it is redundant, don't + # show it. + if num_carets >= len(line.strip()): + return [] + + highlights = " " + highlights += " " * (start_char_offset - num_stripped_chars + 1) + highlights += "^" * num_carets + return [highlights] + def get_exconly( self, excinfo: ExceptionInfo[BaseException], @@ -939,11 +1038,23 @@ def repr_traceback_entry( if source is None: source = Source("???") line_index = 0 + end_line_index, colno, end_colno = None, None, None else: - line_index = entry.lineno - entry.getfirstlinesource() + line_index = entry.relline + end_line_index = entry.end_lineno_relative + colno = entry.colno + end_colno = entry.end_colno short = style == "short" reprargs = self.repr_args(entry) if not short else None - s = self.get_source(source, line_index, excinfo, short=short) + s = self.get_source( + source=source, + line_index=line_index, + excinfo=excinfo, + short=short, + end_line_index=end_line_index, + colno=colno, + end_colno=end_colno, + ) lines.extend(s) if short: message = f"in {entry.name}" @@ -1374,6 +1485,12 @@ def getfslineno(obj: object) -> tuple[str | Path, int]: return code.path, code.firstlineno +def _byte_offset_to_character_offset(str, offset): + """Converts a byte based offset in a string to a code-point.""" + as_utf8 = str.encode("utf-8") + return len(as_utf8[:offset].decode("utf-8", errors="replace")) + + # Relative paths that we use to filter traceback entries from appearing to the user; # see filter_traceback. # note: if we need to add more paths than what we have now we should probably use a list diff --git a/src/_pytest/_code/source.py b/src/_pytest/_code/source.py index e24ee3a260e..a8f7201a40f 100644 --- a/src/_pytest/_code/source.py +++ b/src/_pytest/_code/source.py @@ -22,12 +22,16 @@ class Source: def __init__(self, obj: object = None) -> None: if not obj: self.lines: list[str] = [] + self.raw_lines: list[str] = [] elif isinstance(obj, Source): self.lines = obj.lines + self.raw_lines = obj.raw_lines elif isinstance(obj, (tuple, list)): self.lines = deindent(x.rstrip("\n") for x in obj) + self.raw_lines = list(x.rstrip("\n") for x in obj) elif isinstance(obj, str): self.lines = deindent(obj.split("\n")) + self.raw_lines = obj.split("\n") else: try: rawcode = getrawcode(obj) @@ -35,6 +39,7 @@ def __init__(self, obj: object = None) -> None: except TypeError: src = inspect.getsource(obj) # type: ignore[arg-type] self.lines = deindent(src.split("\n")) + self.raw_lines = src.split("\n") def __eq__(self, other: object) -> bool: if not isinstance(other, Source): @@ -58,6 +63,7 @@ def __getitem__(self, key: int | slice) -> str | Source: raise IndexError("cannot slice a Source with a step") newsource = Source() newsource.lines = self.lines[key.start : key.stop] + newsource.raw_lines = self.raw_lines[key.start : key.stop] return newsource def __iter__(self) -> Iterator[str]: @@ -74,6 +80,7 @@ def strip(self) -> Source: while end > start and not self.lines[end - 1].strip(): end -= 1 source = Source() + source.raw_lines = self.raw_lines source.lines[:] = self.lines[start:end] return source @@ -81,6 +88,7 @@ def indent(self, indent: str = " " * 4) -> Source: """Return a copy of the source object with all lines indented by the given indent-string.""" newsource = Source() + newsource.raw_lines = self.raw_lines newsource.lines = [(indent + line) for line in self.lines] return newsource @@ -102,6 +110,7 @@ def deindent(self) -> Source: """Return a new Source object deindented.""" newsource = Source() newsource.lines[:] = deindent(self.lines) + newsource.raw_lines = self.raw_lines return newsource def __str__(self) -> str: @@ -120,6 +129,7 @@ def findsource(obj) -> tuple[Source | None, int]: return None, -1 source = Source() source.lines = [line.rstrip() for line in sourcelines] + source.raw_lines = sourcelines return source, lineno diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 2e1d4bdf6dc..89088576980 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -883,6 +883,37 @@ def entry(): assert basename in str(reprtb.reprfileloc.path) assert reprtb.reprfileloc.lineno == 3 + @pytest.mark.skipif( + "sys.version_info < (3,11)", + reason="Column level traceback info added in python 3.11", + ) + def test_repr_traceback_entry_short_carets(self, importasmod) -> None: + mod = importasmod( + """ + def div_by_zero(): + return 1 / 0 + def func1(): + return 42 + div_by_zero() + def entry(): + func1() + """ + ) + excinfo = pytest.raises(ZeroDivisionError, mod.entry) + p = FormattedExcinfo(style="short") + reprtb = p.repr_traceback_entry(excinfo.traceback[-3]) + assert len(reprtb.lines) == 1 + assert reprtb.lines[0] == " func1()" + + reprtb = p.repr_traceback_entry(excinfo.traceback[-2]) + assert len(reprtb.lines) == 2 + assert reprtb.lines[0] == " return 42 + div_by_zero()" + assert reprtb.lines[1] == " ^^^^^^^^^^^^^" + + reprtb = p.repr_traceback_entry(excinfo.traceback[-1]) + assert len(reprtb.lines) == 2 + assert reprtb.lines[0] == " return 1 / 0" + assert reprtb.lines[1] == " ^^^^^" + def test_repr_tracebackentry_no(self, importasmod): mod = importasmod( """ @@ -1343,7 +1374,7 @@ def g(): raise ValueError() def h(): - raise AttributeError() + if True: raise AttributeError() """ ) excinfo = pytest.raises(AttributeError, mod.f) @@ -1404,12 +1435,22 @@ def h(): assert tw_mock.lines[40] == ("_ ", None) assert tw_mock.lines[41] == "" assert tw_mock.lines[42] == " def h():" - assert tw_mock.lines[43] == "> raise AttributeError()" - assert tw_mock.lines[44] == "E AttributeError" - assert tw_mock.lines[45] == "" - line = tw_mock.get_write_msg(46) - assert line.endswith("mod.py") - assert tw_mock.lines[47] == ":15: AttributeError" + # On python 3.11 and greater, check for carets in the traceback. + if sys.version_info >= (3, 11): + assert tw_mock.lines[43] == "> if True: raise AttributeError()" + assert tw_mock.lines[44] == " ^^^^^^^^^^^^^^^^^^^^^^" + assert tw_mock.lines[45] == "E AttributeError" + assert tw_mock.lines[46] == "" + line = tw_mock.get_write_msg(47) + assert line.endswith("mod.py") + assert tw_mock.lines[48] == ":15: AttributeError" + else: + assert tw_mock.lines[43] == "> if True: raise AttributeError()" + assert tw_mock.lines[44] == "E AttributeError" + assert tw_mock.lines[45] == "" + line = tw_mock.get_write_msg(46) + assert line.endswith("mod.py") + assert tw_mock.lines[47] == ":15: AttributeError" @pytest.mark.parametrize("mode", ["from_none", "explicit_suppress"]) def test_exc_repr_chain_suppression(self, importasmod, mode, tw_mock): @@ -1528,23 +1569,44 @@ def unreraise(): r = excinfo.getrepr(style="short") r.toterminal(tw_mock) out = "\n".join(line for line in tw_mock.lines if isinstance(line, str)) - expected_out = textwrap.dedent( - """\ - :13: in unreraise - reraise() - :10: in reraise - raise Err() from e - E test_exc_chain_repr_cycle0.mod.Err - - During handling of the above exception, another exception occurred: - :15: in unreraise - raise e.__cause__ - :8: in reraise - fail() - :5: in fail - return 0 / 0 - E ZeroDivisionError: division by zero""" - ) + # Assert highlighting carets in python3.11+ + if sys.version_info >= (3, 11): + expected_out = textwrap.dedent( + """\ + :13: in unreraise + reraise() + :10: in reraise + raise Err() from e + E test_exc_chain_repr_cycle0.mod.Err + + During handling of the above exception, another exception occurred: + :15: in unreraise + raise e.__cause__ + :8: in reraise + fail() + :5: in fail + return 0 / 0 + ^^^^^ + E ZeroDivisionError: division by zero""" + ) + else: + expected_out = textwrap.dedent( + """\ + :13: in unreraise + reraise() + :10: in reraise + raise Err() from e + E test_exc_chain_repr_cycle0.mod.Err + + During handling of the above exception, another exception occurred: + :15: in unreraise + raise e.__cause__ + :8: in reraise + fail() + :5: in fail + return 0 / 0 + E ZeroDivisionError: division by zero""" + ) assert out == expected_out def test_exec_type_error_filter(self, importasmod): From fb7f0440c4b212b8fa34d9224988792006d32931 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 07:58:30 -0300 Subject: [PATCH 1088/1271] build(deps): Bump pypa/gh-action-pypi-publish from 1.12.3 to 1.12.4 (#13165) Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.3 to 1.12.4. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.3...v1.12.4) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 32d55361e54..fb58390b597 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -56,7 +56,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.3 + uses: pypa/gh-action-pypi-publish@v1.12.4 with: attestations: true From 991db2e1b1d478f87ad460ecde98dbeeab53b13b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 07:59:11 -0300 Subject: [PATCH 1089/1271] build(deps): Bump hynek/build-and-inspect-python-package (#13166) Bumps [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) from 2.11.0 to 2.12.0. - [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases) - [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md) - [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v2.11.0...v2.12.0) --- updated-dependencies: - dependency-name: hynek/build-and-inspect-python-package dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/deploy.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index fb58390b597..2ad6e9d5054 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.11.0 + uses: hynek/build-and-inspect-python-package@v2.12.0 with: attest-build-provenance-github: 'true' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5814c81fb30..44c9d68c03d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.11.0 + uses: hynek/build-and-inspect-python-package@v2.12.0 build: needs: [package] From 2f369848ea0ead42182efc77000a5ecef629a0ba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 28 Jan 2025 09:26:40 +0100 Subject: [PATCH 1090/1271] [pre-commit.ci] pre-commit autoupdate (#13167) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.2 → v0.9.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.2...v0.9.3) - [github.com/codespell-project/codespell: v2.3.0 → v2.4.0](https://github.com/codespell-project/codespell/compare/v2.3.0...v2.4.0) --- .pre-commit-config.yaml | 4 ++-- doc/en/how-to/cache.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 763d09eab7a..527586a1f68 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.2" + rev: "v0.9.3" hooks: - id: ruff args: ["--fix"] @@ -21,7 +21,7 @@ repos: - id: blacken-docs additional_dependencies: [black==24.1.1] - repo: https://github.com/codespell-project/codespell - rev: v2.3.0 + rev: v2.4.0 hooks: - id: codespell args: ["--toml=pyproject.toml"] diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index 40cd3f00dd6..a3b2a862534 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -199,7 +199,7 @@ The new config.cache object Plugins or conftest.py support code can get a cached value using the pytest ``config`` object. Here is a basic example plugin which -implements a :ref:`fixture ` which re-uses previously created state +implements a :ref:`fixture ` which reuses previously created state across pytest invocations: .. code-block:: python From 9bcd7704ab77719bf9155a3a92c7191c944ef428 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 31 Jan 2025 13:04:25 +0100 Subject: [PATCH 1091/1271] [automated] Update plugin list (#13162) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 174 ++++++++++++++++++------------- 1 file changed, 103 insertions(+), 71 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index e575d58ac7f..4b1b7241379 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.2.2) + :pypi:`pytest-ai` A Python package to generate regular, edge-case, and security HTTP tests. Jan 22, 2025 N/A N/A :pypi:`pytest-ai1899` pytest plugin for connecting to ai1899 smart system stack Mar 13, 2024 5 - Production/Stable N/A :pypi:`pytest-aio` Pytest plugin for testing async python code Jul 31, 2024 5 - Production/Stable pytest :pypi:`pytest-aioboto3` Aioboto3 Pytest with Moto Jan 17, 2025 N/A N/A :pypi:`pytest-aiofiles` pytest fixtures for writing aiofiles tests with pyfakefs May 14, 2017 5 - Production/Stable N/A :pypi:`pytest-aiogram` May 06, 2023 N/A N/A - :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Sep 06, 2023 4 - Beta pytest >=6.1.0 + :pypi:`pytest-aiohttp` Pytest plugin for aiohttp support Jan 23, 2025 4 - Beta pytest>=6.1.0 :pypi:`pytest-aiohttp-client` Pytest \`client\` fixture for the Aiohttp Jan 10, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-aiomoto` pytest-aiomoto Jun 24, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-aioresponses` py.test integration for aioresponses Jan 02, 2025 4 - Beta pytest>=3.5.0 @@ -78,7 +79,7 @@ This list contains 1574 plugins. :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) :pypi:`pytest-annotated` Pytest plugin to allow use of Annotated in tests to resolve fixtures Sep 30, 2024 N/A pytest>=8.3.3 - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Dec 12, 2024 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jan 21, 2025 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -159,7 +160,7 @@ This list contains 1574 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jan 16, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jan 22, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -259,7 +260,7 @@ This list contains 1574 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Oct 27, 2024 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Jan 19, 2025 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) @@ -433,7 +434,7 @@ This list contains 1574 plugins. :pypi:`pytest-doctest-ellipsis-markers` Setup additional values for ELLIPSIS_MARKER for doctests Jan 12, 2018 4 - Beta N/A :pypi:`pytest-doctest-import` A simple pytest plugin to import names and add them to the doctest namespace. Nov 13, 2018 4 - Beta pytest (>=3.3.0) :pypi:`pytest-doctest-mkdocstrings` Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) Mar 02, 2024 N/A pytest - :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Nov 25, 2024 5 - Production/Stable pytest>=4.6 + :pypi:`pytest-doctestplus` Pytest plugin with advanced doctest features. Jan 25, 2025 5 - Production/Stable pytest>=4.6 :pypi:`pytest-documentary` A simple pytest plugin to generate test documentation Jul 11, 2024 N/A pytest :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 Dec 14, 2023 N/A N/A @@ -449,7 +450,7 @@ This list contains 1574 plugins. :pypi:`pytest-drivings` Tool to allow webdriver automation to be ran locally or remotely Jan 13, 2021 N/A N/A :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection Mar 04, 2024 5 - Production/Stable pytest >=7 :pypi:`pytest-dryci` Test caching plugin for pytest Sep 27, 2024 4 - Beta N/A - :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jul 18, 2023 5 - Production/Stable pytest (>=7.4.0,<8.0.0) + :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jan 19, 2025 5 - Production/Stable pytest<9,>=7.40 :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A @@ -472,15 +473,15 @@ This list contains 1574 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 Jul 25, 2024 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. Dec 02, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Dec 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Dec 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Dec 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Dec 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Dec 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Dec 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Dec 02, 2024 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Dec 02, 2024 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jan 21, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Jan 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 21, 2025 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) @@ -505,7 +506,7 @@ This list contains 1574 plugins. :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) - :pypi:`pytest-evals` A pytest plugin for running and analyzing LLM evaluation tests Jan 16, 2025 N/A pytest>=7.0.0 + :pypi:`pytest-evals` A pytest plugin for running and analyzing LLM evaluation tests Jan 21, 2025 N/A pytest>=7.0.0 :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A @@ -521,6 +522,7 @@ This list contains 1574 plugins. :pypi:`pytest-executable` pytest plugin for testing executables Oct 07, 2023 N/A pytest <8,>=5 :pypi:`pytest-execution-timer` A timer for the phases of Pytest's execution. Dec 24, 2021 4 - Beta N/A :pypi:`pytest-exit-code` A pytest plugin that overrides the built-in exit codes to retain more information about the test results. May 06, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-exit-status` Enhance. Jan 25, 2025 N/A pytest>=8.0.0 :pypi:`pytest-expect` py.test plugin to store test expectations and mark tests based on them Apr 21, 2016 4 - Beta N/A :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-expected` Record and play back your expectations Jan 14, 2025 N/A pytest @@ -537,7 +539,7 @@ This list contains 1574 plugins. :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest - :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI Dec 11, 2024 N/A pytest<8.0.0,>=7.2.1 + :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI Jan 22, 2025 N/A pytest<8.0.0,>=7.2.1 :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) @@ -608,7 +610,7 @@ This list contains 1574 plugins. :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Jul 30, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-freethreaded` pytest plugin for running parallel tests Oct 03, 2024 5 - Production/Stable pytest - :pypi:`pytest-freezeblaster` Wrap tests with fixtures in freeze_time Jul 10, 2024 N/A pytest>=6.2.5 + :pypi:`pytest-freezeblaster` Wrap tests with fixtures in freeze_time Jan 23, 2025 N/A pytest>=6.2.5 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Dec 12, 2024 N/A pytest>=3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -624,13 +626,13 @@ This list contains 1574 plugins. :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Aug 18, 2024 N/A pytest>=7.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-gcs` GCS fixtures and fixture factories for Pytest. Mar 01, 2024 5 - Production/Stable pytest >=6.2 + :pypi:`pytest-gcs` GCS fixtures and fixture factories for Pytest. Jan 24, 2025 5 - Production/Stable pytest>=6.2 :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jan 13, 2025 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-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. Jan 08, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jan 22, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -674,7 +676,7 @@ This list contains 1574 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Jan 10, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Jan 25, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -697,7 +699,7 @@ This list contains 1574 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 11, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Aug 11, 2024 3 - Alpha N/A + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Jan 21, 2025 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Dec 19, 2024 N/A pytest>=8.2.0 :pypi:`pytest-httpx` Send responses to httpx. Nov 28, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -803,7 +805,7 @@ This list contains 1574 plugins. :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Jul 22, 2024 N/A pytest>=7 + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Jan 25, 2025 N/A pytest>=7 :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A @@ -835,7 +837,7 @@ This list contains 1574 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Jan 03, 2025 3 - Alpha pytest + :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Jan 19, 2025 3 - Alpha pytest :pypi:`pytest-logikal` Common testing environment Jan 18, 2025 5 - Production/Stable pytest==8.3.4 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 @@ -872,7 +874,7 @@ This list contains 1574 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Dec 27, 2024 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Jan 23, 2025 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -906,7 +908,7 @@ This list contains 1574 plugins. :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Mar 13, 2024 5 - Production/Stable pytest >=6.2 :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A :pypi:`pytest-mongodb-nono` pytest plugin for MongoDB Jan 07, 2025 N/A N/A - :pypi:`pytest-mongodb-ry` pytest plugin for MongoDB Jan 13, 2025 N/A N/A + :pypi:`pytest-mongodb-ry` pytest plugin for MongoDB Jan 21, 2025 N/A N/A :pypi:`pytest-monitor` Pytest plugin for analyzing resource usage. Jun 25, 2023 5 - Production/Stable pytest :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A @@ -963,6 +965,7 @@ This list contains 1574 plugins. :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Feb 26, 2024 5 - Production/Stable N/A :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 + :pypi:`pytest-oarepo` Jan 22, 2025 N/A pytest>=7.1.2; extra == "local" :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) @@ -1177,7 +1180,7 @@ This list contains 1574 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Jan 09, 2025 N/A pytest>=8.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Jan 25, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1213,7 +1216,7 @@ This list contains 1574 plugins. :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 17, 2024 N/A pytest>=8.3.4 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A - :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments May 14, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Jan 19, 2025 N/A pytest>=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Nov 24, 2024 N/A pytest>=5.3 :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Dec 19, 2024 4 - Beta pytest>=7.0 @@ -1252,7 +1255,7 @@ This list contains 1574 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 14, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 25, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1263,7 +1266,7 @@ This list contains 1574 plugins. :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 Feb 01, 2024 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. Jan 14, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Jan 25, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1401,6 +1404,7 @@ This list contains 1574 plugins. :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A + :pypi:`pytest-teardown` Jan 22, 2025 N/A pytest<9.0.0,>=7.4.1 :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Apr 25, 2024 5 - Production/Stable N/A :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) @@ -1444,7 +1448,7 @@ This list contains 1574 plugins. :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Aug 20, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 :pypi:`pytest-tesults` Tesults plugin for pytest Nov 12, 2024 5 - Production/Stable pytest>=3.5.0 - :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jul 22, 2024 4 - Beta pytest>=8.0.0 + :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jan 23, 2025 5 - Production/Stable pytest>=8.0.0 :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A :pypi:`pytest-tf` Test your OpenTofu and Terraform config using a PyTest plugin May 29, 2024 N/A pytest<9.0.0,>=8.2.1 :pypi:`pytest-th2-bdd` pytest_th2_bdd May 13, 2022 N/A N/A @@ -1452,7 +1456,7 @@ This list contains 1574 plugins. :pypi:`pytest-thread` Jul 07, 2023 N/A N/A :pypi:`pytest-threadleak` Detects thread leaks Jul 03, 2022 4 - Beta pytest (>=3.1.1) :pypi:`pytest-tick` Ticking on tests Aug 31, 2021 5 - Production/Stable pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-time` Aug 28, 2024 3 - Alpha pytest + :pypi:`pytest-time` Jan 20, 2025 3 - Alpha pytest :pypi:`pytest-timeassert-ethan` execution duration Dec 25, 2023 N/A pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A :pypi:`pytest-timeout` pytest plugin to abort hanging tests Mar 07, 2024 5 - Production/Stable pytest >=7.0.0 @@ -1568,7 +1572,7 @@ This list contains 1574 plugins. :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 - :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Jan 15, 2025 N/A pytest<8.0.0,>=7.4.2 + :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Jan 22, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 14, 2024 4 - Beta pytest>=8.2.1 @@ -1725,6 +1729,13 @@ This list contains 1574 plugins. pytest plugin for pytest-repeat that generate aggregate report of the same test cases with additional statistics details. + :pypi:`pytest-ai` + *last release*: Jan 22, 2025, + *status*: N/A, + *requires*: N/A + + A Python package to generate regular, edge-case, and security HTTP tests. + :pypi:`pytest-ai1899` *last release*: Mar 13, 2024, *status*: 5 - Production/Stable, @@ -1761,9 +1772,9 @@ This list contains 1574 plugins. :pypi:`pytest-aiohttp` - *last release*: Sep 06, 2023, + *last release*: Jan 23, 2025, *status*: 4 - Beta, - *requires*: pytest >=6.1.0 + *requires*: pytest>=6.1.0 Pytest plugin for aiohttp support @@ -1922,7 +1933,7 @@ This list contains 1574 plugins. Pytest plugin to allow use of Annotated in tests to resolve fixtures :pypi:`pytest-ansible` - *last release*: Dec 12, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2489,7 +2500,7 @@ This list contains 1574 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jan 16, 2025, + *last release*: Jan 22, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3189,7 +3200,7 @@ This list contains 1574 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Oct 27, 2024, + *last release*: Jan 19, 2025, *status*: N/A, *requires*: pytest<9,>=4 @@ -4407,7 +4418,7 @@ This list contains 1574 plugins. Run pytest --doctest-modules with markdown docstrings in code blocks (\`\`\`) :pypi:`pytest-doctestplus` - *last release*: Nov 25, 2024, + *last release*: Jan 25, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=4.6 @@ -4519,9 +4530,9 @@ This list contains 1574 plugins. Test caching plugin for pytest :pypi:`pytest-dryrun` - *last release*: Jul 18, 2023, + *last release*: Jan 19, 2025, *status*: 5 - Production/Stable, - *requires*: pytest (>=7.4.0,<8.0.0) + *requires*: pytest<9,>=7.40 A Pytest plugin to ignore tests during collection without reporting them in the test summary. @@ -4680,63 +4691,63 @@ This list contains 1574 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Dec 02, 2024, + *last release*: Jan 21, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -4911,7 +4922,7 @@ This list contains 1574 plugins. Pytest Plugin for BDD :pypi:`pytest-evals` - *last release*: Jan 16, 2025, + *last release*: Jan 21, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -5022,6 +5033,13 @@ This list contains 1574 plugins. A pytest plugin that overrides the built-in exit codes to retain more information about the test results. + :pypi:`pytest-exit-status` + *last release*: Jan 25, 2025, + *status*: N/A, + *requires*: pytest>=8.0.0 + + Enhance. + :pypi:`pytest-expect` *last release*: Apr 21, 2016, *status*: 4 - Beta, @@ -5135,7 +5153,7 @@ This list contains 1574 plugins. Additional pytest markers to dynamically enable/disable tests viia CLI flags :pypi:`pytest-f3ts` - *last release*: Dec 11, 2024, + *last release*: Jan 22, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.2.1 @@ -5632,7 +5650,7 @@ This list contains 1574 plugins. pytest plugin for running parallel tests :pypi:`pytest-freezeblaster` - *last release*: Jul 10, 2024, + *last release*: Jan 23, 2025, *status*: N/A, *requires*: pytest>=6.2.5 @@ -5744,9 +5762,9 @@ This list contains 1574 plugins. Uses gcov to measure test coverage of a C library :pypi:`pytest-gcs` - *last release*: Mar 01, 2024, + *last release*: Jan 24, 2025, *status*: 5 - Production/Stable, - *requires*: pytest >=6.2 + *requires*: pytest>=6.2 GCS fixtures and fixture factories for Pytest. @@ -5786,7 +5804,7 @@ This list contains 1574 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jan 08, 2025, + *last release*: Jan 22, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6094,7 +6112,7 @@ This list contains 1574 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jan 10, 2025, + *last release*: Jan 25, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6255,7 +6273,7 @@ This list contains 1574 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest_httpserver` - *last release*: Aug 11, 2024, + *last release*: Jan 21, 2025, *status*: 3 - Alpha, *requires*: N/A @@ -6997,7 +7015,7 @@ This list contains 1574 plugins. It helps to use fixtures in pytest.mark.parametrize :pypi:`pytest-lazy-fixtures` - *last release*: Jul 22, 2024, + *last release*: Jan 25, 2025, *status*: N/A, *requires*: pytest>=7 @@ -7221,7 +7239,7 @@ This list contains 1574 plugins. :pypi:`pytest-logging-strict` - *last release*: Jan 03, 2025, + *last release*: Jan 19, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -7480,7 +7498,7 @@ This list contains 1574 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Dec 27, 2024, + *last release*: Jan 23, 2025, *status*: N/A, *requires*: N/A @@ -7718,7 +7736,7 @@ This list contains 1574 plugins. pytest plugin for MongoDB :pypi:`pytest-mongodb-ry` - *last release*: Jan 13, 2025, + *last release*: Jan 21, 2025, *status*: N/A, *requires*: N/A @@ -8116,6 +8134,13 @@ This list contains 1574 plugins. PyTest plugin for the OAR testing framework + :pypi:`pytest-oarepo` + *last release*: Jan 22, 2025, + *status*: N/A, + *requires*: pytest>=7.1.2; extra == "local" + + + :pypi:`pytest-object-getter` *last release*: Jul 31, 2022, *status*: 5 - Production/Stable, @@ -9615,7 +9640,7 @@ This list contains 1574 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Jan 09, 2025, + *last release*: Jan 25, 2025, *status*: N/A, *requires*: pytest>=8.0.0 @@ -9867,7 +9892,7 @@ This list contains 1574 plugins. A RethinkDB plugin for pytest. :pypi:`pytest-retry` - *last release*: May 14, 2024, + *last release*: Jan 19, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -10140,7 +10165,7 @@ This list contains 1574 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jan 14, 2025, + *last release*: Jan 25, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10217,7 +10242,7 @@ This list contains 1574 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jan 14, 2025, + *last release*: Jan 25, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -11182,6 +11207,13 @@ This list contains 1574 plugins. py.test plugin to introduce block structure in teamcity build log, if output is not captured + :pypi:`pytest-teardown` + *last release*: Jan 22, 2025, + *status*: N/A, + *requires*: pytest<9.0.0,>=7.4.1 + + + :pypi:`pytest-telegram` *last release*: Apr 25, 2024, *status*: 5 - Production/Stable, @@ -11484,8 +11516,8 @@ This list contains 1574 plugins. Tesults plugin for pytest :pypi:`pytest-textual-snapshot` - *last release*: Jul 22, 2024, - *status*: 4 - Beta, + *last release*: Jan 23, 2025, + *status*: 5 - Production/Stable, *requires*: pytest>=8.0.0 Snapshot testing for Textual apps @@ -11540,7 +11572,7 @@ This list contains 1574 plugins. Ticking on tests :pypi:`pytest-time` - *last release*: Aug 28, 2024, + *last release*: Jan 20, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -12352,7 +12384,7 @@ This list contains 1574 plugins. A pytest plugin to list worker statistics after a xdist run. :pypi:`pytest-xdocker` - *last release*: Jan 15, 2025, + *last release*: Jan 22, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.2 From c962c86845aea805f47c33f1c67582640a7d3e6f Mon Sep 17 00:00:00 2001 From: Sadra Barikbin Date: Fri, 31 Jan 2025 16:35:39 +0330 Subject: [PATCH 1092/1271] Update pythonpath.rst (#13181) Fix two tiny typos in `pythonpath.rst` --- doc/en/explanation/pythonpath.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/explanation/pythonpath.rst b/doc/en/explanation/pythonpath.rst index d0314a6dbcd..e68f455cedf 100644 --- a/doc/en/explanation/pythonpath.rst +++ b/doc/en/explanation/pythonpath.rst @@ -8,7 +8,7 @@ pytest import mechanisms and ``sys.path``/``PYTHONPATH`` Import modes ------------ -pytest as a testing framework that needs to import test modules and ``conftest.py`` files for execution. +pytest as a testing framework needs to import test modules and ``conftest.py`` files for execution. Importing files in Python is a non-trivial process, so aspects of the import process can be controlled through the ``--import-mode`` command-line flag, which can assume @@ -78,7 +78,7 @@ these values: For non-test modules, this will work if they are accessible via :py:data:`sys.path`. So for example, ``.env/lib/site-packages/app/core.py`` will be importable as ``app.core``. - This is happens when plugins import non-test modules (for example doctesting). + This happens when plugins import non-test modules (for example doctesting). If this step succeeds, the module is returned. From 5bb569f8432bf99a5b914e4dd297a7ce839eb203 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 2 Feb 2025 19:03:21 -0300 Subject: [PATCH 1093/1271] [automated] Update plugin list (#13184) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 176 ++++++++++++++++++------------- 1 file changed, 100 insertions(+), 76 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 4b1b7241379..2e8bf36500d 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.3 - :pypi:`logassert` Simple but powerful assertion and verification of logged lines. Dec 09, 2024 5 - Production/Stable N/A + :pypi:`logassert` Simple but powerful assertion and verification of logged lines Jan 29, 2025 5 - Production/Stable pytest; extra == "dev" :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A @@ -64,6 +64,7 @@ This list contains 1578 plugins. :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 29, 2024 N/A pytest>=6.0 + :pypi:`pytest-alerts` A pytest plugin for sending test results to Slack and Telegram Feb 01, 2025 4 - Beta pytest>=7.4.0 :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -116,7 +117,7 @@ This list contains 1578 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Jan 08, 2025 4 - Beta pytest<9,>=8.2 + :pypi:`pytest-asyncio` Pytest support for asyncio Jan 28, 2025 4 - Beta pytest<9,>=8.2 :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Jan 17, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -160,7 +161,7 @@ This list contains 1578 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jan 22, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jan 30, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -219,7 +220,7 @@ This list contains 1578 plugins. :pypi:`pytest-cassandra` Cassandra CCM Test Fixtures for pytest Nov 04, 2017 1 - Planning N/A :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A - :pypi:`pytest-cdist` A pytest plugin to split your test suite into multiple parts Jan 07, 2025 N/A pytest>=7 + :pypi:`pytest-cdist` A pytest plugin to split your test suite into multiple parts Jan 30, 2025 N/A pytest>=7 :pypi:`pytest-celery` Pytest plugin for Celery Sep 20, 2024 4 - Beta N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A @@ -253,14 +254,14 @@ This list contains 1578 plugins. :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Nov 08, 2024 5 - Production/Stable N/A - :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Nov 29, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Jan 30, 2025 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Oct 23, 2024 N/A pytest>=3.9 :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Jan 19, 2025 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Jan 29, 2025 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) @@ -271,7 +272,7 @@ This list contains 1578 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jan 09, 2025 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jan 31, 2025 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -292,7 +293,7 @@ This list contains 1578 plugins. :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-continuous` A pytest plugin to run tests continuously until failure or interruption. Apr 23, 2024 N/A N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) - :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Jun 26, 2024 3 - Alpha pytest + :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Jan 31, 2025 3 - Alpha pytest :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A @@ -464,7 +465,7 @@ This list contains 1578 plugins. :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A - :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Dec 05, 2023 5 - Production/Stable pytest >=2.2 + :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Feb 01, 2025 5 - Production/Stable pytest>=6.0 :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Nov 17, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Dec 03, 2024 5 - Production/Stable pytest>=7.0 @@ -473,15 +474,15 @@ This list contains 1578 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 Jul 25, 2024 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. Jan 21, 2025 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 21, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 21, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 21, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Jan 21, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 21, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 21, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 21, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Jan 29, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Jan 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 29, 2025 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) @@ -506,7 +507,7 @@ This list contains 1578 plugins. :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) - :pypi:`pytest-evals` A pytest plugin for running and analyzing LLM evaluation tests Jan 21, 2025 N/A pytest>=7.0.0 + :pypi:`pytest-evals` A pytest plugin for running and analyzing LLM evaluation tests Jan 29, 2025 N/A pytest>=7.0.0 :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A @@ -617,7 +618,7 @@ This list contains 1578 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Dec 12, 2024 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Jan 31, 2025 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A @@ -627,7 +628,7 @@ This list contains 1578 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Jan 24, 2025 5 - Production/Stable pytest>=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jan 13, 2025 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jan 30, 2025 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest @@ -676,7 +677,7 @@ This list contains 1578 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Jan 25, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 01, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -750,7 +751,7 @@ This list contains 1578 plugins. :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipywidgets` Dec 19, 2024 N/A pytest + :pypi:`pytest-ipywidgets` Jan 29, 2025 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Dec 05, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) @@ -838,7 +839,7 @@ This list contains 1578 plugins. :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Jan 19, 2025 3 - Alpha pytest - :pypi:`pytest-logikal` Common testing environment Jan 18, 2025 5 - Production/Stable pytest==8.3.4 + :pypi:`pytest-logikal` Common testing environment Jan 31, 2025 5 - Production/Stable pytest==8.3.4 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" @@ -855,7 +856,7 @@ This list contains 1578 plugins. :pypi:`pytest-mark-manage` 用例标签化管理 Aug 15, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A - :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Sep 27, 2024 N/A N/A + :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Jan 28, 2025 N/A N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Aug 01, 2024 5 - Production/Stable pytest :pypi:`pytest-matchers` Matchers for pytest Aug 26, 2024 N/A pytest<9.0,>=7.0 :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) @@ -927,6 +928,7 @@ This list contains 1578 plugins. :pypi:`pytest-multithreading-allure` pytest_multithreading_allure Nov 25, 2022 N/A N/A :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) + :pypi:`pytest-my-plugin` A pytest plugin that does awesome things Jan 27, 2025 N/A pytest>=6.0 :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Dec 21, 2024 4 - Beta pytest>=7.0.0 @@ -965,7 +967,7 @@ This list contains 1578 plugins. :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Feb 26, 2024 5 - Production/Stable N/A :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 - :pypi:`pytest-oarepo` Jan 22, 2025 N/A pytest>=7.1.2; extra == "local" + :pypi:`pytest-oarepo` Jan 28, 2025 N/A pytest>=7.1.2; extra == "local" :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) @@ -1025,7 +1027,7 @@ This list contains 1578 plugins. :pypi:`pytest-percents` Mar 16, 2024 N/A N/A :pypi:`pytest-perf` Run performance tests against the mainline code. May 20, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-performance` A simple plugin to ensure the execution of critical sections of code has not been impacted Sep 11, 2020 5 - Production/Stable pytest (>=3.7.0) - :pypi:`pytest-performancetotal` A performance plugin for pytest Jan 07, 2025 5 - Production/Stable N/A + :pypi:`pytest-performancetotal` A performance plugin for pytest Feb 01, 2025 5 - Production/Stable N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Aug 21, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 @@ -1045,9 +1047,9 @@ This list contains 1578 plugins. :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Nov 26, 2024 N/A pytest<9.0.0,>=6.2.4 + :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Jan 31, 2025 N/A pytest<9.0.0,>=6.2.4 :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Sep 28, 2024 N/A N/A - :pypi:`pytest-playwright-asyncio` A pytest wrapper with fixtures for Playwright to automate web browsers Nov 26, 2024 N/A pytest<9.0.0,>=6.2.4 + :pypi:`pytest-playwright-asyncio` A pytest wrapper with async fixtures for Playwright to automate web browsers Jan 31, 2025 N/A pytest<9.0.0,>=6.2.4 :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A @@ -1055,7 +1057,7 @@ This list contains 1578 plugins. :pypi:`pytest-plone` Pytest plugin to test Plone addons May 15, 2024 3 - Alpha pytest<8.0.0 :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Mar 26, 2024 5 - Production/Stable pytest>=7.4.2 + :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Jan 31, 2025 5 - Production/Stable pytest>=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A :pypi:`pytest-pogo` Pytest plugin for pogo-migrate Sep 09, 2024 4 - Beta pytest<9,>=7 :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A @@ -1180,7 +1182,7 @@ This list contains 1578 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Jan 25, 2025 N/A pytest>=8.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Feb 01, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1255,18 +1257,19 @@ This list contains 1578 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Jan 25, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 01, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 + :pypi:`pytest-scim2-server` SCIM2 server fixture for Pytest Jan 27, 2025 N/A pytest>=8.3.4 :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-scrutinize` Scrutinize your pytest test suites for slow fixtures, tests and more. Aug 19, 2024 4 - Beta pytest>=6 :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 Feb 01, 2024 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. Jan 25, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Feb 01, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1312,7 +1315,7 @@ This list contains 1578 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A - :pypi:`pytest-smoke` Pytest plugin for smoke testing Jan 10, 2025 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-smoke` Pytest plugin for smoke testing Jan 30, 2025 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -1396,7 +1399,7 @@ This list contains 1578 plugins. :pypi:`pytest-takeltest` Fixtures for ansible, testinfra and molecule Sep 07, 2024 N/A N/A :pypi:`pytest-talisker` Nov 28, 2021 N/A N/A :pypi:`pytest-tally` A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. May 22, 2023 4 - Beta pytest (>=6.2.5) - :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Jul 15, 2023 5 - Production/Stable pytest (>=3.0) + :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Jan 30, 2025 5 - Production/Stable pytest>=3.0 :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) :pypi:`pytest-taskgraph` Add your description here Dec 12, 2024 N/A pytest @@ -1625,11 +1628,11 @@ This list contains 1578 plugins. Python Testing for Databricks :pypi:`logassert` - *last release*: Dec 09, 2024, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest; extra == "dev" - Simple but powerful assertion and verification of logged lines. + Simple but powerful assertion and verification of logged lines :pypi:`logot` *last release*: Mar 23, 2024, @@ -1827,6 +1830,13 @@ This list contains 1578 plugins. A pytest plugin for verifying alembic migrations. + :pypi:`pytest-alerts` + *last release*: Feb 01, 2025, + *status*: 4 - Beta, + *requires*: pytest>=7.4.0 + + A pytest plugin for sending test results to Slack and Telegram + :pypi:`pytest-allclose` *last release*: Jul 30, 2019, *status*: 5 - Production/Stable, @@ -2192,7 +2202,7 @@ This list contains 1578 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jan 08, 2025, + *last release*: Jan 28, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=8.2 @@ -2500,7 +2510,7 @@ This list contains 1578 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jan 22, 2025, + *last release*: Jan 30, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -2913,7 +2923,7 @@ This list contains 1578 plugins. Pytest plugin with server for catching HTTP requests. :pypi:`pytest-cdist` - *last release*: Jan 07, 2025, + *last release*: Jan 30, 2025, *status*: N/A, *requires*: pytest>=7 @@ -3151,7 +3161,7 @@ This list contains 1578 plugins. A cleanup plugin for pytest :pypi:`pytest-clerk` - *last release*: Nov 29, 2024, + *last release*: Jan 30, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -3200,7 +3210,7 @@ This list contains 1578 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Jan 19, 2025, + *last release*: Jan 29, 2025, *status*: N/A, *requires*: pytest<9,>=4 @@ -3277,7 +3287,7 @@ This list contains 1578 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Jan 09, 2025, + *last release*: Jan 31, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3424,7 +3434,7 @@ This list contains 1578 plugins. The pytest plugin for your Cookiecutter templates. 🍪 :pypi:`pytest-copie` - *last release*: Jun 26, 2024, + *last release*: Jan 31, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -4628,9 +4638,9 @@ This list contains 1578 plugins. Pytest execution on EC2 instance :pypi:`pytest-echo` - *last release*: Dec 05, 2023, + *last release*: Feb 01, 2025, *status*: 5 - Production/Stable, - *requires*: pytest >=2.2 + *requires*: pytest>=6.0 pytest plugin with mechanisms for echoing environment variables, package version and generic attributes @@ -4691,63 +4701,63 @@ This list contains 1578 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -4922,7 +4932,7 @@ This list contains 1578 plugins. Pytest Plugin for BDD :pypi:`pytest-evals` - *last release*: Jan 21, 2025, + *last release*: Jan 29, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -5699,7 +5709,7 @@ This list contains 1578 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Dec 12, 2024, + *last release*: Jan 31, 2025, *status*: N/A, *requires*: pytest @@ -5769,7 +5779,7 @@ This list contains 1578 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Jan 13, 2025, + *last release*: Jan 30, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -6112,7 +6122,7 @@ This list contains 1578 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Jan 25, 2025, + *last release*: Feb 01, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6630,7 +6640,7 @@ This list contains 1578 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipywidgets` - *last release*: Dec 19, 2024, + *last release*: Jan 29, 2025, *status*: N/A, *requires*: pytest @@ -7246,7 +7256,7 @@ This list contains 1578 plugins. pytest fixture logging configured from packaged YAML :pypi:`pytest-logikal` - *last release*: Jan 18, 2025, + *last release*: Jan 31, 2025, *status*: 5 - Production/Stable, *requires*: pytest==8.3.4 @@ -7365,7 +7375,7 @@ This list contains 1578 plugins. UNKNOWN :pypi:`pytest-mask-secrets` - *last release*: Sep 27, 2024, + *last release*: Jan 28, 2025, *status*: N/A, *requires*: N/A @@ -7868,6 +7878,13 @@ This list contains 1578 plugins. + :pypi:`pytest-my-plugin` + *last release*: Jan 27, 2025, + *status*: N/A, + *requires*: pytest>=6.0 + + A pytest plugin that does awesome things + :pypi:`pytest-mypy` *last release*: Dec 18, 2022, *status*: 4 - Beta, @@ -8135,7 +8152,7 @@ This list contains 1578 plugins. PyTest plugin for the OAR testing framework :pypi:`pytest-oarepo` - *last release*: Jan 22, 2025, + *last release*: Jan 28, 2025, *status*: N/A, *requires*: pytest>=7.1.2; extra == "local" @@ -8555,7 +8572,7 @@ This list contains 1578 plugins. A simple plugin to ensure the execution of critical sections of code has not been impacted :pypi:`pytest-performancetotal` - *last release*: Jan 07, 2025, + *last release*: Feb 01, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -8695,7 +8712,7 @@ This list contains 1578 plugins. Pytest plugin for reading playbooks. :pypi:`pytest-playwright` - *last release*: Nov 26, 2024, + *last release*: Jan 31, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=6.2.4 @@ -8709,11 +8726,11 @@ This list contains 1578 plugins. ASYNC Pytest plugin for Playwright :pypi:`pytest-playwright-asyncio` - *last release*: Nov 26, 2024, + *last release*: Jan 31, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=6.2.4 - A pytest wrapper with fixtures for Playwright to automate web browsers + A pytest wrapper with async fixtures for Playwright to automate web browsers :pypi:`pytest-playwright-enhanced` *last release*: Mar 24, 2024, @@ -8765,7 +8782,7 @@ This list contains 1578 plugins. A plugin to help developing and testing other plugins :pypi:`pytest-plus` - *last release*: Mar 26, 2024, + *last release*: Jan 31, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.4.2 @@ -9640,7 +9657,7 @@ This list contains 1578 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Jan 25, 2025, + *last release*: Feb 01, 2025, *status*: N/A, *requires*: pytest>=8.0.0 @@ -10165,7 +10182,7 @@ This list contains 1578 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Jan 25, 2025, + *last release*: Feb 01, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10199,6 +10216,13 @@ This list contains 1578 plugins. 👍 Validate return values against a schema-like object in testing + :pypi:`pytest-scim2-server` + *last release*: Jan 27, 2025, + *status*: N/A, + *requires*: pytest>=8.3.4 + + SCIM2 server fixture for Pytest + :pypi:`pytest-screenshot-on-failure` *last release*: Jul 21, 2023, *status*: 4 - Beta, @@ -10242,7 +10266,7 @@ This list contains 1578 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Jan 25, 2025, + *last release*: Feb 01, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10564,7 +10588,7 @@ This list contains 1578 plugins. Automated bad smell detection tool for Pytest :pypi:`pytest-smoke` - *last release*: Jan 10, 2025, + *last release*: Jan 30, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 @@ -11152,9 +11176,9 @@ This list contains 1578 plugins. A Pytest plugin to generate realtime summary stats, and display them in-console using a text-based dashboard. :pypi:`pytest-tap` - *last release*: Jul 15, 2023, + *last release*: Jan 30, 2025, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.0) + *requires*: pytest>=3.0 Test Anything Protocol (TAP) reporting plugin for pytest From 31fd03a67ef759b4cc1ee7119cd199902d270fe3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 06:08:27 +0100 Subject: [PATCH 1094/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#13185) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.25.2 to 0.25.3. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.25.2...v0.25.3) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 4c3c66636ba..3d89d055f2b 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[trio]==4.8.0 django==5.1.5 -pytest-asyncio==0.25.2 +pytest-asyncio==0.25.3 pytest-bdd==8.1.0 pytest-cov==6.0.0 pytest-django==4.9.0 From b4009b31978053fe077a32d219ad947a5ba7243c Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Mon, 3 Feb 2025 14:46:28 +0100 Subject: [PATCH 1095/1271] Add readline workaround for libedit (#13176) * Add readline workaround for libedit We had a very similar workaround before for pyreadline, which had a similar issue: - Introduced in #1281 - Removed in #8848 for #8733 and #8847 This technically will regress the issues above, but those issues just mean that `import readline` is broken in general, so the user should fix it instead (by e.g. uninstalling pyreadline). Fixes #12888 Fixes #13170 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Handle no readline on Windows --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/12888.bugfix.rst | 1 + src/_pytest/capture.py | 18 ++++++++++++++++++ testing/test_capture.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 changelog/12888.bugfix.rst diff --git a/changelog/12888.bugfix.rst b/changelog/12888.bugfix.rst new file mode 100644 index 00000000000..635e35a11ea --- /dev/null +++ b/changelog/12888.bugfix.rst @@ -0,0 +1 @@ +Fixed broken input when using Python 3.13+ and a ``libedit`` build of Python, such as on macOS or with uv-managed Python binaries from the ``python-build-standalone`` project. This could manifest e.g. by a broken prompt when using ``Pdb``, or seeing empty inputs with manual usage of ``input()`` and suspended capturing. diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 5c21590c937..5b64c34e772 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -80,6 +80,23 @@ def _colorama_workaround() -> None: pass +def _readline_workaround() -> None: + """Ensure readline is imported early so it attaches to the correct stdio handles. + + This isn't a problem with the default GNU readline implementation, but in + some configurations, Python uses libedit instead (on macOS, and for prebuilt + binaries such as used by uv). + + In theory this is only needed if readline.backend == "libedit", but the + workaround consists of importing readline here, so we already worked around + the issue by the time we could check if we need to. + """ + try: + import readline # noqa: F401 + except ImportError: + pass + + def _windowsconsoleio_workaround(stream: TextIO) -> None: """Workaround for Windows Unicode console handling. @@ -141,6 +158,7 @@ def pytest_load_initial_conftests(early_config: Config) -> Generator[None]: if ns.capture == "fd": _windowsconsoleio_workaround(sys.stdout) _colorama_workaround() + _readline_workaround() pluginmanager = early_config.pluginmanager capman = CaptureManager(ns.capture) pluginmanager.register(capman, "capturemanager") diff --git a/testing/test_capture.py b/testing/test_capture.py index 98986af6f1f..a59273734c4 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -6,6 +6,7 @@ import io from io import UnsupportedOperation import os +import re import subprocess import sys import textwrap @@ -1666,3 +1667,32 @@ def test_logging(): ) result.stdout.no_fnmatch_line("*Captured stderr call*") result.stdout.no_fnmatch_line("*during collection*") + + +def test_libedit_workaround(pytester: Pytester) -> None: + pytester.makeconftest(""" + import pytest + + + def pytest_terminal_summary(config): + capture = config.pluginmanager.getplugin("capturemanager") + capture.suspend_global_capture(in_=True) + + print("Enter 'hi'") + value = input() + print(f"value: {value!r}") + + capture.resume_global_capture() + """) + readline = pytest.importorskip("readline") + backend = getattr(readline, "backend", readline.__doc__) # added in Python 3.13 + print(f"Readline backend: {backend}") + + child = pytester.spawn_pytest("") + child.expect(r"Enter 'hi'") + child.sendline("hi") + rest = child.read().decode("utf8") + print(rest) + match = re.search(r"^value: '(.*)'\r?$", rest, re.MULTILINE) + assert match is not None + assert match.group(1) == "hi" From afdf03bc23ac24253f851bd3e1b91e776abc506b Mon Sep 17 00:00:00 2001 From: Virendra Patil <70162563+virendrapatil24@users.noreply.github.com> Date: Mon, 3 Feb 2025 19:19:08 +0530 Subject: [PATCH 1096/1271] Fixed invalid regex handling in filterwarnings (#13124) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Thomas Grainger --- changelog/13119.bugfix.rst | 1 + src/_pytest/config/__init__.py | 7 +++++++ testing/test_warnings.py | 23 +++++++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 changelog/13119.bugfix.rst diff --git a/changelog/13119.bugfix.rst b/changelog/13119.bugfix.rst new file mode 100644 index 00000000000..b7e56af9bb8 --- /dev/null +++ b/changelog/13119.bugfix.rst @@ -0,0 +1 @@ +Improved handling of invalid regex patterns for filter warnings by providing a clear error message. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 3db5e3da983..9e5b192b335 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1953,6 +1953,13 @@ def parse_warning_filter( ) from None else: lineno = 0 + try: + re.compile(message) + re.compile(module) + except re.error as e: + raise UsageError( + error_template.format(error=f"Invalid regex {e.pattern!r}: {e}") + ) from None return action, message, category, module, lineno diff --git a/testing/test_warnings.py b/testing/test_warnings.py index d4d0e0b7f93..c302e7c6e3c 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -511,6 +511,29 @@ def test_hidden_by_system(self, pytester: Pytester, monkeypatch) -> None: result = pytester.runpytest_subprocess() assert WARNINGS_SUMMARY_HEADER not in result.stdout.str() + def test_invalid_regex_in_filterwarning(self, pytester: Pytester) -> None: + self.create_file(pytester) + pytester.makeini( + """ + [pytest] + filterwarnings = + ignore::DeprecationWarning:* + """ + ) + result = pytester.runpytest_subprocess() + assert result.ret == pytest.ExitCode.USAGE_ERROR + result.stderr.fnmatch_lines( + [ + "ERROR: while parsing the following warning configuration:", + "", + " ignore::DeprecationWarning:[*]", + "", + "This error occurred:", + "", + "Invalid regex '[*]': nothing to repeat at position 0", + ] + ) + @pytest.mark.skip("not relevant until pytest 9.0") @pytest.mark.parametrize("change_default", [None, "ini", "cmdline"]) From 3930353bb933a579eaa540e7a7267117ba9aa332 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Feb 2025 09:11:25 +0100 Subject: [PATCH 1097/1271] [pre-commit.ci] pre-commit autoupdate (#13190) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.3 → v0.9.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.3...v0.9.4) - [github.com/woodruffw/zizmor-pre-commit: v1.2.2 → v1.3.0](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.2.2...v1.3.0) - [github.com/codespell-project/codespell: v2.4.0 → v2.4.1](https://github.com/codespell-project/codespell/compare/v2.4.0...v2.4.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 527586a1f68..62d72d5e9f3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.3" + rev: "v0.9.4" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.2.2 + rev: v1.3.0 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs @@ -21,7 +21,7 @@ repos: - id: blacken-docs additional_dependencies: [black==24.1.1] - repo: https://github.com/codespell-project/codespell - rev: v2.4.0 + rev: v2.4.1 hooks: - id: codespell args: ["--toml=pyproject.toml"] From 857daa808132a5fd0ef4ea60397c1b53073c3703 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 4 Feb 2025 12:16:47 +0100 Subject: [PATCH 1098/1271] disable gc within the subprocess --- testing/test_unraisableexception.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index 3f191073e2b..328177a7ba3 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -321,6 +321,9 @@ def test_refcycle_unraisable_warning_filter_default(pytester: Pytester) -> None: # see: https://github.com/pytest-dev/pytest/pull/13057#discussion_r1888396126 pytester.makepyfile( test_it=""" + import gc + gc.disable() + import pytest class BrokenDel: @@ -335,8 +338,8 @@ def test_it(): """ ) - with _disable_gc(): - result = pytester.runpytest_subprocess("-Wdefault") + # since we use subprocess we need to disable gc inside test_it + result = pytester.runpytest_subprocess("-Wdefault") assert result.ret == pytest.ExitCode.OK From c93130c1b9048d66551070d28aabe631c0f10b8e Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 4 Feb 2025 13:30:01 +0100 Subject: [PATCH 1099/1271] add RaisesGroup & Matcher --- changelog/11671.feature.rst | 1 + src/_pytest/_raises_group.py | 1003 ++++++++++++++++++++++++++++ src/pytest/__init__.py | 6 + testing/python/raises_group.py | 1137 ++++++++++++++++++++++++++++++++ testing/typing_raises_group.py | 234 +++++++ 5 files changed, 2381 insertions(+) create mode 100644 changelog/11671.feature.rst create mode 100644 src/_pytest/_raises_group.py create mode 100644 testing/python/raises_group.py create mode 100644 testing/typing_raises_group.py diff --git a/changelog/11671.feature.rst b/changelog/11671.feature.rst new file mode 100644 index 00000000000..9e401112ad0 --- /dev/null +++ b/changelog/11671.feature.rst @@ -0,0 +1 @@ +Added `RaisesGroup` (also available as `raises_group`) and `Matcher`, as an equivalent to `raises` for expecting `ExceptionGroup`. It includes the ability to specity multiple different expected exceptions, the structure of nested exception groups, and/or closely emulating `except_star`. diff --git a/src/_pytest/_raises_group.py b/src/_pytest/_raises_group.py new file mode 100644 index 00000000000..68303c4a3fe --- /dev/null +++ b/src/_pytest/_raises_group.py @@ -0,0 +1,1003 @@ +from __future__ import annotations + +from abc import ABC +from abc import abstractmethod +import re +from re import Pattern +import sys +from textwrap import indent +from typing import cast +from typing import final +from typing import Generic +from typing import Literal +from typing import overload +from typing import TYPE_CHECKING + +from _pytest._code import ExceptionInfo +from _pytest.outcomes import fail + + +if TYPE_CHECKING: + from collections.abc import Callable + from collections.abc import Sequence + + # for some reason Sphinx does not play well with 'from types import TracebackType' + import types + + from typing_extensions import TypeGuard + from typing_extensions import TypeVar + + # this conditional definition is because we want to allow a TypeVar default + MatchE = TypeVar( + "MatchE", + bound=BaseException, + default=BaseException, + covariant=True, + ) +else: + from typing import TypeVar + + MatchE = TypeVar("MatchE", bound=BaseException, covariant=True) + +# RaisesGroup doesn't work with a default. +BaseExcT_co = TypeVar("BaseExcT_co", bound=BaseException, covariant=True) +BaseExcT_1 = TypeVar("BaseExcT_1", bound=BaseException) +BaseExcT_2 = TypeVar("BaseExcT_2", bound=BaseException) +ExcT_1 = TypeVar("ExcT_1", bound=Exception) +ExcT_2 = TypeVar("ExcT_2", bound=Exception) + +if sys.version_info < (3, 11): + from exceptiongroup import BaseExceptionGroup + from exceptiongroup import ExceptionGroup + + +# this differs slightly from pytest.ExceptionInfo._stringify_exception +# as we don't want '(1 sub-exception)' when matching group strings +def _stringify_exception(exc: BaseException) -> str: + return "\n".join( + [ + exc.message if isinstance(exc, BaseExceptionGroup) else str(exc), + *getattr(exc, "__notes__", []), + ], + ) + + +# String patterns default to including the unicode flag. +_REGEX_NO_FLAGS = re.compile(r"").flags + + +def _match_pattern(match: Pattern[str]) -> str | Pattern[str]: + """Helper function to remove redundant `re.compile` calls when printing regex""" + return match.pattern if match.flags == _REGEX_NO_FLAGS else match + + +def repr_callable(fun: Callable[[BaseExcT_1], bool]) -> str: + """Get the repr of a ``check`` parameter. + + Split out so it can be monkeypatched (e.g. by hypothesis) + """ + return repr(fun) + + +def _exception_type_name(e: type[BaseException]) -> str: + return repr(e.__name__) + + +def _check_raw_type( + expected_type: type[BaseException] | None, + exception: BaseException, +) -> str | None: + if expected_type is None: + return None + + if not isinstance( + exception, + expected_type, + ): + actual_type_str = _exception_type_name(type(exception)) + expected_type_str = _exception_type_name(expected_type) + if isinstance(exception, BaseExceptionGroup) and not issubclass( + expected_type, BaseExceptionGroup + ): + return f"Unexpected nested {actual_type_str}, expected {expected_type_str}" + return f"{actual_type_str} is not of type {expected_type_str}" + return None + + +class AbstractMatcher(ABC, Generic[BaseExcT_co]): + """ABC with common functionality shared between Matcher and RaisesGroup""" + + def __init__( + self, + match: str | Pattern[str] | None, + check: Callable[[BaseExcT_co], bool] | None, + ) -> None: + if isinstance(match, str): + self.match: Pattern[str] | None = re.compile(match) + else: + self.match = match + self.check = check + self._fail_reason: str | None = None + + # used to suppress repeated printing of `repr(self.check)` + self._nested: bool = False + + @property + def fail_reason(self) -> str | None: + """Set after a call to `matches` to give a human-readable reason for why the match failed. + When used as a context manager the string will be given as the text of an + `Failed`""" + return self._fail_reason + + def _check_check( + self: AbstractMatcher[BaseExcT_1], + exception: BaseExcT_1, + ) -> bool: + if self.check is None: + return True + + if self.check(exception): + return True + + check_repr = "" if self._nested else " " + repr_callable(self.check) + self._fail_reason = f"check{check_repr} did not return True" + return False + + def _check_match(self, e: BaseException) -> bool: + if self.match is None or re.search( + self.match, + stringified_exception := _stringify_exception(e), + ): + return True + + maybe_specify_type = ( + f" of {_exception_type_name(type(e))}" + if isinstance(e, BaseExceptionGroup) + else "" + ) + self._fail_reason = ( + f"Regex pattern {_match_pattern(self.match)!r}" + f" did not match {stringified_exception!r}{maybe_specify_type}" + ) + if _match_pattern(self.match) == stringified_exception: + self._fail_reason += "\n Did you mean to `re.escape()` the regex?" + return False + + @abstractmethod + def matches( + self: AbstractMatcher[BaseExcT_1], exc_val: BaseException + ) -> TypeGuard[BaseExcT_1]: + """Check if an exception matches the requirements of this AbstractMatcher. + If it fails, `AbstractMatcher.fail_reason` should be set. + """ + + +@final +class Matcher(AbstractMatcher[MatchE]): + """Helper class to be used together with RaisesGroups when you want to specify requirements on sub-exceptions. + Only specifying the type is redundant, and it's also unnecessary when the type is a + nested `RaisesGroup` since it supports the same arguments. + The type is checked with `isinstance`, and does not need to be an exact match. + If that is wanted you can use the ``check`` parameter. + :meth:`Matcher.matches` can also be used standalone to check individual exceptions. + + Examples:: + + with RaisesGroups(Matcher(ValueError, match="string")) + ... + with RaisesGroups(Matcher(check=lambda x: x.args == (3, "hello"))): + ... + with RaisesGroups(Matcher(check=lambda x: type(x) is ValueError)): + ... + + Tip: if you install ``hypothesis`` and import it in ``conftest.py`` you will get + readable ``repr``s of ``check`` callables in the output. + """ + + # Trio bundled hypothesis monkeypatching, we will probably instead assume that + # hypothesis will handle that in their pytest plugin by the time this is released. + # Alternatively we could add a version of get_pretty_function_description ourselves + # https://github.com/HypothesisWorks/hypothesis/blob/8ced2f59f5c7bea3344e35d2d53e1f8f8eb9fcd8/hypothesis-python/src/hypothesis/internal/reflection.py#L439 + + # At least one of the three parameters must be passed. + @overload + def __init__( + self: Matcher[MatchE], + exception_type: type[MatchE], + match: str | Pattern[str] = ..., + check: Callable[[MatchE], bool] = ..., + ) -> None: ... + + @overload + def __init__( + self: Matcher[BaseException], # Give E a value. + *, + match: str | Pattern[str], + # If exception_type is not provided, check() must do any typechecks itself. + check: Callable[[BaseException], bool] = ..., + ) -> None: ... + + @overload + def __init__(self, *, check: Callable[[BaseException], bool]) -> None: ... + + def __init__( + self, + exception_type: type[MatchE] | None = None, + match: str | Pattern[str] | None = None, + check: Callable[[MatchE], bool] | None = None, + ): + super().__init__(match, check) + if exception_type is None and match is None and check is None: + raise ValueError("You must specify at least one parameter to match on.") + if exception_type is not None and not issubclass(exception_type, BaseException): + raise TypeError( + f"exception_type {exception_type} must be a subclass of BaseException", + ) + self.exception_type = exception_type + + def matches( + self, + exception: BaseException, + ) -> TypeGuard[MatchE]: + """Check if an exception matches the requirements of this Matcher. + If it fails, `Matcher.fail_reason` will be set. + + Examples:: + + assert Matcher(ValueError).matches(my_exception): + # is equivalent to + assert isinstance(my_exception, ValueError) + + # this can be useful when checking e.g. the ``__cause__`` of an exception. + with pytest.raises(ValueError) as excinfo: + ... + assert Matcher(SyntaxError, match="foo").matches(excinfo.value.__cause__) + # above line is equivalent to + assert isinstance(excinfo.value.__cause__, SyntaxError) + assert re.search("foo", str(excinfo.value.__cause__) + + """ + if not self._check_type(exception): + return False + + if not self._check_match(exception): + return False + + return self._check_check(exception) + + def __repr__(self) -> str: + parameters = [] + if self.exception_type is not None: + parameters.append(self.exception_type.__name__) + if self.match is not None: + # If no flags were specified, discard the redundant re.compile() here. + parameters.append( + f"match={_match_pattern(self.match)!r}", + ) + if self.check is not None: + parameters.append(f"check={repr_callable(self.check)}") + return f"Matcher({', '.join(parameters)})" + + def _check_type(self, exception: BaseException) -> TypeGuard[MatchE]: + self._fail_reason = _check_raw_type(self.exception_type, exception) + return self._fail_reason is None + + +@final +class RaisesGroup(AbstractMatcher[BaseExceptionGroup[BaseExcT_co]]): + """Contextmanager for checking for an expected `ExceptionGroup`. + This works similar to ``pytest.raises``, but allows for specifying the structure of an `ExceptionGroup`. + `ExceptionInfo.group_contains` also tries to handle exception groups, + but it is very bad at checking that you *didn't* get exceptions you didn't expect. + + + The catching behaviour differs from :ref:`except* ` in multiple + different ways, being much stricter by default. + By using ``allow_unwrapped=True`` and ``flatten_subgroups=True`` you can match + ``except*`` fully when expecting a single exception. + + #. All specified exceptions must be present, *and no others*. + + * If you expect a variable number of exceptions you need to use ``pytest.raises(ExceptionGroup)`` and manually + check the contained exceptions. Consider making use of :func:`Matcher.matches`. + + #. It will only catch exceptions wrapped in an exceptiongroup by default. + + * With ``allow_unwrapped=True`` you can specify a single expected exception or `Matcher` and it will match + the exception even if it is not inside an `ExceptionGroup`. + If you expect one of several different exception types you need to use a `Matcher` object. + + #. By default it cares about the full structure with nested `ExceptionGroup`'s. You can specify nested + `ExceptionGroup`'s by passing `RaisesGroup` objects as expected exceptions. + + * With ``flatten_subgroups=True`` it will "flatten" the raised `ExceptionGroup`, + extracting all exceptions inside any nested :class:`ExceptionGroup`, before matching. + + It does not care about the order of the exceptions, so + ``RaisesGroups(ValueError, TypeError)`` + is equivalent to + ``RaisesGroups(TypeError, ValueError)``. + + Examples:: + + with RaisesGroups(ValueError): + raise ExceptionGroup("", (ValueError(),)) + with RaisesGroups( + ValueError, ValueError, Matcher(TypeError, match="expected int") + ): + ... + with RaisesGroups( + KeyboardInterrupt, + match="hello", + check=lambda x: type(x) is BaseExceptionGroup, + ): + ... + with RaisesGroups(RaisesGroups(ValueError)): + raise ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)) + + # flatten_subgroups + with RaisesGroups(ValueError, flatten_subgroups=True): + raise ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)) + + # allow_unwrapped + with RaisesGroups(ValueError, allow_unwrapped=True): + raise ValueError + + + `RaisesGroup.matches` can also be used directly to check a standalone exception group. + + + The matching algorithm is greedy, which means cases such as this may fail:: + + with RaisesGroups(ValueError, Matcher(ValueError, match="hello")): + raise ExceptionGroup("", (ValueError("hello"), ValueError("goodbye"))) + + even though it generally does not care about the order of the exceptions in the group. + To avoid the above you should specify the first ValueError with a Matcher as well. + + Tip: if you install ``hypothesis`` and import it in ``conftest.py`` you will get + readable ``repr``s of ``check`` callables in the output. + """ + + # allow_unwrapped=True requires: singular exception, exception not being + # RaisesGroup instance, match is None, check is None + @overload + def __init__( + self, + exception: type[BaseExcT_co] | Matcher[BaseExcT_co], + *, + allow_unwrapped: Literal[True], + flatten_subgroups: bool = False, + ) -> None: ... + + # flatten_subgroups = True also requires no nested RaisesGroup + @overload + def __init__( + self, + exception: type[BaseExcT_co] | Matcher[BaseExcT_co], + *other_exceptions: type[BaseExcT_co] | Matcher[BaseExcT_co], + flatten_subgroups: Literal[True], + match: str | Pattern[str] | None = None, + check: Callable[[BaseExceptionGroup[BaseExcT_co]], bool] | None = None, + ) -> None: ... + + # simplify the typevars if possible (the following 3 are equivalent but go simpler->complicated) + # ... the first handles RaisesGroup[ValueError], the second RaisesGroup[ExceptionGroup[ValueError]], + # the third RaisesGroup[ValueError | ExceptionGroup[ValueError]]. + # ... otherwise, we will get results like RaisesGroup[ValueError | ExceptionGroup[Never]] (I think) + # (technically correct but misleading) + @overload + def __init__( + self: RaisesGroup[ExcT_1], + exception: type[ExcT_1] | Matcher[ExcT_1], + *other_exceptions: type[ExcT_1] | Matcher[ExcT_1], + match: str | Pattern[str] | None = None, + check: Callable[[ExceptionGroup[ExcT_1]], bool] | None = None, + ) -> None: ... + + @overload + def __init__( + self: RaisesGroup[ExceptionGroup[ExcT_2]], + exception: RaisesGroup[ExcT_2], + *other_exceptions: RaisesGroup[ExcT_2], + match: str | Pattern[str] | None = None, + check: Callable[[ExceptionGroup[ExceptionGroup[ExcT_2]]], bool] | None = None, + ) -> None: ... + + @overload + def __init__( + self: RaisesGroup[ExcT_1 | ExceptionGroup[ExcT_2]], + exception: type[ExcT_1] | Matcher[ExcT_1] | RaisesGroup[ExcT_2], + *other_exceptions: type[ExcT_1] | Matcher[ExcT_1] | RaisesGroup[ExcT_2], + match: str | Pattern[str] | None = None, + check: ( + Callable[[ExceptionGroup[ExcT_1 | ExceptionGroup[ExcT_2]]], bool] | None + ) = None, + ) -> None: ... + + # same as the above 3 but handling BaseException + @overload + def __init__( + self: RaisesGroup[BaseExcT_1], + exception: type[BaseExcT_1] | Matcher[BaseExcT_1], + *other_exceptions: type[BaseExcT_1] | Matcher[BaseExcT_1], + match: str | Pattern[str] | None = None, + check: Callable[[BaseExceptionGroup[BaseExcT_1]], bool] | None = None, + ) -> None: ... + + @overload + def __init__( + self: RaisesGroup[BaseExceptionGroup[BaseExcT_2]], + exception: RaisesGroup[BaseExcT_2], + *other_exceptions: RaisesGroup[BaseExcT_2], + match: str | Pattern[str] | None = None, + check: ( + Callable[[BaseExceptionGroup[BaseExceptionGroup[BaseExcT_2]]], bool] | None + ) = None, + ) -> None: ... + + @overload + def __init__( + self: RaisesGroup[BaseExcT_1 | BaseExceptionGroup[BaseExcT_2]], + exception: type[BaseExcT_1] | Matcher[BaseExcT_1] | RaisesGroup[BaseExcT_2], + *other_exceptions: type[BaseExcT_1] + | Matcher[BaseExcT_1] + | RaisesGroup[BaseExcT_2], + match: str | Pattern[str] | None = None, + check: ( + Callable[ + [BaseExceptionGroup[BaseExcT_1 | BaseExceptionGroup[BaseExcT_2]]], + bool, + ] + | None + ) = None, + ) -> None: ... + + def __init__( + self: RaisesGroup[ExcT_1 | BaseExcT_1 | BaseExceptionGroup[BaseExcT_2]], + exception: type[BaseExcT_1] | Matcher[BaseExcT_1] | RaisesGroup[BaseExcT_2], + *other_exceptions: type[BaseExcT_1] + | Matcher[BaseExcT_1] + | RaisesGroup[BaseExcT_2], + allow_unwrapped: bool = False, + flatten_subgroups: bool = False, + match: str | Pattern[str] | None = None, + check: ( + Callable[[BaseExceptionGroup[BaseExcT_1]], bool] + | Callable[[ExceptionGroup[ExcT_1]], bool] + | None + ) = None, + ): + # The type hint on the `self` and `check` parameters uses different formats + # that are *very* hard to reconcile while adhering to the overloads, so we cast + # it to avoid an error when passing it to super().__init__ + check = cast( + "Callable[[" + "BaseExceptionGroup[ExcT_1|BaseExcT_1|BaseExceptionGroup[BaseExcT_2]]" + "], bool]", + check, + ) + super().__init__(match, check) + self.expected_exceptions: tuple[ + type[BaseExcT_co] | Matcher[BaseExcT_co] | RaisesGroup[BaseException], ... + ] = ( + exception, + *other_exceptions, + ) + self.allow_unwrapped = allow_unwrapped + self.flatten_subgroups: bool = flatten_subgroups + self.is_baseexceptiongroup = False + + if allow_unwrapped and other_exceptions: + raise ValueError( + "You cannot specify multiple exceptions with `allow_unwrapped=True.`" + " If you want to match one of multiple possible exceptions you should" + " use a `Matcher`." + " E.g. `Matcher(check=lambda e: isinstance(e, (...)))`", + ) + if allow_unwrapped and isinstance(exception, RaisesGroup): + raise ValueError( + "`allow_unwrapped=True` has no effect when expecting a `RaisesGroup`." + " You might want it in the expected `RaisesGroup`, or" + " `flatten_subgroups=True` if you don't care about the structure.", + ) + if allow_unwrapped and (match is not None or check is not None): + raise ValueError( + "`allow_unwrapped=True` bypasses the `match` and `check` parameters" + " if the exception is unwrapped. If you intended to match/check the" + " exception you should use a `Matcher` object. If you want to match/check" + " the exceptiongroup when the exception *is* wrapped you need to" + " do e.g. `if isinstance(exc.value, ExceptionGroup):" + " assert RaisesGroup(...).matches(exc.value)` afterwards.", + ) + + # verify `expected_exceptions` and set `self.is_baseexceptiongroup` + for exc in self.expected_exceptions: + if isinstance(exc, RaisesGroup): + if self.flatten_subgroups: + raise ValueError( + "You cannot specify a nested structure inside a RaisesGroup with" + " `flatten_subgroups=True`. The parameter will flatten subgroups" + " in the raised exceptiongroup before matching, which would never" + " match a nested structure.", + ) + self.is_baseexceptiongroup |= exc.is_baseexceptiongroup + exc._nested = True + elif isinstance(exc, Matcher): + if exc.exception_type is not None: + # Matcher __init__ assures it's a subclass of BaseException + self.is_baseexceptiongroup |= not issubclass( + exc.exception_type, + Exception, + ) + exc._nested = True + elif isinstance(exc, type) and issubclass(exc, BaseException): + self.is_baseexceptiongroup |= not issubclass(exc, Exception) + else: + raise TypeError( + f'Invalid argument "{exc!r}" must be exception type, Matcher, or' + " RaisesGroup.", + ) + + @overload + def __enter__( + self: RaisesGroup[ExcT_1], + ) -> ExceptionInfo[ExceptionGroup[ExcT_1]]: ... + @overload + def __enter__( + self: RaisesGroup[BaseExcT_1], + ) -> ExceptionInfo[BaseExceptionGroup[BaseExcT_1]]: ... + + def __enter__(self) -> ExceptionInfo[BaseExceptionGroup[BaseException]]: + self.excinfo: ExceptionInfo[BaseExceptionGroup[BaseExcT_co]] = ( + ExceptionInfo.for_later() + ) + return self.excinfo + + def __repr__(self) -> str: + reqs = [ + e.__name__ if isinstance(e, type) else repr(e) + for e in self.expected_exceptions + ] + if self.allow_unwrapped: + reqs.append(f"allow_unwrapped={self.allow_unwrapped}") + if self.flatten_subgroups: + reqs.append(f"flatten_subgroups={self.flatten_subgroups}") + if self.match is not None: + # If no flags were specified, discard the redundant re.compile() here. + reqs.append(f"match={_match_pattern(self.match)!r}") + if self.check is not None: + reqs.append(f"check={repr_callable(self.check)}") + return f"RaisesGroup({', '.join(reqs)})" + + def _unroll_exceptions( + self, + exceptions: Sequence[BaseException], + ) -> Sequence[BaseException]: + """Used if `flatten_subgroups=True`.""" + res: list[BaseException] = [] + for exc in exceptions: + if isinstance(exc, BaseExceptionGroup): + res.extend(self._unroll_exceptions(exc.exceptions)) + + else: + res.append(exc) + return res + + @overload + def matches( + self: RaisesGroup[ExcT_1], + exc_val: BaseException | None, + ) -> TypeGuard[ExceptionGroup[ExcT_1]]: ... + @overload + def matches( + self: RaisesGroup[BaseExcT_1], + exc_val: BaseException | None, + ) -> TypeGuard[BaseExceptionGroup[BaseExcT_1]]: ... + + def matches( + self, + exc_val: BaseException | None, + ) -> TypeGuard[BaseExceptionGroup[BaseExcT_co]]: + """Check if an exception matches the requirements of this RaisesGroup. + If it fails, `RaisesGroup.fail_reason` will be set. + + Example:: + + with pytest.raises(TypeError) as excinfo: + ... + assert RaisesGroups(ValueError).matches(excinfo.value.__cause__) + # the above line is equivalent to + myexc = excinfo.value.__cause + assert isinstance(myexc, BaseExceptionGroup) + assert len(myexc.exceptions) == 1 + assert isinstance(myexc.exceptions[0], ValueError) + """ + self._fail_reason = None + if exc_val is None: + self._fail_reason = "exception is None" + return False + if not isinstance(exc_val, BaseExceptionGroup): + # we opt to only print type of the exception here, as the repr would + # likely be quite long + not_group_msg = f"{type(exc_val).__name__!r} is not an exception group" + if len(self.expected_exceptions) > 1: + self._fail_reason = not_group_msg + return False + # if we have 1 expected exception, check if it would work even if + # allow_unwrapped is not set + res = self._check_expected(self.expected_exceptions[0], exc_val) + if res is None and self.allow_unwrapped: + return True + + if res is None: + self._fail_reason = ( + f"{not_group_msg}, but would match with `allow_unwrapped=True`" + ) + elif self.allow_unwrapped: + self._fail_reason = res + else: + self._fail_reason = not_group_msg + return False + + actual_exceptions: Sequence[BaseException] = exc_val.exceptions + if self.flatten_subgroups: + actual_exceptions = self._unroll_exceptions(actual_exceptions) + + if not self._check_match(exc_val): + self._fail_reason = cast(str, self._fail_reason) + old_reason = self._fail_reason + if ( + len(actual_exceptions) == len(self.expected_exceptions) == 1 + and isinstance(expected := self.expected_exceptions[0], type) + and isinstance(actual := actual_exceptions[0], expected) + and self._check_match(actual) + ): + assert self.match is not None, "can't be None if _check_match failed" + assert self._fail_reason is old_reason is not None + self._fail_reason += ( + f", but matched the expected {self._repr_expected(expected)}." + f" You might want RaisesGroup(Matcher({expected.__name__}, match={_match_pattern(self.match)!r}))" + ) + else: + self._fail_reason = old_reason + return False + + # do the full check on expected exceptions + if not self._check_exceptions( + exc_val, + actual_exceptions, + ): + self._fail_reason = cast(str, self._fail_reason) + assert self._fail_reason is not None + old_reason = self._fail_reason + # if we're not expecting a nested structure, and there is one, do a second + # pass where we try flattening it + if ( + not self.flatten_subgroups + and not any( + isinstance(e, RaisesGroup) for e in self.expected_exceptions + ) + and any(isinstance(e, BaseExceptionGroup) for e in actual_exceptions) + and self._check_exceptions( + exc_val, + self._unroll_exceptions(exc_val.exceptions), + ) + ): + # only indent if it's a single-line reason. In a multi-line there's already + # indented lines that this does not belong to. + indent = " " if "\n" not in self._fail_reason else "" + self._fail_reason = ( + old_reason + + f"\n{indent}Did you mean to use `flatten_subgroups=True`?" + ) + else: + self._fail_reason = old_reason + return False + + # Only run `self.check` once we know `exc_val` is of the correct type. + if not self._check_check(exc_val): + reason = cast(str, self._fail_reason) + f" on the {type(exc_val).__name__}" + if ( + len(actual_exceptions) == len(self.expected_exceptions) == 1 + and isinstance(expected := self.expected_exceptions[0], type) + # we explicitly break typing here :) + and self._check_check(actual_exceptions[0]) # type: ignore[arg-type] + ): + self._fail_reason = reason + ( + f", but did return True for the expected {self._repr_expected(expected)}." + f" You might want RaisesGroup(Matcher({expected.__name__}, check=<...>))" + ) + else: + self._fail_reason = reason + return False + + return True + + @staticmethod + def _check_expected( + expected_type: ( + type[BaseException] | Matcher[BaseException] | RaisesGroup[BaseException] + ), + exception: BaseException, + ) -> str | None: + """Helper method for `RaisesGroup.matches` and `RaisesGroup._check_exceptions` + to check one of potentially several expected exceptions.""" + if isinstance(expected_type, type): + return _check_raw_type(expected_type, exception) + res = expected_type.matches(exception) + if res: + return None + assert expected_type.fail_reason is not None + if expected_type.fail_reason.startswith("\n"): + return f"\n{expected_type!r}: {indent(expected_type.fail_reason, ' ')}" + return f"{expected_type!r}: {expected_type.fail_reason}" + + @staticmethod + def _repr_expected(e: type[BaseException] | AbstractMatcher[BaseException]) -> str: + """Get the repr of an expected type/Matcher/RaisesGroup, but we only want + the name if it's a type""" + if isinstance(e, type): + return _exception_type_name(e) + return repr(e) + + @overload + def _check_exceptions( + self: RaisesGroup[ExcT_1], + _exc_val: Exception, + actual_exceptions: Sequence[Exception], + ) -> TypeGuard[ExceptionGroup[ExcT_1]]: ... + @overload + def _check_exceptions( + self: RaisesGroup[BaseExcT_1], + _exc_val: BaseException, + actual_exceptions: Sequence[BaseException], + ) -> TypeGuard[BaseExceptionGroup[BaseExcT_1]]: ... + + def _check_exceptions( + self, + _exc_val: BaseException, + actual_exceptions: Sequence[BaseException], + ) -> TypeGuard[BaseExceptionGroup[BaseExcT_co]]: + """Helper method for RaisesGroup.matches that attempts to pair up expected and actual exceptions""" + # full table with all results + results = ResultHolder(self.expected_exceptions, actual_exceptions) + + # (indexes of) raised exceptions that haven't (yet) found an expected + remaining_actual = list(range(len(actual_exceptions))) + # (indexes of) expected exceptions that haven't found a matching raised + failed_expected: list[int] = [] + # successful greedy matches + matches: dict[int, int] = {} + + # loop over expected exceptions first to get a more predictable result + for i_exp, expected in enumerate(self.expected_exceptions): + for i_rem in remaining_actual: + res = self._check_expected(expected, actual_exceptions[i_rem]) + results.set_result(i_exp, i_rem, res) + if res is None: + remaining_actual.remove(i_rem) + matches[i_exp] = i_rem + break + else: + failed_expected.append(i_exp) + + # All exceptions matched up successfully + if not remaining_actual and not failed_expected: + return True + + # in case of a single expected and single raised we simplify the output + if 1 == len(actual_exceptions) == len(self.expected_exceptions): + assert not matches + self._fail_reason = res + return False + + # The test case is failing, so we can do a slow and exhaustive check to find + # duplicate matches etc that will be helpful in debugging + for i_exp, expected in enumerate(self.expected_exceptions): + for i_actual, actual in enumerate(actual_exceptions): + if results.has_result(i_exp, i_actual): + continue + results.set_result( + i_exp, i_actual, self._check_expected(expected, actual) + ) + + successful_str = ( + f"{len(matches)} matched exception{'s' if len(matches) > 1 else ''}. " + if matches + else "" + ) + + # all expected were found + if not failed_expected and results.no_match_for_actual(remaining_actual): + self._fail_reason = ( + f"{successful_str}Unexpected exception(s):" + f" {[actual_exceptions[i] for i in remaining_actual]!r}" + ) + return False + # all raised exceptions were expected + if not remaining_actual and results.no_match_for_expected(failed_expected): + no_match_for_str = ", ".join( + self._repr_expected(self.expected_exceptions[i]) + for i in failed_expected + ) + self._fail_reason = f"{successful_str}Too few exceptions raised, found no match for: [{no_match_for_str}]" + return False + + # if there's only one remaining and one failed, and the unmatched didn't match anything else, + # we elect to only print why the remaining and the failed didn't match. + if ( + 1 == len(remaining_actual) == len(failed_expected) + and results.no_match_for_actual(remaining_actual) + and results.no_match_for_expected(failed_expected) + ): + self._fail_reason = f"{successful_str}{results.get_result(failed_expected[0], remaining_actual[0])}" + return False + + # there's both expected and raised exceptions without matches + s = "" + if matches: + s += f"\n{successful_str}" + indent_1 = " " * 2 + indent_2 = " " * 4 + + if not remaining_actual: + s += "\nToo few exceptions raised!" + elif not failed_expected: + s += "\nUnexpected exception(s)!" + + if failed_expected: + s += "\nThe following expected exceptions did not find a match:" + rev_matches = {v: k for k, v in matches.items()} + for i_failed in failed_expected: + s += ( + f"\n{indent_1}{self._repr_expected(self.expected_exceptions[i_failed])}" + ) + for i_actual, actual in enumerate(actual_exceptions): + if results.get_result(i_exp, i_actual) is None: + # we print full repr of match target + s += ( + f"\n{indent_2}It matches {actual!r} which was paired with " + + self._repr_expected( + self.expected_exceptions[rev_matches[i_actual]] + ) + ) + + if remaining_actual: + s += "\nThe following raised exceptions did not find a match" + for i_actual in remaining_actual: + s += f"\n{indent_1}{actual_exceptions[i_actual]!r}:" + for i_exp, expected in enumerate(self.expected_exceptions): + res = results.get_result(i_exp, i_actual) + if i_exp in failed_expected: + assert res is not None + if res[0] != "\n": + s += "\n" + s += indent(res, indent_2) + if res is None: + # we print full repr of match target + s += ( + f"\n{indent_2}It matches {self._repr_expected(expected)} " + f"which was paired with {actual_exceptions[matches[i_exp]]!r}" + ) + + if len(self.expected_exceptions) == len(actual_exceptions) and possible_match( + results + ): + s += ( + "\nThere exist a possible match when attempting an exhaustive check," + " but RaisesGroup uses a greedy algorithm. " + "Please make your expected exceptions more stringent with `Matcher` etc" + " so the greedy algorithm can function." + ) + self._fail_reason = s + return False + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: types.TracebackType | None, + ) -> bool: + __tracebackhide__ = True + if exc_type is None: + fail(f"DID NOT RAISE any exception, expected {self.expected_type()}") + + assert self.excinfo is not None, ( + "Internal error - should have been constructed in __enter__" + ) + + group_str = ( + "(group)" + if self.allow_unwrapped and not issubclass(exc_type, BaseExceptionGroup) + else "group" + ) + + if not self.matches(exc_val): + fail(f"Raised exception {group_str} did not match: {self._fail_reason}") + + # Cast to narrow the exception type now that it's verified.... + # even though the TypeGuard in self.matches should be narrowing + exc_info = cast( + "tuple[type[BaseExceptionGroup[BaseExcT_co]], BaseExceptionGroup[BaseExcT_co], types.TracebackType]", + (exc_type, exc_val, exc_tb), + ) + self.excinfo.fill_unfilled(exc_info) + return True + + def expected_type(self) -> str: + subexcs = [] + for e in self.expected_exceptions: + if isinstance(e, Matcher): + subexcs.append(str(e)) + elif isinstance(e, RaisesGroup): + subexcs.append(e.expected_type()) + elif isinstance(e, type): + subexcs.append(e.__name__) + else: # pragma: no cover + raise AssertionError("unknown type") + group_type = "Base" if self.is_baseexceptiongroup else "" + return f"{group_type}ExceptionGroup({', '.join(subexcs)})" + + +@final +class NotChecked: + """Singleton for unchecked values in ResultHolder""" + + +class ResultHolder: + """Container for results of checking exceptions. + Used in RaisesGroup._check_exceptions and possible_match. + """ + + def __init__( + self, + expected_exceptions: tuple[ + type[BaseException] | AbstractMatcher[BaseException], ... + ], + actual_exceptions: Sequence[BaseException], + ) -> None: + self.results: list[list[str | type[NotChecked] | None]] = [ + [NotChecked for _ in expected_exceptions] for _ in actual_exceptions + ] + + def set_result(self, expected: int, actual: int, result: str | None) -> None: + self.results[actual][expected] = result + + def get_result(self, expected: int, actual: int) -> str | None: + res = self.results[actual][expected] + assert res is not NotChecked + # mypy doesn't support identity checking against anything but None + return res # type: ignore[return-value] + + def has_result(self, expected: int, actual: int) -> bool: + return self.results[actual][expected] is not NotChecked + + def no_match_for_expected(self, expected: list[int]) -> bool: + for i in expected: + for actual_results in self.results: + assert actual_results[i] is not NotChecked + if actual_results[i] is None: + return False + return True + + def no_match_for_actual(self, actual: list[int]) -> bool: + for i in actual: + for res in self.results[i]: + assert res is not NotChecked + if res is None: + return False + return True + + +def possible_match(results: ResultHolder, used: set[int] | None = None) -> bool: + if used is None: + used = set() + curr_row = len(used) + if curr_row == len(results.results): + return True + + for i, val in enumerate(results.results[curr_row]): + if val is None and i not in used and possible_match(results, used | {i}): + return True + return False diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 70096d6593e..ca2c66fee03 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -6,6 +6,9 @@ from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo +from _pytest._raises_group import Matcher +from _pytest._raises_group import RaisesGroup +from _pytest._raises_group import RaisesGroup as raises_group from _pytest.assertion import register_assert_rewrite from _pytest.cacheprovider import Cache from _pytest.capture import CaptureFixture @@ -113,6 +116,7 @@ "Mark", "MarkDecorator", "MarkGenerator", + "Matcher", "Metafunc", "Module", "MonkeyPatch", @@ -133,6 +137,7 @@ "PytestUnraisableExceptionWarning", "PytestWarning", "Pytester", + "RaisesGroup", "RecordedHookCall", "RunResult", "Session", @@ -162,6 +167,7 @@ "mark", "param", "raises", + "raises_group", "register_assert_rewrite", "set_trace", "skip", diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py new file mode 100644 index 00000000000..c10398d0b9e --- /dev/null +++ b/testing/python/raises_group.py @@ -0,0 +1,1137 @@ +from __future__ import annotations + +# several expected multi-line strings contain long lines. We don't wanna break them up +# as that makes it confusing to see where the line breaks are. +# ruff: noqa: E501 +import re +import sys +from typing import TYPE_CHECKING + +from _pytest._raises_group import Matcher +from _pytest._raises_group import RaisesGroup +from _pytest._raises_group import repr_callable +from _pytest.outcomes import Failed +import pytest + + +if sys.version_info < (3, 11): + from exceptiongroup import BaseExceptionGroup + from exceptiongroup import ExceptionGroup + +if TYPE_CHECKING: + from _pytest.python_api import RaisesContext + + +def wrap_escape(s: str) -> str: + return "^" + re.escape(s) + "$" + + +def fails_raises_group(msg: str, add_prefix: bool = True) -> RaisesContext[Failed]: + assert msg[-1] != "\n", ( + "developer error, expected string should not end with newline" + ) + prefix = "Raised exception group did not match: " if add_prefix else "" + return pytest.raises(Failed, match=wrap_escape(prefix + msg)) + + +def test_raises_group() -> None: + with pytest.raises( + TypeError, + match=wrap_escape( + f'Invalid argument "{ValueError()!r}" must be exception type, Matcher, or RaisesGroup.', + ), + ): + RaisesGroup(ValueError()) # type: ignore[call-overload] + with RaisesGroup(ValueError): + raise ExceptionGroup("foo", (ValueError(),)) + + with ( + fails_raises_group("'SyntaxError' is not of type 'ValueError'"), + RaisesGroup(ValueError), + ): + raise ExceptionGroup("foo", (SyntaxError(),)) + + # multiple exceptions + with RaisesGroup(ValueError, SyntaxError): + raise ExceptionGroup("foo", (ValueError(), SyntaxError())) + + # order doesn't matter + with RaisesGroup(SyntaxError, ValueError): + raise ExceptionGroup("foo", (ValueError(), SyntaxError())) + + # nested exceptions + with RaisesGroup(RaisesGroup(ValueError)): + raise ExceptionGroup("foo", (ExceptionGroup("bar", (ValueError(),)),)) + + with RaisesGroup( + SyntaxError, + RaisesGroup(ValueError), + RaisesGroup(RuntimeError), + ): + raise ExceptionGroup( + "foo", + ( + SyntaxError(), + ExceptionGroup("bar", (ValueError(),)), + ExceptionGroup("", (RuntimeError(),)), + ), + ) + + +def test_incorrect_number_exceptions() -> None: + # We previously gave an error saying the number of exceptions was wrong, + # but we now instead indicate excess/missing exceptions + with ( + fails_raises_group( + "1 matched exception. Unexpected exception(s): [RuntimeError()]" + ), + RaisesGroup(ValueError), + ): + raise ExceptionGroup("", (RuntimeError(), ValueError())) + + # will error if there's missing exceptions + with ( + fails_raises_group( + "1 matched exception. Too few exceptions raised, found no match for: ['SyntaxError']" + ), + RaisesGroup(ValueError, SyntaxError), + ): + raise ExceptionGroup("", (ValueError(),)) + + with ( + fails_raises_group( + "\n" + "1 matched exception. \n" + "Too few exceptions raised!\n" + "The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " It matches ValueError() which was paired with 'ValueError'" + ), + RaisesGroup(ValueError, ValueError), + ): + raise ExceptionGroup("", (ValueError(),)) + + with ( + fails_raises_group( + "\n" + "1 matched exception. \n" + "Unexpected exception(s)!\n" + "The following raised exceptions did not find a match\n" + " ValueError():\n" + " It matches 'ValueError' which was paired with ValueError()" + ), + RaisesGroup(ValueError), + ): + raise ExceptionGroup("", (ValueError(), ValueError())) + + with ( + fails_raises_group( + "\n" + "1 matched exception. \n" + "The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " It matches ValueError() which was paired with 'ValueError'\n" + "The following raised exceptions did not find a match\n" + " SyntaxError():\n" + " 'SyntaxError' is not of type 'ValueError'" + ), + RaisesGroup(ValueError, ValueError), + ): + raise ExceptionGroup("", [ValueError(), SyntaxError()]) + + +def test_flatten_subgroups() -> None: + # loose semantics, as with expect* + with RaisesGroup(ValueError, flatten_subgroups=True): + raise ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)) + + with RaisesGroup(ValueError, TypeError, flatten_subgroups=True): + raise ExceptionGroup("", (ExceptionGroup("", (ValueError(), TypeError())),)) + with RaisesGroup(ValueError, TypeError, flatten_subgroups=True): + raise ExceptionGroup("", [ExceptionGroup("", [ValueError()]), TypeError()]) + + # mixed loose is possible if you want it to be at least N deep + with RaisesGroup(RaisesGroup(ValueError, flatten_subgroups=True)): + raise ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)) + with RaisesGroup(RaisesGroup(ValueError, flatten_subgroups=True)): + raise ExceptionGroup( + "", + (ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)),), + ) + + # but not the other way around + with pytest.raises( + ValueError, + match=r"^You cannot specify a nested structure inside a RaisesGroup with", + ): + RaisesGroup(RaisesGroup(ValueError), flatten_subgroups=True) # type: ignore[call-overload] + + # flatten_subgroups is not sufficient to catch fully unwrapped + with ( + fails_raises_group( + "'ValueError' is not an exception group, but would match with `allow_unwrapped=True`" + ), + RaisesGroup(ValueError, flatten_subgroups=True), + ): + raise ValueError + with ( + fails_raises_group( + "RaisesGroup(ValueError, flatten_subgroups=True): 'ValueError' is not an exception group, but would match with `allow_unwrapped=True`" + ), + RaisesGroup(RaisesGroup(ValueError, flatten_subgroups=True)), + ): + raise ExceptionGroup("", (ValueError(),)) + + # helpful suggestion if flatten_subgroups would make it pass + with ( + fails_raises_group( + "Raised exception group did not match: \n" + "The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " 'TypeError'\n" + "The following raised exceptions did not find a match\n" + " ExceptionGroup('', [ValueError(), TypeError()]):\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Unexpected nested 'ExceptionGroup', expected 'TypeError'\n" + "Did you mean to use `flatten_subgroups=True`?", + add_prefix=False, + ), + RaisesGroup(ValueError, TypeError), + ): + raise ExceptionGroup("", [ExceptionGroup("", [ValueError(), TypeError()])]) + # but doesn't consider check (otherwise we'd break typing guarantees) + with ( + fails_raises_group( + "Raised exception group did not match: \n" + "The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " 'TypeError'\n" + "The following raised exceptions did not find a match\n" + " ExceptionGroup('', [ValueError(), TypeError()]):\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Unexpected nested 'ExceptionGroup', expected 'TypeError'\n" + "Did you mean to use `flatten_subgroups=True`?", + add_prefix=False, + ), + RaisesGroup( + ValueError, + TypeError, + check=lambda eg: len(eg.exceptions) == 1, + ), + ): + raise ExceptionGroup("", [ExceptionGroup("", [ValueError(), TypeError()])]) + # correct number of exceptions, and flatten_subgroups would make it pass + # This now doesn't print a repr of the caught exception at all, but that can be found in the traceback + with ( + fails_raises_group( + "Raised exception group did not match: Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Did you mean to use `flatten_subgroups=True`?", + add_prefix=False, + ), + RaisesGroup(ValueError), + ): + raise ExceptionGroup("", [ExceptionGroup("", [ValueError()])]) + # correct number of exceptions, but flatten_subgroups wouldn't help, so we don't suggest it + with ( + fails_raises_group("Unexpected nested 'ExceptionGroup', expected 'ValueError'"), + RaisesGroup(ValueError), + ): + raise ExceptionGroup("", [ExceptionGroup("", [TypeError()])]) + + # flatten_subgroups can be suggested if nested. This will implicitly ask the user to + # do `RaisesGroup(RaisesGroup(ValueError, flatten_subgroups=True))` which is unlikely + # to be what they actually want - but I don't think it's worth trying to special-case + with ( + fails_raises_group( + "RaisesGroup(ValueError): Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Did you mean to use `flatten_subgroups=True`?", + ), + RaisesGroup(RaisesGroup(ValueError)), + ): + raise ExceptionGroup( + "", + [ExceptionGroup("", [ExceptionGroup("", [ValueError()])])], + ) + + # Don't mention "unexpected nested" if expecting an ExceptionGroup. + # Although it should perhaps be an error to specify `RaisesGroup(ExceptionGroup)` in + # favor of doing `RaisesGroup(RaisesGroup(...))`. + with ( + fails_raises_group("'BaseExceptionGroup' is not of type 'ExceptionGroup'"), + RaisesGroup(ExceptionGroup), + ): + raise BaseExceptionGroup("", [BaseExceptionGroup("", [KeyboardInterrupt()])]) + + +def test_catch_unwrapped_exceptions() -> None: + # Catches lone exceptions with strict=False + # just as except* would + with RaisesGroup(ValueError, allow_unwrapped=True): + raise ValueError + + # expecting multiple unwrapped exceptions is not possible + with pytest.raises( + ValueError, + match=r"^You cannot specify multiple exceptions with", + ): + RaisesGroup(SyntaxError, ValueError, allow_unwrapped=True) # type: ignore[call-overload] + # if users want one of several exception types they need to use a Matcher + # (which the error message suggests) + with RaisesGroup( + Matcher(check=lambda e: isinstance(e, (SyntaxError, ValueError))), + allow_unwrapped=True, + ): + raise ValueError + + # Unwrapped nested `RaisesGroup` is likely a user error, so we raise an error. + with pytest.raises(ValueError, match="has no effect when expecting"): + RaisesGroup(RaisesGroup(ValueError), allow_unwrapped=True) # type: ignore[call-overload] + + # But it *can* be used to check for nesting level +- 1 if they move it to + # the nested RaisesGroup. Users should probably use `Matcher`s instead though. + with RaisesGroup(RaisesGroup(ValueError, allow_unwrapped=True)): + raise ExceptionGroup("", [ExceptionGroup("", [ValueError()])]) + with RaisesGroup(RaisesGroup(ValueError, allow_unwrapped=True)): + raise ExceptionGroup("", [ValueError()]) + + # with allow_unwrapped=False (default) it will not be caught + with ( + fails_raises_group( + "'ValueError' is not an exception group, but would match with `allow_unwrapped=True`" + ), + RaisesGroup(ValueError), + ): + raise ValueError("value error text") + + # allow_unwrapped on its own won't match against nested groups + with ( + fails_raises_group( + "Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Did you mean to use `flatten_subgroups=True`?", + ), + RaisesGroup(ValueError, allow_unwrapped=True), + ): + raise ExceptionGroup("foo", [ExceptionGroup("bar", [ValueError()])]) + + # you need both allow_unwrapped and flatten_subgroups to fully emulate except* + with RaisesGroup(ValueError, allow_unwrapped=True, flatten_subgroups=True): + raise ExceptionGroup("", [ExceptionGroup("", [ValueError()])]) + + # code coverage + with ( + fails_raises_group( + "Raised exception (group) did not match: 'TypeError' is not of type 'ValueError'", + add_prefix=False, + ), + RaisesGroup(ValueError, allow_unwrapped=True), + ): + raise TypeError("this text doesn't show up in the error message") + with ( + fails_raises_group( + "Raised exception (group) did not match: Matcher(ValueError): 'TypeError' is not of type 'ValueError'", + add_prefix=False, + ), + RaisesGroup(Matcher(ValueError), allow_unwrapped=True), + ): + raise TypeError + + # check we don't suggest unwrapping with nested RaisesGroup + with ( + fails_raises_group("'ValueError' is not an exception group"), + RaisesGroup(RaisesGroup(ValueError)), + ): + raise ValueError + + +def test_match() -> None: + # supports match string + with RaisesGroup(ValueError, match="bar"): + raise ExceptionGroup("bar", (ValueError(),)) + + # now also works with ^$ + with RaisesGroup(ValueError, match="^bar$"): + raise ExceptionGroup("bar", (ValueError(),)) + + # it also includes notes + with RaisesGroup(ValueError, match="my note"): + e = ExceptionGroup("bar", (ValueError(),)) + e.add_note("my note") + raise e + + # and technically you can match it all with ^$ + # but you're probably better off using a Matcher at that point + with RaisesGroup(ValueError, match="^bar\nmy note$"): + e = ExceptionGroup("bar", (ValueError(),)) + e.add_note("my note") + raise e + + with ( + fails_raises_group( + "Regex pattern 'foo' did not match 'bar' of 'ExceptionGroup'" + ), + RaisesGroup(ValueError, match="foo"), + ): + raise ExceptionGroup("bar", (ValueError(),)) + + # Suggest a fix for easy pitfall of adding match to the RaisesGroup instead of + # using a Matcher. + # This requires a single expected & raised exception, the expected is a type, + # and `isinstance(raised, expected_type)`. + with ( + fails_raises_group( + "Regex pattern 'foo' did not match 'bar' of 'ExceptionGroup', but matched the expected 'ValueError'. You might want RaisesGroup(Matcher(ValueError, match='foo'))" + ), + RaisesGroup(ValueError, match="foo"), + ): + raise ExceptionGroup("bar", [ValueError("foo")]) + + +def test_check() -> None: + exc = ExceptionGroup("", (ValueError(),)) + + def is_exc(e: ExceptionGroup[ValueError]) -> bool: + return e is exc + + is_exc_repr = repr_callable(is_exc) + with RaisesGroup(ValueError, check=is_exc): + raise exc + + with ( + fails_raises_group( + f"check {is_exc_repr} did not return True on the ExceptionGroup" + ), + RaisesGroup(ValueError, check=is_exc), + ): + raise ExceptionGroup("", (ValueError(),)) + + def is_value_error(e: BaseException) -> bool: + return isinstance(e, ValueError) + + # helpful suggestion if the user thinks the check is for the sub-exception + with ( + fails_raises_group( + f"check {is_value_error} did not return True on the ExceptionGroup, but did return True for the expected 'ValueError'. You might want RaisesGroup(Matcher(ValueError, check=<...>))" + ), + RaisesGroup(ValueError, check=is_value_error), + ): + raise ExceptionGroup("", (ValueError(),)) + + +def test_unwrapped_match_check() -> None: + def my_check(e: object) -> bool: # pragma: no cover + return True + + msg = ( + "`allow_unwrapped=True` bypasses the `match` and `check` parameters" + " if the exception is unwrapped. If you intended to match/check the" + " exception you should use a `Matcher` object. If you want to match/check" + " the exceptiongroup when the exception *is* wrapped you need to" + " do e.g. `if isinstance(exc.value, ExceptionGroup):" + " assert RaisesGroup(...).matches(exc.value)` afterwards." + ) + with pytest.raises(ValueError, match=re.escape(msg)): + RaisesGroup(ValueError, allow_unwrapped=True, match="foo") # type: ignore[call-overload] + with pytest.raises(ValueError, match=re.escape(msg)): + RaisesGroup(ValueError, allow_unwrapped=True, check=my_check) # type: ignore[call-overload] + + # Users should instead use a Matcher + rg = RaisesGroup(Matcher(ValueError, match="^foo$"), allow_unwrapped=True) + with rg: + raise ValueError("foo") + with rg: + raise ExceptionGroup("", [ValueError("foo")]) + + # or if they wanted to match/check the group, do a conditional `.matches()` + with RaisesGroup(ValueError, allow_unwrapped=True) as exc: + raise ExceptionGroup("bar", [ValueError("foo")]) + if isinstance(exc.value, ExceptionGroup): # pragma: no branch + assert RaisesGroup(ValueError, match="bar").matches(exc.value) + + +def test_RaisesGroup_matches() -> None: + rg = RaisesGroup(ValueError) + assert not rg.matches(None) + assert not rg.matches(ValueError()) + assert rg.matches(ExceptionGroup("", (ValueError(),))) + + +def test_message() -> None: + def check_message( + message: str, + body: RaisesGroup[BaseException], + ) -> None: + with ( + pytest.raises( + Failed, + match=f"^DID NOT RAISE any exception, expected {re.escape(message)}$", + ), + body, + ): + ... + + # basic + check_message("ExceptionGroup(ValueError)", RaisesGroup(ValueError)) + # multiple exceptions + check_message( + "ExceptionGroup(ValueError, ValueError)", + RaisesGroup(ValueError, ValueError), + ) + # nested + check_message( + "ExceptionGroup(ExceptionGroup(ValueError))", + RaisesGroup(RaisesGroup(ValueError)), + ) + + # Matcher + check_message( + "ExceptionGroup(Matcher(ValueError, match='my_str'))", + RaisesGroup(Matcher(ValueError, "my_str")), + ) + check_message( + "ExceptionGroup(Matcher(match='my_str'))", + RaisesGroup(Matcher(match="my_str")), + ) + + # BaseExceptionGroup + check_message( + "BaseExceptionGroup(KeyboardInterrupt)", + RaisesGroup(KeyboardInterrupt), + ) + # BaseExceptionGroup with type inside Matcher + check_message( + "BaseExceptionGroup(Matcher(KeyboardInterrupt))", + RaisesGroup(Matcher(KeyboardInterrupt)), + ) + # Base-ness transfers to parent containers + check_message( + "BaseExceptionGroup(BaseExceptionGroup(KeyboardInterrupt))", + RaisesGroup(RaisesGroup(KeyboardInterrupt)), + ) + # but not to child containers + check_message( + "BaseExceptionGroup(BaseExceptionGroup(KeyboardInterrupt), ExceptionGroup(ValueError))", + RaisesGroup(RaisesGroup(KeyboardInterrupt), RaisesGroup(ValueError)), + ) + + +def test_assert_message() -> None: + # the message does not need to list all parameters to RaisesGroup, nor all exceptions + # in the exception group, as those are both visible in the traceback. + # first fails to match + with ( + fails_raises_group("'TypeError' is not of type 'ValueError'"), + RaisesGroup(ValueError), + ): + raise ExceptionGroup("a", [TypeError()]) + with ( + fails_raises_group( + "Raised exception group did not match: \n" + "The following expected exceptions did not find a match:\n" + " RaisesGroup(ValueError)\n" + " RaisesGroup(ValueError, match='a')\n" + "The following raised exceptions did not find a match\n" + " ExceptionGroup('', [RuntimeError()]):\n" + " RaisesGroup(ValueError): 'RuntimeError' is not of type 'ValueError'\n" + " RaisesGroup(ValueError, match='a'): Regex pattern 'a' did not match '' of 'ExceptionGroup'\n" + " RuntimeError():\n" + " RaisesGroup(ValueError): 'RuntimeError' is not an exception group\n" + " RaisesGroup(ValueError, match='a'): 'RuntimeError' is not an exception group", + add_prefix=False, # to see the full structure + ), + RaisesGroup(RaisesGroup(ValueError), RaisesGroup(ValueError, match="a")), + ): + raise ExceptionGroup( + "", + [ExceptionGroup("", [RuntimeError()]), RuntimeError()], + ) + + with ( + fails_raises_group( + "Raised exception group did not match: \n" + "2 matched exceptions. \n" + "The following expected exceptions did not find a match:\n" + " RaisesGroup(RuntimeError)\n" + " RaisesGroup(ValueError)\n" + "The following raised exceptions did not find a match\n" + " RuntimeError():\n" + # " 'RuntimeError' is not of type 'ValueError'\n" + # " Matcher(TypeError): 'RuntimeError' is not of type 'TypeError'\n" + " RaisesGroup(RuntimeError): 'RuntimeError' is not an exception group, but would match with `allow_unwrapped=True`\n" + " RaisesGroup(ValueError): 'RuntimeError' is not an exception group\n" + " ValueError('bar'):\n" + " It matches 'ValueError' which was paired with ValueError('foo')\n" + " RaisesGroup(RuntimeError): 'ValueError' is not an exception group\n" + " RaisesGroup(ValueError): 'ValueError' is not an exception group, but would match with `allow_unwrapped=True`", + add_prefix=False, # to see the full structure + ), + RaisesGroup( + ValueError, + Matcher(TypeError), + RaisesGroup(RuntimeError), + RaisesGroup(ValueError), + ), + ): + raise ExceptionGroup( + "a", + [RuntimeError(), TypeError(), ValueError("foo"), ValueError("bar")], + ) + + with ( + fails_raises_group( + "1 matched exception. 'AssertionError' is not of type 'TypeError'" + ), + RaisesGroup(ValueError, TypeError), + ): + raise ExceptionGroup("a", [ValueError(), AssertionError()]) + + with ( + fails_raises_group( + "Matcher(ValueError): 'TypeError' is not of type 'ValueError'" + ), + RaisesGroup(Matcher(ValueError)), + ): + raise ExceptionGroup("a", [TypeError()]) + + # suggest escaping + with ( + fails_raises_group( + "Raised exception group did not match: Regex pattern 'h(ell)o' did not match 'h(ell)o' of 'ExceptionGroup'\n" + " Did you mean to `re.escape()` the regex?", + add_prefix=False, # to see the full structure + ), + RaisesGroup(ValueError, match="h(ell)o"), + ): + raise ExceptionGroup("h(ell)o", [ValueError()]) + with ( + fails_raises_group( + "Matcher(match='h(ell)o'): Regex pattern 'h(ell)o' did not match 'h(ell)o'\n" + " Did you mean to `re.escape()` the regex?", + ), + RaisesGroup(Matcher(match="h(ell)o")), + ): + raise ExceptionGroup("", [ValueError("h(ell)o")]) + + with ( + fails_raises_group( + "Raised exception group did not match: \n" + "The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " 'ValueError'\n" + " 'ValueError'\n" + " 'ValueError'\n" + "The following raised exceptions did not find a match\n" + " ExceptionGroup('', [ValueError(), TypeError()]):\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'", + add_prefix=False, # to see the full structure + ), + RaisesGroup(ValueError, ValueError, ValueError, ValueError), + ): + raise ExceptionGroup("", [ExceptionGroup("", [ValueError(), TypeError()])]) + + +def test_message_indent() -> None: + with ( + fails_raises_group( + "Raised exception group did not match: \n" + "The following expected exceptions did not find a match:\n" + " RaisesGroup(ValueError, ValueError)\n" + " 'ValueError'\n" + "The following raised exceptions did not find a match\n" + " ExceptionGroup('', [TypeError(), RuntimeError()]):\n" + " RaisesGroup(ValueError, ValueError): \n" + " The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " 'ValueError'\n" + " The following raised exceptions did not find a match\n" + " TypeError():\n" + " 'TypeError' is not of type 'ValueError'\n" + " 'TypeError' is not of type 'ValueError'\n" + " RuntimeError():\n" + " 'RuntimeError' is not of type 'ValueError'\n" + " 'RuntimeError' is not of type 'ValueError'\n" + # TODO: this line is not great, should maybe follow the same format as the other and say + # 'ValueError': Unexpected nested 'ExceptionGroup' (?) + " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " TypeError():\n" + " RaisesGroup(ValueError, ValueError): 'TypeError' is not an exception group\n" + " 'TypeError' is not of type 'ValueError'", + add_prefix=False, + ), + RaisesGroup( + RaisesGroup(ValueError, ValueError), + ValueError, + ), + ): + raise ExceptionGroup( + "", + [ + ExceptionGroup("", [TypeError(), RuntimeError()]), + TypeError(), + ], + ) + with ( + fails_raises_group( + "Raised exception group did not match: \n" + "RaisesGroup(ValueError, ValueError): \n" + " The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " 'ValueError'\n" + " The following raised exceptions did not find a match\n" + " TypeError():\n" + " 'TypeError' is not of type 'ValueError'\n" + " 'TypeError' is not of type 'ValueError'\n" + " RuntimeError():\n" + " 'RuntimeError' is not of type 'ValueError'\n" + " 'RuntimeError' is not of type 'ValueError'", + add_prefix=False, + ), + RaisesGroup( + RaisesGroup(ValueError, ValueError), + ), + ): + raise ExceptionGroup( + "", + [ + ExceptionGroup("", [TypeError(), RuntimeError()]), + ], + ) + + +def test_suggestion_on_nested_and_brief_error() -> None: + # Make sure "Did you mean" suggestion gets indented iff it follows a single-line error + with ( + fails_raises_group( + "\n" + "The following expected exceptions did not find a match:\n" + " RaisesGroup(ValueError)\n" + " 'ValueError'\n" + "The following raised exceptions did not find a match\n" + " ExceptionGroup('', [ExceptionGroup('', [ValueError()])]):\n" + " RaisesGroup(ValueError): Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Did you mean to use `flatten_subgroups=True`?\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'", + ), + RaisesGroup(RaisesGroup(ValueError), ValueError), + ): + raise ExceptionGroup( + "", + [ExceptionGroup("", [ExceptionGroup("", [ValueError()])])], + ) + # if indented here it would look like another raised exception + with ( + fails_raises_group( + "\n" + "The following expected exceptions did not find a match:\n" + " RaisesGroup(ValueError, ValueError)\n" + " 'ValueError'\n" + "The following raised exceptions did not find a match\n" + " ExceptionGroup('', [ValueError(), ExceptionGroup('', [ValueError()])]):\n" + " RaisesGroup(ValueError, ValueError): \n" + " 1 matched exception. \n" + " The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " It matches ValueError() which was paired with 'ValueError'\n" + " The following raised exceptions did not find a match\n" + " ExceptionGroup('', [ValueError()]):\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Did you mean to use `flatten_subgroups=True`?\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'" + ), + RaisesGroup(RaisesGroup(ValueError, ValueError), ValueError), + ): + raise ExceptionGroup( + "", + [ExceptionGroup("", [ValueError(), ExceptionGroup("", [ValueError()])])], + ) + + # re.escape always comes after single-line errors + with ( + fails_raises_group( + "\n" + "The following expected exceptions did not find a match:\n" + " RaisesGroup(Exception, match='^hello')\n" + " 'ValueError'\n" + "The following raised exceptions did not find a match\n" + " ExceptionGroup('^hello', [Exception()]):\n" + " RaisesGroup(Exception, match='^hello'): Regex pattern '^hello' did not match '^hello' of 'ExceptionGroup'\n" + " Did you mean to `re.escape()` the regex?\n" + " Unexpected nested 'ExceptionGroup', expected 'ValueError'" + ), + RaisesGroup(RaisesGroup(Exception, match="^hello"), ValueError), + ): + raise ExceptionGroup("", [ExceptionGroup("^hello", [Exception()])]) + + +def test_assert_message_nested() -> None: + # we only get one instance of aaaaaaaaaa... and bbbbbb..., but we do get multiple instances of ccccc... and dddddd.. + # but I think this now only prints the full repr when that is necessary to disambiguate exceptions + with ( + fails_raises_group( + "Raised exception group did not match: \n" + "The following expected exceptions did not find a match:\n" + " RaisesGroup(ValueError)\n" + " RaisesGroup(RaisesGroup(ValueError))\n" + " RaisesGroup(Matcher(TypeError, match='foo'))\n" + " RaisesGroup(TypeError, ValueError)\n" + "The following raised exceptions did not find a match\n" + " TypeError('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'):\n" + " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" + " RaisesGroup(RaisesGroup(ValueError)): 'TypeError' is not an exception group\n" + " RaisesGroup(Matcher(TypeError, match='foo')): 'TypeError' is not an exception group\n" + " RaisesGroup(TypeError, ValueError): 'TypeError' is not an exception group\n" + " ExceptionGroup('Exceptions from Trio nursery', [TypeError('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb')]):\n" + " RaisesGroup(ValueError): 'TypeError' is not of type 'ValueError'\n" + " RaisesGroup(RaisesGroup(ValueError)): RaisesGroup(ValueError): 'TypeError' is not an exception group\n" + " RaisesGroup(Matcher(TypeError, match='foo')): Matcher(TypeError, match='foo'): Regex pattern 'foo' did not match 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'\n" + " RaisesGroup(TypeError, ValueError): 1 matched exception. Too few exceptions raised, found no match for: ['ValueError']\n" + " ExceptionGroup('Exceptions from Trio nursery', [TypeError('cccccccccccccccccccccccccccccc'), TypeError('dddddddddddddddddddddddddddddd')]):\n" + " RaisesGroup(ValueError): \n" + " The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " The following raised exceptions did not find a match\n" + " TypeError('cccccccccccccccccccccccccccccc'):\n" + " 'TypeError' is not of type 'ValueError'\n" + " TypeError('dddddddddddddddddddddddddddddd'):\n" + " 'TypeError' is not of type 'ValueError'\n" + " RaisesGroup(RaisesGroup(ValueError)): \n" + " The following expected exceptions did not find a match:\n" + " RaisesGroup(ValueError)\n" + " The following raised exceptions did not find a match\n" + " TypeError('cccccccccccccccccccccccccccccc'):\n" + " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" + " TypeError('dddddddddddddddddddddddddddddd'):\n" + " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" + " RaisesGroup(Matcher(TypeError, match='foo')): \n" + " The following expected exceptions did not find a match:\n" + " Matcher(TypeError, match='foo')\n" + " The following raised exceptions did not find a match\n" + " TypeError('cccccccccccccccccccccccccccccc'):\n" + " Matcher(TypeError, match='foo'): Regex pattern 'foo' did not match 'cccccccccccccccccccccccccccccc'\n" + " TypeError('dddddddddddddddddddddddddddddd'):\n" + " Matcher(TypeError, match='foo'): Regex pattern 'foo' did not match 'dddddddddddddddddddddddddddddd'\n" + " RaisesGroup(TypeError, ValueError): \n" + " 1 matched exception. \n" + " The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " The following raised exceptions did not find a match\n" + " TypeError('dddddddddddddddddddddddddddddd'):\n" + " It matches 'TypeError' which was paired with TypeError('cccccccccccccccccccccccccccccc')\n" + " 'TypeError' is not of type 'ValueError'", + add_prefix=False, # to see the full structure + ), + RaisesGroup( + RaisesGroup(ValueError), + RaisesGroup(RaisesGroup(ValueError)), + RaisesGroup(Matcher(TypeError, match="foo")), + RaisesGroup(TypeError, ValueError), + ), + ): + raise ExceptionGroup( + "", + [ + TypeError("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + ExceptionGroup( + "Exceptions from Trio nursery", + [TypeError("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")], + ), + ExceptionGroup( + "Exceptions from Trio nursery", + [ + TypeError("cccccccccccccccccccccccccccccc"), + TypeError("dddddddddddddddddddddddddddddd"), + ], + ), + ], + ) + + +@pytest.mark.skipif( + "hypothesis" in sys.modules, + reason="hypothesis may have monkeypatched _check_repr", +) +def test_check_no_patched_repr() -> None: + # We make `_check_repr` monkeypatchable to avoid this very ugly and verbose + # repr. The other tests that use `check` make use of `_check_repr` so they'll + # continue passing in case it is patched - but we have this one test that + # demonstrates just how nasty it gets otherwise. + match_str = ( + r"^Raised exception group did not match: \n" + r"The following expected exceptions did not find a match:\n" + r" Matcher\(check=. at .*>\)\n" + r" 'TypeError'\n" + r"The following raised exceptions did not find a match\n" + r" ValueError\('foo'\):\n" + r" Matcher\(check=. at .*>\): check did not return True\n" + r" 'ValueError' is not of type 'TypeError'\n" + r" ValueError\('bar'\):\n" + r" Matcher\(check=. at .*>\): check did not return True\n" + r" 'ValueError' is not of type 'TypeError'$" + ) + with ( + pytest.raises(Failed, match=match_str), + RaisesGroup(Matcher(check=lambda x: False), TypeError), + ): + raise ExceptionGroup("", [ValueError("foo"), ValueError("bar")]) + + +def test_misordering_example() -> None: + with ( + fails_raises_group( + "\n" + "3 matched exceptions. \n" + "The following expected exceptions did not find a match:\n" + " Matcher(ValueError, match='foo')\n" + " It matches ValueError('foo') which was paired with 'ValueError'\n" + " It matches ValueError('foo') which was paired with 'ValueError'\n" + " It matches ValueError('foo') which was paired with 'ValueError'\n" + "The following raised exceptions did not find a match\n" + " ValueError('bar'):\n" + " It matches 'ValueError' which was paired with ValueError('foo')\n" + " It matches 'ValueError' which was paired with ValueError('foo')\n" + " It matches 'ValueError' which was paired with ValueError('foo')\n" + " Matcher(ValueError, match='foo'): Regex pattern 'foo' did not match 'bar'\n" + "There exist a possible match when attempting an exhaustive check, but RaisesGroup uses a greedy algorithm. Please make your expected exceptions more stringent with `Matcher` etc so the greedy algorithm can function." + ), + RaisesGroup( + ValueError, ValueError, ValueError, Matcher(ValueError, match="foo") + ), + ): + raise ExceptionGroup( + "", + [ + ValueError("foo"), + ValueError("foo"), + ValueError("foo"), + ValueError("bar"), + ], + ) + + +def test_brief_error_on_one_fail() -> None: + """If only one raised and one expected fail to match up, we print a full table iff + the raised exception would match one of the expected that previously got matched""" + # no also-matched + with ( + fails_raises_group( + "1 matched exception. 'TypeError' is not of type 'RuntimeError'" + ), + RaisesGroup(ValueError, RuntimeError), + ): + raise ExceptionGroup("", [ValueError(), TypeError()]) + + # raised would match an expected + with ( + fails_raises_group( + "\n" + "1 matched exception. \n" + "The following expected exceptions did not find a match:\n" + " 'RuntimeError'\n" + "The following raised exceptions did not find a match\n" + " TypeError():\n" + " It matches 'Exception' which was paired with ValueError()\n" + " 'TypeError' is not of type 'RuntimeError'" + ), + RaisesGroup(Exception, RuntimeError), + ): + raise ExceptionGroup("", [ValueError(), TypeError()]) + + # expected would match a raised + with ( + fails_raises_group( + "\n" + "1 matched exception. \n" + "The following expected exceptions did not find a match:\n" + " 'ValueError'\n" + " It matches ValueError() which was paired with 'ValueError'\n" + "The following raised exceptions did not find a match\n" + " TypeError():\n" + " 'TypeError' is not of type 'ValueError'" + ), + RaisesGroup(ValueError, ValueError), + ): + raise ExceptionGroup("", [ValueError(), TypeError()]) + + +def test_identity_oopsies() -> None: + # it's both possible to have several instances of the same exception in the same group + # and to expect multiple of the same type + # this previously messed up the logic + + with ( + fails_raises_group( + "3 matched exceptions. 'RuntimeError' is not of type 'TypeError'" + ), + RaisesGroup(ValueError, ValueError, ValueError, TypeError), + ): + raise ExceptionGroup( + "", [ValueError(), ValueError(), ValueError(), RuntimeError()] + ) + + e = ValueError("foo") + m = Matcher(match="bar") + with ( + fails_raises_group( + "\n" + "The following expected exceptions did not find a match:\n" + " Matcher(match='bar')\n" + " Matcher(match='bar')\n" + " Matcher(match='bar')\n" + "The following raised exceptions did not find a match\n" + " ValueError('foo'):\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " ValueError('foo'):\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " ValueError('foo'):\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'" + ), + RaisesGroup(m, m, m), + ): + raise ExceptionGroup("", [e, e, e]) + + +def test_matcher() -> None: + with pytest.raises( + ValueError, + match=r"^You must specify at least one parameter to match on.$", + ): + Matcher() # type: ignore[call-overload] + with pytest.raises( + TypeError, + match=f"^exception_type {re.escape(repr(object))} must be a subclass of BaseException$", + ): + Matcher(object) # type: ignore[type-var] + + with RaisesGroup(Matcher(ValueError)): + raise ExceptionGroup("", (ValueError(),)) + with ( + fails_raises_group( + "Matcher(TypeError): 'ValueError' is not of type 'TypeError'" + ), + RaisesGroup(Matcher(TypeError)), + ): + raise ExceptionGroup("", (ValueError(),)) + + +def test_matcher_match() -> None: + with RaisesGroup(Matcher(ValueError, "foo")): + raise ExceptionGroup("", (ValueError("foo"),)) + with ( + fails_raises_group( + "Matcher(ValueError, match='foo'): Regex pattern 'foo' did not match 'bar'" + ), + RaisesGroup(Matcher(ValueError, "foo")), + ): + raise ExceptionGroup("", (ValueError("bar"),)) + + # Can be used without specifying the type + with RaisesGroup(Matcher(match="foo")): + raise ExceptionGroup("", (ValueError("foo"),)) + with ( + fails_raises_group( + "Matcher(match='foo'): Regex pattern 'foo' did not match 'bar'" + ), + RaisesGroup(Matcher(match="foo")), + ): + raise ExceptionGroup("", (ValueError("bar"),)) + + # check ^$ + with RaisesGroup(Matcher(ValueError, match="^bar$")): + raise ExceptionGroup("", [ValueError("bar")]) + with ( + fails_raises_group( + "Matcher(ValueError, match='^bar$'): Regex pattern '^bar$' did not match 'barr'" + ), + RaisesGroup(Matcher(ValueError, match="^bar$")), + ): + raise ExceptionGroup("", [ValueError("barr")]) + + +def test_Matcher_check() -> None: + def check_oserror_and_errno_is_5(e: BaseException) -> bool: + return isinstance(e, OSError) and e.errno == 5 + + with RaisesGroup(Matcher(check=check_oserror_and_errno_is_5)): + raise ExceptionGroup("", (OSError(5, ""),)) + + # specifying exception_type narrows the parameter type to the callable + def check_errno_is_5(e: OSError) -> bool: + return e.errno == 5 + + with RaisesGroup(Matcher(OSError, check=check_errno_is_5)): + raise ExceptionGroup("", (OSError(5, ""),)) + + # avoid printing overly verbose repr multiple times + with ( + fails_raises_group( + f"Matcher(OSError, check={check_errno_is_5!r}): check did not return True" + ), + RaisesGroup(Matcher(OSError, check=check_errno_is_5)), + ): + raise ExceptionGroup("", (OSError(6, ""),)) + + # in nested cases you still get it multiple times though + # to address this you'd need logic in Matcher.__repr__ and RaisesGroup.__repr__ + with ( + fails_raises_group( + f"RaisesGroup(Matcher(OSError, check={check_errno_is_5!r})): Matcher(OSError, check={check_errno_is_5!r}): check did not return True" + ), + RaisesGroup(RaisesGroup(Matcher(OSError, check=check_errno_is_5))), + ): + raise ExceptionGroup("", [ExceptionGroup("", [OSError(6, "")])]) + + +def test_matcher_tostring() -> None: + assert str(Matcher(ValueError)) == "Matcher(ValueError)" + assert str(Matcher(match="[a-z]")) == "Matcher(match='[a-z]')" + pattern_no_flags = re.compile(r"noflag", 0) + assert str(Matcher(match=pattern_no_flags)) == "Matcher(match='noflag')" + pattern_flags = re.compile(r"noflag", re.IGNORECASE) + assert str(Matcher(match=pattern_flags)) == f"Matcher(match={pattern_flags!r})" + assert ( + str(Matcher(ValueError, match="re", check=bool)) + == f"Matcher(ValueError, match='re', check={bool!r})" + ) + + +def test_raisesgroup_tostring() -> None: + def check_str_and_repr(s: str) -> None: + evaled = eval(s) + assert s == str(evaled) == repr(evaled) + + check_str_and_repr("RaisesGroup(ValueError)") + check_str_and_repr("RaisesGroup(RaisesGroup(ValueError))") + check_str_and_repr("RaisesGroup(Matcher(ValueError))") + check_str_and_repr("RaisesGroup(ValueError, allow_unwrapped=True)") + check_str_and_repr("RaisesGroup(ValueError, match='aoeu')") + + assert ( + str(RaisesGroup(ValueError, match="[a-z]", check=bool)) + == f"RaisesGroup(ValueError, match='[a-z]', check={bool!r})" + ) + + +def test_assert_matches() -> None: + e = ValueError() + + # it's easy to do this + assert Matcher(ValueError).matches(e) + + # but you don't get a helpful error + with pytest.raises(AssertionError, match=r"assert False\n \+ where False = .*"): + assert Matcher(TypeError).matches(e) + + # you'd need to do this arcane incantation + with pytest.raises(AssertionError, match="'ValueError' is not of type 'TypeError'"): + assert (m := Matcher(TypeError)).matches(e), m.fail_reason + + # but even if we add assert_matches, will people remember to use it? + # other than writing a linter rule, I don't think we can catch `assert Matcher(...).matches` diff --git a/testing/typing_raises_group.py b/testing/typing_raises_group.py new file mode 100644 index 00000000000..2dc35031dac --- /dev/null +++ b/testing/typing_raises_group.py @@ -0,0 +1,234 @@ +from __future__ import annotations + +import sys +from typing import Callable +from typing import Union + +from typing_extensions import assert_type + +from _pytest._raises_group import Matcher +from _pytest._raises_group import RaisesGroup + + +if sys.version_info < (3, 11): + from exceptiongroup import BaseExceptionGroup + from exceptiongroup import ExceptionGroup + +# split into functions to isolate the different scopes + + +def check_matcher_typevar_default(e: Matcher) -> None: + assert e.exception_type is not None + _exc: type[BaseException] = e.exception_type + # this would previously pass, as the type would be `Any` + e.exception_type().blah() # type: ignore + + +def check_basic_contextmanager() -> None: + with RaisesGroup(ValueError) as e: + raise ExceptionGroup("foo", (ValueError(),)) + assert_type(e.value, ExceptionGroup[ValueError]) + + +def check_basic_matches() -> None: + # check that matches gets rid of the naked ValueError in the union + exc: ExceptionGroup[ValueError] | ValueError = ExceptionGroup("", (ValueError(),)) + if RaisesGroup(ValueError).matches(exc): + assert_type(exc, ExceptionGroup[ValueError]) + + # also check that BaseExceptionGroup shows up for BaseExceptions + if RaisesGroup(KeyboardInterrupt).matches(exc): + assert_type(exc, BaseExceptionGroup[KeyboardInterrupt]) + + +def check_matches_with_different_exception_type() -> None: + e: BaseExceptionGroup[KeyboardInterrupt] = BaseExceptionGroup( + "", + (KeyboardInterrupt(),), + ) + + # note: it might be tempting to have this warn. + # however, that isn't possible with current typing + if RaisesGroup(ValueError).matches(e): + assert_type(e, ExceptionGroup[ValueError]) + + +def check_matcher_init() -> None: + def check_exc(exc: BaseException) -> bool: + return isinstance(exc, ValueError) + + # Check various combinations of constructor signatures. + # At least 1 arg must be provided. + Matcher() # type: ignore + Matcher(ValueError) + Matcher(ValueError, "regex") + Matcher(ValueError, "regex", check_exc) + Matcher(exception_type=ValueError) + Matcher(match="regex") + Matcher(check=check_exc) + Matcher(ValueError, match="regex") + Matcher(match="regex", check=check_exc) + + def check_filenotfound(exc: FileNotFoundError) -> bool: + return not exc.filename.endswith(".tmp") + + # If exception_type is provided, that narrows the `check` method's argument. + Matcher(FileNotFoundError, check=check_filenotfound) + Matcher(ValueError, check=check_filenotfound) # type: ignore + Matcher(check=check_filenotfound) # type: ignore + Matcher(FileNotFoundError, match="regex", check=check_filenotfound) + + +def raisesgroup_check_type_narrowing() -> None: + """Check type narrowing on the `check` argument to `RaisesGroup`. + All `type: ignore`s are correctly pointing out type errors. + """ + + def handle_exc(e: BaseExceptionGroup[BaseException]) -> bool: + return True + + def handle_kbi(e: BaseExceptionGroup[KeyboardInterrupt]) -> bool: + return True + + def handle_value(e: BaseExceptionGroup[ValueError]) -> bool: + return True + + RaisesGroup(BaseException, check=handle_exc) + RaisesGroup(BaseException, check=handle_kbi) # type: ignore + + RaisesGroup(Exception, check=handle_exc) + RaisesGroup(Exception, check=handle_value) # type: ignore + + RaisesGroup(KeyboardInterrupt, check=handle_exc) + RaisesGroup(KeyboardInterrupt, check=handle_kbi) + RaisesGroup(KeyboardInterrupt, check=handle_value) # type: ignore + + RaisesGroup(ValueError, check=handle_exc) + RaisesGroup(ValueError, check=handle_kbi) # type: ignore + RaisesGroup(ValueError, check=handle_value) + + RaisesGroup(ValueError, KeyboardInterrupt, check=handle_exc) + RaisesGroup(ValueError, KeyboardInterrupt, check=handle_kbi) # type: ignore + RaisesGroup(ValueError, KeyboardInterrupt, check=handle_value) # type: ignore + + +def raisesgroup_narrow_baseexceptiongroup() -> None: + """Check type narrowing specifically for the container exceptiongroup.""" + + def handle_group(e: ExceptionGroup[Exception]) -> bool: + return True + + def handle_group_value(e: ExceptionGroup[ValueError]) -> bool: + return True + + RaisesGroup(ValueError, check=handle_group_value) + + RaisesGroup(Exception, check=handle_group) + + +def check_matcher_transparent() -> None: + with RaisesGroup(Matcher(ValueError)) as e: + ... + _: BaseExceptionGroup[ValueError] = e.value + assert_type(e.value, ExceptionGroup[ValueError]) + + +def check_nested_raisesgroups_contextmanager() -> None: + with RaisesGroup(RaisesGroup(ValueError)) as excinfo: + raise ExceptionGroup("foo", (ValueError(),)) + + _: BaseExceptionGroup[BaseExceptionGroup[ValueError]] = excinfo.value + + assert_type( + excinfo.value, + ExceptionGroup[ExceptionGroup[ValueError]], + ) + + assert_type( + excinfo.value.exceptions[0], + # this union is because of how typeshed defines .exceptions + Union[ + ExceptionGroup[ValueError], + ExceptionGroup[ExceptionGroup[ValueError]], + ], + ) + + +def check_nested_raisesgroups_matches() -> None: + """Check nested RaisesGroups with .matches""" + exc: ExceptionGroup[ExceptionGroup[ValueError]] = ExceptionGroup( + "", + (ExceptionGroup("", (ValueError(),)),), + ) + + if RaisesGroup(RaisesGroup(ValueError)).matches(exc): + assert_type(exc, ExceptionGroup[ExceptionGroup[ValueError]]) + + +def check_multiple_exceptions_1() -> None: + a = RaisesGroup(ValueError, ValueError) + b = RaisesGroup(Matcher(ValueError), Matcher(ValueError)) + c = RaisesGroup(ValueError, Matcher(ValueError)) + + d: RaisesGroup[ValueError] + d = a + d = b + d = c + assert d + + +def check_multiple_exceptions_2() -> None: + # This previously failed due to lack of covariance in the TypeVar + a = RaisesGroup(Matcher(ValueError), Matcher(TypeError)) + b = RaisesGroup(Matcher(ValueError), TypeError) + c = RaisesGroup(ValueError, TypeError) + + d: RaisesGroup[Exception] + d = a + d = b + d = c + assert d + + +def check_raisesgroup_overloads() -> None: + # allow_unwrapped=True does not allow: + # multiple exceptions + RaisesGroup(ValueError, TypeError, allow_unwrapped=True) # type: ignore + # nested RaisesGroup + RaisesGroup(RaisesGroup(ValueError), allow_unwrapped=True) # type: ignore + # specifying match + RaisesGroup(ValueError, match="foo", allow_unwrapped=True) # type: ignore + # specifying check + RaisesGroup(ValueError, check=bool, allow_unwrapped=True) # type: ignore + # allowed variants + RaisesGroup(ValueError, allow_unwrapped=True) + RaisesGroup(ValueError, allow_unwrapped=True, flatten_subgroups=True) + RaisesGroup(Matcher(ValueError), allow_unwrapped=True) + + # flatten_subgroups=True does not allow nested RaisesGroup + RaisesGroup(RaisesGroup(ValueError), flatten_subgroups=True) # type: ignore + # but rest is plenty fine + RaisesGroup(ValueError, TypeError, flatten_subgroups=True) + RaisesGroup(ValueError, match="foo", flatten_subgroups=True) + RaisesGroup(ValueError, check=bool, flatten_subgroups=True) + RaisesGroup(ValueError, flatten_subgroups=True) + RaisesGroup(Matcher(ValueError), flatten_subgroups=True) + + # if they're both false we can of course specify nested raisesgroup + RaisesGroup(RaisesGroup(ValueError)) + + +def check_triple_nested_raisesgroup() -> None: + with RaisesGroup(RaisesGroup(RaisesGroup(ValueError))) as e: + assert_type(e.value, ExceptionGroup[ExceptionGroup[ExceptionGroup[ValueError]]]) + + +def check_check_typing() -> None: + # `BaseExceptiongroup` should perhaps be `ExceptionGroup`, but close enough + assert_type( + RaisesGroup(ValueError).check, + Union[ + Callable[[BaseExceptionGroup[ValueError]], bool], + None, + ], + ) From 4737c8cf95eb6b65d936d51479d29dbbfa009575 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 4 Feb 2025 15:33:06 +0100 Subject: [PATCH 1100/1271] add AbstractMatcher support to xfail --- src/_pytest/mark/structures.py | 6 +++++- src/_pytest/skipping.py | 23 +++++++++++++++++++---- testing/python/raises_group.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 1a0b3c5b5b8..b5f54d559e5 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -23,6 +23,7 @@ from .._code import getfslineno from ..compat import NOTSET from ..compat import NotSetType +from _pytest._raises_group import AbstractMatcher from _pytest.config import Config from _pytest.deprecated import check_ispytest from _pytest.deprecated import MARKED_FIXTURE @@ -459,7 +460,10 @@ def __call__( *conditions: str | bool, reason: str = ..., run: bool = ..., - raises: None | type[BaseException] | tuple[type[BaseException], ...] = ..., + raises: None + | type[BaseException] + | tuple[type[BaseException], ...] + | AbstractMatcher[BaseException] = ..., strict: bool = ..., ) -> MarkDecorator: ... diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index d21be181955..0736f48aa45 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -12,6 +12,7 @@ import traceback from typing import Optional +from _pytest._raises_group import AbstractMatcher from _pytest.config import Config from _pytest.config import hookimpl from _pytest.config.argparsing import Parser @@ -201,7 +202,12 @@ class Xfail: reason: str run: bool strict: bool - raises: tuple[type[BaseException], ...] | None + raises: ( + type[BaseException] + | tuple[type[BaseException], ...] + | AbstractMatcher[BaseException] + | None + ) def evaluate_xfail_marks(item: Item) -> Xfail | None: @@ -277,11 +283,20 @@ def pytest_runtest_makereport( elif not rep.skipped and xfailed: if call.excinfo: raises = xfailed.raises - if raises is not None and not isinstance(call.excinfo.value, raises): - rep.outcome = "failed" - else: + if raises is None or ( + ( + isinstance(raises, (type, tuple)) + and isinstance(call.excinfo.value, raises) + ) + or ( + isinstance(raises, AbstractMatcher) + and raises.matches(call.excinfo.value) + ) + ): rep.outcome = "skipped" rep.wasxfail = xfailed.reason + else: + rep.outcome = "failed" elif call.when == "call": if xfailed.strict: rep.outcome = "failed" diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index c10398d0b9e..73715ee1c21 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -11,6 +11,7 @@ from _pytest._raises_group import RaisesGroup from _pytest._raises_group import repr_callable from _pytest.outcomes import Failed +from _pytest.pytester import Pytester import pytest @@ -1135,3 +1136,30 @@ def test_assert_matches() -> None: # but even if we add assert_matches, will people remember to use it? # other than writing a linter rule, I don't think we can catch `assert Matcher(...).matches` + + +# https://github.com/pytest-dev/pytest/issues/12504 +def test_xfail_raisesgroup(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + @pytest.mark.xfail(raises=pytest.RaisesGroup(ValueError)) + def test_foo() -> None: + raise ExceptionGroup("foo", [ValueError()]) + """ + ) + result = pytester.runpytest() + result.assert_outcomes(xfailed=1) + + +def test_xfail_Matcher(pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + @pytest.mark.xfail(raises=pytest.Matcher(ValueError)) + def test_foo() -> None: + raise ValueError + """ + ) + result = pytester.runpytest() + result.assert_outcomes(xfailed=1) From 1f1a10c0da051ada2cbb04d1592d0e14f6de1ac6 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 5 Feb 2025 16:11:40 +0100 Subject: [PATCH 1101/1271] doc: Change training to remote only (#13196) --- doc/en/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 8b34d589643..7f3dbdd800d 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,7 @@ .. sidebar:: **Next Open Trainings and Events** - - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Leipzig (DE) / Remote + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Remote Also see :doc:`previous talks and blogposts ` From e1e1874cda7b8ee51172092158ab774960fa8d6c Mon Sep 17 00:00:00 2001 From: jakkdl <11260241+jakkdl@users.noreply.github.com> Date: Thu, 6 Feb 2025 15:39:25 +0100 Subject: [PATCH 1102/1271] rename AbstractMatcher -> AbstractRaises, Matcher->RaisesExc. Add docs on RaisesGroup&RaisesExc. Add warnings to group_contains. Remove group_contains example from getting-started page --- changelog/11538.feature.rst | 1 + changelog/11671.feature.rst | 1 - changelog/12504.feature.rst | 1 + doc/en/conf.py | 2 + doc/en/getting-started.rst | 26 +---- doc/en/how-to/assert.rst | 89 +++++++++++++- doc/en/reference/reference.rst | 12 ++ src/_pytest/_code/code.py | 7 ++ src/_pytest/_raises_group.py | 126 ++++++++++---------- src/_pytest/mark/structures.py | 4 +- src/_pytest/python_api.py | 5 + src/_pytest/skipping.py | 6 +- src/pytest/__init__.py | 4 +- testing/python/raises_group.py | 208 ++++++++++++++++++--------------- testing/typing_raises_group.py | 48 ++++---- 15 files changed, 325 insertions(+), 215 deletions(-) create mode 100644 changelog/11538.feature.rst delete mode 100644 changelog/11671.feature.rst create mode 100644 changelog/12504.feature.rst diff --git a/changelog/11538.feature.rst b/changelog/11538.feature.rst new file mode 100644 index 00000000000..60f191d05cb --- /dev/null +++ b/changelog/11538.feature.rst @@ -0,0 +1 @@ +Added :class:`pytest.RaisesGroup` (also export as ``pytest.raises_group``) and :class:`pytest.RaisesExc`, as an equivalent to :func:`pytest.raises` for expecting :exc:`ExceptionGroup`. It includes the ability to specify multiple different expected exceptions, the structure of nested exception groups, and flags for emulating :ref:`except* `. See :ref:`assert-matching-exception-groups` and docstrings for more information. diff --git a/changelog/11671.feature.rst b/changelog/11671.feature.rst deleted file mode 100644 index 9e401112ad0..00000000000 --- a/changelog/11671.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added `RaisesGroup` (also available as `raises_group`) and `Matcher`, as an equivalent to `raises` for expecting `ExceptionGroup`. It includes the ability to specity multiple different expected exceptions, the structure of nested exception groups, and/or closely emulating `except_star`. diff --git a/changelog/12504.feature.rst b/changelog/12504.feature.rst new file mode 100644 index 00000000000..d72b97958c2 --- /dev/null +++ b/changelog/12504.feature.rst @@ -0,0 +1 @@ +:func:`pytest.mark.xfail` now accepts :class:`pytest.RaisesGroup` for the ``raises`` parameter when you expect an exception group. You can also pass a :class:`pytest.RaisesExc` if you e.g. want to make use of the ``check`` parameter. diff --git a/doc/en/conf.py b/doc/en/conf.py index 47fc70dce85..c89e14d07fa 100644 --- a/doc/en/conf.py +++ b/doc/en/conf.py @@ -106,6 +106,8 @@ ("py:obj", "_pytest.fixtures.FixtureValue"), ("py:obj", "_pytest.stash.T"), ("py:class", "_ScopeName"), + ("py:class", "BaseExcT_1"), + ("py:class", "ExcT_1"), ] add_module_names = False diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index faf81154c48..73ce82f6b7c 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -97,30 +97,6 @@ Use the :ref:`raises ` helper to assert that some code raises an e with pytest.raises(SystemExit): f() -You can also use the context provided by :ref:`raises ` to -assert that an expected exception is part of a raised :class:`ExceptionGroup`: - -.. code-block:: python - - # content of test_exceptiongroup.py - import pytest - - - def f(): - raise ExceptionGroup( - "Group message", - [ - RuntimeError(), - ], - ) - - - def test_exception_in_group(): - with pytest.raises(ExceptionGroup) as excinfo: - f() - assert excinfo.group_contains(RuntimeError) - assert not excinfo.group_contains(TypeError) - Execute the test function with “quiet” reporting mode: .. code-block:: pytest @@ -133,6 +109,8 @@ Execute the test function with “quiet” reporting mode: The ``-q/--quiet`` flag keeps the output brief in this and following examples. +See :ref:`assertraises` for specifying more details about the expected exception. + Group multiple tests in a class -------------------------------------------------------------- diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 7b027744695..08e030b8cab 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -145,8 +145,93 @@ Notes: .. _`assert-matching-exception-groups`: -Matching exception groups -~~~~~~~~~~~~~~~~~~~~~~~~~ +Assertions about expected exception groups +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When expecting a :exc:`BaseExceptionGroup` or :exc:`ExceptionGroup` you can use :class:`pytest.RaisesGroup`, also available as :class:`pytest.raises_group `: + +.. code-block:: python + + def test_exception_in_group(): + with pytest.raises_group(ValueError): + raise ExceptionGroup("group msg", [ValueError("value msg")]) + with pytest.raises_group(ValueError, TypeError): + raise ExceptionGroup("msg", [ValueError("foo"), TypeError("bar")]) + + +It accepts a ``match`` parameter, that checks against the group message, and a ``check`` parameter that takes an arbitrary callable which it passes the group to, and only succeeds if the callable returns ``True``. + +.. code-block:: python + + def test_raisesgroup_match_and_check(): + with pytest.raises_group(BaseException, match="my group msg"): + raise BaseExceptionGroup("my group msg", [KeyboardInterrupt()]) + with pytest.raises_group( + Exception, check=lambda eg: isinstance(eg.__cause__, ValueError) + ): + raise ExceptionGroup("", [TypeError()]) from ValueError() + +It is strict about structure and unwrapped exceptions, unlike :ref:`except* `, so you might want to set the ``flatten_subgroups`` and/or ``allow_unwrapped`` parameters. + +.. code-block:: python + + def test_structure(): + with pytest.raises_group(pytest.raises_group(ValueError)): + raise ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)) + with pytest.raises_group(ValueError, flatten_subgroups=True): + raise ExceptionGroup("1st group", [ExceptionGroup("2nd group", [ValueError()])]) + with pytest.raises_group(ValueError, allow_unwrapped=True): + raise ValueError + +To specify more details about the contained exception you can use :class:`pytest.RaisesExc` + +.. code-block:: python + + def test_raises_exc(): + with pytest.raises_group(pytest.RaisesExc(ValueError, match="foo")): + raise ExceptionGroup("", (ValueError("foo"))) + +They both supply a method :meth:`pytest.RaisesGroup.matches` :meth:`pytest.RaisesExc.matches` if you want to do matching outside of using it as a contextmanager. This can be helpful when checking ``.__context__`` or ``.__cause__``. + +.. code-block:: python + + def test_matches(): + exc = ValueError() + exc_group = ExceptionGroup("", [exc]) + if RaisesGroup(ValueError).matches(exc_group): + ... + # helpful error is available in `.fail_reason` if it fails to match + r = RaisesExc(ValueError) + assert r.matches(e), r.fail_reason + +Check the documentation on :class:`pytest.RaisesGroup` and :class:`pytest.RaisesExc` for more details and examples. + +``ExceptionInfo.group_contains()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. warning:: + + This helper makes it easy to check for the presence of specific exceptions, but it is very bad for checking that the group does *not* contain *any other exceptions*. So this will pass: + + .. code-block:: python + + class EXTREMELYBADERROR(BaseException): + """This is a very bad error to miss""" + + + def test_for_value_error(): + with pytest.raises(ExceptionGroup) as excinfo: + excs = [ValueError()] + if very_unlucky(): + excs.append(EXTREMELYBADERROR()) + raise ExceptionGroup("", excs) + # this passes regardless of if there's other exceptions + assert excinfo.group_contains(ValueError) + # you can't simply list all exceptions you *don't* want to get here + + + There is no good way of using :func:`excinfo.group_contains() ` to ensure you're not getting *any* other exceptions than the one you expected. + You should instead use :class:`pytest.raises_group `, see :ref:`assert-matching-exception-groups`. You can also use the :func:`excinfo.group_contains() ` method to test for exceptions returned as part of an :class:`ExceptionGroup`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 809e97b4747..d7cf09100b7 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1014,6 +1014,18 @@ PytestPluginManager :inherited-members: :show-inheritance: +RaisesExc +~~~~~~~~~ + +.. autoclass:: pytest.RaisesExc() + :members: + +RaisesGroup +~~~~~~~~~~~ + +.. autoclass:: pytest.RaisesGroup() + :members: + TerminalReporter ~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index f812f0633c8..5b85d295d36 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -828,6 +828,13 @@ def group_contains( the exceptions contained within the topmost exception group). .. versionadded:: 8.0 + + .. warning:: + This helper makes it easy to check for the presence of specific exceptions, + but it is very bad for checking that the group does *not* contain + *any other exceptions*. + You should instead consider using :class:`pytest.raises_group ` + """ msg = "Captured exception is not an instance of `BaseExceptionGroup`" assert isinstance(self.value, BaseExceptionGroup), msg diff --git a/src/_pytest/_raises_group.py b/src/_pytest/_raises_group.py index 68303c4a3fe..db4e51fc211 100644 --- a/src/_pytest/_raises_group.py +++ b/src/_pytest/_raises_group.py @@ -28,8 +28,8 @@ from typing_extensions import TypeVar # this conditional definition is because we want to allow a TypeVar default - MatchE = TypeVar( - "MatchE", + BaseExcT_co_default = TypeVar( + "BaseExcT_co_default", bound=BaseException, default=BaseException, covariant=True, @@ -37,7 +37,9 @@ else: from typing import TypeVar - MatchE = TypeVar("MatchE", bound=BaseException, covariant=True) + BaseExcT_co_default = TypeVar( + "BaseExcT_co_default", bound=BaseException, covariant=True + ) # RaisesGroup doesn't work with a default. BaseExcT_co = TypeVar("BaseExcT_co", bound=BaseException, covariant=True) @@ -104,8 +106,8 @@ def _check_raw_type( return None -class AbstractMatcher(ABC, Generic[BaseExcT_co]): - """ABC with common functionality shared between Matcher and RaisesGroup""" +class AbstractRaises(ABC, Generic[BaseExcT_co]): + """ABC with common functionality shared between RaisesExc and RaisesGroup""" def __init__( self, @@ -130,7 +132,7 @@ def fail_reason(self) -> str | None: return self._fail_reason def _check_check( - self: AbstractMatcher[BaseExcT_1], + self: AbstractRaises[BaseExcT_1], exception: BaseExcT_1, ) -> bool: if self.check is None: @@ -165,29 +167,29 @@ def _check_match(self, e: BaseException) -> bool: @abstractmethod def matches( - self: AbstractMatcher[BaseExcT_1], exc_val: BaseException + self: AbstractRaises[BaseExcT_1], exc_val: BaseException ) -> TypeGuard[BaseExcT_1]: - """Check if an exception matches the requirements of this AbstractMatcher. - If it fails, `AbstractMatcher.fail_reason` should be set. + """Check if an exception matches the requirements of this AbstractRaises. + If it fails, `AbstractRaises.fail_reason` should be set. """ @final -class Matcher(AbstractMatcher[MatchE]): +class RaisesExc(AbstractRaises[BaseExcT_co_default]): """Helper class to be used together with RaisesGroups when you want to specify requirements on sub-exceptions. Only specifying the type is redundant, and it's also unnecessary when the type is a nested `RaisesGroup` since it supports the same arguments. The type is checked with `isinstance`, and does not need to be an exact match. If that is wanted you can use the ``check`` parameter. - :meth:`Matcher.matches` can also be used standalone to check individual exceptions. + :meth:`RaisesExc.matches` can also be used standalone to check individual exceptions. Examples:: - with RaisesGroups(Matcher(ValueError, match="string")) + with RaisesGroups(RaisesExc(ValueError, match="string")) ... - with RaisesGroups(Matcher(check=lambda x: x.args == (3, "hello"))): + with RaisesGroups(RaisesExc(check=lambda x: x.args == (3, "hello"))): ... - with RaisesGroups(Matcher(check=lambda x: type(x) is ValueError)): + with RaisesGroups(RaisesExc(check=lambda x: type(x) is ValueError)): ... Tip: if you install ``hypothesis`` and import it in ``conftest.py`` you will get @@ -202,15 +204,15 @@ class Matcher(AbstractMatcher[MatchE]): # At least one of the three parameters must be passed. @overload def __init__( - self: Matcher[MatchE], - exception_type: type[MatchE], + self: RaisesExc[BaseExcT_co_default], + exception_type: type[BaseExcT_co_default], match: str | Pattern[str] = ..., - check: Callable[[MatchE], bool] = ..., + check: Callable[[BaseExcT_co_default], bool] = ..., ) -> None: ... @overload def __init__( - self: Matcher[BaseException], # Give E a value. + self: RaisesExc[BaseException], # Give E a value. *, match: str | Pattern[str], # If exception_type is not provided, check() must do any typechecks itself. @@ -222,9 +224,9 @@ def __init__(self, *, check: Callable[[BaseException], bool]) -> None: ... def __init__( self, - exception_type: type[MatchE] | None = None, + exception_type: type[BaseExcT_co_default] | None = None, match: str | Pattern[str] | None = None, - check: Callable[[MatchE], bool] | None = None, + check: Callable[[BaseExcT_co_default], bool] | None = None, ): super().__init__(match, check) if exception_type is None and match is None and check is None: @@ -238,20 +240,20 @@ def __init__( def matches( self, exception: BaseException, - ) -> TypeGuard[MatchE]: - """Check if an exception matches the requirements of this Matcher. - If it fails, `Matcher.fail_reason` will be set. + ) -> TypeGuard[BaseExcT_co_default]: + """Check if an exception matches the requirements of this RaisesExc. + If it fails, `RaisesExc.fail_reason` will be set. Examples:: - assert Matcher(ValueError).matches(my_exception): + assert RaisesExc(ValueError).matches(my_exception): # is equivalent to assert isinstance(my_exception, ValueError) # this can be useful when checking e.g. the ``__cause__`` of an exception. with pytest.raises(ValueError) as excinfo: ... - assert Matcher(SyntaxError, match="foo").matches(excinfo.value.__cause__) + assert RaisesExc(SyntaxError, match="foo").matches(excinfo.value.__cause__) # above line is equivalent to assert isinstance(excinfo.value.__cause__, SyntaxError) assert re.search("foo", str(excinfo.value.__cause__) @@ -276,15 +278,15 @@ def __repr__(self) -> str: ) if self.check is not None: parameters.append(f"check={repr_callable(self.check)}") - return f"Matcher({', '.join(parameters)})" + return f"RaisesExc({', '.join(parameters)})" - def _check_type(self, exception: BaseException) -> TypeGuard[MatchE]: + def _check_type(self, exception: BaseException) -> TypeGuard[BaseExcT_co_default]: self._fail_reason = _check_raw_type(self.exception_type, exception) return self._fail_reason is None @final -class RaisesGroup(AbstractMatcher[BaseExceptionGroup[BaseExcT_co]]): +class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): """Contextmanager for checking for an expected `ExceptionGroup`. This works similar to ``pytest.raises``, but allows for specifying the structure of an `ExceptionGroup`. `ExceptionInfo.group_contains` also tries to handle exception groups, @@ -299,13 +301,13 @@ class RaisesGroup(AbstractMatcher[BaseExceptionGroup[BaseExcT_co]]): #. All specified exceptions must be present, *and no others*. * If you expect a variable number of exceptions you need to use ``pytest.raises(ExceptionGroup)`` and manually - check the contained exceptions. Consider making use of :func:`Matcher.matches`. + check the contained exceptions. Consider making use of :func:`RaisesExc.matches`. #. It will only catch exceptions wrapped in an exceptiongroup by default. - * With ``allow_unwrapped=True`` you can specify a single expected exception or `Matcher` and it will match + * With ``allow_unwrapped=True`` you can specify a single expected exception or `RaisesExc` and it will match the exception even if it is not inside an `ExceptionGroup`. - If you expect one of several different exception types you need to use a `Matcher` object. + If you expect one of several different exception types you need to use a `RaisesExc` object. #. By default it cares about the full structure with nested `ExceptionGroup`'s. You can specify nested `ExceptionGroup`'s by passing `RaisesGroup` objects as expected exceptions. @@ -323,7 +325,7 @@ class RaisesGroup(AbstractMatcher[BaseExceptionGroup[BaseExcT_co]]): with RaisesGroups(ValueError): raise ExceptionGroup("", (ValueError(),)) with RaisesGroups( - ValueError, ValueError, Matcher(TypeError, match="expected int") + ValueError, ValueError, RaisesExc(TypeError, match="expected int") ): ... with RaisesGroups( @@ -349,11 +351,11 @@ class RaisesGroup(AbstractMatcher[BaseExceptionGroup[BaseExcT_co]]): The matching algorithm is greedy, which means cases such as this may fail:: - with RaisesGroups(ValueError, Matcher(ValueError, match="hello")): + with RaisesGroups(ValueError, RaisesExc(ValueError, match="hello")): raise ExceptionGroup("", (ValueError("hello"), ValueError("goodbye"))) even though it generally does not care about the order of the exceptions in the group. - To avoid the above you should specify the first ValueError with a Matcher as well. + To avoid the above you should specify the first ValueError with a RaisesExc as well. Tip: if you install ``hypothesis`` and import it in ``conftest.py`` you will get readable ``repr``s of ``check`` callables in the output. @@ -364,7 +366,7 @@ class RaisesGroup(AbstractMatcher[BaseExceptionGroup[BaseExcT_co]]): @overload def __init__( self, - exception: type[BaseExcT_co] | Matcher[BaseExcT_co], + exception: type[BaseExcT_co] | RaisesExc[BaseExcT_co], *, allow_unwrapped: Literal[True], flatten_subgroups: bool = False, @@ -374,8 +376,8 @@ def __init__( @overload def __init__( self, - exception: type[BaseExcT_co] | Matcher[BaseExcT_co], - *other_exceptions: type[BaseExcT_co] | Matcher[BaseExcT_co], + exception: type[BaseExcT_co] | RaisesExc[BaseExcT_co], + *other_exceptions: type[BaseExcT_co] | RaisesExc[BaseExcT_co], flatten_subgroups: Literal[True], match: str | Pattern[str] | None = None, check: Callable[[BaseExceptionGroup[BaseExcT_co]], bool] | None = None, @@ -389,8 +391,8 @@ def __init__( @overload def __init__( self: RaisesGroup[ExcT_1], - exception: type[ExcT_1] | Matcher[ExcT_1], - *other_exceptions: type[ExcT_1] | Matcher[ExcT_1], + exception: type[ExcT_1] | RaisesExc[ExcT_1], + *other_exceptions: type[ExcT_1] | RaisesExc[ExcT_1], match: str | Pattern[str] | None = None, check: Callable[[ExceptionGroup[ExcT_1]], bool] | None = None, ) -> None: ... @@ -407,8 +409,8 @@ def __init__( @overload def __init__( self: RaisesGroup[ExcT_1 | ExceptionGroup[ExcT_2]], - exception: type[ExcT_1] | Matcher[ExcT_1] | RaisesGroup[ExcT_2], - *other_exceptions: type[ExcT_1] | Matcher[ExcT_1] | RaisesGroup[ExcT_2], + exception: type[ExcT_1] | RaisesExc[ExcT_1] | RaisesGroup[ExcT_2], + *other_exceptions: type[ExcT_1] | RaisesExc[ExcT_1] | RaisesGroup[ExcT_2], match: str | Pattern[str] | None = None, check: ( Callable[[ExceptionGroup[ExcT_1 | ExceptionGroup[ExcT_2]]], bool] | None @@ -419,8 +421,8 @@ def __init__( @overload def __init__( self: RaisesGroup[BaseExcT_1], - exception: type[BaseExcT_1] | Matcher[BaseExcT_1], - *other_exceptions: type[BaseExcT_1] | Matcher[BaseExcT_1], + exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1], + *other_exceptions: type[BaseExcT_1] | RaisesExc[BaseExcT_1], match: str | Pattern[str] | None = None, check: Callable[[BaseExceptionGroup[BaseExcT_1]], bool] | None = None, ) -> None: ... @@ -439,9 +441,9 @@ def __init__( @overload def __init__( self: RaisesGroup[BaseExcT_1 | BaseExceptionGroup[BaseExcT_2]], - exception: type[BaseExcT_1] | Matcher[BaseExcT_1] | RaisesGroup[BaseExcT_2], + exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], *other_exceptions: type[BaseExcT_1] - | Matcher[BaseExcT_1] + | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], match: str | Pattern[str] | None = None, check: ( @@ -455,9 +457,9 @@ def __init__( def __init__( self: RaisesGroup[ExcT_1 | BaseExcT_1 | BaseExceptionGroup[BaseExcT_2]], - exception: type[BaseExcT_1] | Matcher[BaseExcT_1] | RaisesGroup[BaseExcT_2], + exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], *other_exceptions: type[BaseExcT_1] - | Matcher[BaseExcT_1] + | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], allow_unwrapped: bool = False, flatten_subgroups: bool = False, @@ -479,7 +481,7 @@ def __init__( ) super().__init__(match, check) self.expected_exceptions: tuple[ - type[BaseExcT_co] | Matcher[BaseExcT_co] | RaisesGroup[BaseException], ... + type[BaseExcT_co] | RaisesExc[BaseExcT_co] | RaisesGroup[BaseException], ... ] = ( exception, *other_exceptions, @@ -492,8 +494,8 @@ def __init__( raise ValueError( "You cannot specify multiple exceptions with `allow_unwrapped=True.`" " If you want to match one of multiple possible exceptions you should" - " use a `Matcher`." - " E.g. `Matcher(check=lambda e: isinstance(e, (...)))`", + " use a `RaisesExc`." + " E.g. `RaisesExc(check=lambda e: isinstance(e, (...)))`", ) if allow_unwrapped and isinstance(exception, RaisesGroup): raise ValueError( @@ -505,7 +507,7 @@ def __init__( raise ValueError( "`allow_unwrapped=True` bypasses the `match` and `check` parameters" " if the exception is unwrapped. If you intended to match/check the" - " exception you should use a `Matcher` object. If you want to match/check" + " exception you should use a `RaisesExc` object. If you want to match/check" " the exceptiongroup when the exception *is* wrapped you need to" " do e.g. `if isinstance(exc.value, ExceptionGroup):" " assert RaisesGroup(...).matches(exc.value)` afterwards.", @@ -523,9 +525,9 @@ def __init__( ) self.is_baseexceptiongroup |= exc.is_baseexceptiongroup exc._nested = True - elif isinstance(exc, Matcher): + elif isinstance(exc, RaisesExc): if exc.exception_type is not None: - # Matcher __init__ assures it's a subclass of BaseException + # RaisesExc __init__ assures it's a subclass of BaseException self.is_baseexceptiongroup |= not issubclass( exc.exception_type, Exception, @@ -535,7 +537,7 @@ def __init__( self.is_baseexceptiongroup |= not issubclass(exc, Exception) else: raise TypeError( - f'Invalid argument "{exc!r}" must be exception type, Matcher, or' + f'Invalid argument "{exc!r}" must be exception type, RaisesExc, or' " RaisesGroup.", ) @@ -657,7 +659,7 @@ def matches( assert self._fail_reason is old_reason is not None self._fail_reason += ( f", but matched the expected {self._repr_expected(expected)}." - f" You might want RaisesGroup(Matcher({expected.__name__}, match={_match_pattern(self.match)!r}))" + f" You might want RaisesGroup(RaisesExc({expected.__name__}, match={_match_pattern(self.match)!r}))" ) else: self._fail_reason = old_reason @@ -706,7 +708,7 @@ def matches( ): self._fail_reason = reason + ( f", but did return True for the expected {self._repr_expected(expected)}." - f" You might want RaisesGroup(Matcher({expected.__name__}, check=<...>))" + f" You might want RaisesGroup(RaisesExc({expected.__name__}, check=<...>))" ) else: self._fail_reason = reason @@ -717,7 +719,7 @@ def matches( @staticmethod def _check_expected( expected_type: ( - type[BaseException] | Matcher[BaseException] | RaisesGroup[BaseException] + type[BaseException] | RaisesExc[BaseException] | RaisesGroup[BaseException] ), exception: BaseException, ) -> str | None: @@ -734,8 +736,8 @@ def _check_expected( return f"{expected_type!r}: {expected_type.fail_reason}" @staticmethod - def _repr_expected(e: type[BaseException] | AbstractMatcher[BaseException]) -> str: - """Get the repr of an expected type/Matcher/RaisesGroup, but we only want + def _repr_expected(e: type[BaseException] | AbstractRaises[BaseException]) -> str: + """Get the repr of an expected type/RaisesExc/RaisesGroup, but we only want the name if it's a type""" if isinstance(e, type): return _exception_type_name(e) @@ -887,7 +889,7 @@ def _check_exceptions( s += ( "\nThere exist a possible match when attempting an exhaustive check," " but RaisesGroup uses a greedy algorithm. " - "Please make your expected exceptions more stringent with `Matcher` etc" + "Please make your expected exceptions more stringent with `RaisesExc` etc" " so the greedy algorithm can function." ) self._fail_reason = s @@ -928,7 +930,7 @@ def __exit__( def expected_type(self) -> str: subexcs = [] for e in self.expected_exceptions: - if isinstance(e, Matcher): + if isinstance(e, RaisesExc): subexcs.append(str(e)) elif isinstance(e, RaisesGroup): subexcs.append(e.expected_type()) @@ -953,7 +955,7 @@ class ResultHolder: def __init__( self, expected_exceptions: tuple[ - type[BaseException] | AbstractMatcher[BaseException], ... + type[BaseException] | AbstractRaises[BaseException], ... ], actual_exceptions: Sequence[BaseException], ) -> None: diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index b5f54d559e5..50225f7529f 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -23,7 +23,7 @@ from .._code import getfslineno from ..compat import NOTSET from ..compat import NotSetType -from _pytest._raises_group import AbstractMatcher +from _pytest._raises_group import AbstractRaises from _pytest.config import Config from _pytest.deprecated import check_ispytest from _pytest.deprecated import MARKED_FIXTURE @@ -463,7 +463,7 @@ def __call__( raises: None | type[BaseException] | tuple[type[BaseException], ...] - | AbstractMatcher[BaseException] = ..., + | AbstractRaises[BaseException] = ..., strict: bool = ..., ) -> MarkDecorator: ... diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index ddbf9b87251..c90f67f7b3d 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -908,6 +908,11 @@ def raises( ... >>> assert exc_info.type is ValueError + **Expecting exception groups** + + When expecting exceptions wrapped in :exc:`BaseExceptionGroup` or + :exc:`ExceptionGroup`, you should instead use :class:`pytest.RaisesGroup`. + **Using with** ``pytest.mark.parametrize`` When using :ref:`pytest.mark.parametrize ref` diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 0736f48aa45..293bea704cb 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -12,7 +12,7 @@ import traceback from typing import Optional -from _pytest._raises_group import AbstractMatcher +from _pytest._raises_group import AbstractRaises from _pytest.config import Config from _pytest.config import hookimpl from _pytest.config.argparsing import Parser @@ -205,7 +205,7 @@ class Xfail: raises: ( type[BaseException] | tuple[type[BaseException], ...] - | AbstractMatcher[BaseException] + | AbstractRaises[BaseException] | None ) @@ -289,7 +289,7 @@ def pytest_runtest_makereport( and isinstance(call.excinfo.value, raises) ) or ( - isinstance(raises, AbstractMatcher) + isinstance(raises, AbstractRaises) and raises.matches(call.excinfo.value) ) ): diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index ca2c66fee03..a16377ca6bb 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -6,7 +6,7 @@ from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo -from _pytest._raises_group import Matcher +from _pytest._raises_group import RaisesExc from _pytest._raises_group import RaisesGroup from _pytest._raises_group import RaisesGroup as raises_group from _pytest.assertion import register_assert_rewrite @@ -116,7 +116,6 @@ "Mark", "MarkDecorator", "MarkGenerator", - "Matcher", "Metafunc", "Module", "MonkeyPatch", @@ -137,6 +136,7 @@ "PytestUnraisableExceptionWarning", "PytestWarning", "Pytester", + "RaisesExc", "RaisesGroup", "RecordedHookCall", "RunResult", diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index 73715ee1c21..d0d443cc0cc 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -3,11 +3,13 @@ # several expected multi-line strings contain long lines. We don't wanna break them up # as that makes it confusing to see where the line breaks are. # ruff: noqa: E501 +from contextlib import AbstractContextManager import re import sys from typing import TYPE_CHECKING -from _pytest._raises_group import Matcher +from _pytest._code import ExceptionInfo +from _pytest._raises_group import RaisesExc from _pytest._raises_group import RaisesGroup from _pytest._raises_group import repr_callable from _pytest.outcomes import Failed @@ -39,7 +41,7 @@ def test_raises_group() -> None: with pytest.raises( TypeError, match=wrap_escape( - f'Invalid argument "{ValueError()!r}" must be exception type, Matcher, or RaisesGroup.', + f'Invalid argument "{ValueError()!r}" must be exception type, RaisesExc, or RaisesGroup.', ), ): RaisesGroup(ValueError()) # type: ignore[call-overload] @@ -276,10 +278,10 @@ def test_catch_unwrapped_exceptions() -> None: match=r"^You cannot specify multiple exceptions with", ): RaisesGroup(SyntaxError, ValueError, allow_unwrapped=True) # type: ignore[call-overload] - # if users want one of several exception types they need to use a Matcher + # if users want one of several exception types they need to use a RaisesExc # (which the error message suggests) with RaisesGroup( - Matcher(check=lambda e: isinstance(e, (SyntaxError, ValueError))), + RaisesExc(check=lambda e: isinstance(e, (SyntaxError, ValueError))), allow_unwrapped=True, ): raise ValueError @@ -289,7 +291,7 @@ def test_catch_unwrapped_exceptions() -> None: RaisesGroup(RaisesGroup(ValueError), allow_unwrapped=True) # type: ignore[call-overload] # But it *can* be used to check for nesting level +- 1 if they move it to - # the nested RaisesGroup. Users should probably use `Matcher`s instead though. + # the nested RaisesGroup. Users should probably use `RaisesExc`s instead though. with RaisesGroup(RaisesGroup(ValueError, allow_unwrapped=True)): raise ExceptionGroup("", [ExceptionGroup("", [ValueError()])]) with RaisesGroup(RaisesGroup(ValueError, allow_unwrapped=True)): @@ -329,10 +331,10 @@ def test_catch_unwrapped_exceptions() -> None: raise TypeError("this text doesn't show up in the error message") with ( fails_raises_group( - "Raised exception (group) did not match: Matcher(ValueError): 'TypeError' is not of type 'ValueError'", + "Raised exception (group) did not match: RaisesExc(ValueError): 'TypeError' is not of type 'ValueError'", add_prefix=False, ), - RaisesGroup(Matcher(ValueError), allow_unwrapped=True), + RaisesGroup(RaisesExc(ValueError), allow_unwrapped=True), ): raise TypeError @@ -360,7 +362,7 @@ def test_match() -> None: raise e # and technically you can match it all with ^$ - # but you're probably better off using a Matcher at that point + # but you're probably better off using a RaisesExc at that point with RaisesGroup(ValueError, match="^bar\nmy note$"): e = ExceptionGroup("bar", (ValueError(),)) e.add_note("my note") @@ -375,12 +377,12 @@ def test_match() -> None: raise ExceptionGroup("bar", (ValueError(),)) # Suggest a fix for easy pitfall of adding match to the RaisesGroup instead of - # using a Matcher. + # using a RaisesExc. # This requires a single expected & raised exception, the expected is a type, # and `isinstance(raised, expected_type)`. with ( fails_raises_group( - "Regex pattern 'foo' did not match 'bar' of 'ExceptionGroup', but matched the expected 'ValueError'. You might want RaisesGroup(Matcher(ValueError, match='foo'))" + "Regex pattern 'foo' did not match 'bar' of 'ExceptionGroup', but matched the expected 'ValueError'. You might want RaisesGroup(RaisesExc(ValueError, match='foo'))" ), RaisesGroup(ValueError, match="foo"), ): @@ -411,7 +413,7 @@ def is_value_error(e: BaseException) -> bool: # helpful suggestion if the user thinks the check is for the sub-exception with ( fails_raises_group( - f"check {is_value_error} did not return True on the ExceptionGroup, but did return True for the expected 'ValueError'. You might want RaisesGroup(Matcher(ValueError, check=<...>))" + f"check {is_value_error} did not return True on the ExceptionGroup, but did return True for the expected 'ValueError'. You might want RaisesGroup(RaisesExc(ValueError, check=<...>))" ), RaisesGroup(ValueError, check=is_value_error), ): @@ -425,7 +427,7 @@ def my_check(e: object) -> bool: # pragma: no cover msg = ( "`allow_unwrapped=True` bypasses the `match` and `check` parameters" " if the exception is unwrapped. If you intended to match/check the" - " exception you should use a `Matcher` object. If you want to match/check" + " exception you should use a `RaisesExc` object. If you want to match/check" " the exceptiongroup when the exception *is* wrapped you need to" " do e.g. `if isinstance(exc.value, ExceptionGroup):" " assert RaisesGroup(...).matches(exc.value)` afterwards." @@ -435,8 +437,8 @@ def my_check(e: object) -> bool: # pragma: no cover with pytest.raises(ValueError, match=re.escape(msg)): RaisesGroup(ValueError, allow_unwrapped=True, check=my_check) # type: ignore[call-overload] - # Users should instead use a Matcher - rg = RaisesGroup(Matcher(ValueError, match="^foo$"), allow_unwrapped=True) + # Users should instead use a RaisesExc + rg = RaisesGroup(RaisesExc(ValueError, match="^foo$"), allow_unwrapped=True) with rg: raise ValueError("foo") with rg: @@ -483,14 +485,14 @@ def check_message( RaisesGroup(RaisesGroup(ValueError)), ) - # Matcher + # RaisesExc check_message( - "ExceptionGroup(Matcher(ValueError, match='my_str'))", - RaisesGroup(Matcher(ValueError, "my_str")), + "ExceptionGroup(RaisesExc(ValueError, match='my_str'))", + RaisesGroup(RaisesExc(ValueError, "my_str")), ) check_message( - "ExceptionGroup(Matcher(match='my_str'))", - RaisesGroup(Matcher(match="my_str")), + "ExceptionGroup(RaisesExc(match='my_str'))", + RaisesGroup(RaisesExc(match="my_str")), ) # BaseExceptionGroup @@ -498,10 +500,10 @@ def check_message( "BaseExceptionGroup(KeyboardInterrupt)", RaisesGroup(KeyboardInterrupt), ) - # BaseExceptionGroup with type inside Matcher + # BaseExceptionGroup with type inside RaisesExc check_message( - "BaseExceptionGroup(Matcher(KeyboardInterrupt))", - RaisesGroup(Matcher(KeyboardInterrupt)), + "BaseExceptionGroup(RaisesExc(KeyboardInterrupt))", + RaisesGroup(RaisesExc(KeyboardInterrupt)), ) # Base-ness transfers to parent containers check_message( @@ -556,7 +558,7 @@ def test_assert_message() -> None: "The following raised exceptions did not find a match\n" " RuntimeError():\n" # " 'RuntimeError' is not of type 'ValueError'\n" - # " Matcher(TypeError): 'RuntimeError' is not of type 'TypeError'\n" + # " RaisesExc(TypeError): 'RuntimeError' is not of type 'TypeError'\n" " RaisesGroup(RuntimeError): 'RuntimeError' is not an exception group, but would match with `allow_unwrapped=True`\n" " RaisesGroup(ValueError): 'RuntimeError' is not an exception group\n" " ValueError('bar'):\n" @@ -567,7 +569,7 @@ def test_assert_message() -> None: ), RaisesGroup( ValueError, - Matcher(TypeError), + RaisesExc(TypeError), RaisesGroup(RuntimeError), RaisesGroup(ValueError), ), @@ -587,9 +589,9 @@ def test_assert_message() -> None: with ( fails_raises_group( - "Matcher(ValueError): 'TypeError' is not of type 'ValueError'" + "RaisesExc(ValueError): 'TypeError' is not of type 'ValueError'" ), - RaisesGroup(Matcher(ValueError)), + RaisesGroup(RaisesExc(ValueError)), ): raise ExceptionGroup("a", [TypeError()]) @@ -605,10 +607,10 @@ def test_assert_message() -> None: raise ExceptionGroup("h(ell)o", [ValueError()]) with ( fails_raises_group( - "Matcher(match='h(ell)o'): Regex pattern 'h(ell)o' did not match 'h(ell)o'\n" + "RaisesExc(match='h(ell)o'): Regex pattern 'h(ell)o' did not match 'h(ell)o'\n" " Did you mean to `re.escape()` the regex?", ), - RaisesGroup(Matcher(match="h(ell)o")), + RaisesGroup(RaisesExc(match="h(ell)o")), ): raise ExceptionGroup("", [ValueError("h(ell)o")]) @@ -775,18 +777,18 @@ def test_assert_message_nested() -> None: "The following expected exceptions did not find a match:\n" " RaisesGroup(ValueError)\n" " RaisesGroup(RaisesGroup(ValueError))\n" - " RaisesGroup(Matcher(TypeError, match='foo'))\n" + " RaisesGroup(RaisesExc(TypeError, match='foo'))\n" " RaisesGroup(TypeError, ValueError)\n" "The following raised exceptions did not find a match\n" " TypeError('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'):\n" " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" " RaisesGroup(RaisesGroup(ValueError)): 'TypeError' is not an exception group\n" - " RaisesGroup(Matcher(TypeError, match='foo')): 'TypeError' is not an exception group\n" + " RaisesGroup(RaisesExc(TypeError, match='foo')): 'TypeError' is not an exception group\n" " RaisesGroup(TypeError, ValueError): 'TypeError' is not an exception group\n" " ExceptionGroup('Exceptions from Trio nursery', [TypeError('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb')]):\n" " RaisesGroup(ValueError): 'TypeError' is not of type 'ValueError'\n" " RaisesGroup(RaisesGroup(ValueError)): RaisesGroup(ValueError): 'TypeError' is not an exception group\n" - " RaisesGroup(Matcher(TypeError, match='foo')): Matcher(TypeError, match='foo'): Regex pattern 'foo' did not match 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'\n" + " RaisesGroup(RaisesExc(TypeError, match='foo')): RaisesExc(TypeError, match='foo'): Regex pattern 'foo' did not match 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'\n" " RaisesGroup(TypeError, ValueError): 1 matched exception. Too few exceptions raised, found no match for: ['ValueError']\n" " ExceptionGroup('Exceptions from Trio nursery', [TypeError('cccccccccccccccccccccccccccccc'), TypeError('dddddddddddddddddddddddddddddd')]):\n" " RaisesGroup(ValueError): \n" @@ -805,14 +807,14 @@ def test_assert_message_nested() -> None: " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" " TypeError('dddddddddddddddddddddddddddddd'):\n" " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" - " RaisesGroup(Matcher(TypeError, match='foo')): \n" + " RaisesGroup(RaisesExc(TypeError, match='foo')): \n" " The following expected exceptions did not find a match:\n" - " Matcher(TypeError, match='foo')\n" + " RaisesExc(TypeError, match='foo')\n" " The following raised exceptions did not find a match\n" " TypeError('cccccccccccccccccccccccccccccc'):\n" - " Matcher(TypeError, match='foo'): Regex pattern 'foo' did not match 'cccccccccccccccccccccccccccccc'\n" + " RaisesExc(TypeError, match='foo'): Regex pattern 'foo' did not match 'cccccccccccccccccccccccccccccc'\n" " TypeError('dddddddddddddddddddddddddddddd'):\n" - " Matcher(TypeError, match='foo'): Regex pattern 'foo' did not match 'dddddddddddddddddddddddddddddd'\n" + " RaisesExc(TypeError, match='foo'): Regex pattern 'foo' did not match 'dddddddddddddddddddddddddddddd'\n" " RaisesGroup(TypeError, ValueError): \n" " 1 matched exception. \n" " The following expected exceptions did not find a match:\n" @@ -826,7 +828,7 @@ def test_assert_message_nested() -> None: RaisesGroup( RaisesGroup(ValueError), RaisesGroup(RaisesGroup(ValueError)), - RaisesGroup(Matcher(TypeError, match="foo")), + RaisesGroup(RaisesExc(TypeError, match="foo")), RaisesGroup(TypeError, ValueError), ), ): @@ -861,19 +863,19 @@ def test_check_no_patched_repr() -> None: match_str = ( r"^Raised exception group did not match: \n" r"The following expected exceptions did not find a match:\n" - r" Matcher\(check=. at .*>\)\n" + r" RaisesExc\(check=. at .*>\)\n" r" 'TypeError'\n" r"The following raised exceptions did not find a match\n" r" ValueError\('foo'\):\n" - r" Matcher\(check=. at .*>\): check did not return True\n" + r" RaisesExc\(check=. at .*>\): check did not return True\n" r" 'ValueError' is not of type 'TypeError'\n" r" ValueError\('bar'\):\n" - r" Matcher\(check=. at .*>\): check did not return True\n" + r" RaisesExc\(check=. at .*>\): check did not return True\n" r" 'ValueError' is not of type 'TypeError'$" ) with ( pytest.raises(Failed, match=match_str), - RaisesGroup(Matcher(check=lambda x: False), TypeError), + RaisesGroup(RaisesExc(check=lambda x: False), TypeError), ): raise ExceptionGroup("", [ValueError("foo"), ValueError("bar")]) @@ -884,7 +886,7 @@ def test_misordering_example() -> None: "\n" "3 matched exceptions. \n" "The following expected exceptions did not find a match:\n" - " Matcher(ValueError, match='foo')\n" + " RaisesExc(ValueError, match='foo')\n" " It matches ValueError('foo') which was paired with 'ValueError'\n" " It matches ValueError('foo') which was paired with 'ValueError'\n" " It matches ValueError('foo') which was paired with 'ValueError'\n" @@ -893,11 +895,11 @@ def test_misordering_example() -> None: " It matches 'ValueError' which was paired with ValueError('foo')\n" " It matches 'ValueError' which was paired with ValueError('foo')\n" " It matches 'ValueError' which was paired with ValueError('foo')\n" - " Matcher(ValueError, match='foo'): Regex pattern 'foo' did not match 'bar'\n" - "There exist a possible match when attempting an exhaustive check, but RaisesGroup uses a greedy algorithm. Please make your expected exceptions more stringent with `Matcher` etc so the greedy algorithm can function." + " RaisesExc(ValueError, match='foo'): Regex pattern 'foo' did not match 'bar'\n" + "There exist a possible match when attempting an exhaustive check, but RaisesGroup uses a greedy algorithm. Please make your expected exceptions more stringent with `RaisesExc` etc so the greedy algorithm can function." ), RaisesGroup( - ValueError, ValueError, ValueError, Matcher(ValueError, match="foo") + ValueError, ValueError, ValueError, RaisesExc(ValueError, match="foo") ), ): raise ExceptionGroup( @@ -972,134 +974,134 @@ def test_identity_oopsies() -> None: ) e = ValueError("foo") - m = Matcher(match="bar") + m = RaisesExc(match="bar") with ( fails_raises_group( "\n" "The following expected exceptions did not find a match:\n" - " Matcher(match='bar')\n" - " Matcher(match='bar')\n" - " Matcher(match='bar')\n" + " RaisesExc(match='bar')\n" + " RaisesExc(match='bar')\n" + " RaisesExc(match='bar')\n" "The following raised exceptions did not find a match\n" " ValueError('foo'):\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" " ValueError('foo'):\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" " ValueError('foo'):\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " Matcher(match='bar'): Regex pattern 'bar' did not match 'foo'" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'" ), RaisesGroup(m, m, m), ): raise ExceptionGroup("", [e, e, e]) -def test_matcher() -> None: +def test_raisesexc() -> None: with pytest.raises( ValueError, match=r"^You must specify at least one parameter to match on.$", ): - Matcher() # type: ignore[call-overload] + RaisesExc() # type: ignore[call-overload] with pytest.raises( TypeError, match=f"^exception_type {re.escape(repr(object))} must be a subclass of BaseException$", ): - Matcher(object) # type: ignore[type-var] + RaisesExc(object) # type: ignore[type-var] - with RaisesGroup(Matcher(ValueError)): + with RaisesGroup(RaisesExc(ValueError)): raise ExceptionGroup("", (ValueError(),)) with ( fails_raises_group( - "Matcher(TypeError): 'ValueError' is not of type 'TypeError'" + "RaisesExc(TypeError): 'ValueError' is not of type 'TypeError'" ), - RaisesGroup(Matcher(TypeError)), + RaisesGroup(RaisesExc(TypeError)), ): raise ExceptionGroup("", (ValueError(),)) -def test_matcher_match() -> None: - with RaisesGroup(Matcher(ValueError, "foo")): +def test_raisesexc_match() -> None: + with RaisesGroup(RaisesExc(ValueError, "foo")): raise ExceptionGroup("", (ValueError("foo"),)) with ( fails_raises_group( - "Matcher(ValueError, match='foo'): Regex pattern 'foo' did not match 'bar'" + "RaisesExc(ValueError, match='foo'): Regex pattern 'foo' did not match 'bar'" ), - RaisesGroup(Matcher(ValueError, "foo")), + RaisesGroup(RaisesExc(ValueError, "foo")), ): raise ExceptionGroup("", (ValueError("bar"),)) # Can be used without specifying the type - with RaisesGroup(Matcher(match="foo")): + with RaisesGroup(RaisesExc(match="foo")): raise ExceptionGroup("", (ValueError("foo"),)) with ( fails_raises_group( - "Matcher(match='foo'): Regex pattern 'foo' did not match 'bar'" + "RaisesExc(match='foo'): Regex pattern 'foo' did not match 'bar'" ), - RaisesGroup(Matcher(match="foo")), + RaisesGroup(RaisesExc(match="foo")), ): raise ExceptionGroup("", (ValueError("bar"),)) # check ^$ - with RaisesGroup(Matcher(ValueError, match="^bar$")): + with RaisesGroup(RaisesExc(ValueError, match="^bar$")): raise ExceptionGroup("", [ValueError("bar")]) with ( fails_raises_group( - "Matcher(ValueError, match='^bar$'): Regex pattern '^bar$' did not match 'barr'" + "RaisesExc(ValueError, match='^bar$'): Regex pattern '^bar$' did not match 'barr'" ), - RaisesGroup(Matcher(ValueError, match="^bar$")), + RaisesGroup(RaisesExc(ValueError, match="^bar$")), ): raise ExceptionGroup("", [ValueError("barr")]) -def test_Matcher_check() -> None: +def test_RaisesExc_check() -> None: def check_oserror_and_errno_is_5(e: BaseException) -> bool: return isinstance(e, OSError) and e.errno == 5 - with RaisesGroup(Matcher(check=check_oserror_and_errno_is_5)): + with RaisesGroup(RaisesExc(check=check_oserror_and_errno_is_5)): raise ExceptionGroup("", (OSError(5, ""),)) # specifying exception_type narrows the parameter type to the callable def check_errno_is_5(e: OSError) -> bool: return e.errno == 5 - with RaisesGroup(Matcher(OSError, check=check_errno_is_5)): + with RaisesGroup(RaisesExc(OSError, check=check_errno_is_5)): raise ExceptionGroup("", (OSError(5, ""),)) # avoid printing overly verbose repr multiple times with ( fails_raises_group( - f"Matcher(OSError, check={check_errno_is_5!r}): check did not return True" + f"RaisesExc(OSError, check={check_errno_is_5!r}): check did not return True" ), - RaisesGroup(Matcher(OSError, check=check_errno_is_5)), + RaisesGroup(RaisesExc(OSError, check=check_errno_is_5)), ): raise ExceptionGroup("", (OSError(6, ""),)) # in nested cases you still get it multiple times though - # to address this you'd need logic in Matcher.__repr__ and RaisesGroup.__repr__ + # to address this you'd need logic in RaisesExc.__repr__ and RaisesGroup.__repr__ with ( fails_raises_group( - f"RaisesGroup(Matcher(OSError, check={check_errno_is_5!r})): Matcher(OSError, check={check_errno_is_5!r}): check did not return True" + f"RaisesGroup(RaisesExc(OSError, check={check_errno_is_5!r})): RaisesExc(OSError, check={check_errno_is_5!r}): check did not return True" ), - RaisesGroup(RaisesGroup(Matcher(OSError, check=check_errno_is_5))), + RaisesGroup(RaisesGroup(RaisesExc(OSError, check=check_errno_is_5))), ): raise ExceptionGroup("", [ExceptionGroup("", [OSError(6, "")])]) -def test_matcher_tostring() -> None: - assert str(Matcher(ValueError)) == "Matcher(ValueError)" - assert str(Matcher(match="[a-z]")) == "Matcher(match='[a-z]')" +def test_raisesexc_tostring() -> None: + assert str(RaisesExc(ValueError)) == "RaisesExc(ValueError)" + assert str(RaisesExc(match="[a-z]")) == "RaisesExc(match='[a-z]')" pattern_no_flags = re.compile(r"noflag", 0) - assert str(Matcher(match=pattern_no_flags)) == "Matcher(match='noflag')" + assert str(RaisesExc(match=pattern_no_flags)) == "RaisesExc(match='noflag')" pattern_flags = re.compile(r"noflag", re.IGNORECASE) - assert str(Matcher(match=pattern_flags)) == f"Matcher(match={pattern_flags!r})" + assert str(RaisesExc(match=pattern_flags)) == f"RaisesExc(match={pattern_flags!r})" assert ( - str(Matcher(ValueError, match="re", check=bool)) - == f"Matcher(ValueError, match='re', check={bool!r})" + str(RaisesExc(ValueError, match="re", check=bool)) + == f"RaisesExc(ValueError, match='re', check={bool!r})" ) @@ -1110,7 +1112,7 @@ def check_str_and_repr(s: str) -> None: check_str_and_repr("RaisesGroup(ValueError)") check_str_and_repr("RaisesGroup(RaisesGroup(ValueError))") - check_str_and_repr("RaisesGroup(Matcher(ValueError))") + check_str_and_repr("RaisesGroup(RaisesExc(ValueError))") check_str_and_repr("RaisesGroup(ValueError, allow_unwrapped=True)") check_str_and_repr("RaisesGroup(ValueError, match='aoeu')") @@ -1124,18 +1126,18 @@ def test_assert_matches() -> None: e = ValueError() # it's easy to do this - assert Matcher(ValueError).matches(e) + assert RaisesExc(ValueError).matches(e) # but you don't get a helpful error with pytest.raises(AssertionError, match=r"assert False\n \+ where False = .*"): - assert Matcher(TypeError).matches(e) + assert RaisesExc(TypeError).matches(e) # you'd need to do this arcane incantation with pytest.raises(AssertionError, match="'ValueError' is not of type 'TypeError'"): - assert (m := Matcher(TypeError)).matches(e), m.fail_reason + assert (m := RaisesExc(TypeError)).matches(e), m.fail_reason # but even if we add assert_matches, will people remember to use it? - # other than writing a linter rule, I don't think we can catch `assert Matcher(...).matches` + # other than writing a linter rule, I don't think we can catch `assert RaisesExc(...).matches` # https://github.com/pytest-dev/pytest/issues/12504 @@ -1152,14 +1154,30 @@ def test_foo() -> None: result.assert_outcomes(xfailed=1) -def test_xfail_Matcher(pytester: Pytester) -> None: +def test_xfail_RaisesExc(pytester: Pytester) -> None: pytester.makepyfile( """ import pytest - @pytest.mark.xfail(raises=pytest.Matcher(ValueError)) + @pytest.mark.xfail(raises=pytest.RaisesExc(ValueError)) def test_foo() -> None: raise ValueError """ ) result = pytester.runpytest() result.assert_outcomes(xfailed=1) + + +@pytest.mark.parametrize( + "wrap_in_group,handler", + [ + (False, pytest.raises(ValueError)), + (True, RaisesGroup(ValueError)), + ], +) +def test_parametrizing_conditional_raisesgroup( + wrap_in_group: bool, handler: AbstractContextManager[ExceptionInfo[BaseException]] +) -> None: + with handler: + if wrap_in_group: + raise ExceptionGroup("", [ValueError()]) + raise ValueError() diff --git a/testing/typing_raises_group.py b/testing/typing_raises_group.py index 2dc35031dac..87cce35b72d 100644 --- a/testing/typing_raises_group.py +++ b/testing/typing_raises_group.py @@ -6,7 +6,7 @@ from typing_extensions import assert_type -from _pytest._raises_group import Matcher +from _pytest._raises_group import RaisesExc from _pytest._raises_group import RaisesGroup @@ -17,7 +17,7 @@ # split into functions to isolate the different scopes -def check_matcher_typevar_default(e: Matcher) -> None: +def check_raisesexc_typevar_default(e: RaisesExc) -> None: assert e.exception_type is not None _exc: type[BaseException] = e.exception_type # this would previously pass, as the type would be `Any` @@ -53,30 +53,30 @@ def check_matches_with_different_exception_type() -> None: assert_type(e, ExceptionGroup[ValueError]) -def check_matcher_init() -> None: +def check_raisesexc_init() -> None: def check_exc(exc: BaseException) -> bool: return isinstance(exc, ValueError) # Check various combinations of constructor signatures. # At least 1 arg must be provided. - Matcher() # type: ignore - Matcher(ValueError) - Matcher(ValueError, "regex") - Matcher(ValueError, "regex", check_exc) - Matcher(exception_type=ValueError) - Matcher(match="regex") - Matcher(check=check_exc) - Matcher(ValueError, match="regex") - Matcher(match="regex", check=check_exc) + RaisesExc() # type: ignore + RaisesExc(ValueError) + RaisesExc(ValueError, "regex") + RaisesExc(ValueError, "regex", check_exc) + RaisesExc(exception_type=ValueError) + RaisesExc(match="regex") + RaisesExc(check=check_exc) + RaisesExc(ValueError, match="regex") + RaisesExc(match="regex", check=check_exc) def check_filenotfound(exc: FileNotFoundError) -> bool: return not exc.filename.endswith(".tmp") # If exception_type is provided, that narrows the `check` method's argument. - Matcher(FileNotFoundError, check=check_filenotfound) - Matcher(ValueError, check=check_filenotfound) # type: ignore - Matcher(check=check_filenotfound) # type: ignore - Matcher(FileNotFoundError, match="regex", check=check_filenotfound) + RaisesExc(FileNotFoundError, check=check_filenotfound) + RaisesExc(ValueError, check=check_filenotfound) # type: ignore + RaisesExc(check=check_filenotfound) # type: ignore + RaisesExc(FileNotFoundError, match="regex", check=check_filenotfound) def raisesgroup_check_type_narrowing() -> None: @@ -126,8 +126,8 @@ def handle_group_value(e: ExceptionGroup[ValueError]) -> bool: RaisesGroup(Exception, check=handle_group) -def check_matcher_transparent() -> None: - with RaisesGroup(Matcher(ValueError)) as e: +def check_raisesexc_transparent() -> None: + with RaisesGroup(RaisesExc(ValueError)) as e: ... _: BaseExceptionGroup[ValueError] = e.value assert_type(e.value, ExceptionGroup[ValueError]) @@ -167,8 +167,8 @@ def check_nested_raisesgroups_matches() -> None: def check_multiple_exceptions_1() -> None: a = RaisesGroup(ValueError, ValueError) - b = RaisesGroup(Matcher(ValueError), Matcher(ValueError)) - c = RaisesGroup(ValueError, Matcher(ValueError)) + b = RaisesGroup(RaisesExc(ValueError), RaisesExc(ValueError)) + c = RaisesGroup(ValueError, RaisesExc(ValueError)) d: RaisesGroup[ValueError] d = a @@ -179,8 +179,8 @@ def check_multiple_exceptions_1() -> None: def check_multiple_exceptions_2() -> None: # This previously failed due to lack of covariance in the TypeVar - a = RaisesGroup(Matcher(ValueError), Matcher(TypeError)) - b = RaisesGroup(Matcher(ValueError), TypeError) + a = RaisesGroup(RaisesExc(ValueError), RaisesExc(TypeError)) + b = RaisesGroup(RaisesExc(ValueError), TypeError) c = RaisesGroup(ValueError, TypeError) d: RaisesGroup[Exception] @@ -203,7 +203,7 @@ def check_raisesgroup_overloads() -> None: # allowed variants RaisesGroup(ValueError, allow_unwrapped=True) RaisesGroup(ValueError, allow_unwrapped=True, flatten_subgroups=True) - RaisesGroup(Matcher(ValueError), allow_unwrapped=True) + RaisesGroup(RaisesExc(ValueError), allow_unwrapped=True) # flatten_subgroups=True does not allow nested RaisesGroup RaisesGroup(RaisesGroup(ValueError), flatten_subgroups=True) # type: ignore @@ -212,7 +212,7 @@ def check_raisesgroup_overloads() -> None: RaisesGroup(ValueError, match="foo", flatten_subgroups=True) RaisesGroup(ValueError, check=bool, flatten_subgroups=True) RaisesGroup(ValueError, flatten_subgroups=True) - RaisesGroup(Matcher(ValueError), flatten_subgroups=True) + RaisesGroup(RaisesExc(ValueError), flatten_subgroups=True) # if they're both false we can of course specify nested raisesgroup RaisesGroup(RaisesGroup(ValueError)) From e73c4111d201f5614b8a5b8e064efc5e46b0acf2 Mon Sep 17 00:00:00 2001 From: jakkdl <11260241+jakkdl@users.noreply.github.com> Date: Thu, 6 Feb 2025 15:52:56 +0100 Subject: [PATCH 1103/1271] fix test on py<311 --- testing/python/raises_group.py | 2 ++ tox.ini | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index d0d443cc0cc..f3f3bcb5316 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -1145,6 +1145,8 @@ def test_xfail_raisesgroup(pytester: Pytester) -> None: pytester.makepyfile( """ import pytest + if sys.version_info < (3, 11): + from exceptiongroup import ExceptionGroup @pytest.mark.xfail(raises=pytest.RaisesGroup(ValueError)) def test_foo() -> None: raise ExceptionGroup("foo", [ValueError()]) diff --git a/tox.ini b/tox.ini index 80fae513142..645a28f0126 100644 --- a/tox.ini +++ b/tox.ini @@ -107,8 +107,8 @@ allowlist_externals = git commands = # Retrieve possibly missing commits: - -git fetch --unshallow - -git fetch --tags + #-git fetch --unshallow + #-git fetch --tags sphinx-build \ -j auto \ From ff36649db4b7f37c1c559677027b8afac124e532 Mon Sep 17 00:00:00 2001 From: jakkdl <11260241+jakkdl@users.noreply.github.com> Date: Thu, 6 Feb 2025 16:14:37 +0100 Subject: [PATCH 1104/1271] remove git fetch from tox docs environment --- tox.ini | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tox.ini b/tox.ini index 80fae513142..97a74dde937 100644 --- a/tox.ini +++ b/tox.ini @@ -103,13 +103,7 @@ basepython = python3.12 # sync with rtd to get errors usedevelop = True deps = -r{toxinidir}/doc/en/requirements.txt -allowlist_externals = - git commands = - # Retrieve possibly missing commits: - -git fetch --unshallow - -git fetch --tags - sphinx-build \ -j auto \ -W --keep-going \ From c011e9b6f3d1d177947190428df14ee54fbc3cf1 Mon Sep 17 00:00:00 2001 From: jakkdl <11260241+jakkdl@users.noreply.github.com> Date: Thu, 6 Feb 2025 17:12:56 +0100 Subject: [PATCH 1105/1271] fix test, fix references in docstrings --- doc/en/reference/reference.rst | 5 +++ src/_pytest/_raises_group.py | 62 ++++++++++++++++++---------------- testing/python/raises_group.py | 1 + tox.ini | 4 +-- 4 files changed, 41 insertions(+), 31 deletions(-) diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index d7cf09100b7..2f1c2206596 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1020,12 +1020,17 @@ RaisesExc .. autoclass:: pytest.RaisesExc() :members: + .. autoattribute:: fail_reason + RaisesGroup ~~~~~~~~~~~ +**Tutorial**: :ref:`assert-matching-exception-groups` .. autoclass:: pytest.RaisesGroup() :members: + .. autoattribute:: fail_reason + TerminalReporter ~~~~~~~~~~~~~~~~ diff --git a/src/_pytest/_raises_group.py b/src/_pytest/_raises_group.py index db4e51fc211..92884409694 100644 --- a/src/_pytest/_raises_group.py +++ b/src/_pytest/_raises_group.py @@ -126,9 +126,9 @@ def __init__( @property def fail_reason(self) -> str | None: - """Set after a call to `matches` to give a human-readable reason for why the match failed. - When used as a context manager the string will be given as the text of an - `Failed`""" + """Set after a call to :meth:`matches` to give a human-readable reason for why the match failed. + When used as a context manager the string will be printed as the reason for the + test failing.""" return self._fail_reason def _check_check( @@ -170,17 +170,20 @@ def matches( self: AbstractRaises[BaseExcT_1], exc_val: BaseException ) -> TypeGuard[BaseExcT_1]: """Check if an exception matches the requirements of this AbstractRaises. - If it fails, `AbstractRaises.fail_reason` should be set. + If it fails, :meth:`AbstractRaises.fail_reason` should be set. """ @final class RaisesExc(AbstractRaises[BaseExcT_co_default]): """Helper class to be used together with RaisesGroups when you want to specify requirements on sub-exceptions. - Only specifying the type is redundant, and it's also unnecessary when the type is a - nested `RaisesGroup` since it supports the same arguments. - The type is checked with `isinstance`, and does not need to be an exact match. + + You don't need this if you only want to specify the type, since :class:`RaisesGroup` + accepts ``type[BaseException]``. + + The type is checked with :func:`isinstance`, and does not need to be an exact match. If that is wanted you can use the ``check`` parameter. + :meth:`RaisesExc.matches` can also be used standalone to check individual exceptions. Examples:: @@ -193,7 +196,7 @@ class RaisesExc(AbstractRaises[BaseExcT_co_default]): ... Tip: if you install ``hypothesis`` and import it in ``conftest.py`` you will get - readable ``repr``s of ``check`` callables in the output. + readable ``repr``'s of ``check`` callables in the output. """ # Trio bundled hypothesis monkeypatching, we will probably instead assume that @@ -241,8 +244,8 @@ def matches( self, exception: BaseException, ) -> TypeGuard[BaseExcT_co_default]: - """Check if an exception matches the requirements of this RaisesExc. - If it fails, `RaisesExc.fail_reason` will be set. + """Check if an exception matches the requirements of this :class:`RaisesExc`. + If it fails, :attr:`RaisesExc.fail_reason` will be set. Examples:: @@ -287,33 +290,34 @@ def _check_type(self, exception: BaseException) -> TypeGuard[BaseExcT_co_default @final class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): - """Contextmanager for checking for an expected `ExceptionGroup`. - This works similar to ``pytest.raises``, but allows for specifying the structure of an `ExceptionGroup`. - `ExceptionInfo.group_contains` also tries to handle exception groups, - but it is very bad at checking that you *didn't* get exceptions you didn't expect. + """Contextmanager for checking for an expected :exc:`ExceptionGroup`. + This works similar to :func:`pytest.raises`, but allows for specifying the structure of an :exc:`ExceptionGroup`. + :meth:`ExceptionInfo.group_contains` also tries to handle exception groups, + but it is very bad at checking that you *didn't* get unexpected exceptions. - The catching behaviour differs from :ref:`except* ` in multiple - different ways, being much stricter by default. + The catching behaviour differs from :ref:`except* `, being much + stricter about the structure by default. By using ``allow_unwrapped=True`` and ``flatten_subgroups=True`` you can match - ``except*`` fully when expecting a single exception. + :ref:`except* ` fully when expecting a single exception. #. All specified exceptions must be present, *and no others*. - * If you expect a variable number of exceptions you need to use ``pytest.raises(ExceptionGroup)`` and manually - check the contained exceptions. Consider making use of :func:`RaisesExc.matches`. + * If you expect a variable number of exceptions you need to use + :func:`pytest.raises(ExceptionGroup) ` and manually check + the contained exceptions. Consider making use of :meth:`RaisesExc.matches`. #. It will only catch exceptions wrapped in an exceptiongroup by default. - * With ``allow_unwrapped=True`` you can specify a single expected exception or `RaisesExc` and it will match - the exception even if it is not inside an `ExceptionGroup`. - If you expect one of several different exception types you need to use a `RaisesExc` object. + * With ``allow_unwrapped=True`` you can specify a single expected exception (or `RaisesExc`) and it will match + the exception even if it is not inside an :exc:`ExceptionGroup`. + If you expect one of several different exception types you need to use a :class:`RaisesExc` object. - #. By default it cares about the full structure with nested `ExceptionGroup`'s. You can specify nested - `ExceptionGroup`'s by passing `RaisesGroup` objects as expected exceptions. + #. By default it cares about the full structure with nested :exc:`ExceptionGroup`'s. You can specify nested + :exc:`ExceptionGroup`'s by passing :class:`RaisesGroup` objects as expected exceptions. - * With ``flatten_subgroups=True`` it will "flatten" the raised `ExceptionGroup`, - extracting all exceptions inside any nested :class:`ExceptionGroup`, before matching. + * With ``flatten_subgroups=True`` it will "flatten" the raised :exc:`ExceptionGroup`, + extracting all exceptions inside any nested :exc:`ExceptionGroup`, before matching. It does not care about the order of the exceptions, so ``RaisesGroups(ValueError, TypeError)`` @@ -346,7 +350,7 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): raise ValueError - `RaisesGroup.matches` can also be used directly to check a standalone exception group. + :meth:`RaisesGroup.matches` can also be used directly to check a standalone exception group. The matching algorithm is greedy, which means cases such as this may fail:: @@ -355,10 +359,10 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): raise ExceptionGroup("", (ValueError("hello"), ValueError("goodbye"))) even though it generally does not care about the order of the exceptions in the group. - To avoid the above you should specify the first ValueError with a RaisesExc as well. + To avoid the above you should specify the first :exc:`ValueError` with a :class:`RaisesExc` as well. Tip: if you install ``hypothesis`` and import it in ``conftest.py`` you will get - readable ``repr``s of ``check`` callables in the output. + readable ``repr``'s of ``check`` callables in the output. """ # allow_unwrapped=True requires: singular exception, exception not being diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index f3f3bcb5316..4ac6f8a7ced 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -1144,6 +1144,7 @@ def test_assert_matches() -> None: def test_xfail_raisesgroup(pytester: Pytester) -> None: pytester.makepyfile( """ + import sys import pytest if sys.version_info < (3, 11): from exceptiongroup import ExceptionGroup diff --git a/tox.ini b/tox.ini index 645a28f0126..80fae513142 100644 --- a/tox.ini +++ b/tox.ini @@ -107,8 +107,8 @@ allowlist_externals = git commands = # Retrieve possibly missing commits: - #-git fetch --unshallow - #-git fetch --tags + -git fetch --unshallow + -git fetch --tags sphinx-build \ -j auto \ From a3d55a69552dfe34e3039a4bcb0a8bf8f9376716 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 8 Feb 2025 17:07:57 +0100 Subject: [PATCH 1106/1271] Make pygments mandatory and fix string highlighting (#13189) * Make pygments dependency required Closes #7683 * Also highlight comparisons between strings Fixes #13175 --- changelog/13175.bugfix.rst | 1 + changelog/7683.improvement.rst | 1 + pyproject.toml | 2 +- src/_pytest/_io/terminalwriter.py | 54 ++++++++++--------------------- src/_pytest/assertion/util.py | 29 +++++++++++++---- testing/test_assertion.py | 10 ++++++ 6 files changed, 52 insertions(+), 45 deletions(-) create mode 100644 changelog/13175.bugfix.rst create mode 100644 changelog/7683.improvement.rst diff --git a/changelog/13175.bugfix.rst b/changelog/13175.bugfix.rst new file mode 100644 index 00000000000..bdbb72b41e1 --- /dev/null +++ b/changelog/13175.bugfix.rst @@ -0,0 +1 @@ +The diff is now also highlighted correctly when comparing two strings. diff --git a/changelog/7683.improvement.rst b/changelog/7683.improvement.rst new file mode 100644 index 00000000000..311abe4df93 --- /dev/null +++ b/changelog/7683.improvement.rst @@ -0,0 +1 @@ +The formerly optional ``pygments`` dependency is now required, causing output always to be source-highlighted (unless disabled via the ``--code-highlight=no`` CLI option). diff --git a/pyproject.toml b/pyproject.toml index 3c3c04d2d5b..263e0c23836 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,6 +51,7 @@ dependencies = [ "iniconfig", "packaging", "pluggy>=1.5,<2", + "pygments>=2.7.2", "tomli>=1; python_version<'3.11'", ] optional-dependencies.dev = [ @@ -58,7 +59,6 @@ optional-dependencies.dev = [ "attrs>=19.2", "hypothesis>=3.56", "mock", - "pygments>=2.7.2", "requests", "setuptools", "xmlschema", diff --git a/src/_pytest/_io/terminalwriter.py b/src/_pytest/_io/terminalwriter.py index 50ce463f6b2..fd808f8b3b7 100644 --- a/src/_pytest/_io/terminalwriter.py +++ b/src/_pytest/_io/terminalwriter.py @@ -9,17 +9,17 @@ from typing import final from typing import Literal from typing import TextIO -from typing import TYPE_CHECKING + +import pygments +from pygments.formatters.terminal import TerminalFormatter +from pygments.lexer import Lexer +from pygments.lexers.diff import DiffLexer +from pygments.lexers.python import PythonLexer from ..compat import assert_never from .wcwidth import wcswidth -if TYPE_CHECKING: - from pygments.formatter import Formatter - from pygments.lexer import Lexer - - # This code was initially copied from py 1.8.1, file _io/terminalwriter.py. @@ -201,37 +201,22 @@ def _write_source(self, lines: Sequence[str], indents: Sequence[str] = ()) -> No for indent, new_line in zip(indents, new_lines): self.line(indent + new_line) - def _get_pygments_lexer(self, lexer: Literal["python", "diff"]) -> Lexer | None: - try: - if lexer == "python": - from pygments.lexers.python import PythonLexer - - return PythonLexer() - elif lexer == "diff": - from pygments.lexers.diff import DiffLexer - - return DiffLexer() - else: - assert_never(lexer) - except ModuleNotFoundError: - return None - - def _get_pygments_formatter(self) -> Formatter | None: - try: - import pygments.util - except ModuleNotFoundError: - return None + def _get_pygments_lexer(self, lexer: Literal["python", "diff"]) -> Lexer: + if lexer == "python": + return PythonLexer() + elif lexer == "diff": + return DiffLexer() + else: + assert_never(lexer) + def _get_pygments_formatter(self) -> TerminalFormatter: from _pytest.config.exceptions import UsageError theme = os.getenv("PYTEST_THEME") theme_mode = os.getenv("PYTEST_THEME_MODE", "dark") try: - from pygments.formatters.terminal import TerminalFormatter - return TerminalFormatter(bg=theme_mode, style=theme) - except pygments.util.ClassNotFound as e: raise UsageError( f"PYTEST_THEME environment variable has an invalid value: '{theme}'. " @@ -251,16 +236,11 @@ def _highlight( return source pygments_lexer = self._get_pygments_lexer(lexer) - if pygments_lexer is None: - return source - pygments_formatter = self._get_pygments_formatter() - if pygments_formatter is None: - return source - - from pygments import highlight - highlighted: str = highlight(source, pygments_lexer, pygments_formatter) + highlighted: str = pygments.highlight( + source, pygments_lexer, pygments_formatter + ) # pygments terminal formatter may add a newline when there wasn't one. # We don't want this, remove. if highlighted[-1] == "\n" and source[-1] != "\n": diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 3fe7eb9d862..30aee185d57 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -43,6 +43,14 @@ def __call__(self, source: str, lexer: Literal["diff", "python"] = "python") -> """Apply highlighting to the given source.""" +def dummy_highlighter(source: str, lexer: Literal["diff", "python"] = "python") -> str: + """Dummy highlighter that returns the text unprocessed. + + Needed for _notin_text, as the diff gets post-processed to only show the "+" part. + """ + return source + + def format_explanation(explanation: str) -> str: r"""Format an explanation. @@ -242,7 +250,7 @@ def _compare_eq_any( ) -> list[str]: explanation = [] if istext(left) and istext(right): - explanation = _diff_text(left, right, verbose) + explanation = _diff_text(left, right, highlighter, verbose) else: from _pytest.python_api import ApproxBase @@ -274,7 +282,9 @@ def _compare_eq_any( return explanation -def _diff_text(left: str, right: str, verbose: int = 0) -> list[str]: +def _diff_text( + left: str, right: str, highlighter: _HighlightFunc, verbose: int = 0 +) -> list[str]: """Return the explanation for the diff between text. Unless --verbose is used this will skip leading and trailing @@ -315,10 +325,15 @@ def _diff_text(left: str, right: str, verbose: int = 0) -> list[str]: explanation += ["Strings contain only whitespace, escaping them using repr()"] # "right" is the expected base against which we compare "left", # see https://github.com/pytest-dev/pytest/issues/3333 - explanation += [ - line.strip("\n") - for line in ndiff(right.splitlines(keepends), left.splitlines(keepends)) - ] + explanation.extend( + highlighter( + "\n".join( + line.strip("\n") + for line in ndiff(right.splitlines(keepends), left.splitlines(keepends)) + ), + lexer="diff", + ).splitlines() + ) return explanation @@ -586,7 +601,7 @@ def _notin_text(term: str, text: str, verbose: int = 0) -> list[str]: head = text[:index] tail = text[index + len(term) :] correct_text = head + tail - diff = _diff_text(text, correct_text, verbose) + diff = _diff_text(text, correct_text, dummy_highlighter, verbose) newdiff = [f"{saferepr(term, maxsize=42)} is contained here:"] for line in diff: if line.startswith("Skipping"): diff --git a/testing/test_assertion.py b/testing/test_assertion.py index a2e2304d342..e3d45478466 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -2019,6 +2019,16 @@ def test(): "{bold}{red}E {light-green}+ 'number-is-5': 5,{hl-reset}{endline}{reset}", ], ), + ( + """ + def test(): + assert "abcd" == "abce" + """, + [ + "{bold}{red}E {reset}{light-red}- abce{hl-reset}{endline}{reset}", + "{bold}{red}E {light-green}+ abcd{hl-reset}{endline}{reset}", + ], + ), ), ) def test_comparisons_handle_colors( From 4c3f286532b452e7ce4966f34d010369cbe08342 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 9 Feb 2025 06:23:44 +0000 Subject: [PATCH 1107/1271] [automated] Update plugin list (#13206) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 134 +++++++++++++++++-------------- 1 file changed, 75 insertions(+), 59 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 2e8bf36500d..cf1f0902885 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,14 +27,14 @@ please refer to `the update script =8.3 + :pypi:`databricks-labs-pytester` Python Testing for Databricks Feb 03, 2025 4 - Beta pytest>=8.3 :pypi:`logassert` Simple but powerful assertion and verification of logged lines Jan 29, 2025 5 - Production/Stable pytest; extra == "dev" :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 @@ -161,7 +161,7 @@ This list contains 1581 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Jan 30, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Feb 05, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -332,7 +332,7 @@ This list contains 1581 plugins. :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Oct 20, 2024 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest - :pypi:`pytest-datadir` pytest plugin for test data directories and files Oct 03, 2023 5 - Production/Stable pytest >=5.0 + :pypi:`pytest-datadir` pytest plugin for test data directories and files Feb 07, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) :pypi:`pytest-datadir-ng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Dec 25, 2019 5 - Production/Stable pytest :pypi:`pytest-datadir-nng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Nov 09, 2022 5 - Production/Stable pytest (>=7.0.0,<8.0.0) @@ -353,6 +353,7 @@ This list contains 1581 plugins. :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-dbt-core` Pytest extension for dbt. Jun 04, 2024 N/A pytest>=6.2.5; extra == "test" + :pypi:`pytest-dbt-duckdb` Add your description here Feb 07, 2025 N/A pytest>=8.3.4 :pypi:`pytest-dbt-postgres` Pytest tooling to unittest DBT & Postgres models Sep 03, 2024 N/A pytest<9.0.0,>=8.3.2 :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) @@ -412,7 +413,7 @@ This list contains 1581 plugins. :pypi:`pytest-doc` A documentation plugin for py.test. Jun 28, 2015 5 - Production/Stable N/A :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A - :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Feb 02, 2024 N/A pytest <9.0,>=4.0 + :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Feb 06, 2025 N/A pytest<9.0,>=4.0 :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) @@ -474,15 +475,15 @@ This list contains 1581 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 Jul 25, 2024 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. Jan 29, 2025 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Jan 29, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Jan 29, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Jan 29, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Jan 29, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Jan 29, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Jan 29, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Jan 29, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Jan 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Feb 06, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 06, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 06, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 06, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Feb 06, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 06, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 06, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 06, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 06, 2025 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) @@ -507,7 +508,7 @@ This list contains 1581 plugins. :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) - :pypi:`pytest-evals` A pytest plugin for running and analyzing LLM evaluation tests Jan 29, 2025 N/A pytest>=7.0.0 + :pypi:`pytest-evals` A pytest plugin for running and analyzing LLM evaluation tests Feb 02, 2025 N/A pytest>=7.0.0 :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A @@ -677,7 +678,7 @@ This list contains 1581 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Feb 01, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 08, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -709,13 +710,13 @@ This list contains 1581 plugins. :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Jul 25, 2024 4 - Beta pytest>=7.0.0 - :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Aug 05, 2022 4 - Beta pytest>=7.1 + :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Feb 06, 2025 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A :pypi:`pytest-idem` A pytest plugin to help with testing idem projects Dec 13, 2023 5 - Production/Stable N/A :pypi:`pytest-idempotent` Pytest plugin for testing function idempotence. Jul 25, 2022 N/A N/A :pypi:`pytest-ignore-flaky` ignore failures from flaky tests (pytest plugin) Apr 20, 2024 5 - Production/Stable pytest>=6.0 - :pypi:`pytest-ignore-test-results` A pytest plugin to ignore test results. Aug 17, 2023 2 - Pre-Alpha pytest>=7.0 + :pypi:`pytest-ignore-test-results` A pytest plugin to ignore test results. Feb 03, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-image-diff` Dec 31, 2024 3 - Alpha pytest :pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Jul 01, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-import-check` pytest plugin to check whether Python modules can be imported Jul 19, 2024 3 - Alpha pytest>=8.1 @@ -796,7 +797,7 @@ This list contains 1581 plugins. :pypi:`pytest-kookit` Your simple but kooky integration testing with pytest Sep 10, 2024 N/A N/A :pypi:`pytest-koopmans` A plugin for testing the koopmans package Nov 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-krtech-common` pytest krtech common library Nov 28, 2016 4 - Beta N/A - :pypi:`pytest-kubernetes` Oct 28, 2024 N/A pytest<9.0.0,>=8.3.0 + :pypi:`pytest-kubernetes` Feb 04, 2025 N/A pytest<9.0.0,>=8.3.0 :pypi:`pytest-kuunda` pytest plugin to help with test data setup for PySpark tests Feb 25, 2024 4 - Beta pytest >=6.2.0 :pypi:`pytest-kwparametrize` Alternate syntax for @pytest.mark.parametrize with test cases as dictionaries and default value fallbacks Jan 22, 2021 N/A pytest (>=6) :pypi:`pytest-lambda` Define pytest fixtures with lambda functions. May 27, 2024 5 - Production/Stable pytest<9,>=3.6 @@ -875,7 +876,7 @@ This list contains 1581 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Jan 23, 2025 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Feb 06, 2025 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -914,7 +915,7 @@ This list contains 1581 plugins. :pypi:`pytest-monkeyplus` pytest's monkeypatch subclass with extra functionalities Sep 18, 2012 5 - Production/Stable N/A :pypi:`pytest-monkeytype` pytest-monkeytype: Generate Monkeytype annotations from your pytest tests. Jul 29, 2020 4 - Beta N/A :pypi:`pytest-moto` Fixtures for integration tests of AWS services,uses moto mocking library. Aug 28, 2015 1 - Planning N/A - :pypi:`pytest-moto-fixtures` Fixtures for testing code that interacts with AWS Oct 24, 2024 1 - Planning pytest<9.0,>=8.3; extra == "pytest" + :pypi:`pytest-moto-fixtures` Fixtures for testing code that interacts with AWS Feb 04, 2025 1 - Planning pytest<9,>=8.3; extra == "pytest" :pypi:`pytest-motor` A pytest plugin for motor, the non-blocking MongoDB driver. Jul 21, 2021 3 - Alpha pytest :pypi:`pytest-mp` A test batcher for multiprocessed Pytest runs May 23, 2018 4 - Beta pytest :pypi:`pytest-mpi` pytest plugin to collect information from tests Jan 08, 2022 3 - Alpha pytest @@ -1057,7 +1058,7 @@ This list contains 1581 plugins. :pypi:`pytest-plone` Pytest plugin to test Plone addons May 15, 2024 3 - Alpha pytest<8.0.0 :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Jan 31, 2025 5 - Production/Stable pytest>=7.4.2 + :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Feb 02, 2025 5 - Production/Stable pytest>=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A :pypi:`pytest-pogo` Pytest plugin for pogo-migrate Sep 09, 2024 4 - Beta pytest<9,>=7 :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A @@ -1176,7 +1177,7 @@ This list contains 1581 plugins. :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest :pypi:`pytest_repeater` py.test plugin for repeating single test multiple times. Feb 09, 2018 1 - Planning N/A - :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Nov 29, 2024 5 - Production/Stable pytest + :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Feb 05, 2025 5 - Production/Stable pytest :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest @@ -1241,7 +1242,7 @@ This list contains 1581 plugins. :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 21, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A - :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Jan 06, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Feb 05, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 @@ -1257,7 +1258,7 @@ This list contains 1581 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 01, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 08, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1269,7 +1270,7 @@ This list contains 1581 plugins. :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 Feb 01, 2024 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. Feb 01, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Feb 08, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1407,7 +1408,7 @@ This list contains 1581 plugins. :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A - :pypi:`pytest-teardown` Jan 22, 2025 N/A pytest<9.0.0,>=7.4.1 + :pypi:`pytest-teardown` Feb 03, 2025 N/A pytest<9.0.0,>=7.4.1 :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Apr 25, 2024 5 - Production/Stable N/A :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) @@ -1450,6 +1451,7 @@ This list contains 1581 plugins. :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Aug 20, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 + :pypi:`pytest-test-yaml` a pytest test package Feb 08, 2025 N/A pytest :pypi:`pytest-tesults` Tesults plugin for pytest Nov 12, 2024 5 - Production/Stable pytest>=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jan 23, 2025 5 - Production/Stable pytest>=8.0.0 :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A @@ -1544,7 +1546,7 @@ This list contains 1581 plugins. :pypi:`pytest-voluptuous` Pytest plugin for asserting data against voluptuous schema. Jun 09, 2020 N/A pytest :pypi:`pytest-vscodedebug` A pytest plugin to easily enable debugging tests within Visual Studio Code Dec 04, 2020 4 - Beta N/A :pypi:`pytest-vscode-pycharm-cls` A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. Feb 01, 2023 N/A pytest - :pypi:`pytest-vtestify` A pytest plugin for visual assertion using SSIM and image comparison. Oct 10, 2024 N/A pytest + :pypi:`pytest-vtestify` A pytest plugin for visual assertion using SSIM and image comparison. Feb 04, 2025 N/A pytest :pypi:`pytest-vts` pytest plugin for automatic recording of http stubbed tests Jun 05, 2019 N/A pytest (>=2.3) :pypi:`pytest-vulture` A pytest plugin to checks dead code with vulture Nov 25, 2024 N/A pytest>=7.0.0 :pypi:`pytest-vw` pytest-vw makes your failing test cases succeed under CI tools scrutiny Oct 07, 2015 4 - Beta N/A @@ -1621,7 +1623,7 @@ This list contains 1581 plugins. :pypi:`databricks-labs-pytester` - *last release*: Nov 15, 2024, + *last release*: Feb 03, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3 @@ -2510,7 +2512,7 @@ This list contains 1581 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Jan 30, 2025, + *last release*: Feb 05, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3707,9 +3709,9 @@ This list contains 1581 plugins. Pytest plugin for remote Databricks notebooks testing :pypi:`pytest-datadir` - *last release*: Oct 03, 2023, + *last release*: Feb 07, 2025, *status*: 5 - Production/Stable, - *requires*: pytest >=5.0 + *requires*: pytest>=7.0 pytest plugin for test data directories and files @@ -3853,6 +3855,13 @@ This list contains 1581 plugins. Pytest extension for dbt. + :pypi:`pytest-dbt-duckdb` + *last release*: Feb 07, 2025, + *status*: N/A, + *requires*: pytest>=8.3.4 + + Add your description here + :pypi:`pytest-dbt-postgres` *last release*: Sep 03, 2024, *status*: N/A, @@ -4267,9 +4276,9 @@ This list contains 1581 plugins. An RST Documentation Generator for pytest-based test suites :pypi:`pytest-docker` - *last release*: Feb 02, 2024, + *last release*: Feb 06, 2025, *status*: N/A, - *requires*: pytest <9.0,>=4.0 + *requires*: pytest<9.0,>=4.0 Simple pytest fixtures for Docker and Docker Compose based tests @@ -4701,63 +4710,63 @@ This list contains 1581 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Jan 29, 2025, + *last release*: Feb 06, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -4932,7 +4941,7 @@ This list contains 1581 plugins. Pytest Plugin for BDD :pypi:`pytest-evals` - *last release*: Jan 29, 2025, + *last release*: Feb 02, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -6122,7 +6131,7 @@ This list contains 1581 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 01, 2025, + *last release*: Feb 08, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6346,7 +6355,7 @@ This list contains 1581 plugins. A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite :pypi:`pytest-ibutsu` - *last release*: Aug 05, 2022, + *last release*: Feb 06, 2025, *status*: 4 - Beta, *requires*: pytest>=7.1 @@ -6388,8 +6397,8 @@ This list contains 1581 plugins. ignore failures from flaky tests (pytest plugin) :pypi:`pytest-ignore-test-results` - *last release*: Aug 17, 2023, - *status*: 2 - Pre-Alpha, + *last release*: Feb 03, 2025, + *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin to ignore test results. @@ -6955,7 +6964,7 @@ This list contains 1581 plugins. pytest krtech common library :pypi:`pytest-kubernetes` - *last release*: Oct 28, 2024, + *last release*: Feb 04, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=8.3.0 @@ -7508,7 +7517,7 @@ This list contains 1581 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Jan 23, 2025, + *last release*: Feb 06, 2025, *status*: N/A, *requires*: N/A @@ -7781,9 +7790,9 @@ This list contains 1581 plugins. Fixtures for integration tests of AWS services,uses moto mocking library. :pypi:`pytest-moto-fixtures` - *last release*: Oct 24, 2024, + *last release*: Feb 04, 2025, *status*: 1 - Planning, - *requires*: pytest<9.0,>=8.3; extra == "pytest" + *requires*: pytest<9,>=8.3; extra == "pytest" Fixtures for testing code that interacts with AWS @@ -8782,7 +8791,7 @@ This list contains 1581 plugins. A plugin to help developing and testing other plugins :pypi:`pytest-plus` - *last release*: Jan 31, 2025, + *last release*: Feb 02, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.4.2 @@ -9615,7 +9624,7 @@ This list contains 1581 plugins. py.test plugin for repeating single test multiple times. :pypi:`pytest-replay` - *last release*: Nov 29, 2024, + *last release*: Feb 05, 2025, *status*: 5 - Production/Stable, *requires*: pytest @@ -10070,7 +10079,7 @@ This list contains 1581 plugins. implement a --failed option for pytest :pypi:`pytest-run-parallel` - *last release*: Jan 06, 2025, + *last release*: Feb 05, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -10182,7 +10191,7 @@ This list contains 1581 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Feb 01, 2025, + *last release*: Feb 08, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10266,7 +10275,7 @@ This list contains 1581 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Feb 01, 2025, + *last release*: Feb 08, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -11232,7 +11241,7 @@ This list contains 1581 plugins. py.test plugin to introduce block structure in teamcity build log, if output is not captured :pypi:`pytest-teardown` - *last release*: Jan 22, 2025, + *last release*: Feb 03, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=7.4.1 @@ -11532,6 +11541,13 @@ This list contains 1581 plugins. + :pypi:`pytest-test-yaml` + *last release*: Feb 08, 2025, + *status*: N/A, + *requires*: pytest + + a pytest test package + :pypi:`pytest-tesults` *last release*: Nov 12, 2024, *status*: 5 - Production/Stable, @@ -12191,7 +12207,7 @@ This list contains 1581 plugins. A PyTest helper to enable start remote debugger on test start or failure or when pytest.set_trace is used. :pypi:`pytest-vtestify` - *last release*: Oct 10, 2024, + *last release*: Feb 04, 2025, *status*: N/A, *requires*: pytest From 2a8593c701856e82547a09e86eedcfbc017e9dd5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 08:45:39 +0100 Subject: [PATCH 1108/1271] build(deps): Bump django in /testing/plugins_integration (#13210) Bumps [django](https://github.com/django/django) from 5.1.5 to 5.1.6. - [Commits](https://github.com/django/django/compare/5.1.5...5.1.6) --- updated-dependencies: - dependency-name: django dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 3d89d055f2b..ca4f6f700c4 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[trio]==4.8.0 -django==5.1.5 +django==5.1.6 pytest-asyncio==0.25.3 pytest-bdd==8.1.0 pytest-cov==6.0.0 From 05cc85400c3dfa0666be8da3d16988deeae81a37 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 01:38:22 +0100 Subject: [PATCH 1109/1271] [pre-commit.ci] pre-commit autoupdate (#13214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.4 → v0.9.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.4...v0.9.6) - [github.com/woodruffw/zizmor-pre-commit: v1.3.0 → v1.3.1](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.3.0...v1.3.1) - [github.com/pre-commit/mirrors-mypy: v1.14.1 → v1.15.0](https://github.com/pre-commit/mirrors-mypy/compare/v1.14.1...v1.15.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 62d72d5e9f3..d746af2e4e5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.4" + rev: "v0.9.6" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.3.0 + rev: v1.3.1 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs @@ -32,7 +32,7 @@ repos: hooks: - id: python-use-type-annotations - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.14.1 + rev: v1.15.0 hooks: - id: mypy files: ^(src/|testing/|scripts/) From f0cc122edddea0c10e4ec4139065b6137ce45ad1 Mon Sep 17 00:00:00 2001 From: Samuel Bronson Date: Thu, 13 Feb 2025 10:13:18 +0000 Subject: [PATCH 1110/1271] Update capture-warnings.rst: Fix PEP number in link (#13215) This was linking to a completely unrelated PEP, presumably due to a typo. Sorry there's no changelog, filing from my phone. --- doc/en/how-to/capture-warnings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 65a43cec6e8..4b1de6f3704 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -250,7 +250,7 @@ See :ref:`@pytest.mark.filterwarnings ` and the :envvar:`python:PYTHONWARNINGS` environment variable or the ``-W`` command-line option, pytest will not configure any filters by default. - Also pytest doesn't follow :pep:`506` suggestion of resetting all warning filters because + Also pytest doesn't follow :pep:`565` suggestion of resetting all warning filters because it might break test suites that configure warning filters themselves by calling :func:`warnings.simplefilter` (see :issue:`2430` for an example of that). From 62aa4272229a4e604582db534796df1a729b4752 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 15 Feb 2025 15:48:35 +0100 Subject: [PATCH 1111/1271] doc: Clarify capturing .readouterr() return value (#13222) This got added in 38fb6aae7830837209c40ec1a4ccb68950bc107c, where the "The return value ... changed" made a lot of sense. However, 9c5da9c0d15ccf7ab9f3a8fbd6540e4a56ea789f removed the "versionadded" without adjusting the wording. Also see 3a4435fb59604d40c5d2e2f65e9acba99dd9cff0. --- doc/en/how-to/capture-stdout-stderr.rst | 2 +- doc/en/how-to/parametrize.rst | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index 9f7ddce3499..d91bef736e7 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -131,7 +131,7 @@ test from having to care about setting/resetting output streams and also interacts well with pytest's own per-test capturing. -The return value from ``readouterr`` changed to a ``namedtuple`` with two attributes, ``out`` and ``err``. +The return value of ``readouterr()`` is a ``namedtuple`` with two attributes, ``out`` and ``err``. If the code under test writes non-textual data (``bytes``), you can capture this using the :fixture:`capsysbinary` fixture which instead returns ``bytes`` from diff --git a/doc/en/how-to/parametrize.rst b/doc/en/how-to/parametrize.rst index b6466c491b4..5a16684eb96 100644 --- a/doc/en/how-to/parametrize.rst +++ b/doc/en/how-to/parametrize.rst @@ -29,10 +29,6 @@ pytest enables test parametrization at several levels: .. regendoc: wipe - - - Several improvements. - The builtin :ref:`pytest.mark.parametrize ref` decorator enables parametrization of arguments for a test function. Here is a typical example of a test function that implements checking that a certain input leads From 60173b59fd269bdcaa660b7a5ed813f380b721bc Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 13 Feb 2025 12:31:56 +0100 Subject: [PATCH 1112/1271] Move CLI options to correct help section Before: pytest-warnings: -W, --pythonwarnings PYTHONWARNINGS Set which warnings to report, see -W option of Python itself --maxfail=num Exit after first num failures or errors --strict-config Any warnings encountered while parsing the `pytest` section of the configuration file raise errors --strict-markers Markers not registered in the `markers` section of the configuration file raise errors --strict (Deprecated) alias to --strict-markers -c, --config-file FILE Load configuration from `FILE` instead of trying to locate one of the implicit configuration files. --continue-on-collection-errors Force test execution even if collection errors occur --rootdir=ROOTDIR Define root directory for tests. Can be relative path: 'root_dir', './root_dir', 'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with variables: '$HOME/root_dir'. But other than -W, those options aren't related to pytest-warnings at all. This is a regression in 19e99ab4131fbd709ce0e5a17694e1be3b22f355, which added `group = parser.getgroup("pytest-warnings")` in the middle of those "general" options, thus moving the help section for some of them. --- src/_pytest/main.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 26b0db74ff9..64ffb488d94 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -92,20 +92,6 @@ def pytest_addoption(parser: Parser) -> None: const=1, help="Exit instantly on first error or failed test", ) - group = parser.getgroup("pytest-warnings") - group.addoption( - "-W", - "--pythonwarnings", - action="append", - help="Set which warnings to report, see -W option of Python itself", - ) - parser.addini( - "filterwarnings", - type="linelist", - help="Each line specifies a pattern for " - "warnings.filterwarnings. " - "Processed after -W/--pythonwarnings.", - ) group._addoption( "--maxfail", metavar="num", @@ -157,6 +143,21 @@ def pytest_addoption(parser: Parser) -> None: "'$HOME/root_dir'.", ) + group = parser.getgroup("pytest-warnings") + group.addoption( + "-W", + "--pythonwarnings", + action="append", + help="Set which warnings to report, see -W option of Python itself", + ) + parser.addini( + "filterwarnings", + type="linelist", + help="Each line specifies a pattern for " + "warnings.filterwarnings. " + "Processed after -W/--pythonwarnings.", + ) + group = parser.getgroup("collect", "collection") group.addoption( "--collectonly", From d7176e25f7ffd9865b8cd4a3492e3a93f59f1c8b Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 13 Feb 2025 12:38:14 +0100 Subject: [PATCH 1113/1271] Move collection options to correct section Moves --continue-on-collection-errors to "collection:" --- src/_pytest/main.py | 72 ++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 64ffb488d94..344df7a53ed 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -54,35 +54,6 @@ def pytest_addoption(parser: Parser) -> None: - parser.addini( - "norecursedirs", - "Directory patterns to avoid for recursion", - type="args", - default=[ - "*.egg", - ".*", - "_darcs", - "build", - "CVS", - "dist", - "node_modules", - "venv", - "{arch}", - ], - ) - parser.addini( - "testpaths", - "Directories to search for tests when no files or directories are given on the " - "command line", - type="args", - default=[], - ) - parser.addini( - "collect_imported_tests", - "Whether to collect tests in imported modules outside `testpaths`", - type="bool", - default=True, - ) group = parser.getgroup("general", "Running and selection options") group._addoption( "-x", @@ -127,13 +98,6 @@ def pytest_addoption(parser: Parser) -> None: help="Load configuration from `FILE` instead of trying to locate one of the " "implicit configuration files.", ) - group._addoption( - "--continue-on-collection-errors", - action="store_true", - default=False, - dest="continue_on_collection_errors", - help="Force test execution even if collection errors occur", - ) group._addoption( "--rootdir", action="store", @@ -219,6 +183,13 @@ def pytest_addoption(parser: Parser) -> None: default=False, help="Don't ignore tests in a local virtualenv directory", ) + group._addoption( + "--continue-on-collection-errors", + action="store_true", + default=False, + dest="continue_on_collection_errors", + help="Force test execution even if collection errors occur", + ) group.addoption( "--import-mode", default="prepend", @@ -227,6 +198,35 @@ def pytest_addoption(parser: Parser) -> None: help="Prepend/append to sys.path when importing test modules and conftest " "files. Default: prepend.", ) + parser.addini( + "norecursedirs", + "Directory patterns to avoid for recursion", + type="args", + default=[ + "*.egg", + ".*", + "_darcs", + "build", + "CVS", + "dist", + "node_modules", + "venv", + "{arch}", + ], + ) + parser.addini( + "testpaths", + "Directories to search for tests when no files or directories are given on the " + "command line", + type="args", + default=[], + ) + parser.addini( + "collect_imported_tests", + "Whether to collect tests in imported modules outside `testpaths`", + type="bool", + default=True, + ) parser.addini( "consider_namespace_packages", type="bool", From 71ae4d1df4d8b1ceb688f364e04a8bbcccebc495 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 13 Feb 2025 12:39:47 +0100 Subject: [PATCH 1114/1271] Move --config-file / --rootdir options "test session [...] configuration" seems more fitting than "general" --- src/_pytest/main.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 344df7a53ed..81350781f3f 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -89,23 +89,6 @@ def pytest_addoption(parser: Parser) -> None: action="store_true", help="(Deprecated) alias to --strict-markers", ) - group._addoption( - "-c", - "--config-file", - metavar="FILE", - type=str, - dest="inifilename", - help="Load configuration from `FILE` instead of trying to locate one of the " - "implicit configuration files.", - ) - group._addoption( - "--rootdir", - action="store", - dest="rootdir", - help="Define root directory for tests. Can be relative path: 'root_dir', './root_dir', " - "'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with variables: " - "'$HOME/root_dir'.", - ) group = parser.getgroup("pytest-warnings") group.addoption( @@ -235,6 +218,23 @@ def pytest_addoption(parser: Parser) -> None: ) group = parser.getgroup("debugconfig", "test session debugging and configuration") + group._addoption( + "-c", + "--config-file", + metavar="FILE", + type=str, + dest="inifilename", + help="Load configuration from `FILE` instead of trying to locate one of the " + "implicit configuration files.", + ) + group._addoption( + "--rootdir", + action="store", + dest="rootdir", + help="Define root directory for tests. Can be relative path: 'root_dir', './root_dir', " + "'root_dir/another_dir/'; absolute path: '/home/user/root_dir'; path with variables: " + "'$HOME/root_dir'.", + ) group.addoption( "--basetemp", dest="basetemp", From 2861de3293e0be788cb047aa5fc52faf90b6e744 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Thu, 13 Feb 2025 12:49:29 +0100 Subject: [PATCH 1115/1271] Avoid using private _addoption The only differences between the two is that: - `addoption` checks for conflicts, but `_addoption` does not - `addoption` complains if a lower-case short option is given, `_addoption` does not Yet it looks like using the latter has been inconsistently cargo-culted with newer options. --- src/_pytest/capture.py | 4 ++-- src/_pytest/debugging.py | 6 +++--- src/_pytest/helpconfig.py | 6 +++--- src/_pytest/main.py | 16 ++++++++-------- src/_pytest/mark/__init__.py | 4 ++-- src/_pytest/pastebin.py | 2 +- src/_pytest/terminal.py | 34 +++++++++++++++++----------------- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 5b64c34e772..d447d087031 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -48,7 +48,7 @@ def pytest_addoption(parser: Parser) -> None: group = parser.getgroup("general") - group._addoption( + group.addoption( "--capture", action="store", default="fd", @@ -56,7 +56,7 @@ def pytest_addoption(parser: Parser) -> None: choices=["fd", "sys", "no", "tee-sys"], help="Per-test capturing method: one of fd|sys|no|tee-sys", ) - group._addoption( + group._addoption( # private to use reserved lower-case short option "-s", action="store_const", const="no", diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index a9886c29d3c..040e8994b37 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -40,13 +40,13 @@ def _validate_usepdb_cls(value: str) -> tuple[str, str]: def pytest_addoption(parser: Parser) -> None: group = parser.getgroup("general") - group._addoption( + group.addoption( "--pdb", dest="usepdb", action="store_true", help="Start the interactive Python debugger on errors or KeyboardInterrupt", ) - group._addoption( + group.addoption( "--pdbcls", dest="usepdb_cls", metavar="modulename:classname", @@ -54,7 +54,7 @@ def pytest_addoption(parser: Parser) -> None: help="Specify a custom interactive Python debugger for use with --pdb." "For example: --pdbcls=IPython.terminal.debugger:TerminalPdb", ) - group._addoption( + group.addoption( "--trace", dest="trace", action="store_true", diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 3d607189dbe..2b377c70f7b 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -55,14 +55,14 @@ def pytest_addoption(parser: Parser) -> None: help="Display pytest version and information about plugins. " "When given twice, also display information about plugins.", ) - group._addoption( + group._addoption( # private to use reserved lower-case short option "-h", "--help", action=HelpAction, dest="help", help="Show help message and configuration info", ) - group._addoption( + group._addoption( # private to use reserved lower-case short option "-p", action="append", dest="plugins", @@ -90,7 +90,7 @@ def pytest_addoption(parser: Parser) -> None: "This file is opened with 'w' and truncated as a result, care advised. " "Default: pytestdebug.log.", ) - group._addoption( + group._addoption( # private to use reserved lower-case short option "-o", "--override-ini", dest="override_ini", diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 81350781f3f..dac084b553a 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -55,7 +55,7 @@ def pytest_addoption(parser: Parser) -> None: group = parser.getgroup("general", "Running and selection options") - group._addoption( + group._addoption( # private to use reserved lower-case short option "-x", "--exitfirst", action="store_const", @@ -63,7 +63,7 @@ def pytest_addoption(parser: Parser) -> None: const=1, help="Exit instantly on first error or failed test", ) - group._addoption( + group.addoption( "--maxfail", metavar="num", action="store", @@ -72,19 +72,19 @@ def pytest_addoption(parser: Parser) -> None: default=0, help="Exit after first num failures or errors", ) - group._addoption( + group.addoption( "--strict-config", action="store_true", help="Any warnings encountered while parsing the `pytest` section of the " "configuration file raise errors", ) - group._addoption( + group.addoption( "--strict-markers", action="store_true", help="Markers not registered in the `markers` section of the configuration " "file raise errors", ) - group._addoption( + group.addoption( "--strict", action="store_true", help="(Deprecated) alias to --strict-markers", @@ -166,7 +166,7 @@ def pytest_addoption(parser: Parser) -> None: default=False, help="Don't ignore tests in a local virtualenv directory", ) - group._addoption( + group.addoption( "--continue-on-collection-errors", action="store_true", default=False, @@ -218,7 +218,7 @@ def pytest_addoption(parser: Parser) -> None: ) group = parser.getgroup("debugconfig", "test session debugging and configuration") - group._addoption( + group._addoption( # private to use reserved lower-case short option "-c", "--config-file", metavar="FILE", @@ -227,7 +227,7 @@ def pytest_addoption(parser: Parser) -> None: help="Load configuration from `FILE` instead of trying to locate one of the " "implicit configuration files.", ) - group._addoption( + group.addoption( "--rootdir", action="store", dest="rootdir", diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index efb966c09aa..488b562a298 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -79,7 +79,7 @@ def test_eval(test_input, expected): def pytest_addoption(parser: Parser) -> None: group = parser.getgroup("general") - group._addoption( + group._addoption( # private to use reserved lower-case short option "-k", action="store", dest="keyword", @@ -99,7 +99,7 @@ def pytest_addoption(parser: Parser) -> None: "The matching is case-insensitive.", ) - group._addoption( + group._addoption( # private to use reserved lower-case short option "-m", action="store", dest="markexpr", diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index 69c011ed24a..d5c4f29c4c3 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -20,7 +20,7 @@ def pytest_addoption(parser: Parser) -> None: group = parser.getgroup("terminal reporting") - group._addoption( + group.addoption( "--pastebin", metavar="mode", action="store", diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index b2cdda37507..3297c38e848 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -132,7 +132,7 @@ class TestShortLogReport(NamedTuple): def pytest_addoption(parser: Parser) -> None: group = parser.getgroup("terminal reporting", "Reporting", after="general") - group._addoption( + group._addoption( # private to use reserved lower-case short option "-v", "--verbose", action="count", @@ -140,35 +140,35 @@ def pytest_addoption(parser: Parser) -> None: dest="verbose", help="Increase verbosity", ) - group._addoption( + group.addoption( "--no-header", action="store_true", default=False, dest="no_header", help="Disable header", ) - group._addoption( + group.addoption( "--no-summary", action="store_true", default=False, dest="no_summary", help="Disable summary", ) - group._addoption( + group.addoption( "--no-fold-skipped", action="store_false", dest="fold_skipped", default=True, help="Do not fold skipped tests in short summary.", ) - group._addoption( + group.addoption( "--force-short-summary", action="store_true", dest="force_short_summary", default=False, help="Force condensed summary output regardless of verbosity level.", ) - group._addoption( + group._addoption( # private to use reserved lower-case short option "-q", "--quiet", action=MoreQuietAction, @@ -176,14 +176,14 @@ def pytest_addoption(parser: Parser) -> None: dest="verbose", help="Decrease verbosity", ) - group._addoption( + group.addoption( "--verbosity", dest="verbose", type=int, default=0, help="Set verbosity. Default: 0.", ) - group._addoption( + group._addoption( # private to use reserved lower-case short option "-r", action="store", dest="reportchars", @@ -195,7 +195,7 @@ def pytest_addoption(parser: Parser) -> None: "(w)arnings are enabled by default (see --disable-warnings), " "'N' can be used to reset the list. (default: 'fE').", ) - group._addoption( + group.addoption( "--disable-warnings", "--disable-pytest-warnings", default=False, @@ -203,7 +203,7 @@ def pytest_addoption(parser: Parser) -> None: action="store_true", help="Disable warnings summary", ) - group._addoption( + group._addoption( # private to use reserved lower-case short option "-l", "--showlocals", action="store_true", @@ -211,13 +211,13 @@ def pytest_addoption(parser: Parser) -> None: default=False, help="Show locals in tracebacks (disabled by default)", ) - group._addoption( + group.addoption( "--no-showlocals", action="store_false", dest="showlocals", help="Hide locals in tracebacks (negate --showlocals passed through addopts)", ) - group._addoption( + group.addoption( "--tb", metavar="style", action="store", @@ -226,14 +226,14 @@ def pytest_addoption(parser: Parser) -> None: choices=["auto", "long", "short", "no", "line", "native"], help="Traceback print mode (auto/long/short/line/native/no)", ) - group._addoption( + group.addoption( "--xfail-tb", action="store_true", dest="xfail_tb", default=False, help="Show tracebacks for xfail (as long as --tb != no)", ) - group._addoption( + group.addoption( "--show-capture", action="store", dest="showcapture", @@ -242,14 +242,14 @@ def pytest_addoption(parser: Parser) -> None: help="Controls how captured stdout/stderr/log is shown on failed tests. " "Default: all.", ) - group._addoption( + group.addoption( "--fulltrace", "--full-trace", action="store_true", default=False, help="Don't cut any tracebacks (default is to cut)", ) - group._addoption( + group.addoption( "--color", metavar="color", action="store", @@ -258,7 +258,7 @@ def pytest_addoption(parser: Parser) -> None: choices=["yes", "no", "auto"], help="Color terminal output (yes/no/auto)", ) - group._addoption( + group.addoption( "--code-highlight", default="yes", choices=["yes", "no"], From 174333e940c3548a8f494824d0ff1092b94a3722 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 15 Feb 2025 16:02:44 +0100 Subject: [PATCH 1116/1271] Add changelog --- changelog/13221.doc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/13221.doc.rst diff --git a/changelog/13221.doc.rst b/changelog/13221.doc.rst new file mode 100644 index 00000000000..cfd35f821b4 --- /dev/null +++ b/changelog/13221.doc.rst @@ -0,0 +1 @@ +Improved grouping of CLI options in the ``--help`` output. From d126389308eb787efa0c0ebffc566a5bb1619e4d Mon Sep 17 00:00:00 2001 From: Harmin Parra Rueda Date: Sat, 15 Feb 2025 20:30:12 +0100 Subject: [PATCH 1117/1271] Add 'int' and 'float' ini option types Fixes #11381 --------- Co-authored-by: Bruno Oliveira Co-authored-by: Florian Bruhin --- changelog/11381.improvement.rst | 17 +++++++ src/_pytest/config/__init__.py | 22 +++++++-- src/_pytest/config/argparsing.py | 27 +++++++++++- src/_pytest/config/findpaths.py | 17 +++++-- testing/test_config.py | 76 ++++++++++++++++++++++++++++++++ 5 files changed, 151 insertions(+), 8 deletions(-) create mode 100644 changelog/11381.improvement.rst diff --git a/changelog/11381.improvement.rst b/changelog/11381.improvement.rst new file mode 100644 index 00000000000..74c080cc188 --- /dev/null +++ b/changelog/11381.improvement.rst @@ -0,0 +1,17 @@ +The ``type`` parameter of the ``parser.addini`` method now accepts `"int"` and ``"float"`` parameters, facilitating the parsing of configuration values in the configuration file. + +Example: + +.. code-block:: python + + def pytest_addoption(parser): + parser.addini("int_value", type="int", default=2, help="my int value") + parser.addini("float_value", type="float", default=4.2, help="my float value") + +The `pytest.ini` file: + +.. code-block:: ini + + [pytest] + int_value = 3 + float_value = 5.4 diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 9e5b192b335..02da5cf9229 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1587,6 +1587,8 @@ def getini(self, name: str): ``paths``, ``pathlist``, ``args`` and ``linelist`` : empty list ``[]`` ``bool`` : ``False`` ``string`` : empty string ``""`` + ``int`` : ``0`` + ``float`` : ``0.0`` If neither the ``default`` nor the ``type`` parameter is passed while registering the configuration through @@ -1605,9 +1607,11 @@ def getini(self, name: str): # Meant for easy monkeypatching by legacypath plugin. # Can be inlined back (with no cover removed) once legacypath is gone. - def _getini_unknown_type(self, name: str, type: str, value: str | list[str]): - msg = f"unknown configuration type: {type}" - raise ValueError(msg, value) # pragma: no cover + def _getini_unknown_type(self, name: str, type: str, value: object): + msg = ( + f"Option {name} has unknown configuration type {type} with value {value!r}" + ) + raise ValueError(msg) # pragma: no cover def _getini(self, name: str): try: @@ -1656,6 +1660,18 @@ def _getini(self, name: str): return _strtobool(str(value).strip()) elif type == "string": return value + elif type == "int": + if not isinstance(value, str): + raise TypeError( + f"Expected an int string for option {name} of type integer, but got: {value!r}" + ) from None + return int(value) + elif type == "float": + if not isinstance(value, str): + raise TypeError( + f"Expected a float string for option {name} of type float, but got: {value!r}" + ) from None + return float(value) elif type is None: return value else: diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index d535fe1096a..948dfe8a510 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -191,6 +191,12 @@ def addini( * ``linelist``: a list of strings, separated by line breaks * ``paths``: a list of :class:`pathlib.Path`, separated as in a shell * ``pathlist``: a list of ``py.path``, separated as in a shell + * ``int``: an integer + * ``float``: a floating-point number + + .. versionadded:: 8.4 + + The ``float`` and ``int`` types. For ``paths`` and ``pathlist`` types, they are considered relative to the ini-file. In case the execution is happening without an ini-file defined, @@ -209,7 +215,17 @@ def addini( The value of ini-variables can be retrieved via a call to :py:func:`config.getini(name) `. """ - assert type in (None, "string", "paths", "pathlist", "args", "linelist", "bool") + assert type in ( + None, + "string", + "paths", + "pathlist", + "args", + "linelist", + "bool", + "int", + "float", + ) if default is NOT_SET: default = get_ini_default_for_type(type) @@ -218,7 +234,10 @@ def addini( def get_ini_default_for_type( - type: Literal["string", "paths", "pathlist", "args", "linelist", "bool"] | None, + type: Literal[ + "string", "paths", "pathlist", "args", "linelist", "bool", "int", "float" + ] + | None, ) -> Any: """ Used by addini to get the default value for a given ini-option type, when @@ -230,6 +249,10 @@ def get_ini_default_for_type( return [] elif type == "bool": return False + elif type == "int": + return 0 + elif type == "float": + return 0.0 else: return "" diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index a7f45bf593e..15bfbb0613e 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -5,6 +5,7 @@ import os from pathlib import Path import sys +from typing import TYPE_CHECKING import iniconfig @@ -15,6 +16,16 @@ from _pytest.pathlib import safe_exists +if TYPE_CHECKING: + from typing import Union + + from typing_extensions import TypeAlias + + # Even though TOML supports richer data types, all values are converted to str/list[str] during + # parsing to maintain compatibility with the rest of the configuration system. + ConfigDict: TypeAlias = dict[str, Union[str, list[str]]] + + def _parse_ini_config(path: Path) -> iniconfig.IniConfig: """Parse the given generic '.ini' file using legacy IniConfig parser, returning the parsed object. @@ -29,7 +40,7 @@ def _parse_ini_config(path: Path) -> iniconfig.IniConfig: def load_config_dict_from_file( filepath: Path, -) -> dict[str, str | list[str]] | None: +) -> ConfigDict | None: """Load pytest configuration from the given file path, if supported. Return None if the file does not contain valid pytest configuration. @@ -85,7 +96,7 @@ def make_scalar(v: object) -> str | list[str]: def locate_config( invocation_dir: Path, args: Iterable[Path], -) -> tuple[Path | None, Path | None, dict[str, str | list[str]]]: +) -> tuple[Path | None, Path | None, ConfigDict]: """Search in the list of arguments for a valid ini-file for pytest, and return a tuple of (rootdir, inifile, cfg-dict).""" config_names = [ @@ -172,7 +183,7 @@ def determine_setup( args: Sequence[str], rootdir_cmd_arg: str | None, invocation_dir: Path, -) -> tuple[Path, Path | None, dict[str, str | list[str]]]: +) -> tuple[Path, Path | None, ConfigDict]: """Determine the rootdir, inifile and ini configuration values from the command line arguments. diff --git a/testing/test_config.py b/testing/test_config.py index 53f26269f09..de07141238c 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -848,6 +848,82 @@ def pytest_addoption(parser): config = pytester.parseconfig() assert config.getini("strip") is bool_val + @pytest.mark.parametrize("str_val, int_val", [("10", 10), ("no-ini", 2)]) + def test_addini_int(self, pytester: Pytester, str_val: str, int_val: bool) -> None: + pytester.makeconftest( + """ + def pytest_addoption(parser): + parser.addini("ini_param", "", type="int", default=2) + """ + ) + if str_val != "no-ini": + pytester.makeini( + f""" + [pytest] + ini_param={str_val} + """ + ) + config = pytester.parseconfig() + assert config.getini("ini_param") == int_val + + def test_addini_int_invalid(self, pytester: Pytester) -> None: + pytester.makeconftest( + """ + def pytest_addoption(parser): + parser.addini("ini_param", "", type="int", default=2) + """ + ) + pytester.makepyprojecttoml( + """ + [tool.pytest.ini_options] + ini_param=["foo"] + """ + ) + config = pytester.parseconfig() + with pytest.raises( + TypeError, match="Expected an int string for option ini_param" + ): + _ = config.getini("ini_param") + + @pytest.mark.parametrize("str_val, float_val", [("10.5", 10.5), ("no-ini", 2.2)]) + def test_addini_float( + self, pytester: Pytester, str_val: str, float_val: bool + ) -> None: + pytester.makeconftest( + """ + def pytest_addoption(parser): + parser.addini("ini_param", "", type="float", default=2.2) + """ + ) + if str_val != "no-ini": + pytester.makeini( + f""" + [pytest] + ini_param={str_val} + """ + ) + config = pytester.parseconfig() + assert config.getini("ini_param") == float_val + + def test_addini_float_invalid(self, pytester: Pytester) -> None: + pytester.makeconftest( + """ + def pytest_addoption(parser): + parser.addini("ini_param", "", type="float", default=2.2) + """ + ) + pytester.makepyprojecttoml( + """ + [tool.pytest.ini_options] + ini_param=["foo"] + """ + ) + config = pytester.parseconfig() + with pytest.raises( + TypeError, match="Expected a float string for option ini_param" + ): + _ = config.getini("ini_param") + def test_addinivalue_line_existing(self, pytester: Pytester) -> None: pytester.makeconftest( """ From 7d73ace975a294f0a297fe19a6af92fbac7024b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Feb 2025 06:43:55 +0100 Subject: [PATCH 1118/1271] build(deps): Bump pytest-django in /testing/plugins_integration (#13231) Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.9.0 to 4.10.0. - [Release notes](https://github.com/pytest-dev/pytest-django/releases) - [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.9.0...v4.10.0) --- updated-dependencies: - dependency-name: pytest-django dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index ca4f6f700c4..5562329e1de 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -3,7 +3,7 @@ django==5.1.6 pytest-asyncio==0.25.3 pytest-bdd==8.1.0 pytest-cov==6.0.0 -pytest-django==4.9.0 +pytest-django==4.10.0 pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.14.0 From d68ad68e35277e8a1763dcc0b9425a95bc031cce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 07:17:58 -0300 Subject: [PATCH 1119/1271] [automated] Update plugin list (#13226) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 172 +++++++++++++++++-------------- 1 file changed, 94 insertions(+), 78 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index cf1f0902885..28492e22a62 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Jan 17, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Feb 10, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -161,7 +161,7 @@ This list contains 1583 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Feb 05, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Feb 11, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -230,7 +230,7 @@ This list contains 1583 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Aug 28, 2024 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Feb 13, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-checkdocs` check the README when running tests Apr 30, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -261,7 +261,7 @@ This list contains 1583 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Jan 29, 2025 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Feb 09, 2025 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) @@ -330,7 +330,7 @@ This list contains 1583 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Oct 20, 2024 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Feb 11, 2025 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Feb 07, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -353,7 +353,7 @@ This list contains 1583 plugins. :pypi:`pytest-dbt-adapter` A pytest plugin for testing dbt adapter plugins Nov 24, 2021 N/A pytest (<7,>=6) :pypi:`pytest-dbt-conventions` A pytest plugin for linting a dbt project's conventions Mar 02, 2022 N/A pytest (>=6.2.5,<7.0.0) :pypi:`pytest-dbt-core` Pytest extension for dbt. Jun 04, 2024 N/A pytest>=6.2.5; extra == "test" - :pypi:`pytest-dbt-duckdb` Add your description here Feb 07, 2025 N/A pytest>=8.3.4 + :pypi:`pytest-dbt-duckdb` Fearless testing for dbt models, powered by DuckDB. Feb 09, 2025 4 - Beta pytest>=8.3.4 :pypi:`pytest-dbt-postgres` Pytest tooling to unittest DBT & Postgres models Sep 03, 2024 N/A pytest<9.0.0,>=8.3.2 :pypi:`pytest-dbus-notification` D-BUS notifications for pytest results. Mar 05, 2014 5 - Production/Stable N/A :pypi:`pytest-dbx` Pytest plugin to run unit tests for dbx (Databricks CLI extensions) related code Nov 29, 2022 N/A pytest (>=7.1.3,<8.0.0) @@ -388,7 +388,7 @@ This list contains 1583 plugins. :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. Jun 09, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-ditto-pandas` pytest-ditto plugin for pandas snapshots. May 29, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-ditto-pyarrow` pytest-ditto plugin for pyarrow tables. Jun 09, 2024 4 - Beta pytest>=3.5.0 - :pypi:`pytest-django` A Django plugin for pytest. Sep 02, 2024 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-django` A Django plugin for pytest. Feb 10, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A @@ -475,15 +475,15 @@ This list contains 1583 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 Jul 25, 2024 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. Feb 06, 2025 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 06, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 06, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 06, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Feb 06, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 06, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 06, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 06, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 06, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Feb 11, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 11, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 11, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 11, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Feb 11, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 11, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 11, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 11, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 11, 2025 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) @@ -513,11 +513,11 @@ This list contains 1583 plugins. :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Nov 20, 2024 N/A pytest>=7 - :pypi:`pytest-exasol-backend` Nov 22, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-extension` Oct 10, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-backend` Feb 11, 2025 N/A pytest<9,>=7 + :pypi:`pytest-exasol-extension` Feb 11, 2025 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Nov 22, 2024 N/A pytest<9,>=7 :pypi:`pytest-exasol-saas` Nov 22, 2024 N/A pytest<9,>=7 - :pypi:`pytest-exasol-slc` Nov 01, 2024 N/A pytest<9,>=7 + :pypi:`pytest-exasol-slc` Feb 11, 2025 N/A pytest<9,>=7 :pypi:`pytest-excel` pytest plugin for generating excel reports Jun 18, 2024 5 - Production/Stable pytest>3.6 :pypi:`pytest-exceptional` Better exceptions Mar 16, 2017 4 - Beta N/A :pypi:`pytest-exception-script` Walk your code through exception script to check it's resiliency to failures. Aug 04, 2020 3 - Alpha pytest @@ -612,7 +612,7 @@ This list contains 1583 plugins. :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Jul 30, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-freethreaded` pytest plugin for running parallel tests Oct 03, 2024 5 - Production/Stable pytest - :pypi:`pytest-freezeblaster` Wrap tests with fixtures in freeze_time Jan 23, 2025 N/A pytest>=6.2.5 + :pypi:`pytest-freezeblaster` Wrap tests with fixtures in freeze_time Feb 11, 2025 N/A pytest>=6.2.5 :pypi:`pytest-freezegun` Wrap tests with fixtures in freeze_time Jul 19, 2020 4 - Beta pytest (>=3.0.0) :pypi:`pytest-freezer` Pytest plugin providing a fixture interface for spulec/freezegun Dec 12, 2024 N/A pytest>=3.6 :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A @@ -634,7 +634,7 @@ This list contains 1583 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Jan 22, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Feb 14, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -678,7 +678,7 @@ This list contains 1583 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Feb 08, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 15, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -698,7 +698,7 @@ This list contains 1583 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Sep 18, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace Jan 11, 2025 4 - Beta pytest>=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace. Feb 11, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Jan 21, 2025 3 - Alpha N/A @@ -746,12 +746,13 @@ This list contains 1583 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. Nov 19, 2024 4 - Beta pytest + :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Feb 13, 2025 4 - Beta pytest :pypi:`pytest-invenio` Pytest fixtures for Invenio. Dec 02, 2024 5 - Production/Stable pytest<9.0.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A + :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Feb 14, 2025 N/A pytest :pypi:`pytest-ipywidgets` Jan 29, 2025 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Dec 05, 2024 4 - Beta pytest>=5 @@ -859,7 +860,7 @@ This list contains 1583 plugins. :pypi:`pytest-marks` UNKNOWN Nov 23, 2012 3 - Alpha N/A :pypi:`pytest-mask-secrets` Pytest plugin to hide sensitive data in test reports Jan 28, 2025 N/A N/A :pypi:`pytest-matcher` Easy way to match captured \`pytest\` output against expectations stored in files Aug 01, 2024 5 - Production/Stable pytest - :pypi:`pytest-matchers` Matchers for pytest Aug 26, 2024 N/A pytest<9.0,>=7.0 + :pypi:`pytest-matchers` Matchers for pytest Feb 11, 2025 N/A pytest<9.0,>=7.0 :pypi:`pytest-match-skip` Skip matching marks. Matches partial marks using wildcards. May 15, 2019 4 - Beta pytest (>=4.4.1) :pypi:`pytest-mat-report` this is report Jan 20, 2021 N/A N/A :pypi:`pytest-matrix` Provide tools for generating tests from combinations of fixtures. Jun 24, 2020 5 - Production/Stable pytest (>=5.4.3,<6.0.0) @@ -876,7 +877,7 @@ This list contains 1583 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Feb 06, 2025 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Feb 14, 2025 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -933,7 +934,7 @@ This list contains 1583 plugins. :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Dec 21, 2024 4 - Beta pytest>=7.0.0 - :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Apr 12, 2021 N/A pytest>=6.0.0 + :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Feb 14, 2025 N/A pytest>=6.0.0 :pypi:`pytest-mypy-runner` Run the mypy static type checker as a pytest test case Apr 23, 2024 N/A pytest>=8.0 :pypi:`pytest-mypy-testing` Pytest plugin to check mypy output. Mar 04, 2024 N/A pytest>=7,<9 :pypi:`pytest-mysql` MySQL process and client fixtures for pytest Dec 10, 2024 5 - Production/Stable pytest>=6.2 @@ -968,7 +969,7 @@ This list contains 1583 plugins. :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Feb 26, 2024 5 - Production/Stable N/A :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 - :pypi:`pytest-oarepo` Jan 28, 2025 N/A pytest>=7.1.2; extra == "local" + :pypi:`pytest-oarepo` Feb 14, 2025 N/A pytest>=7.1.2; extra == "base" :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) @@ -994,7 +995,7 @@ This list contains 1583 plugins. :pypi:`pytest-order-modify` 新增run_marker 来自定义用例的执行顺序 Nov 04, 2022 N/A N/A :pypi:`pytest-osxnotify` OS X notifications for py.test results. May 15, 2015 N/A N/A :pypi:`pytest-ot` A pytest plugin for instrumenting test runs via OpenTelemetry Mar 21, 2024 N/A pytest; extra == "dev" - :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Mar 18, 2024 N/A pytest==8.1.1 + :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Feb 10, 2025 N/A pytest==8.3.4 :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A :pypi:`pytest-owner` Add owner mark for tests Aug 19, 2024 N/A pytest :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A @@ -1127,7 +1128,7 @@ This list contains 1583 plugins. :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-qanova` A pytest plugin to collect test information Sep 05, 2024 3 - Alpha pytest - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Jan 08, 2025 5 - Production/Stable pytest<9.0.0,>=7.2.2 + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Feb 11, 2025 5 - Production/Stable pytest<9.0.0,>=7.2.2 :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 14, 2024 5 - Production/Stable pytest>=6.0 @@ -1258,7 +1259,7 @@ This list contains 1583 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 08, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 13, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1270,7 +1271,7 @@ This list contains 1583 plugins. :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 Feb 01, 2024 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. Feb 08, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Feb 13, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1451,7 +1452,6 @@ This list contains 1583 plugins. :pypi:`pytest-test-tracer-for-pytest` A plugin that allows coll test data for use on Test Tracer Jun 28, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-tracer-for-pytest-bdd` A plugin that allows coll test data for use on Test Tracer Aug 20, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-test-utils` Feb 08, 2024 N/A pytest >=3.9 - :pypi:`pytest-test-yaml` a pytest test package Feb 08, 2025 N/A pytest :pypi:`pytest-tesults` Tesults plugin for pytest Nov 12, 2024 5 - Production/Stable pytest>=3.5.0 :pypi:`pytest-textual-snapshot` Snapshot testing for Textual apps Jan 23, 2025 5 - Production/Stable pytest>=8.0.0 :pypi:`pytest-tezos` pytest-ligo Jan 16, 2020 4 - Beta N/A @@ -1522,6 +1522,7 @@ This list contains 1583 plugins. :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) :pypi:`pytest-unique` Pytest fixture to generate unique values. Jan 03, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) + :pypi:`pytest-unittest-id-runner` A pytest plugin to run tests using unittest-style test IDs Feb 09, 2025 N/A pytest>=6.0.0 :pypi:`pytest-unmagic` Pytest fixtures with conventional import semantics Oct 22, 2024 5 - Production/Stable pytest :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Jul 05, 2024 4 - Beta pytest>=7.0.0 @@ -1595,6 +1596,7 @@ This list contains 1583 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. Dec 15, 2024 4 - Beta pytest>=7.2.2 :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-fei` a pytest yaml allure package Feb 09, 2025 N/A pytest :pypi:`pytest-yaml-sanmu` Pytest plugin for generating test cases with YAML. In test cases, you can use markers, fixtures, variables, and even call Python functions. Jan 03, 2025 N/A pytest>=8.2.2 :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 @@ -2211,7 +2213,7 @@ This list contains 1583 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Jan 17, 2025, + *last release*: Feb 10, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2512,7 +2514,7 @@ This list contains 1583 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Feb 05, 2025, + *last release*: Feb 11, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -2995,7 +2997,7 @@ This list contains 1583 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Aug 28, 2024, + *last release*: Feb 13, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -3212,7 +3214,7 @@ This list contains 1583 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Jan 29, 2025, + *last release*: Feb 09, 2025, *status*: N/A, *requires*: pytest<9,>=4 @@ -3695,7 +3697,7 @@ This list contains 1583 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Oct 20, 2024, + *last release*: Feb 11, 2025, *status*: 4 - Beta, *requires*: pytest @@ -3856,11 +3858,11 @@ This list contains 1583 plugins. Pytest extension for dbt. :pypi:`pytest-dbt-duckdb` - *last release*: Feb 07, 2025, - *status*: N/A, + *last release*: Feb 09, 2025, + *status*: 4 - Beta, *requires*: pytest>=8.3.4 - Add your description here + Fearless testing for dbt models, powered by DuckDB. :pypi:`pytest-dbt-postgres` *last release*: Sep 03, 2024, @@ -4101,7 +4103,7 @@ This list contains 1583 plugins. pytest-ditto plugin for pyarrow tables. :pypi:`pytest-django` - *last release*: Sep 02, 2024, + *last release*: Feb 10, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -4710,63 +4712,63 @@ This list contains 1583 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Feb 06, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -4976,14 +4978,14 @@ This list contains 1583 plugins. Pytest plugin for testing examples in docstrings and markdown files. :pypi:`pytest-exasol-backend` - *last release*: Nov 22, 2024, + *last release*: Feb 11, 2025, *status*: N/A, *requires*: pytest<9,>=7 :pypi:`pytest-exasol-extension` - *last release*: Oct 10, 2024, + *last release*: Feb 11, 2025, *status*: N/A, *requires*: pytest<9,>=7 @@ -5004,7 +5006,7 @@ This list contains 1583 plugins. :pypi:`pytest-exasol-slc` - *last release*: Nov 01, 2024, + *last release*: Feb 11, 2025, *status*: N/A, *requires*: pytest<9,>=7 @@ -5669,7 +5671,7 @@ This list contains 1583 plugins. pytest plugin for running parallel tests :pypi:`pytest-freezeblaster` - *last release*: Jan 23, 2025, + *last release*: Feb 11, 2025, *status*: N/A, *requires*: pytest>=6.2.5 @@ -5823,7 +5825,7 @@ This list contains 1583 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Jan 22, 2025, + *last release*: Feb 14, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6131,7 +6133,7 @@ This list contains 1583 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 08, 2025, + *last release*: Feb 15, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6271,11 +6273,11 @@ This list contains 1583 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Jan 11, 2025, + *last release*: Feb 11, 2025, *status*: 4 - Beta, *requires*: pytest>=7.0.0 - A pytest plugin to record HTTP(S) requests with stack trace + A pytest plugin to record HTTP(S) requests with stack trace. :pypi:`pytest-http-mocker` *last release*: Oct 20, 2019, @@ -6607,7 +6609,7 @@ This list contains 1583 plugins. Pytest plugin for intercepting outgoing connection requests during pytest run. :pypi:`pytest-interface-tester` - *last release*: Nov 19, 2024, + *last release*: Feb 13, 2025, *status*: 4 - Beta, *requires*: pytest @@ -6648,6 +6650,13 @@ This list contains 1583 plugins. THIS PROJECT IS ABANDONED + :pypi:`pytest-ipynb2` + *last release*: Feb 14, 2025, + *status*: N/A, + *requires*: pytest + + Pytest plugin to run tests in Jupyter Notebooks + :pypi:`pytest-ipywidgets` *last release*: Jan 29, 2025, *status*: N/A, @@ -7398,7 +7407,7 @@ This list contains 1583 plugins. Easy way to match captured \`pytest\` output against expectations stored in files :pypi:`pytest-matchers` - *last release*: Aug 26, 2024, + *last release*: Feb 11, 2025, *status*: N/A, *requires*: pytest<9.0,>=7.0 @@ -7517,7 +7526,7 @@ This list contains 1583 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Feb 06, 2025, + *last release*: Feb 14, 2025, *status*: N/A, *requires*: N/A @@ -7916,7 +7925,7 @@ This list contains 1583 plugins. pytest plugin for writing tests for mypy plugins :pypi:`pytest-mypy-plugins-shim` - *last release*: Apr 12, 2021, + *last release*: Feb 14, 2025, *status*: N/A, *requires*: pytest>=6.0.0 @@ -8161,9 +8170,9 @@ This list contains 1583 plugins. PyTest plugin for the OAR testing framework :pypi:`pytest-oarepo` - *last release*: Jan 28, 2025, + *last release*: Feb 14, 2025, *status*: N/A, - *requires*: pytest>=7.1.2; extra == "local" + *requires*: pytest>=7.1.2; extra == "base" @@ -8343,9 +8352,9 @@ This list contains 1583 plugins. A pytest plugin for instrumenting test runs via OpenTelemetry :pypi:`pytest-otel` - *last release*: Mar 18, 2024, + *last release*: Feb 10, 2025, *status*: N/A, - *requires*: pytest==8.1.1 + *requires*: pytest==8.3.4 OpenTelemetry plugin for Pytest @@ -9274,7 +9283,7 @@ This list contains 1583 plugins. A pytest plugin to collect test information :pypi:`pytest-qaseio` - *last release*: Jan 08, 2025, + *last release*: Feb 11, 2025, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=7.2.2 @@ -10191,7 +10200,7 @@ This list contains 1583 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Feb 08, 2025, + *last release*: Feb 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10275,7 +10284,7 @@ This list contains 1583 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Feb 08, 2025, + *last release*: Feb 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -11541,13 +11550,6 @@ This list contains 1583 plugins. - :pypi:`pytest-test-yaml` - *last release*: Feb 08, 2025, - *status*: N/A, - *requires*: pytest - - a pytest test package - :pypi:`pytest-tesults` *last release*: Nov 12, 2024, *status*: 5 - Production/Stable, @@ -12038,6 +12040,13 @@ This list contains 1583 plugins. A pytest plugin for filtering unittest-based test classes + :pypi:`pytest-unittest-id-runner` + *last release*: Feb 09, 2025, + *status*: N/A, + *requires*: pytest>=6.0.0 + + A pytest plugin to run tests using unittest-style test IDs + :pypi:`pytest-unmagic` *last release*: Oct 22, 2024, *status*: 5 - Production/Stable, @@ -12549,6 +12558,13 @@ This list contains 1583 plugins. This plugin is used to load yaml output to your test using pytest framework. + :pypi:`pytest-yaml-fei` + *last release*: Feb 09, 2025, + *status*: N/A, + *requires*: pytest + + a pytest yaml allure package + :pypi:`pytest-yaml-sanmu` *last release*: Jan 03, 2025, *status*: N/A, From 426fe19199a0e2e3ce5ba1fdd0ec45e9fd383ca9 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Tue, 18 Feb 2025 13:20:08 +0100 Subject: [PATCH 1120/1271] Apply suggestions from code review add `versionadded` Co-authored-by: Bruno Oliveira --- src/_pytest/_raises_group.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/_pytest/_raises_group.py b/src/_pytest/_raises_group.py index 92884409694..64b0388a103 100644 --- a/src/_pytest/_raises_group.py +++ b/src/_pytest/_raises_group.py @@ -290,7 +290,10 @@ def _check_type(self, exception: BaseException) -> TypeGuard[BaseExcT_co_default @final class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): - """Contextmanager for checking for an expected :exc:`ExceptionGroup`. + """ + .. versionadded:: 8.4 + + Contextmanager for checking for an expected :exc:`ExceptionGroup`. This works similar to :func:`pytest.raises`, but allows for specifying the structure of an :exc:`ExceptionGroup`. :meth:`ExceptionInfo.group_contains` also tries to handle exception groups, but it is very bad at checking that you *didn't* get unexpected exceptions. @@ -309,7 +312,7 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): #. It will only catch exceptions wrapped in an exceptiongroup by default. - * With ``allow_unwrapped=True`` you can specify a single expected exception (or `RaisesExc`) and it will match + * With ``allow_unwrapped=True`` you can specify a single expected exception (or :class:`RaisesExc`) and it will match the exception even if it is not inside an :exc:`ExceptionGroup`. If you expect one of several different exception types you need to use a :class:`RaisesExc` object. From 7f9966bab49f7a76356ab10c56fc54ffb6a7eb70 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 12:20:35 +0000 Subject: [PATCH 1121/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/_raises_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/_raises_group.py b/src/_pytest/_raises_group.py index 64b0388a103..a66eea45f94 100644 --- a/src/_pytest/_raises_group.py +++ b/src/_pytest/_raises_group.py @@ -292,7 +292,7 @@ def _check_type(self, exception: BaseException) -> TypeGuard[BaseExcT_co_default class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): """ .. versionadded:: 8.4 - + Contextmanager for checking for an expected :exc:`ExceptionGroup`. This works similar to :func:`pytest.raises`, but allows for specifying the structure of an :exc:`ExceptionGroup`. :meth:`ExceptionInfo.group_contains` also tries to handle exception groups, From 0cdc5da1faecba5f860f66c8b57d7d3b80b8bea5 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Tue, 18 Feb 2025 13:21:10 +0100 Subject: [PATCH 1122/1271] Update src/_pytest/_raises_group.py Co-authored-by: Bruno Oliveira --- src/_pytest/_raises_group.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/_pytest/_raises_group.py b/src/_pytest/_raises_group.py index a66eea45f94..5df3b8df9aa 100644 --- a/src/_pytest/_raises_group.py +++ b/src/_pytest/_raises_group.py @@ -176,7 +176,10 @@ def matches( @final class RaisesExc(AbstractRaises[BaseExcT_co_default]): - """Helper class to be used together with RaisesGroups when you want to specify requirements on sub-exceptions. + """ + .. versionadded:: 8.4 + + Helper class to be used together with RaisesGroups when you want to specify requirements on sub-exceptions. You don't need this if you only want to specify the type, since :class:`RaisesGroup` accepts ``type[BaseException]``. From cb3067436e963e24143fdd7e346e831b3924d280 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Feb 2025 12:21:36 +0000 Subject: [PATCH 1123/1271] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/_raises_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/_raises_group.py b/src/_pytest/_raises_group.py index 5df3b8df9aa..f31a9634af0 100644 --- a/src/_pytest/_raises_group.py +++ b/src/_pytest/_raises_group.py @@ -178,7 +178,7 @@ def matches( class RaisesExc(AbstractRaises[BaseExcT_co_default]): """ .. versionadded:: 8.4 - + Helper class to be used together with RaisesGroups when you want to specify requirements on sub-exceptions. You don't need this if you only want to specify the type, since :class:`RaisesGroup` From 9714dc0b5c467d70e672311bc7165bf8739f7a02 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 18 Feb 2025 15:11:00 +0100 Subject: [PATCH 1124/1271] doc improvements after review --- doc/en/how-to/assert.rst | 22 ++++++++++++++----- .../{_raises_group.py => raises_group.py} | 12 +++++----- 2 files changed, 24 insertions(+), 10 deletions(-) rename src/_pytest/{_raises_group.py => raises_group.py} (98%) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 08e030b8cab..c01e59a7a0e 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -279,12 +279,12 @@ exception at a specific level; exceptions contained directly in the top assert not excinfo.group_contains(RuntimeError, depth=2) assert not excinfo.group_contains(TypeError, depth=1) -Alternate form (legacy) -~~~~~~~~~~~~~~~~~~~~~~~ +Alternate `pytest.raises` form (legacy) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There is an alternate form where you pass -a function that will be executed, along ``*args`` and ``**kwargs``, and :func:`pytest.raises` -will execute the function with the arguments and assert that the given exception is raised: +There is an alternate form of :func:`pytest.raises` where you pass +a function that will be executed, along with ``*args`` and ``**kwargs``. :func:`pytest.raises` +will then execute the function with those arguments and assert that the given exception is raised: .. code-block:: python @@ -329,6 +329,18 @@ This will only "xfail" if the test fails by raising ``IndexError`` or subclasses * Using :func:`pytest.raises` is likely to be better for cases where you are testing exceptions your own code is deliberately raising, which is the majority of cases. +You can also use :class:`pytest.RaisesGroup`: + +.. code-block:: python + + def f(): + raise ExceptionGroup("", [IndexError()]) + + + @pytest.mark.xfail(raises=RaisesGroup(IndexError)) + def test_f(): + f() + .. _`assertwarns`: diff --git a/src/_pytest/_raises_group.py b/src/_pytest/raises_group.py similarity index 98% rename from src/_pytest/_raises_group.py rename to src/_pytest/raises_group.py index f31a9634af0..a6caab919da 100644 --- a/src/_pytest/_raises_group.py +++ b/src/_pytest/raises_group.py @@ -197,9 +197,6 @@ class RaisesExc(AbstractRaises[BaseExcT_co_default]): ... with RaisesGroups(RaisesExc(check=lambda x: type(x) is ValueError)): ... - - Tip: if you install ``hypothesis`` and import it in ``conftest.py`` you will get - readable ``repr``'s of ``check`` callables in the output. """ # Trio bundled hypothesis monkeypatching, we will probably instead assume that @@ -367,8 +364,13 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): even though it generally does not care about the order of the exceptions in the group. To avoid the above you should specify the first :exc:`ValueError` with a :class:`RaisesExc` as well. - Tip: if you install ``hypothesis`` and import it in ``conftest.py`` you will get - readable ``repr``'s of ``check`` callables in the output. + .. note:: + When raised exceptions don't match the expected ones, you'll get a detailed error + message explaining why. This includes ``repr(check)`` if set, which in Python can be + overly verbose, showing memory locations etc etc. + + If installed and imported (in e.g. ``conftest.py``), the ``hypothesis`` library will + monkeypatch this output to provide shorter & more readable repr's. """ # allow_unwrapped=True requires: singular exception, exception not being From 4d2c70911b55f211eba704b8baedca38c79da62a Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 18 Feb 2025 15:16:36 +0100 Subject: [PATCH 1125/1271] fix imports after file rename --- src/_pytest/mark/structures.py | 2 +- src/_pytest/skipping.py | 2 +- src/pytest/__init__.py | 6 +++--- testing/python/raises_group.py | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 50225f7529f..b624a089617 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -23,11 +23,11 @@ from .._code import getfslineno from ..compat import NOTSET from ..compat import NotSetType -from _pytest._raises_group import AbstractRaises from _pytest.config import Config from _pytest.deprecated import check_ispytest from _pytest.deprecated import MARKED_FIXTURE from _pytest.outcomes import fail +from _pytest.raises_group import AbstractRaises from _pytest.scope import _ScopeName from _pytest.warning_types import PytestUnknownMarkWarning diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 293bea704cb..20efefb84df 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -12,7 +12,6 @@ import traceback from typing import Optional -from _pytest._raises_group import AbstractRaises from _pytest.config import Config from _pytest.config import hookimpl from _pytest.config.argparsing import Parser @@ -21,6 +20,7 @@ from _pytest.outcomes import fail from _pytest.outcomes import skip from _pytest.outcomes import xfail +from _pytest.raises_group import AbstractRaises from _pytest.reports import BaseReport from _pytest.reports import TestReport from _pytest.runner import CallInfo diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index a16377ca6bb..e3e782654fe 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -6,9 +6,6 @@ from _pytest import __version__ from _pytest import version_tuple from _pytest._code import ExceptionInfo -from _pytest._raises_group import RaisesExc -from _pytest._raises_group import RaisesGroup -from _pytest._raises_group import RaisesGroup as raises_group from _pytest.assertion import register_assert_rewrite from _pytest.cacheprovider import Cache from _pytest.capture import CaptureFixture @@ -63,6 +60,9 @@ from _pytest.python import Package from _pytest.python_api import approx from _pytest.python_api import raises +from _pytest.raises_group import RaisesExc +from _pytest.raises_group import RaisesGroup +from _pytest.raises_group import RaisesGroup as raises_group from _pytest.recwarn import deprecated_call from _pytest.recwarn import WarningsRecorder from _pytest.recwarn import warns diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index 4ac6f8a7ced..60eb28386f8 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -9,11 +9,11 @@ from typing import TYPE_CHECKING from _pytest._code import ExceptionInfo -from _pytest._raises_group import RaisesExc -from _pytest._raises_group import RaisesGroup -from _pytest._raises_group import repr_callable from _pytest.outcomes import Failed from _pytest.pytester import Pytester +from _pytest.raises_group import RaisesExc +from _pytest.raises_group import RaisesGroup +from _pytest.raises_group import repr_callable import pytest From 9e38a9ed2c4375b91c0c4553608470987187b4e2 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 18 Feb 2025 16:00:09 +0100 Subject: [PATCH 1126/1271] fix another import --- src/_pytest/raises_group.py | 4 ++-- testing/typing_raises_group.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index a6caab919da..9c2a6aa05e4 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -312,8 +312,8 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): #. It will only catch exceptions wrapped in an exceptiongroup by default. - * With ``allow_unwrapped=True`` you can specify a single expected exception (or :class:`RaisesExc`) and it will match - the exception even if it is not inside an :exc:`ExceptionGroup`. + * With ``allow_unwrapped=True`` you can specify a single expected exception (or :class:`RaisesExc`) and it will + match the exception even if it is not inside an :exc:`ExceptionGroup`. If you expect one of several different exception types you need to use a :class:`RaisesExc` object. #. By default it cares about the full structure with nested :exc:`ExceptionGroup`'s. You can specify nested diff --git a/testing/typing_raises_group.py b/testing/typing_raises_group.py index 87cce35b72d..3dd786672b6 100644 --- a/testing/typing_raises_group.py +++ b/testing/typing_raises_group.py @@ -6,8 +6,8 @@ from typing_extensions import assert_type -from _pytest._raises_group import RaisesExc -from _pytest._raises_group import RaisesGroup +from _pytest.raises_group import RaisesExc +from _pytest.raises_group import RaisesGroup if sys.version_info < (3, 11): From ff9dd38a7a194374eaafeae34f930aea8a749acb Mon Sep 17 00:00:00 2001 From: jakkdl Date: Tue, 18 Feb 2025 16:29:54 +0100 Subject: [PATCH 1127/1271] sed s/RaisesGroups/RaisesGroup --- src/_pytest/raises_group.py | 28 ++++++++++++++-------------- testing/typing_raises_group.py | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index 9c2a6aa05e4..d9b514089de 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -179,7 +179,7 @@ class RaisesExc(AbstractRaises[BaseExcT_co_default]): """ .. versionadded:: 8.4 - Helper class to be used together with RaisesGroups when you want to specify requirements on sub-exceptions. + Helper class to be used together with RaisesGroup when you want to specify requirements on sub-exceptions. You don't need this if you only want to specify the type, since :class:`RaisesGroup` accepts ``type[BaseException]``. @@ -191,11 +191,11 @@ class RaisesExc(AbstractRaises[BaseExcT_co_default]): Examples:: - with RaisesGroups(RaisesExc(ValueError, match="string")) + with RaisesGroup(RaisesExc(ValueError, match="string")) ... - with RaisesGroups(RaisesExc(check=lambda x: x.args == (3, "hello"))): + with RaisesGroup(RaisesExc(check=lambda x: x.args == (3, "hello"))): ... - with RaisesGroups(RaisesExc(check=lambda x: type(x) is ValueError)): + with RaisesGroup(RaisesExc(check=lambda x: type(x) is ValueError)): ... """ @@ -323,33 +323,33 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): extracting all exceptions inside any nested :exc:`ExceptionGroup`, before matching. It does not care about the order of the exceptions, so - ``RaisesGroups(ValueError, TypeError)`` + ``RaisesGroup(ValueError, TypeError)`` is equivalent to - ``RaisesGroups(TypeError, ValueError)``. + ``RaisesGroup(TypeError, ValueError)``. Examples:: - with RaisesGroups(ValueError): + with RaisesGroup(ValueError): raise ExceptionGroup("", (ValueError(),)) - with RaisesGroups( + with RaisesGroup( ValueError, ValueError, RaisesExc(TypeError, match="expected int") ): ... - with RaisesGroups( + with RaisesGroup( KeyboardInterrupt, match="hello", check=lambda x: type(x) is BaseExceptionGroup, ): ... - with RaisesGroups(RaisesGroups(ValueError)): + with RaisesGroup(RaisesGroup(ValueError)): raise ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)) # flatten_subgroups - with RaisesGroups(ValueError, flatten_subgroups=True): + with RaisesGroup(ValueError, flatten_subgroups=True): raise ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)) # allow_unwrapped - with RaisesGroups(ValueError, allow_unwrapped=True): + with RaisesGroup(ValueError, allow_unwrapped=True): raise ValueError @@ -358,7 +358,7 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): The matching algorithm is greedy, which means cases such as this may fail:: - with RaisesGroups(ValueError, RaisesExc(ValueError, match="hello")): + with RaisesGroup(ValueError, RaisesExc(ValueError, match="hello")): raise ExceptionGroup("", (ValueError("hello"), ValueError("goodbye"))) even though it generally does not care about the order of the exceptions in the group. @@ -620,7 +620,7 @@ def matches( with pytest.raises(TypeError) as excinfo: ... - assert RaisesGroups(ValueError).matches(excinfo.value.__cause__) + assert RaisesGroup(ValueError).matches(excinfo.value.__cause__) # the above line is equivalent to myexc = excinfo.value.__cause assert isinstance(myexc, BaseExceptionGroup) diff --git a/testing/typing_raises_group.py b/testing/typing_raises_group.py index 3dd786672b6..6e91cbf6da1 100644 --- a/testing/typing_raises_group.py +++ b/testing/typing_raises_group.py @@ -155,7 +155,7 @@ def check_nested_raisesgroups_contextmanager() -> None: def check_nested_raisesgroups_matches() -> None: - """Check nested RaisesGroups with .matches""" + """Check nested RaisesGroup with .matches""" exc: ExceptionGroup[ExceptionGroup[ValueError]] = ExceptionGroup( "", (ExceptionGroup("", (ValueError(),)),), From 2c8cd64d5f0f4bf8ea6c9f5723f6422a03b28bf7 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Thu, 20 Feb 2025 16:38:02 +0100 Subject: [PATCH 1128/1271] make pytest.raises use RaisesExc... which made me notice about a million small things differing between raises and RaisesExc, and some random other stuff... --- src/_pytest/_code/code.py | 2 +- src/_pytest/python_api.py | 172 ++++--------- src/_pytest/raises_group.py | 399 ++++++++++++++++++++++-------- testing/python/raises.py | 63 ++++- testing/python/raises_group.py | 427 ++++++++++++++++++++++----------- testing/typing_raises_group.py | 6 +- 6 files changed, 687 insertions(+), 382 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 5b85d295d36..429b856596b 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -763,7 +763,7 @@ def match(self, regexp: str | re.Pattern[str]) -> Literal[True]: """ __tracebackhide__ = True value = self._stringify_exception(self.value) - msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" + msg = f"Raised exception did not match: Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" if regexp == value: msg += "\n Did you mean to `re.escape()` the regex?" assert re.search(regexp, value), msg diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index c90f67f7b3d..8a11a128293 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -6,30 +6,25 @@ from collections.abc import Mapping from collections.abc import Sequence from collections.abc import Sized -from contextlib import AbstractContextManager from decimal import Decimal import math from numbers import Complex import pprint import re import sys -from types import TracebackType from typing import Any -from typing import cast -from typing import final -from typing import get_args -from typing import get_origin from typing import overload from typing import TYPE_CHECKING from typing import TypeVar import _pytest._code from _pytest.outcomes import fail +from _pytest.raises_group import BaseExcT_co_default +from _pytest.raises_group import RaisesExc if sys.version_info < (3, 11): - from exceptiongroup import BaseExceptionGroup - from exceptiongroup import ExceptionGroup + pass if TYPE_CHECKING: from numpy import ndarray @@ -791,7 +786,7 @@ def _as_numpy_array(obj: object) -> ndarray | None: # builtin pytest.raises helper -E = TypeVar("E", bound=BaseException) +E = TypeVar("E", bound=BaseException, default=BaseException) @overload @@ -799,7 +794,21 @@ def raises( expected_exception: type[E] | tuple[type[E], ...], *, match: str | re.Pattern[str] | None = ..., -) -> RaisesContext[E]: ... + check: Callable[[BaseExcT_co_default], bool] = ..., +) -> RaisesExc[E]: ... + + +@overload +def raises( + *, + match: str | re.Pattern[str], + # If exception_type is not provided, check() must do any typechecks itself. + check: Callable[[BaseException], bool] = ..., +) -> RaisesExc[BaseException]: ... + + +@overload +def raises(*, check: Callable[[BaseException], bool]) -> RaisesExc[BaseException]: ... @overload @@ -812,8 +821,10 @@ def raises( def raises( - expected_exception: type[E] | tuple[type[E], ...], *args: Any, **kwargs: Any -) -> RaisesContext[E] | _pytest._code.ExceptionInfo[E]: + expected_exception: type[E] | tuple[type[E], ...] | None = None, + *args: Any, + **kwargs: Any, +) -> RaisesExc[BaseException] | _pytest._code.ExceptionInfo[E]: r"""Assert that a code block/function call raises an exception type, or one of its subclasses. :param expected_exception: @@ -960,117 +971,38 @@ def raises( """ __tracebackhide__ = True + if not args: + if set(kwargs) - {"match", "check", "expected_exception"}: + msg = "Unexpected keyword arguments passed to pytest.raises: " + msg += ", ".join(sorted(kwargs)) + msg += "\nUse context-manager form instead?" + raise TypeError(msg) + + if expected_exception is None: + return RaisesExc(**kwargs) + return RaisesExc(expected_exception, **kwargs) + if not expected_exception: raise ValueError( f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. " f"Raising exceptions is already understood as failing the test, so you don't need " f"any special code to say 'this should never raise an exception'." ) - - expected_exceptions: tuple[type[E], ...] - origin_exc: type[E] | None = get_origin(expected_exception) - if isinstance(expected_exception, type): - expected_exceptions = (expected_exception,) - elif origin_exc and issubclass(origin_exc, BaseExceptionGroup): - expected_exceptions = (cast(type[E], expected_exception),) - else: - expected_exceptions = expected_exception - - def validate_exc(exc: type[E]) -> type[E]: - __tracebackhide__ = True - origin_exc: type[E] | None = get_origin(exc) - if origin_exc and issubclass(origin_exc, BaseExceptionGroup): - exc_type = get_args(exc)[0] - if ( - issubclass(origin_exc, ExceptionGroup) and exc_type in (Exception, Any) - ) or ( - issubclass(origin_exc, BaseExceptionGroup) - and exc_type in (BaseException, Any) - ): - return cast(type[E], origin_exc) - else: - raise ValueError( - f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` " - f"are accepted as generic types but got `{exc}`. " - f"As `raises` will catch all instances of the specified group regardless of the " - f"generic argument specific nested exceptions has to be checked " - f"with `ExceptionInfo.group_contains()`" - ) - - elif not isinstance(exc, type) or not issubclass(exc, BaseException): - msg = "expected exception must be a BaseException type, not {}" # type: ignore[unreachable] - not_a = exc.__name__ if isinstance(exc, type) else type(exc).__name__ - raise TypeError(msg.format(not_a)) - else: - return exc - - expected_exceptions = tuple(validate_exc(exc) for exc in expected_exceptions) - - message = f"DID NOT RAISE {expected_exception}" - - if not args: - match: str | re.Pattern[str] | None = kwargs.pop("match", None) - if kwargs: - msg = "Unexpected keyword arguments passed to pytest.raises: " - msg += ", ".join(sorted(kwargs)) - msg += "\nUse context-manager form instead?" - raise TypeError(msg) - return RaisesContext(expected_exceptions, message, match) - else: - func = args[0] - if not callable(func): - raise TypeError(f"{func!r} object (type: {type(func)}) must be callable") - try: - func(*args[1:], **kwargs) - except expected_exceptions as e: - return _pytest._code.ExceptionInfo.from_exception(e) - fail(message) - - -# This doesn't work with mypy for now. Use fail.Exception instead. -raises.Exception = fail.Exception # type: ignore - - -@final -class RaisesContext(AbstractContextManager[_pytest._code.ExceptionInfo[E]]): - def __init__( - self, - expected_exception: type[E] | tuple[type[E], ...], - message: str, - match_expr: str | re.Pattern[str] | None = None, - ) -> None: - self.expected_exception = expected_exception - self.message = message - self.match_expr = match_expr - self.excinfo: _pytest._code.ExceptionInfo[E] | None = None - if self.match_expr is not None: - re_error = None - try: - re.compile(self.match_expr) - except re.error as e: - re_error = e - if re_error is not None: - fail(f"Invalid regex pattern provided to 'match': {re_error}") - - def __enter__(self) -> _pytest._code.ExceptionInfo[E]: - self.excinfo = _pytest._code.ExceptionInfo.for_later() - return self.excinfo - - def __exit__( - self, - exc_type: type[BaseException] | None, - exc_val: BaseException | None, - exc_tb: TracebackType | None, - ) -> bool: - __tracebackhide__ = True - if exc_type is None: - fail(self.message) - assert self.excinfo is not None - if not issubclass(exc_type, self.expected_exception): - return False - # Cast to narrow the exception type now that it's verified. - exc_info = cast(tuple[type[E], E, TracebackType], (exc_type, exc_val, exc_tb)) - self.excinfo.fill_unfilled(exc_info) - if self.match_expr is not None: - self.excinfo.match(self.match_expr) - return True + func = args[0] + if not callable(func): + raise TypeError(f"{func!r} object (type: {type(func)}) must be callable") + with RaisesExc(expected_exception) as excinfo: + func(*args[1:], **kwargs) + try: + return excinfo + finally: + del excinfo + + +# note: RaisesExc/RaisesGroup uses fail() internally, so this alias +# indicates (to [internal] plugins?) that `pytest.raises` will +# raise `_pytest.outcomes.Failed`, where +# `outcomes.Failed is outcomes.fail.Exception is raises.Exception` +# note: this is *not* the same as `_pytest.main.Failed` +# note: mypy does not recognize this attribute +raises.Exception = fail.Exception # type: ignore[attr-defined] diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index d9b514089de..e549b8e8975 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -6,15 +6,20 @@ from re import Pattern import sys from textwrap import indent +from typing import Any from typing import cast from typing import final from typing import Generic +from typing import get_args +from typing import get_origin from typing import Literal from typing import overload from typing import TYPE_CHECKING +import warnings from _pytest._code import ExceptionInfo from _pytest.outcomes import fail +from _pytest.warning_types import PytestWarning if TYPE_CHECKING: @@ -24,9 +29,12 @@ # for some reason Sphinx does not play well with 'from types import TracebackType' import types + from typing_extensions import ParamSpec from typing_extensions import TypeGuard from typing_extensions import TypeVar + P = ParamSpec("P") + # this conditional definition is because we want to allow a TypeVar default BaseExcT_co_default = TypeVar( "BaseExcT_co_default", @@ -81,31 +89,58 @@ def repr_callable(fun: Callable[[BaseExcT_1], bool]) -> str: return repr(fun) -def _exception_type_name(e: type[BaseException]) -> str: - return repr(e.__name__) +def backquote(s: str) -> str: + return "`" + s + "`" + + +def _exception_type_name( + e: type[BaseException] | tuple[type[BaseException], ...], +) -> str: + if isinstance(e, type): + return e.__name__ + if len(e) == 1: + return e[0].__name__ + return "(" + ", ".join(ee.__name__ for ee in e) + ")" def _check_raw_type( - expected_type: type[BaseException] | None, + expected_type: type[BaseException] | tuple[type[BaseException], ...] | None, exception: BaseException, ) -> str | None: - if expected_type is None: + if expected_type is None or expected_type == (): return None if not isinstance( exception, expected_type, ): - actual_type_str = _exception_type_name(type(exception)) - expected_type_str = _exception_type_name(expected_type) - if isinstance(exception, BaseExceptionGroup) and not issubclass( - expected_type, BaseExceptionGroup + actual_type_str = backquote(_exception_type_name(type(exception)) + "()") + expected_type_str = backquote(_exception_type_name(expected_type)) + if ( + isinstance(exception, BaseExceptionGroup) + and isinstance(expected_type, type) + and not issubclass(expected_type, BaseExceptionGroup) ): return f"Unexpected nested {actual_type_str}, expected {expected_type_str}" - return f"{actual_type_str} is not of type {expected_type_str}" + return f"{actual_type_str} is not an instance of {expected_type_str}" return None +def is_fully_escaped(s: str) -> bool: + # we know we won't compile with re.VERBOSE, so whitespace doesn't need to be escaped + metacharacters = "{}()+.*?^$[]" + + for i, c in enumerate(s): + if c in metacharacters and (i == 0 or s[i - 1] != "\\"): + return False + + return True + + +def unescape(s: str) -> str: + return re.sub(r"\\([{}()+-.*?^$\[\]\s\\])", r"\1", s) + + class AbstractRaises(ABC, Generic[BaseExcT_co]): """ABC with common functionality shared between RaisesExc and RaisesGroup""" @@ -115,15 +150,85 @@ def __init__( check: Callable[[BaseExcT_co], bool] | None, ) -> None: if isinstance(match, str): - self.match: Pattern[str] | None = re.compile(match) + # juggle error in order to avoid context to fail (necessary?) + re_error = None + try: + self.match: Pattern[str] | None = re.compile(match) + except re.error as e: + re_error = e + if re_error is not None: + fail(f"Invalid regex pattern provided to 'match': {re_error}") + if match == "": + warnings.warn( + PytestWarning( + "session.shouldstop cannot be unset after it has been set; ignoring." + "matching against an empty string will *always* pass. If you want " + "to check for an empty message you need to pass '^$'. If you don't " + "want to match you should pass `None` or leave out the parameter." + ), + stacklevel=2, + ) else: self.match = match + + # check if this is a fully escaped regex and has ^$ to match fully + # in which case we can do a proper diff on error + self.rawmatch: str | None = None + if isinstance(match, str) or ( + isinstance(match, Pattern) and match.flags == _REGEX_NO_FLAGS + ): + if isinstance(match, Pattern): + match = match.pattern + if ( + match + and match[0] == "^" + and match[-1] == "$" + and is_fully_escaped(match[1:-1]) + ): + self.rawmatch = unescape(match[1:-1]) + self.check = check self._fail_reason: str | None = None # used to suppress repeated printing of `repr(self.check)` self._nested: bool = False + # set in self._parse_exc + self.is_baseexception = False + + def _parse_exc( + self, exc: type[BaseExcT_1] | types.GenericAlias, expected: str + ) -> type[BaseExcT_1]: + if isinstance(exc, type) and issubclass(exc, BaseException): + if not issubclass(exc, Exception): + self.is_baseexception = True + return exc + # because RaisesGroup does not support variable number of exceptions there's + # still a use for RaisesExc(ExceptionGroup[Exception]). + origin_exc: type[BaseException] | None = get_origin(exc) + if origin_exc and issubclass(origin_exc, BaseExceptionGroup): + exc_type = get_args(exc)[0] + if ( + issubclass(origin_exc, ExceptionGroup) and exc_type in (Exception, Any) + ) or ( + issubclass(origin_exc, BaseExceptionGroup) + and exc_type in (BaseException, Any) + ): + if not isinstance(exc, Exception): + self.is_baseexception = True + return cast(type[BaseExcT_1], origin_exc) + else: + raise TypeError( + f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` " + f"are accepted as generic types but got `{exc}`. " + f"As `raises` will catch all instances of the specified group regardless of the " + f"generic argument specific nested exceptions has to be checked " + f"with `RaisesGroup`." + ) + not_a = exc.__name__ if isinstance(exc, type) else type(exc).__name__ + msg = f"expected exception must be {expected}, not {not_a}" + raise TypeError(msg) + @property def fail_reason(self) -> str | None: """Set after a call to :meth:`matches` to give a human-readable reason for why the match failed. @@ -152,22 +257,37 @@ def _check_match(self, e: BaseException) -> bool: ): return True + # if we're matching a group, make sure we're explicit to reduce confusion + # if they're trying to match an exception contained within the group maybe_specify_type = ( - f" of {_exception_type_name(type(e))}" + f" the `{_exception_type_name(type(e))}()`" if isinstance(e, BaseExceptionGroup) else "" ) + if isinstance(self.rawmatch, str): + # TODO: it instructs to use `-v` to print leading text, but that doesn't work + # I also don't know if this is the proper entry point, or tool to use at all + from _pytest.assertion.util import _diff_text + from _pytest.assertion.util import dummy_highlighter + + diff = _diff_text(self.rawmatch, stringified_exception, dummy_highlighter) + self._fail_reason = ("\n" if diff[0][0] == "-" else "") + "\n".join(diff) + return False + + # I don't love "Regex"+"Input" vs something like "expected regex"+"exception message" + # when they're similar it's not always obvious which is which self._fail_reason = ( - f"Regex pattern {_match_pattern(self.match)!r}" - f" did not match {stringified_exception!r}{maybe_specify_type}" + f"Regex pattern did not match{maybe_specify_type}.\n" + f" Regex: {_match_pattern(self.match)!r}\n" + f" Input: {stringified_exception!r}" ) if _match_pattern(self.match) == stringified_exception: - self._fail_reason += "\n Did you mean to `re.escape()` the regex?" + self._fail_reason += "\n Did you mean to `re.escape()` the regex?" return False @abstractmethod def matches( - self: AbstractRaises[BaseExcT_1], exc_val: BaseException + self: AbstractRaises[BaseExcT_1], exception: BaseException ) -> TypeGuard[BaseExcT_1]: """Check if an exception matches the requirements of this AbstractRaises. If it fails, :meth:`AbstractRaises.fail_reason` should be set. @@ -208,18 +328,20 @@ class RaisesExc(AbstractRaises[BaseExcT_co_default]): @overload def __init__( self: RaisesExc[BaseExcT_co_default], - exception_type: type[BaseExcT_co_default], - match: str | Pattern[str] = ..., - check: Callable[[BaseExcT_co_default], bool] = ..., + expected_exception: ( + type[BaseExcT_co_default] | tuple[type[BaseExcT_co_default], ...] + ), + match: str | Pattern[str] | None = ..., + check: Callable[[BaseExcT_co_default], bool] | None = ..., ) -> None: ... @overload def __init__( self: RaisesExc[BaseException], # Give E a value. *, - match: str | Pattern[str], + match: str | Pattern[str] | None, # If exception_type is not provided, check() must do any typechecks itself. - check: Callable[[BaseException], bool] = ..., + check: Callable[[BaseException], bool] | None = ..., ) -> None: ... @overload @@ -227,22 +349,31 @@ def __init__(self, *, check: Callable[[BaseException], bool]) -> None: ... def __init__( self, - exception_type: type[BaseExcT_co_default] | None = None, + expected_exception: ( + type[BaseExcT_co_default] | tuple[type[BaseExcT_co_default], ...] | None + ) = None, match: str | Pattern[str] | None = None, check: Callable[[BaseExcT_co_default], bool] | None = None, ): super().__init__(match, check) - if exception_type is None and match is None and check is None: + if isinstance(expected_exception, tuple): + expected_exceptions = expected_exception + elif expected_exception is None: + expected_exceptions = () + else: + expected_exceptions = (expected_exception,) + + if (expected_exceptions == ()) and match is None and check is None: raise ValueError("You must specify at least one parameter to match on.") - if exception_type is not None and not issubclass(exception_type, BaseException): - raise TypeError( - f"exception_type {exception_type} must be a subclass of BaseException", - ) - self.exception_type = exception_type + + self.expected_exceptions = tuple( + self._parse_exc(e, expected="a BaseException type") + for e in expected_exceptions + ) def matches( self, - exception: BaseException, + exception: BaseException | None, ) -> TypeGuard[BaseExcT_co_default]: """Check if an exception matches the requirements of this :class:`RaisesExc`. If it fails, :attr:`RaisesExc.fail_reason` will be set. @@ -262,6 +393,9 @@ def matches( assert re.search("foo", str(excinfo.value.__cause__) """ + if exception is None: + self._fail_reason = "exception is None" + return False if not self._check_type(exception): return False @@ -272,8 +406,8 @@ def matches( def __repr__(self) -> str: parameters = [] - if self.exception_type is not None: - parameters.append(self.exception_type.__name__) + if self.expected_exceptions: + parameters.append(_exception_type_name(self.expected_exceptions)) if self.match is not None: # If no flags were specified, discard the redundant re.compile() here. parameters.append( @@ -284,9 +418,50 @@ def __repr__(self) -> str: return f"RaisesExc({', '.join(parameters)})" def _check_type(self, exception: BaseException) -> TypeGuard[BaseExcT_co_default]: - self._fail_reason = _check_raw_type(self.exception_type, exception) + self._fail_reason = _check_raw_type(self.expected_exceptions, exception) return self._fail_reason is None + def __enter__(self) -> ExceptionInfo[BaseExcT_co_default]: + self.excinfo: ExceptionInfo[BaseExcT_co_default] = ExceptionInfo.for_later() + return self.excinfo + + def expected_type(self) -> str: + if self.expected_exceptions == (): + return "BaseException" + return _exception_type_name(self.expected_exceptions) + + # TODO: move common code into superclass + def __exit__( + self, + exc_type: type[BaseException] | None, + exc_val: BaseException | None, + exc_tb: types.TracebackType | None, + ) -> bool: + __tracebackhide__ = True + if exc_type is None: + if not self.expected_exceptions: + fail("DID NOT RAISE any exception") + if len(self.expected_exceptions) > 1: + fail(f"DID NOT RAISE any of {self.expected_exceptions!r}") + + fail(f"DID NOT RAISE {self.expected_exceptions[0]!r}") + + assert self.excinfo is not None, ( + "Internal error - should have been constructed in __enter__" + ) + + if not self.matches(exc_val): + raise AssertionError(f"Raised exception did not match: {self._fail_reason}") + + # Cast to narrow the exception type now that it's verified.... + # even though the TypeGuard in self.matches should be narrowing + exc_info = cast( + "tuple[type[BaseExcT_co_default], BaseExcT_co_default, types.TracebackType]", + (exc_type, exc_val, exc_tb), + ) + self.excinfo.fill_unfilled(exc_info) + return True + @final class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): @@ -378,7 +553,7 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): @overload def __init__( self, - exception: type[BaseExcT_co] | RaisesExc[BaseExcT_co], + expected_exception: type[BaseExcT_co] | RaisesExc[BaseExcT_co], *, allow_unwrapped: Literal[True], flatten_subgroups: bool = False, @@ -388,7 +563,7 @@ def __init__( @overload def __init__( self, - exception: type[BaseExcT_co] | RaisesExc[BaseExcT_co], + expected_exception: type[BaseExcT_co] | RaisesExc[BaseExcT_co], *other_exceptions: type[BaseExcT_co] | RaisesExc[BaseExcT_co], flatten_subgroups: Literal[True], match: str | Pattern[str] | None = None, @@ -403,7 +578,7 @@ def __init__( @overload def __init__( self: RaisesGroup[ExcT_1], - exception: type[ExcT_1] | RaisesExc[ExcT_1], + expected_exception: type[ExcT_1] | RaisesExc[ExcT_1], *other_exceptions: type[ExcT_1] | RaisesExc[ExcT_1], match: str | Pattern[str] | None = None, check: Callable[[ExceptionGroup[ExcT_1]], bool] | None = None, @@ -412,7 +587,7 @@ def __init__( @overload def __init__( self: RaisesGroup[ExceptionGroup[ExcT_2]], - exception: RaisesGroup[ExcT_2], + expected_exception: RaisesGroup[ExcT_2], *other_exceptions: RaisesGroup[ExcT_2], match: str | Pattern[str] | None = None, check: Callable[[ExceptionGroup[ExceptionGroup[ExcT_2]]], bool] | None = None, @@ -421,7 +596,7 @@ def __init__( @overload def __init__( self: RaisesGroup[ExcT_1 | ExceptionGroup[ExcT_2]], - exception: type[ExcT_1] | RaisesExc[ExcT_1] | RaisesGroup[ExcT_2], + expected_exception: type[ExcT_1] | RaisesExc[ExcT_1] | RaisesGroup[ExcT_2], *other_exceptions: type[ExcT_1] | RaisesExc[ExcT_1] | RaisesGroup[ExcT_2], match: str | Pattern[str] | None = None, check: ( @@ -433,7 +608,7 @@ def __init__( @overload def __init__( self: RaisesGroup[BaseExcT_1], - exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1], + expected_exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1], *other_exceptions: type[BaseExcT_1] | RaisesExc[BaseExcT_1], match: str | Pattern[str] | None = None, check: Callable[[BaseExceptionGroup[BaseExcT_1]], bool] | None = None, @@ -442,7 +617,7 @@ def __init__( @overload def __init__( self: RaisesGroup[BaseExceptionGroup[BaseExcT_2]], - exception: RaisesGroup[BaseExcT_2], + expected_exception: RaisesGroup[BaseExcT_2], *other_exceptions: RaisesGroup[BaseExcT_2], match: str | Pattern[str] | None = None, check: ( @@ -453,7 +628,9 @@ def __init__( @overload def __init__( self: RaisesGroup[BaseExcT_1 | BaseExceptionGroup[BaseExcT_2]], - exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], + expected_exception: type[BaseExcT_1] + | RaisesExc[BaseExcT_1] + | RaisesGroup[BaseExcT_2], *other_exceptions: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], @@ -469,7 +646,9 @@ def __init__( def __init__( self: RaisesGroup[ExcT_1 | BaseExcT_1 | BaseExceptionGroup[BaseExcT_2]], - exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], + expected_exception: type[BaseExcT_1] + | RaisesExc[BaseExcT_1] + | RaisesGroup[BaseExcT_2], *other_exceptions: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], @@ -492,15 +671,9 @@ def __init__( check, ) super().__init__(match, check) - self.expected_exceptions: tuple[ - type[BaseExcT_co] | RaisesExc[BaseExcT_co] | RaisesGroup[BaseException], ... - ] = ( - exception, - *other_exceptions, - ) self.allow_unwrapped = allow_unwrapped self.flatten_subgroups: bool = flatten_subgroups - self.is_baseexceptiongroup = False + self.is_baseexception = False if allow_unwrapped and other_exceptions: raise ValueError( @@ -509,7 +682,7 @@ def __init__( " use a `RaisesExc`." " E.g. `RaisesExc(check=lambda e: isinstance(e, (...)))`", ) - if allow_unwrapped and isinstance(exception, RaisesGroup): + if allow_unwrapped and isinstance(expected_exception, RaisesGroup): raise ValueError( "`allow_unwrapped=True` has no effect when expecting a `RaisesGroup`." " You might want it in the expected `RaisesGroup`, or" @@ -525,33 +698,45 @@ def __init__( " assert RaisesGroup(...).matches(exc.value)` afterwards.", ) - # verify `expected_exceptions` and set `self.is_baseexceptiongroup` - for exc in self.expected_exceptions: - if isinstance(exc, RaisesGroup): - if self.flatten_subgroups: - raise ValueError( - "You cannot specify a nested structure inside a RaisesGroup with" - " `flatten_subgroups=True`. The parameter will flatten subgroups" - " in the raised exceptiongroup before matching, which would never" - " match a nested structure.", - ) - self.is_baseexceptiongroup |= exc.is_baseexceptiongroup - exc._nested = True - elif isinstance(exc, RaisesExc): - if exc.exception_type is not None: - # RaisesExc __init__ assures it's a subclass of BaseException - self.is_baseexceptiongroup |= not issubclass( - exc.exception_type, - Exception, - ) - exc._nested = True - elif isinstance(exc, type) and issubclass(exc, BaseException): - self.is_baseexceptiongroup |= not issubclass(exc, Exception) - else: - raise TypeError( - f'Invalid argument "{exc!r}" must be exception type, RaisesExc, or' - " RaisesGroup.", + self.expected_exceptions: tuple[ + type[BaseExcT_co] | RaisesExc[BaseExcT_co] | RaisesGroup[BaseException], ... + ] = tuple( + self._parse_excgroup(e, "a BaseException type, RaisesExc, or RaisesGroup") + for e in ( + expected_exception, + *other_exceptions, + ) + ) + + def _parse_excgroup( + self, + exc: ( + type[BaseExcT_co] + | types.GenericAlias + | RaisesExc[BaseExcT_1] + | RaisesGroup[BaseExcT_2] + ), + expected: str, + ) -> type[BaseExcT_co] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2]: + # verify exception type and set `self.is_baseexception` + if isinstance(exc, RaisesGroup): + if self.flatten_subgroups: + raise ValueError( + "You cannot specify a nested structure inside a RaisesGroup with" + " `flatten_subgroups=True`. The parameter will flatten subgroups" + " in the raised exceptiongroup before matching, which would never" + " match a nested structure.", ) + self.is_baseexception |= exc.is_baseexception + exc._nested = True + return exc + elif isinstance(exc, RaisesExc): + self.is_baseexception |= exc.is_baseexception + exc._nested = True + return exc + else: + # validate_exc transforms GenericAlias ExceptionGroup[Exception] -> type[ExceptionGroup] + return super()._parse_exc(exc, expected) @overload def __enter__( @@ -601,17 +786,17 @@ def _unroll_exceptions( @overload def matches( self: RaisesGroup[ExcT_1], - exc_val: BaseException | None, + exception: BaseException | None, ) -> TypeGuard[ExceptionGroup[ExcT_1]]: ... @overload def matches( self: RaisesGroup[BaseExcT_1], - exc_val: BaseException | None, + exception: BaseException | None, ) -> TypeGuard[BaseExceptionGroup[BaseExcT_1]]: ... def matches( self, - exc_val: BaseException | None, + exception: BaseException | None, ) -> TypeGuard[BaseExceptionGroup[BaseExcT_co]]: """Check if an exception matches the requirements of this RaisesGroup. If it fails, `RaisesGroup.fail_reason` will be set. @@ -628,19 +813,19 @@ def matches( assert isinstance(myexc.exceptions[0], ValueError) """ self._fail_reason = None - if exc_val is None: + if exception is None: self._fail_reason = "exception is None" return False - if not isinstance(exc_val, BaseExceptionGroup): + if not isinstance(exception, BaseExceptionGroup): # we opt to only print type of the exception here, as the repr would # likely be quite long - not_group_msg = f"{type(exc_val).__name__!r} is not an exception group" + not_group_msg = f"`{type(exception).__name__}()` is not an exception group" if len(self.expected_exceptions) > 1: self._fail_reason = not_group_msg return False # if we have 1 expected exception, check if it would work even if # allow_unwrapped is not set - res = self._check_expected(self.expected_exceptions[0], exc_val) + res = self._check_expected(self.expected_exceptions[0], exception) if res is None and self.allow_unwrapped: return True @@ -654,11 +839,11 @@ def matches( self._fail_reason = not_group_msg return False - actual_exceptions: Sequence[BaseException] = exc_val.exceptions + actual_exceptions: Sequence[BaseException] = exception.exceptions if self.flatten_subgroups: actual_exceptions = self._unroll_exceptions(actual_exceptions) - if not self._check_match(exc_val): + if not self._check_match(exception): self._fail_reason = cast(str, self._fail_reason) old_reason = self._fail_reason if ( @@ -670,8 +855,10 @@ def matches( assert self.match is not None, "can't be None if _check_match failed" assert self._fail_reason is old_reason is not None self._fail_reason += ( - f", but matched the expected {self._repr_expected(expected)}." - f" You might want RaisesGroup(RaisesExc({expected.__name__}, match={_match_pattern(self.match)!r}))" + f"\n" + f" but matched the expected `{self._repr_expected(expected)}`.\n" + f" You might want " + f"`RaisesGroup(RaisesExc({expected.__name__}, match={_match_pattern(self.match)!r}))`" ) else: self._fail_reason = old_reason @@ -679,7 +866,7 @@ def matches( # do the full check on expected exceptions if not self._check_exceptions( - exc_val, + exception, actual_exceptions, ): self._fail_reason = cast(str, self._fail_reason) @@ -694,8 +881,8 @@ def matches( ) and any(isinstance(e, BaseExceptionGroup) for e in actual_exceptions) and self._check_exceptions( - exc_val, - self._unroll_exceptions(exc_val.exceptions), + exception, + self._unroll_exceptions(exception.exceptions), ) ): # only indent if it's a single-line reason. In a multi-line there's already @@ -709,9 +896,11 @@ def matches( self._fail_reason = old_reason return False - # Only run `self.check` once we know `exc_val` is of the correct type. - if not self._check_check(exc_val): - reason = cast(str, self._fail_reason) + f" on the {type(exc_val).__name__}" + # Only run `self.check` once we know `exception` is of the correct type. + if not self._check_check(exception): + reason = ( + cast(str, self._fail_reason) + f" on the {type(exception).__name__}" + ) if ( len(actual_exceptions) == len(self.expected_exceptions) == 1 and isinstance(expected := self.expected_exceptions[0], type) @@ -758,22 +947,24 @@ def _repr_expected(e: type[BaseException] | AbstractRaises[BaseException]) -> st @overload def _check_exceptions( self: RaisesGroup[ExcT_1], - _exc_val: Exception, + _exception: Exception, actual_exceptions: Sequence[Exception], ) -> TypeGuard[ExceptionGroup[ExcT_1]]: ... @overload def _check_exceptions( self: RaisesGroup[BaseExcT_1], - _exc_val: BaseException, + _exception: BaseException, actual_exceptions: Sequence[BaseException], ) -> TypeGuard[BaseExceptionGroup[BaseExcT_1]]: ... def _check_exceptions( self, - _exc_val: BaseException, + _exception: BaseException, actual_exceptions: Sequence[BaseException], ) -> TypeGuard[BaseExceptionGroup[BaseExcT_co]]: """Helper method for RaisesGroup.matches that attempts to pair up expected and actual exceptions""" + # The _exception parameter is not used, but necessary for the TypeGuard + # full table with all results results = ResultHolder(self.expected_exceptions, actual_exceptions) @@ -871,9 +1062,11 @@ def _check_exceptions( if results.get_result(i_exp, i_actual) is None: # we print full repr of match target s += ( - f"\n{indent_2}It matches {actual!r} which was paired with " - + self._repr_expected( - self.expected_exceptions[rev_matches[i_actual]] + f"\n{indent_2}It matches {backquote(repr(actual))} which was paired with " + + backquote( + self._repr_expected( + self.expected_exceptions[rev_matches[i_actual]] + ) ) ) @@ -891,8 +1084,8 @@ def _check_exceptions( if res is None: # we print full repr of match target s += ( - f"\n{indent_2}It matches {self._repr_expected(expected)} " - f"which was paired with {actual_exceptions[matches[i_exp]]!r}" + f"\n{indent_2}It matches {backquote(self._repr_expected(expected))} " + f"which was paired with {backquote(repr(actual_exceptions[matches[i_exp]]))}" ) if len(self.expected_exceptions) == len(actual_exceptions) and possible_match( @@ -915,12 +1108,14 @@ def __exit__( ) -> bool: __tracebackhide__ = True if exc_type is None: - fail(f"DID NOT RAISE any exception, expected {self.expected_type()}") + fail(f"DID NOT RAISE any exception, expected `{self.expected_type()}`") assert self.excinfo is not None, ( "Internal error - should have been constructed in __enter__" ) + # group_str is the only thing that differs between RaisesExc and RaisesGroup... + # I might just scrap it? Or make it part of fail_reason group_str = ( "(group)" if self.allow_unwrapped and not issubclass(exc_type, BaseExceptionGroup) @@ -943,14 +1138,14 @@ def expected_type(self) -> str: subexcs = [] for e in self.expected_exceptions: if isinstance(e, RaisesExc): - subexcs.append(str(e)) + subexcs.append(repr(e)) elif isinstance(e, RaisesGroup): subexcs.append(e.expected_type()) elif isinstance(e, type): subexcs.append(e.__name__) else: # pragma: no cover raise AssertionError("unknown type") - group_type = "Base" if self.is_baseexceptiongroup else "" + group_type = "Base" if self.is_baseexception else "" return f"{group_type}ExceptionGroup({', '.join(subexcs)})" diff --git a/testing/python/raises.py b/testing/python/raises.py index 2011c81615e..c7ecc301701 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -6,9 +6,14 @@ from _pytest.outcomes import Failed from _pytest.pytester import Pytester +from _pytest.warning_types import PytestWarning import pytest +def wrap_escape(s: str) -> str: + return "^" + re.escape(s) + "$" + + class TestRaises: def test_check_callable(self) -> None: with pytest.raises(TypeError, match=r".* must be callable"): @@ -23,13 +28,19 @@ def test_raises_function(self): assert "invalid literal" in str(excinfo.value) def test_raises_does_not_allow_none(self): - with pytest.raises(ValueError, match="Expected an exception type or"): + with pytest.raises( + ValueError, + match=wrap_escape("You must specify at least one parameter to match on."), + ): # We're testing that this invalid usage gives a helpful error, # so we can ignore Mypy telling us that None is invalid. pytest.raises(expected_exception=None) # type: ignore def test_raises_does_not_allow_empty_tuple(self): - with pytest.raises(ValueError, match="Expected an exception type or"): + with pytest.raises( + ValueError, + match=wrap_escape("You must specify at least one parameter to match on."), + ): pytest.raises(expected_exception=()) def test_raises_callable_no_exception(self) -> None: @@ -84,7 +95,7 @@ def test_noraise(): int() def test_raise_wrong_exception_passes_by(): - with pytest.raises(ZeroDivisionError): + with pytest.raises(AssertionError): with pytest.raises(ValueError): 1/0 """ @@ -181,7 +192,9 @@ def test_no_raise_message(self) -> None: else: assert False, "Expected pytest.raises.Exception" - @pytest.mark.parametrize("method", ["function", "function_match", "with"]) + @pytest.mark.parametrize( + "method", ["function", "function_match", "with", "with_raisesexc", "with_group"] + ) def test_raises_cyclic_reference(self, method): """Ensure pytest.raises does not leave a reference cycle (#1965).""" import gc @@ -197,9 +210,17 @@ def __call__(self): pytest.raises(ValueError, t) elif method == "function_match": pytest.raises(ValueError, t).match("^$") - else: + elif method == "with": with pytest.raises(ValueError): t() + elif method == "with_raisesexc": + with pytest.RaisesExc(ValueError): + t() + elif method == "with_group": + with pytest.RaisesGroup(ValueError, allow_unwrapped=True): + t() + else: + raise AssertionError("bad parametrization") # ensure both forms of pytest.raises don't leave exceptions in sys.exc_info() assert sys.exc_info() == (None, None, None) @@ -217,11 +238,11 @@ def test_raises_match(self) -> None: msg = "with base 16" expr = ( - "Regex pattern did not match.\n" + "Raised exception did not match: Regex pattern did not match.\n" f" Regex: {msg!r}\n" " Input: \"invalid literal for int() with base 10: 'asdf'\"" ) - with pytest.raises(AssertionError, match="(?m)" + re.escape(expr)): + with pytest.raises(AssertionError, match="^" + re.escape(expr) + "$"): with pytest.raises(ValueError, match=msg): int("asdf", base=10) @@ -239,12 +260,27 @@ def tfunc(match): pytest.raises(ValueError, tfunc, match="asdf").match("match=asdf") pytest.raises(ValueError, tfunc, match="").match("match=") + # empty string matches everything, which is probably not what the user wants + # FIXME: I have no clue what session.shouldstop is doing here + with pytest.warns( + PytestWarning, + match=wrap_escape( + "session.shouldstop cannot be unset after it has been set; ignoring.matching against " + "an empty string will *always* pass. If you want to check for an empty message you " + "need to pass '^$'. If you don't want to match you should pass `None` or leave out the parameter." + ), + ): + pytest.raises(match="") + def test_match_failure_string_quoting(self): with pytest.raises(AssertionError) as excinfo: with pytest.raises(AssertionError, match="'foo"): raise AssertionError("'bar") (msg,) = excinfo.value.args - assert msg == '''Regex pattern did not match.\n Regex: "'foo"\n Input: "'bar"''' + assert ( + msg + == '''Raised exception did not match: Regex pattern did not match.\n Regex: "'foo"\n Input: "'bar"''' + ) def test_match_failure_exact_string_message(self): message = "Oh here is a message with (42) numbers in parameters" @@ -253,7 +289,7 @@ def test_match_failure_exact_string_message(self): raise AssertionError(message) (msg,) = excinfo.value.args assert msg == ( - "Regex pattern did not match.\n" + "Raised exception did not match: Regex pattern did not match.\n" " Regex: 'Oh here is a message with (42) numbers in parameters'\n" " Input: 'Oh here is a message with (42) numbers in parameters'\n" " Did you mean to `re.escape()` the regex?" @@ -265,7 +301,12 @@ def test_raises_match_wrong_type(self): pytest should throw the unexpected exception - the pattern match is not really relevant if we got a different exception. """ - with pytest.raises(ValueError): + with pytest.raises( + AssertionError, + match=wrap_escape( + "Raised exception did not match: `ValueError()` is not an instance of `IndexError`" + ), + ): with pytest.raises(IndexError, match="nomatch"): int("asdf") @@ -301,6 +342,8 @@ def __class__(self): assert "via __class__" in excinfo.value.args[0] def test_raises_context_manager_with_kwargs(self): + with pytest.raises(expected_exception=ValueError): + raise ValueError with pytest.raises(TypeError) as excinfo: with pytest.raises(OSError, foo="bar"): # type: ignore[call-overload] pass diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index 60eb28386f8..5e00aaa06bb 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -6,7 +6,6 @@ from contextlib import AbstractContextManager import re import sys -from typing import TYPE_CHECKING from _pytest._code import ExceptionInfo from _pytest.outcomes import Failed @@ -21,15 +20,12 @@ from exceptiongroup import BaseExceptionGroup from exceptiongroup import ExceptionGroup -if TYPE_CHECKING: - from _pytest.python_api import RaisesContext - def wrap_escape(s: str) -> str: return "^" + re.escape(s) + "$" -def fails_raises_group(msg: str, add_prefix: bool = True) -> RaisesContext[Failed]: +def fails_raises_group(msg: str, add_prefix: bool = True) -> RaisesExc[Failed]: assert msg[-1] != "\n", ( "developer error, expected string should not end with newline" ) @@ -40,8 +36,9 @@ def fails_raises_group(msg: str, add_prefix: bool = True) -> RaisesContext[Faile def test_raises_group() -> None: with pytest.raises( TypeError, + # TODO: bad sentence structure match=wrap_escape( - f'Invalid argument "{ValueError()!r}" must be exception type, RaisesExc, or RaisesGroup.', + "expected exception must be a BaseException type, RaisesExc, or RaisesGroup, not ValueError", ), ): RaisesGroup(ValueError()) # type: ignore[call-overload] @@ -49,7 +46,7 @@ def test_raises_group() -> None: raise ExceptionGroup("foo", (ValueError(),)) with ( - fails_raises_group("'SyntaxError' is not of type 'ValueError'"), + fails_raises_group("`SyntaxError()` is not an instance of `ValueError`"), RaisesGroup(ValueError), ): raise ExceptionGroup("foo", (SyntaxError(),)) @@ -95,7 +92,7 @@ def test_incorrect_number_exceptions() -> None: # will error if there's missing exceptions with ( fails_raises_group( - "1 matched exception. Too few exceptions raised, found no match for: ['SyntaxError']" + "1 matched exception. Too few exceptions raised, found no match for: [SyntaxError]" ), RaisesGroup(ValueError, SyntaxError), ): @@ -107,8 +104,8 @@ def test_incorrect_number_exceptions() -> None: "1 matched exception. \n" "Too few exceptions raised!\n" "The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " It matches ValueError() which was paired with 'ValueError'" + " ValueError\n" + " It matches `ValueError()` which was paired with `ValueError`" ), RaisesGroup(ValueError, ValueError), ): @@ -120,23 +117,23 @@ def test_incorrect_number_exceptions() -> None: "1 matched exception. \n" "Unexpected exception(s)!\n" "The following raised exceptions did not find a match\n" - " ValueError():\n" - " It matches 'ValueError' which was paired with ValueError()" + " ValueError('b'):\n" + " It matches `ValueError` which was paired with `ValueError('a')`" ), RaisesGroup(ValueError), ): - raise ExceptionGroup("", (ValueError(), ValueError())) + raise ExceptionGroup("", (ValueError("a"), ValueError("b"))) with ( fails_raises_group( "\n" "1 matched exception. \n" "The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " It matches ValueError() which was paired with 'ValueError'\n" + " ValueError\n" + " It matches `ValueError()` which was paired with `ValueError`\n" "The following raised exceptions did not find a match\n" " SyntaxError():\n" - " 'SyntaxError' is not of type 'ValueError'" + " `SyntaxError()` is not an instance of `ValueError`" ), RaisesGroup(ValueError, ValueError), ): @@ -172,14 +169,14 @@ def test_flatten_subgroups() -> None: # flatten_subgroups is not sufficient to catch fully unwrapped with ( fails_raises_group( - "'ValueError' is not an exception group, but would match with `allow_unwrapped=True`" + "`ValueError()` is not an exception group, but would match with `allow_unwrapped=True`" ), RaisesGroup(ValueError, flatten_subgroups=True), ): raise ValueError with ( fails_raises_group( - "RaisesGroup(ValueError, flatten_subgroups=True): 'ValueError' is not an exception group, but would match with `allow_unwrapped=True`" + "RaisesGroup(ValueError, flatten_subgroups=True): `ValueError()` is not an exception group, but would match with `allow_unwrapped=True`" ), RaisesGroup(RaisesGroup(ValueError, flatten_subgroups=True)), ): @@ -190,12 +187,12 @@ def test_flatten_subgroups() -> None: fails_raises_group( "Raised exception group did not match: \n" "The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " 'TypeError'\n" + " ValueError\n" + " TypeError\n" "The following raised exceptions did not find a match\n" " ExceptionGroup('', [ValueError(), TypeError()]):\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" - " Unexpected nested 'ExceptionGroup', expected 'TypeError'\n" + " Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" + " Unexpected nested `ExceptionGroup()`, expected `TypeError`\n" "Did you mean to use `flatten_subgroups=True`?", add_prefix=False, ), @@ -207,12 +204,12 @@ def test_flatten_subgroups() -> None: fails_raises_group( "Raised exception group did not match: \n" "The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " 'TypeError'\n" + " ValueError\n" + " TypeError\n" "The following raised exceptions did not find a match\n" " ExceptionGroup('', [ValueError(), TypeError()]):\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" - " Unexpected nested 'ExceptionGroup', expected 'TypeError'\n" + " Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" + " Unexpected nested `ExceptionGroup()`, expected `TypeError`\n" "Did you mean to use `flatten_subgroups=True`?", add_prefix=False, ), @@ -227,7 +224,7 @@ def test_flatten_subgroups() -> None: # This now doesn't print a repr of the caught exception at all, but that can be found in the traceback with ( fails_raises_group( - "Raised exception group did not match: Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + "Raised exception group did not match: Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" " Did you mean to use `flatten_subgroups=True`?", add_prefix=False, ), @@ -236,7 +233,9 @@ def test_flatten_subgroups() -> None: raise ExceptionGroup("", [ExceptionGroup("", [ValueError()])]) # correct number of exceptions, but flatten_subgroups wouldn't help, so we don't suggest it with ( - fails_raises_group("Unexpected nested 'ExceptionGroup', expected 'ValueError'"), + fails_raises_group( + "Unexpected nested `ExceptionGroup()`, expected `ValueError`" + ), RaisesGroup(ValueError), ): raise ExceptionGroup("", [ExceptionGroup("", [TypeError()])]) @@ -246,7 +245,7 @@ def test_flatten_subgroups() -> None: # to be what they actually want - but I don't think it's worth trying to special-case with ( fails_raises_group( - "RaisesGroup(ValueError): Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + "RaisesGroup(ValueError): Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" " Did you mean to use `flatten_subgroups=True`?", ), RaisesGroup(RaisesGroup(ValueError)), @@ -260,7 +259,9 @@ def test_flatten_subgroups() -> None: # Although it should perhaps be an error to specify `RaisesGroup(ExceptionGroup)` in # favor of doing `RaisesGroup(RaisesGroup(...))`. with ( - fails_raises_group("'BaseExceptionGroup' is not of type 'ExceptionGroup'"), + fails_raises_group( + "`BaseExceptionGroup()` is not an instance of `ExceptionGroup`" + ), RaisesGroup(ExceptionGroup), ): raise BaseExceptionGroup("", [BaseExceptionGroup("", [KeyboardInterrupt()])]) @@ -300,7 +301,7 @@ def test_catch_unwrapped_exceptions() -> None: # with allow_unwrapped=False (default) it will not be caught with ( fails_raises_group( - "'ValueError' is not an exception group, but would match with `allow_unwrapped=True`" + "`ValueError()` is not an exception group, but would match with `allow_unwrapped=True`" ), RaisesGroup(ValueError), ): @@ -309,7 +310,7 @@ def test_catch_unwrapped_exceptions() -> None: # allow_unwrapped on its own won't match against nested groups with ( fails_raises_group( - "Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + "Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" " Did you mean to use `flatten_subgroups=True`?", ), RaisesGroup(ValueError, allow_unwrapped=True), @@ -323,7 +324,7 @@ def test_catch_unwrapped_exceptions() -> None: # code coverage with ( fails_raises_group( - "Raised exception (group) did not match: 'TypeError' is not of type 'ValueError'", + "Raised exception (group) did not match: `TypeError()` is not an instance of `ValueError`", add_prefix=False, ), RaisesGroup(ValueError, allow_unwrapped=True), @@ -331,7 +332,7 @@ def test_catch_unwrapped_exceptions() -> None: raise TypeError("this text doesn't show up in the error message") with ( fails_raises_group( - "Raised exception (group) did not match: RaisesExc(ValueError): 'TypeError' is not of type 'ValueError'", + "Raised exception (group) did not match: RaisesExc(ValueError): `TypeError()` is not an instance of `ValueError`", add_prefix=False, ), RaisesGroup(RaisesExc(ValueError), allow_unwrapped=True), @@ -340,7 +341,7 @@ def test_catch_unwrapped_exceptions() -> None: # check we don't suggest unwrapping with nested RaisesGroup with ( - fails_raises_group("'ValueError' is not an exception group"), + fails_raises_group("`ValueError()` is not an exception group"), RaisesGroup(RaisesGroup(ValueError)), ): raise ValueError @@ -370,7 +371,9 @@ def test_match() -> None: with ( fails_raises_group( - "Regex pattern 'foo' did not match 'bar' of 'ExceptionGroup'" + "Regex pattern did not match the `ExceptionGroup()`.\n" + " Regex: 'foo'\n" + " Input: 'bar'" ), RaisesGroup(ValueError, match="foo"), ): @@ -382,7 +385,11 @@ def test_match() -> None: # and `isinstance(raised, expected_type)`. with ( fails_raises_group( - "Regex pattern 'foo' did not match 'bar' of 'ExceptionGroup', but matched the expected 'ValueError'. You might want RaisesGroup(RaisesExc(ValueError, match='foo'))" + "Regex pattern did not match the `ExceptionGroup()`.\n" + " Regex: 'foo'\n" + " Input: 'bar'\n" + " but matched the expected `ValueError`.\n" + " You might want `RaisesGroup(RaisesExc(ValueError, match='foo'))`" ), RaisesGroup(ValueError, match="foo"), ): @@ -413,7 +420,7 @@ def is_value_error(e: BaseException) -> bool: # helpful suggestion if the user thinks the check is for the sub-exception with ( fails_raises_group( - f"check {is_value_error} did not return True on the ExceptionGroup, but did return True for the expected 'ValueError'. You might want RaisesGroup(RaisesExc(ValueError, check=<...>))" + f"check {is_value_error} did not return True on the ExceptionGroup, but did return True for the expected ValueError. You might want RaisesGroup(RaisesExc(ValueError, check=<...>))" ), RaisesGroup(ValueError, check=is_value_error), ): @@ -466,7 +473,7 @@ def check_message( with ( pytest.raises( Failed, - match=f"^DID NOT RAISE any exception, expected {re.escape(message)}$", + match=f"^DID NOT RAISE any exception, expected `{re.escape(message)}`$", ), body, ): @@ -494,6 +501,15 @@ def check_message( "ExceptionGroup(RaisesExc(match='my_str'))", RaisesGroup(RaisesExc(match="my_str")), ) + # one-size tuple is printed as not being a tuple + check_message( + "ExceptionGroup(RaisesExc(ValueError))", + RaisesGroup(RaisesExc((ValueError,))), + ) + check_message( + "ExceptionGroup(RaisesExc((ValueError, IndexError)))", + RaisesGroup(RaisesExc((ValueError, IndexError))), + ) # BaseExceptionGroup check_message( @@ -505,6 +521,10 @@ def check_message( "BaseExceptionGroup(RaisesExc(KeyboardInterrupt))", RaisesGroup(RaisesExc(KeyboardInterrupt)), ) + check_message( + "BaseExceptionGroup(RaisesExc((ValueError, KeyboardInterrupt)))", + RaisesGroup(RaisesExc((ValueError, KeyboardInterrupt))), + ) # Base-ness transfers to parent containers check_message( "BaseExceptionGroup(BaseExceptionGroup(KeyboardInterrupt))", @@ -522,7 +542,7 @@ def test_assert_message() -> None: # in the exception group, as those are both visible in the traceback. # first fails to match with ( - fails_raises_group("'TypeError' is not of type 'ValueError'"), + fails_raises_group("`TypeError()` is not an instance of `ValueError`"), RaisesGroup(ValueError), ): raise ExceptionGroup("a", [TypeError()]) @@ -534,11 +554,13 @@ def test_assert_message() -> None: " RaisesGroup(ValueError, match='a')\n" "The following raised exceptions did not find a match\n" " ExceptionGroup('', [RuntimeError()]):\n" - " RaisesGroup(ValueError): 'RuntimeError' is not of type 'ValueError'\n" - " RaisesGroup(ValueError, match='a'): Regex pattern 'a' did not match '' of 'ExceptionGroup'\n" + " RaisesGroup(ValueError): `RuntimeError()` is not an instance of `ValueError`\n" + " RaisesGroup(ValueError, match='a'): Regex pattern did not match the `ExceptionGroup()`.\n" + " Regex: 'a'\n" + " Input: ''\n" " RuntimeError():\n" - " RaisesGroup(ValueError): 'RuntimeError' is not an exception group\n" - " RaisesGroup(ValueError, match='a'): 'RuntimeError' is not an exception group", + " RaisesGroup(ValueError): `RuntimeError()` is not an exception group\n" + " RaisesGroup(ValueError, match='a'): `RuntimeError()` is not an exception group", add_prefix=False, # to see the full structure ), RaisesGroup(RaisesGroup(ValueError), RaisesGroup(ValueError, match="a")), @@ -557,14 +579,12 @@ def test_assert_message() -> None: " RaisesGroup(ValueError)\n" "The following raised exceptions did not find a match\n" " RuntimeError():\n" - # " 'RuntimeError' is not of type 'ValueError'\n" - # " RaisesExc(TypeError): 'RuntimeError' is not of type 'TypeError'\n" - " RaisesGroup(RuntimeError): 'RuntimeError' is not an exception group, but would match with `allow_unwrapped=True`\n" - " RaisesGroup(ValueError): 'RuntimeError' is not an exception group\n" + " RaisesGroup(RuntimeError): `RuntimeError()` is not an exception group, but would match with `allow_unwrapped=True`\n" + " RaisesGroup(ValueError): `RuntimeError()` is not an exception group\n" " ValueError('bar'):\n" - " It matches 'ValueError' which was paired with ValueError('foo')\n" - " RaisesGroup(RuntimeError): 'ValueError' is not an exception group\n" - " RaisesGroup(ValueError): 'ValueError' is not an exception group, but would match with `allow_unwrapped=True`", + " It matches `ValueError` which was paired with `ValueError('foo')`\n" + " RaisesGroup(RuntimeError): `ValueError()` is not an exception group\n" + " RaisesGroup(ValueError): `ValueError()` is not an exception group, but would match with `allow_unwrapped=True`", add_prefix=False, # to see the full structure ), RaisesGroup( @@ -581,7 +601,7 @@ def test_assert_message() -> None: with ( fails_raises_group( - "1 matched exception. 'AssertionError' is not of type 'TypeError'" + "1 matched exception. `AssertionError()` is not an instance of `TypeError`" ), RaisesGroup(ValueError, TypeError), ): @@ -589,7 +609,7 @@ def test_assert_message() -> None: with ( fails_raises_group( - "RaisesExc(ValueError): 'TypeError' is not of type 'ValueError'" + "RaisesExc(ValueError): `TypeError()` is not an instance of `ValueError`" ), RaisesGroup(RaisesExc(ValueError)), ): @@ -598,8 +618,11 @@ def test_assert_message() -> None: # suggest escaping with ( fails_raises_group( - "Raised exception group did not match: Regex pattern 'h(ell)o' did not match 'h(ell)o' of 'ExceptionGroup'\n" - " Did you mean to `re.escape()` the regex?", + # TODO: did not match Exceptiongroup('h(ell)o', ...) ? + "Raised exception group did not match: Regex pattern did not match the `ExceptionGroup()`.\n" + " Regex: 'h(ell)o'\n" + " Input: 'h(ell)o'\n" + " Did you mean to `re.escape()` the regex?", add_prefix=False, # to see the full structure ), RaisesGroup(ValueError, match="h(ell)o"), @@ -607,8 +630,10 @@ def test_assert_message() -> None: raise ExceptionGroup("h(ell)o", [ValueError()]) with ( fails_raises_group( - "RaisesExc(match='h(ell)o'): Regex pattern 'h(ell)o' did not match 'h(ell)o'\n" - " Did you mean to `re.escape()` the regex?", + "RaisesExc(match='h(ell)o'): Regex pattern did not match.\n" + " Regex: 'h(ell)o'\n" + " Input: 'h(ell)o'\n" + " Did you mean to `re.escape()` the regex?", ), RaisesGroup(RaisesExc(match="h(ell)o")), ): @@ -618,16 +643,16 @@ def test_assert_message() -> None: fails_raises_group( "Raised exception group did not match: \n" "The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " 'ValueError'\n" - " 'ValueError'\n" - " 'ValueError'\n" + " ValueError\n" + " ValueError\n" + " ValueError\n" + " ValueError\n" "The following raised exceptions did not find a match\n" " ExceptionGroup('', [ValueError(), TypeError()]):\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'", + " Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" + " Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" + " Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" + " Unexpected nested `ExceptionGroup()`, expected `ValueError`", add_prefix=False, # to see the full structure ), RaisesGroup(ValueError, ValueError, ValueError, ValueError), @@ -641,26 +666,26 @@ def test_message_indent() -> None: "Raised exception group did not match: \n" "The following expected exceptions did not find a match:\n" " RaisesGroup(ValueError, ValueError)\n" - " 'ValueError'\n" + " ValueError\n" "The following raised exceptions did not find a match\n" " ExceptionGroup('', [TypeError(), RuntimeError()]):\n" " RaisesGroup(ValueError, ValueError): \n" " The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " 'ValueError'\n" + " ValueError\n" + " ValueError\n" " The following raised exceptions did not find a match\n" " TypeError():\n" - " 'TypeError' is not of type 'ValueError'\n" - " 'TypeError' is not of type 'ValueError'\n" + " `TypeError()` is not an instance of `ValueError`\n" + " `TypeError()` is not an instance of `ValueError`\n" " RuntimeError():\n" - " 'RuntimeError' is not of type 'ValueError'\n" - " 'RuntimeError' is not of type 'ValueError'\n" + " `RuntimeError()` is not an instance of `ValueError`\n" + " `RuntimeError()` is not an instance of `ValueError`\n" # TODO: this line is not great, should maybe follow the same format as the other and say - # 'ValueError': Unexpected nested 'ExceptionGroup' (?) - " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + # ValueError: Unexpected nested `ExceptionGroup()` (?) + " Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" " TypeError():\n" - " RaisesGroup(ValueError, ValueError): 'TypeError' is not an exception group\n" - " 'TypeError' is not of type 'ValueError'", + " RaisesGroup(ValueError, ValueError): `TypeError()` is not an exception group\n" + " `TypeError()` is not an instance of `ValueError`", add_prefix=False, ), RaisesGroup( @@ -680,15 +705,15 @@ def test_message_indent() -> None: "Raised exception group did not match: \n" "RaisesGroup(ValueError, ValueError): \n" " The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " 'ValueError'\n" + " ValueError\n" + " ValueError\n" " The following raised exceptions did not find a match\n" " TypeError():\n" - " 'TypeError' is not of type 'ValueError'\n" - " 'TypeError' is not of type 'ValueError'\n" + " `TypeError()` is not an instance of `ValueError`\n" + " `TypeError()` is not an instance of `ValueError`\n" " RuntimeError():\n" - " 'RuntimeError' is not of type 'ValueError'\n" - " 'RuntimeError' is not of type 'ValueError'", + " `RuntimeError()` is not an instance of `ValueError`\n" + " `RuntimeError()` is not an instance of `ValueError`", add_prefix=False, ), RaisesGroup( @@ -710,12 +735,12 @@ def test_suggestion_on_nested_and_brief_error() -> None: "\n" "The following expected exceptions did not find a match:\n" " RaisesGroup(ValueError)\n" - " 'ValueError'\n" + " ValueError\n" "The following raised exceptions did not find a match\n" " ExceptionGroup('', [ExceptionGroup('', [ValueError()])]):\n" - " RaisesGroup(ValueError): Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " RaisesGroup(ValueError): Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" " Did you mean to use `flatten_subgroups=True`?\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'", + " Unexpected nested `ExceptionGroup()`, expected `ValueError`", ), RaisesGroup(RaisesGroup(ValueError), ValueError), ): @@ -729,19 +754,19 @@ def test_suggestion_on_nested_and_brief_error() -> None: "\n" "The following expected exceptions did not find a match:\n" " RaisesGroup(ValueError, ValueError)\n" - " 'ValueError'\n" + " ValueError\n" "The following raised exceptions did not find a match\n" " ExceptionGroup('', [ValueError(), ExceptionGroup('', [ValueError()])]):\n" " RaisesGroup(ValueError, ValueError): \n" " 1 matched exception. \n" " The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " It matches ValueError() which was paired with 'ValueError'\n" + " ValueError\n" + " It matches `ValueError()` which was paired with `ValueError`\n" " The following raised exceptions did not find a match\n" " ExceptionGroup('', [ValueError()]):\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'\n" + " Unexpected nested `ExceptionGroup()`, expected `ValueError`\n" " Did you mean to use `flatten_subgroups=True`?\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'" + " Unexpected nested `ExceptionGroup()`, expected `ValueError`" ), RaisesGroup(RaisesGroup(ValueError, ValueError), ValueError), ): @@ -756,12 +781,14 @@ def test_suggestion_on_nested_and_brief_error() -> None: "\n" "The following expected exceptions did not find a match:\n" " RaisesGroup(Exception, match='^hello')\n" - " 'ValueError'\n" + " ValueError\n" "The following raised exceptions did not find a match\n" " ExceptionGroup('^hello', [Exception()]):\n" - " RaisesGroup(Exception, match='^hello'): Regex pattern '^hello' did not match '^hello' of 'ExceptionGroup'\n" - " Did you mean to `re.escape()` the regex?\n" - " Unexpected nested 'ExceptionGroup', expected 'ValueError'" + " RaisesGroup(Exception, match='^hello'): Regex pattern did not match the `ExceptionGroup()`.\n" + " Regex: '^hello'\n" + " Input: '^hello'\n" + " Did you mean to `re.escape()` the regex?\n" + " Unexpected nested `ExceptionGroup()`, expected `ValueError`" ), RaisesGroup(RaisesGroup(Exception, match="^hello"), ValueError), ): @@ -781,48 +808,54 @@ def test_assert_message_nested() -> None: " RaisesGroup(TypeError, ValueError)\n" "The following raised exceptions did not find a match\n" " TypeError('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'):\n" - " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" - " RaisesGroup(RaisesGroup(ValueError)): 'TypeError' is not an exception group\n" - " RaisesGroup(RaisesExc(TypeError, match='foo')): 'TypeError' is not an exception group\n" - " RaisesGroup(TypeError, ValueError): 'TypeError' is not an exception group\n" + " RaisesGroup(ValueError): `TypeError()` is not an exception group\n" + " RaisesGroup(RaisesGroup(ValueError)): `TypeError()` is not an exception group\n" + " RaisesGroup(RaisesExc(TypeError, match='foo')): `TypeError()` is not an exception group\n" + " RaisesGroup(TypeError, ValueError): `TypeError()` is not an exception group\n" " ExceptionGroup('Exceptions from Trio nursery', [TypeError('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb')]):\n" - " RaisesGroup(ValueError): 'TypeError' is not of type 'ValueError'\n" - " RaisesGroup(RaisesGroup(ValueError)): RaisesGroup(ValueError): 'TypeError' is not an exception group\n" - " RaisesGroup(RaisesExc(TypeError, match='foo')): RaisesExc(TypeError, match='foo'): Regex pattern 'foo' did not match 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'\n" - " RaisesGroup(TypeError, ValueError): 1 matched exception. Too few exceptions raised, found no match for: ['ValueError']\n" + " RaisesGroup(ValueError): `TypeError()` is not an instance of `ValueError`\n" + " RaisesGroup(RaisesGroup(ValueError)): RaisesGroup(ValueError): `TypeError()` is not an exception group\n" + " RaisesGroup(RaisesExc(TypeError, match='foo')): RaisesExc(TypeError, match='foo'): Regex pattern did not match.\n" + " Regex: 'foo'\n" + " Input: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'\n" + " RaisesGroup(TypeError, ValueError): 1 matched exception. Too few exceptions raised, found no match for: [ValueError]\n" " ExceptionGroup('Exceptions from Trio nursery', [TypeError('cccccccccccccccccccccccccccccc'), TypeError('dddddddddddddddddddddddddddddd')]):\n" " RaisesGroup(ValueError): \n" " The following expected exceptions did not find a match:\n" - " 'ValueError'\n" + " ValueError\n" " The following raised exceptions did not find a match\n" " TypeError('cccccccccccccccccccccccccccccc'):\n" - " 'TypeError' is not of type 'ValueError'\n" + " `TypeError()` is not an instance of `ValueError`\n" " TypeError('dddddddddddddddddddddddddddddd'):\n" - " 'TypeError' is not of type 'ValueError'\n" + " `TypeError()` is not an instance of `ValueError`\n" " RaisesGroup(RaisesGroup(ValueError)): \n" " The following expected exceptions did not find a match:\n" " RaisesGroup(ValueError)\n" " The following raised exceptions did not find a match\n" " TypeError('cccccccccccccccccccccccccccccc'):\n" - " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" + " RaisesGroup(ValueError): `TypeError()` is not an exception group\n" " TypeError('dddddddddddddddddddddddddddddd'):\n" - " RaisesGroup(ValueError): 'TypeError' is not an exception group\n" + " RaisesGroup(ValueError): `TypeError()` is not an exception group\n" " RaisesGroup(RaisesExc(TypeError, match='foo')): \n" " The following expected exceptions did not find a match:\n" " RaisesExc(TypeError, match='foo')\n" " The following raised exceptions did not find a match\n" " TypeError('cccccccccccccccccccccccccccccc'):\n" - " RaisesExc(TypeError, match='foo'): Regex pattern 'foo' did not match 'cccccccccccccccccccccccccccccc'\n" + " RaisesExc(TypeError, match='foo'): Regex pattern did not match.\n" + " Regex: 'foo'\n" + " Input: 'cccccccccccccccccccccccccccccc'\n" " TypeError('dddddddddddddddddddddddddddddd'):\n" - " RaisesExc(TypeError, match='foo'): Regex pattern 'foo' did not match 'dddddddddddddddddddddddddddddd'\n" + " RaisesExc(TypeError, match='foo'): Regex pattern did not match.\n" + " Regex: 'foo'\n" + " Input: 'dddddddddddddddddddddddddddddd'\n" " RaisesGroup(TypeError, ValueError): \n" " 1 matched exception. \n" " The following expected exceptions did not find a match:\n" - " 'ValueError'\n" + " ValueError\n" " The following raised exceptions did not find a match\n" " TypeError('dddddddddddddddddddddddddddddd'):\n" - " It matches 'TypeError' which was paired with TypeError('cccccccccccccccccccccccccccccc')\n" - " 'TypeError' is not of type 'ValueError'", + " It matches `TypeError` which was paired with `TypeError('cccccccccccccccccccccccccccccc')`\n" + " `TypeError()` is not an instance of `ValueError`", add_prefix=False, # to see the full structure ), RaisesGroup( @@ -864,14 +897,14 @@ def test_check_no_patched_repr() -> None: r"^Raised exception group did not match: \n" r"The following expected exceptions did not find a match:\n" r" RaisesExc\(check=. at .*>\)\n" - r" 'TypeError'\n" + r" TypeError\n" r"The following raised exceptions did not find a match\n" r" ValueError\('foo'\):\n" r" RaisesExc\(check=. at .*>\): check did not return True\n" - r" 'ValueError' is not of type 'TypeError'\n" + r" `ValueError\(\)` is not an instance of `TypeError`\n" r" ValueError\('bar'\):\n" r" RaisesExc\(check=. at .*>\): check did not return True\n" - r" 'ValueError' is not of type 'TypeError'$" + r" `ValueError\(\)` is not an instance of `TypeError`$" ) with ( pytest.raises(Failed, match=match_str), @@ -887,15 +920,17 @@ def test_misordering_example() -> None: "3 matched exceptions. \n" "The following expected exceptions did not find a match:\n" " RaisesExc(ValueError, match='foo')\n" - " It matches ValueError('foo') which was paired with 'ValueError'\n" - " It matches ValueError('foo') which was paired with 'ValueError'\n" - " It matches ValueError('foo') which was paired with 'ValueError'\n" + " It matches `ValueError('foo')` which was paired with `ValueError`\n" + " It matches `ValueError('foo')` which was paired with `ValueError`\n" + " It matches `ValueError('foo')` which was paired with `ValueError`\n" "The following raised exceptions did not find a match\n" " ValueError('bar'):\n" - " It matches 'ValueError' which was paired with ValueError('foo')\n" - " It matches 'ValueError' which was paired with ValueError('foo')\n" - " It matches 'ValueError' which was paired with ValueError('foo')\n" - " RaisesExc(ValueError, match='foo'): Regex pattern 'foo' did not match 'bar'\n" + " It matches `ValueError` which was paired with `ValueError('foo')`\n" + " It matches `ValueError` which was paired with `ValueError('foo')`\n" + " It matches `ValueError` which was paired with `ValueError('foo')`\n" + " RaisesExc(ValueError, match='foo'): Regex pattern did not match.\n" + " Regex: 'foo'\n" + " Input: 'bar'\n" "There exist a possible match when attempting an exhaustive check, but RaisesGroup uses a greedy algorithm. Please make your expected exceptions more stringent with `RaisesExc` etc so the greedy algorithm can function." ), RaisesGroup( @@ -919,7 +954,7 @@ def test_brief_error_on_one_fail() -> None: # no also-matched with ( fails_raises_group( - "1 matched exception. 'TypeError' is not of type 'RuntimeError'" + "1 matched exception. `TypeError()` is not an instance of `RuntimeError`" ), RaisesGroup(ValueError, RuntimeError), ): @@ -931,11 +966,11 @@ def test_brief_error_on_one_fail() -> None: "\n" "1 matched exception. \n" "The following expected exceptions did not find a match:\n" - " 'RuntimeError'\n" + " RuntimeError\n" "The following raised exceptions did not find a match\n" " TypeError():\n" - " It matches 'Exception' which was paired with ValueError()\n" - " 'TypeError' is not of type 'RuntimeError'" + " It matches `Exception` which was paired with `ValueError()`\n" + " `TypeError()` is not an instance of `RuntimeError`" ), RaisesGroup(Exception, RuntimeError), ): @@ -947,11 +982,11 @@ def test_brief_error_on_one_fail() -> None: "\n" "1 matched exception. \n" "The following expected exceptions did not find a match:\n" - " 'ValueError'\n" - " It matches ValueError() which was paired with 'ValueError'\n" + " ValueError\n" + " It matches `ValueError()` which was paired with `ValueError`\n" "The following raised exceptions did not find a match\n" " TypeError():\n" - " 'TypeError' is not of type 'ValueError'" + " `TypeError()` is not an instance of `ValueError`" ), RaisesGroup(ValueError, ValueError), ): @@ -965,7 +1000,7 @@ def test_identity_oopsies() -> None: with ( fails_raises_group( - "3 matched exceptions. 'RuntimeError' is not of type 'TypeError'" + "3 matched exceptions. `RuntimeError()` is not an instance of `TypeError`" ), RaisesGroup(ValueError, ValueError, ValueError, TypeError), ): @@ -984,17 +1019,35 @@ def test_identity_oopsies() -> None: " RaisesExc(match='bar')\n" "The following raised exceptions did not find a match\n" " ValueError('foo'):\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'\n" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'\n" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'\n" " ValueError('foo'):\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'\n" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'\n" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'\n" " ValueError('foo'):\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'\n" - " RaisesExc(match='bar'): Regex pattern 'bar' did not match 'foo'" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'\n" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'\n" + " RaisesExc(match='bar'): Regex pattern did not match.\n" + " Regex: 'bar'\n" + " Input: 'foo'" ), RaisesGroup(m, m, m), ): @@ -1009,7 +1062,9 @@ def test_raisesexc() -> None: RaisesExc() # type: ignore[call-overload] with pytest.raises( TypeError, - match=f"^exception_type {re.escape(repr(object))} must be a subclass of BaseException$", + match=wrap_escape( + "expected exception must be a BaseException type, not object" + ), ): RaisesExc(object) # type: ignore[type-var] @@ -1017,19 +1072,53 @@ def test_raisesexc() -> None: raise ExceptionGroup("", (ValueError(),)) with ( fails_raises_group( - "RaisesExc(TypeError): 'ValueError' is not of type 'TypeError'" + "RaisesExc(TypeError): `ValueError()` is not an instance of `TypeError`" ), RaisesGroup(RaisesExc(TypeError)), ): raise ExceptionGroup("", (ValueError(),)) + with RaisesExc(ValueError): + raise ValueError + + # FIXME: leaving this one formatted differently for now to not change + # tests in python/raises.py + with pytest.raises(Failed, match=wrap_escape("DID NOT RAISE ")): + with RaisesExc(ValueError): + ... + + with pytest.raises(Failed, match=wrap_escape("DID NOT RAISE any exception")): + with RaisesExc(match="foo"): + ... + + with pytest.raises( + # FIXME: do we want repr(type) or type.__name__ ? + Failed, + match=wrap_escape( + "DID NOT RAISE any of (, )" + ), + ): + with RaisesExc((ValueError, TypeError)): + ... + + with pytest.raises( + AssertionError, + match=wrap_escape( + "Raised exception did not match: `TypeError()` is not an instance of `ValueError`" + ), + ): + with RaisesExc(ValueError): + raise TypeError + def test_raisesexc_match() -> None: with RaisesGroup(RaisesExc(ValueError, "foo")): raise ExceptionGroup("", (ValueError("foo"),)) with ( fails_raises_group( - "RaisesExc(ValueError, match='foo'): Regex pattern 'foo' did not match 'bar'" + "RaisesExc(ValueError, match='foo'): Regex pattern did not match.\n" + " Regex: 'foo'\n" + " Input: 'bar'" ), RaisesGroup(RaisesExc(ValueError, "foo")), ): @@ -1040,7 +1129,9 @@ def test_raisesexc_match() -> None: raise ExceptionGroup("", (ValueError("foo"),)) with ( fails_raises_group( - "RaisesExc(match='foo'): Regex pattern 'foo' did not match 'bar'" + "RaisesExc(match='foo'): Regex pattern did not match.\n" + " Regex: 'foo'\n" + " Input: 'bar'" ), RaisesGroup(RaisesExc(match="foo")), ): @@ -1051,7 +1142,7 @@ def test_raisesexc_match() -> None: raise ExceptionGroup("", [ValueError("bar")]) with ( fails_raises_group( - "RaisesExc(ValueError, match='^bar$'): Regex pattern '^bar$' did not match 'barr'" + "\nRaisesExc(ValueError, match='^bar$'): \n - barr\n ? -\n + bar" ), RaisesGroup(RaisesExc(ValueError, match="^bar$")), ): @@ -1132,12 +1223,21 @@ def test_assert_matches() -> None: with pytest.raises(AssertionError, match=r"assert False\n \+ where False = .*"): assert RaisesExc(TypeError).matches(e) - # you'd need to do this arcane incantation - with pytest.raises(AssertionError, match="'ValueError' is not of type 'TypeError'"): + with pytest.raises( + AssertionError, + match=wrap_escape( + "`ValueError()` is not an instance of `TypeError`\n" + "assert False\n" + " + where False = matches(ValueError())\n" + " + where matches = RaisesExc(TypeError).matches" + ), + ): + # you'd need to do this arcane incantation assert (m := RaisesExc(TypeError)).matches(e), m.fail_reason # but even if we add assert_matches, will people remember to use it? # other than writing a linter rule, I don't think we can catch `assert RaisesExc(...).matches` + # ... no wait pytest catches other asserts ... so we probably can?? # https://github.com/pytest-dev/pytest/issues/12504 @@ -1184,3 +1284,38 @@ def test_parametrizing_conditional_raisesgroup( if wrap_in_group: raise ExceptionGroup("", [ValueError()]) raise ValueError() + + +def test_annotated_group() -> None: + fail_msg = wrap_escape( + "Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` are accepted as generic types but got `ExceptionGroup[ValueError]`. As `raises` will catch all instances of the specified group regardless of the generic argument specific nested exceptions has to be checked with `RaisesGroup`." + ) + with pytest.raises(TypeError, match=fail_msg): + with RaisesGroup(ExceptionGroup[ValueError]): + ... # pragma: no cover + with pytest.raises(TypeError, match=fail_msg): + with RaisesExc(ExceptionGroup[ValueError]): + ... # pragma: no cover + with RaisesGroup(ExceptionGroup[Exception]): + raise ExceptionGroup( + "", [ExceptionGroup("", [ValueError(), ValueError(), ValueError()])] + ) + with RaisesExc(BaseExceptionGroup[BaseException]): + raise BaseExceptionGroup("", [KeyboardInterrupt()]) + + +def test_tuples() -> None: + # raises has historically supported one of several exceptions being raised + with pytest.raises((ValueError, IndexError)): + raise ValueError + # so now RaisesExc also does + with RaisesExc((ValueError, IndexError)): + raise IndexError + # but RaisesGroup currently doesn't. There's an argument it shouldn't because + # it can be confusing - RaisesGroup((ValueError, TypeError)) looks a lot like + # RaisesGroup(ValueError, TypeError), and the former might be interpreted as the latter. + with pytest.raises( + TypeError, + match="expected exception must be a BaseException type, RaisesExc, or RaisesGroup, not tuple", + ): + RaisesGroup((ValueError, IndexError)) # type: ignore[call-overload] diff --git a/testing/typing_raises_group.py b/testing/typing_raises_group.py index 6e91cbf6da1..380c80768d0 100644 --- a/testing/typing_raises_group.py +++ b/testing/typing_raises_group.py @@ -18,8 +18,8 @@ def check_raisesexc_typevar_default(e: RaisesExc) -> None: - assert e.exception_type is not None - _exc: type[BaseException] = e.exception_type + assert e.expected_exceptions is not None + _exc: type[BaseException] | tuple[type[BaseException], ...] = e.expected_exceptions # this would previously pass, as the type would be `Any` e.exception_type().blah() # type: ignore @@ -63,7 +63,7 @@ def check_exc(exc: BaseException) -> bool: RaisesExc(ValueError) RaisesExc(ValueError, "regex") RaisesExc(ValueError, "regex", check_exc) - RaisesExc(exception_type=ValueError) + RaisesExc(expected_exception=ValueError) RaisesExc(match="regex") RaisesExc(check=check_exc) RaisesExc(ValueError, match="regex") From 09d06fe99dcf2493383c0ef82d04e9561ab0fd7e Mon Sep 17 00:00:00 2001 From: jakkdl Date: Thu, 20 Feb 2025 17:14:43 +0100 Subject: [PATCH 1129/1271] fix tests --- src/_pytest/_code/code.py | 2 +- src/_pytest/python_api.py | 4 ++-- src/_pytest/raises_group.py | 5 +++-- testing/code/test_excinfo.py | 5 +++-- testing/python/raises.py | 13 ++++--------- testing/python/raises_group.py | 13 +++++++------ 6 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 429b856596b..5b85d295d36 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -763,7 +763,7 @@ def match(self, regexp: str | re.Pattern[str]) -> Literal[True]: """ __tracebackhide__ = True value = self._stringify_exception(self.value) - msg = f"Raised exception did not match: Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" + msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" if regexp == value: msg += "\n Did you mean to `re.escape()` the regex?" assert re.search(regexp, value), msg diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 8a11a128293..b1da082134f 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -29,6 +29,8 @@ if TYPE_CHECKING: from numpy import ndarray + E = TypeVar("E", bound=BaseException, default=BaseException) + def _compare_approx( full_object: object, @@ -786,8 +788,6 @@ def _as_numpy_array(obj: object) -> ndarray | None: # builtin pytest.raises helper -E = TypeVar("E", bound=BaseException, default=BaseException) - @overload def raises( diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index e549b8e8975..d314f14af1c 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -218,7 +218,8 @@ def _parse_exc( self.is_baseexception = True return cast(type[BaseExcT_1], origin_exc) else: - raise TypeError( + # I kinda think this should be a TypeError... + raise ValueError( f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` " f"are accepted as generic types but got `{exc}`. " f"As `raises` will catch all instances of the specified group regardless of the " @@ -451,7 +452,7 @@ def __exit__( ) if not self.matches(exc_val): - raise AssertionError(f"Raised exception did not match: {self._fail_reason}") + raise AssertionError(self._fail_reason) # Cast to narrow the exception type now that it's verified.... # even though the TypeGuard in self.matches should be narrowing diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 89088576980..438a5259f20 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -481,8 +481,9 @@ def test_raises_exception_escapes_generic_group() -> None: try: with pytest.raises(ExceptionGroup[Exception]): raise ValueError("my value error") - except ValueError as e: - assert str(e) == "my value error" + except AssertionError as e: + assert str(e) == "`ValueError()` is not an instance of `ExceptionGroup`" + assert str(e.__context__) == "my value error" else: pytest.fail("Expected ValueError to be raised") diff --git a/testing/python/raises.py b/testing/python/raises.py index c7ecc301701..65081b2adb1 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -238,7 +238,7 @@ def test_raises_match(self) -> None: msg = "with base 16" expr = ( - "Raised exception did not match: Regex pattern did not match.\n" + "Regex pattern did not match.\n" f" Regex: {msg!r}\n" " Input: \"invalid literal for int() with base 10: 'asdf'\"" ) @@ -277,10 +277,7 @@ def test_match_failure_string_quoting(self): with pytest.raises(AssertionError, match="'foo"): raise AssertionError("'bar") (msg,) = excinfo.value.args - assert ( - msg - == '''Raised exception did not match: Regex pattern did not match.\n Regex: "'foo"\n Input: "'bar"''' - ) + assert msg == '''Regex pattern did not match.\n Regex: "'foo"\n Input: "'bar"''' def test_match_failure_exact_string_message(self): message = "Oh here is a message with (42) numbers in parameters" @@ -289,7 +286,7 @@ def test_match_failure_exact_string_message(self): raise AssertionError(message) (msg,) = excinfo.value.args assert msg == ( - "Raised exception did not match: Regex pattern did not match.\n" + "Regex pattern did not match.\n" " Regex: 'Oh here is a message with (42) numbers in parameters'\n" " Input: 'Oh here is a message with (42) numbers in parameters'\n" " Did you mean to `re.escape()` the regex?" @@ -303,9 +300,7 @@ def test_raises_match_wrong_type(self): """ with pytest.raises( AssertionError, - match=wrap_escape( - "Raised exception did not match: `ValueError()` is not an instance of `IndexError`" - ), + match=wrap_escape("`ValueError()` is not an instance of `IndexError`"), ): with pytest.raises(IndexError, match="nomatch"): int("asdf") diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index 5e00aaa06bb..2619eb41c1d 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -1101,11 +1101,10 @@ def test_raisesexc() -> None: with RaisesExc((ValueError, TypeError)): ... + # currently RaisesGroup says "Raised exception did not match" but RaisesExc doesn't... with pytest.raises( AssertionError, - match=wrap_escape( - "Raised exception did not match: `TypeError()` is not an instance of `ValueError`" - ), + match=wrap_escape("`TypeError()` is not an instance of `ValueError`"), ): with RaisesExc(ValueError): raise TypeError @@ -1287,13 +1286,15 @@ def test_parametrizing_conditional_raisesgroup( def test_annotated_group() -> None: + # repr depends on if exceptiongroup backport is being used or not + t = repr(ExceptionGroup[ValueError]) fail_msg = wrap_escape( - "Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` are accepted as generic types but got `ExceptionGroup[ValueError]`. As `raises` will catch all instances of the specified group regardless of the generic argument specific nested exceptions has to be checked with `RaisesGroup`." + f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` are accepted as generic types but got `{t}`. As `raises` will catch all instances of the specified group regardless of the generic argument specific nested exceptions has to be checked with `RaisesGroup`." ) - with pytest.raises(TypeError, match=fail_msg): + with pytest.raises(ValueError, match=fail_msg): with RaisesGroup(ExceptionGroup[ValueError]): ... # pragma: no cover - with pytest.raises(TypeError, match=fail_msg): + with pytest.raises(ValueError, match=fail_msg): with RaisesExc(ExceptionGroup[ValueError]): ... # pragma: no cover with RaisesGroup(ExceptionGroup[Exception]): From 753df941da92bd02b9f4d453c14006e382c004e0 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Fri, 21 Feb 2025 13:01:57 +0100 Subject: [PATCH 1130/1271] harmonize stringify_exception, various comments --- src/_pytest/_code/code.py | 49 +++++++++++++++++++--------------- src/_pytest/outcomes.py | 4 +-- src/_pytest/python_api.py | 13 ++++++--- src/_pytest/raises_group.py | 24 ++++++++--------- testing/python/raises.py | 4 +-- testing/typing_raises_group.py | 13 +++++++-- 6 files changed, 62 insertions(+), 45 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 5b85d295d36..0a5a20161e4 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -459,6 +459,32 @@ def recursionindex(self) -> int | None: return None +def stringify_exception( + exc: BaseException, include_subexception_msg: bool = True +) -> str: + try: + notes = getattr(exc, "__notes__", []) + except KeyError: + # Workaround for https://github.com/python/cpython/issues/98778 on + # Python <= 3.9, and some 3.10 and 3.11 patch versions. + HTTPError = getattr(sys.modules.get("urllib.error", None), "HTTPError", ()) + if sys.version_info < (3, 12) and isinstance(exc, HTTPError): + notes = [] + else: + raise + if not include_subexception_msg and isinstance(exc, BaseExceptionGroup): + message = exc.message + else: + message = str(exc) + + return "\n".join( + [ + message, + *notes, + ] + ) + + E = TypeVar("E", bound=BaseException, covariant=True) @@ -736,25 +762,6 @@ def getrepr( ) return fmt.repr_excinfo(self) - def _stringify_exception(self, exc: BaseException) -> str: - try: - notes = getattr(exc, "__notes__", []) - except KeyError: - # Workaround for https://github.com/python/cpython/issues/98778 on - # Python <= 3.9, and some 3.10 and 3.11 patch versions. - HTTPError = getattr(sys.modules.get("urllib.error", None), "HTTPError", ()) - if sys.version_info < (3, 12) and isinstance(exc, HTTPError): - notes = [] - else: - raise - - return "\n".join( - [ - str(exc), - *notes, - ] - ) - def match(self, regexp: str | re.Pattern[str]) -> Literal[True]: """Check whether the regular expression `regexp` matches the string representation of the exception using :func:`python:re.search`. @@ -762,7 +769,7 @@ def match(self, regexp: str | re.Pattern[str]) -> Literal[True]: If it matches `True` is returned, otherwise an `AssertionError` is raised. """ __tracebackhide__ = True - value = self._stringify_exception(self.value) + value = stringify_exception(self.value) msg = f"Regex pattern did not match.\n Regex: {regexp!r}\n Input: {value!r}" if regexp == value: msg += "\n Did you mean to `re.escape()` the regex?" @@ -794,7 +801,7 @@ def _group_contains( if not isinstance(exc, expected_exception): continue if match is not None: - value = self._stringify_exception(exc) + value = stringify_exception(exc) if not re.search(match, value): continue return True diff --git a/src/_pytest/outcomes.py b/src/_pytest/outcomes.py index d792382a9c1..68ba0543365 100644 --- a/src/_pytest/outcomes.py +++ b/src/_pytest/outcomes.py @@ -77,8 +77,8 @@ def __init__( super().__init__(msg) -# Elaborate hack to work around https://github.com/python/mypy/issues/2087. -# Ideally would just be `exit.Exception = Exit` etc. +# We need a callable protocol to add attributes, for discussion see +# https://github.com/python/mypy/issues/2087. _F = TypeVar("_F", bound=Callable[..., object]) _ET = TypeVar("_ET", bound=type[BaseException]) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index b1da082134f..c8edce4274a 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -787,6 +787,9 @@ def _as_numpy_array(obj: object) -> ndarray | None: # builtin pytest.raises helper +# FIXME: This should probably me moved to 'src/_pytest.raises_group.py' +# (and rename the file to 'raises.py') +# since it's much more closely tied to those than to the other stuff in this file. @overload @@ -1000,9 +1003,11 @@ def raises( # note: RaisesExc/RaisesGroup uses fail() internally, so this alias -# indicates (to [internal] plugins?) that `pytest.raises` will -# raise `_pytest.outcomes.Failed`, where -# `outcomes.Failed is outcomes.fail.Exception is raises.Exception` +# indicates (to [internal] plugins?) that `pytest.raises` will +# raise `_pytest.outcomes.Failed`, where +# `outcomes.Failed is outcomes.fail.Exception is raises.Exception` # note: this is *not* the same as `_pytest.main.Failed` -# note: mypy does not recognize this attribute +# note: mypy does not recognize this attribute, and it's not possible +# to use a protocol/decorator like the others in outcomes due to +# https://github.com/python/mypy/issues/18715 raises.Exception = fail.Exception # type: ignore[attr-defined] diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index d314f14af1c..f60bacb7184 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -18,6 +18,7 @@ import warnings from _pytest._code import ExceptionInfo +from _pytest._code.code import stringify_exception from _pytest.outcomes import fail from _pytest.warning_types import PytestWarning @@ -61,17 +62,6 @@ from exceptiongroup import ExceptionGroup -# this differs slightly from pytest.ExceptionInfo._stringify_exception -# as we don't want '(1 sub-exception)' when matching group strings -def _stringify_exception(exc: BaseException) -> str: - return "\n".join( - [ - exc.message if isinstance(exc, BaseExceptionGroup) else str(exc), - *getattr(exc, "__notes__", []), - ], - ) - - # String patterns default to including the unicode flag. _REGEX_NO_FLAGS = re.compile(r"").flags @@ -141,6 +131,12 @@ def unescape(s: str) -> str: return re.sub(r"\\([{}()+-.*?^$\[\]\s\\])", r"\1", s) +# These classes conceptually differ from ExceptionInfo in that ExceptionInfo is tied, and +# constructed from, a particular exception - whereas these are constructed with expected +# exceptions, and later allow matching towards particular exceptions. +# But there's overlap in `ExceptionInfo.match` and `AbstractRaises._check_match`, as with +# `AbstractRaises.matches` and `ExceptionInfo.errisinstance`+`ExceptionInfo.group_contains`. +# The interaction between these classes should perhaps be improved. class AbstractRaises(ABC, Generic[BaseExcT_co]): """ABC with common functionality shared between RaisesExc and RaisesGroup""" @@ -161,7 +157,6 @@ def __init__( if match == "": warnings.warn( PytestWarning( - "session.shouldstop cannot be unset after it has been set; ignoring." "matching against an empty string will *always* pass. If you want " "to check for an empty message you need to pass '^$'. If you don't " "want to match you should pass `None` or leave out the parameter." @@ -251,10 +246,13 @@ def _check_check( self._fail_reason = f"check{check_repr} did not return True" return False + # TODO: harmonize with ExceptionInfo.match def _check_match(self, e: BaseException) -> bool: if self.match is None or re.search( self.match, - stringified_exception := _stringify_exception(e), + stringified_exception := stringify_exception( + e, include_subexception_msg=False + ), ): return True diff --git a/testing/python/raises.py b/testing/python/raises.py index 65081b2adb1..5dafef7a78d 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -261,12 +261,10 @@ def tfunc(match): pytest.raises(ValueError, tfunc, match="").match("match=") # empty string matches everything, which is probably not what the user wants - # FIXME: I have no clue what session.shouldstop is doing here with pytest.warns( PytestWarning, match=wrap_escape( - "session.shouldstop cannot be unset after it has been set; ignoring.matching against " - "an empty string will *always* pass. If you want to check for an empty message you " + "matching against an empty string will *always* pass. If you want to check for an empty message you " "need to pass '^$'. If you don't want to match you should pass `None` or leave out the parameter." ), ): diff --git a/testing/typing_raises_group.py b/testing/typing_raises_group.py index 380c80768d0..f27943e3a58 100644 --- a/testing/typing_raises_group.py +++ b/testing/typing_raises_group.py @@ -6,10 +6,19 @@ from typing_extensions import assert_type -from _pytest.raises_group import RaisesExc -from _pytest.raises_group import RaisesGroup +from _pytest.main import Failed as main_Failed +from _pytest.outcomes import Failed +from pytest import raises +from pytest import RaisesExc +from pytest import RaisesGroup +# does not work +assert_type(raises.Exception, Failed) # type: ignore[assert-type, attr-defined] + +# FIXME: these are different for some reason(?) +assert Failed is not main_Failed # type: ignore[comparison-overlap] + if sys.version_info < (3, 11): from exceptiongroup import BaseExceptionGroup from exceptiongroup import ExceptionGroup From 77f2c63a542fc9511f5919ddf7f4b64d237fda07 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:40:57 -0300 Subject: [PATCH 1131/1271] [automated] Update plugin list (#13247) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 124 +++++++++++++++++-------------- 1 file changed, 70 insertions(+), 54 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 28492e22a62..b143608b6fd 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 29, 2024 N/A pytest>=6.0 - :pypi:`pytest-alerts` A pytest plugin for sending test results to Slack and Telegram Feb 01, 2025 4 - Beta pytest>=7.4.0 + :pypi:`pytest-alerts` A pytest plugin for sending test results to Slack and Telegram Feb 21, 2025 4 - Beta pytest>=7.4.0 :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) :pypi:`pytest-allure-adaptor2` Plugin for py.test to generate allure xml reports Oct 14, 2020 N/A pytest (>=2.7.3) @@ -161,7 +161,7 @@ This list contains 1585 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Feb 11, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Feb 17, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -221,7 +221,7 @@ This list contains 1585 plugins. :pypi:`pytest-catchlog` py.test plugin to catch log messages. This is a fork of pytest-capturelog. Jan 24, 2016 4 - Beta pytest (>=2.6) :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A :pypi:`pytest-cdist` A pytest plugin to split your test suite into multiple parts Jan 30, 2025 N/A pytest>=7 - :pypi:`pytest-celery` Pytest plugin for Celery Sep 20, 2024 4 - Beta N/A + :pypi:`pytest-celery` Pytest plugin for Celery Feb 21, 2025 5 - Production/Stable N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -261,7 +261,7 @@ This list contains 1585 plugins. :pypi:`pytest-cloud` Distributed tests planner plugin for pytest testing framework. Oct 05, 2020 6 - Mature N/A :pypi:`pytest-cloudflare-worker` pytest plugin for testing cloudflare workers Mar 30, 2021 4 - Beta pytest (>=6.0.0) :pypi:`pytest-cloudist` Distribute tests to cloud machines without fuss Sep 02, 2022 4 - Beta pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-cmake` Provide CMake module for Pytest Feb 09, 2025 N/A pytest<9,>=4 + :pypi:`pytest-cmake` Provide CMake module for Pytest Feb 17, 2025 N/A pytest<9,>=4 :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) @@ -475,15 +475,15 @@ This list contains 1585 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 Jul 25, 2024 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. Feb 11, 2025 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 11, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 11, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 11, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Feb 11, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 11, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 11, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 11, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 11, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Feb 20, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 20, 2025 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) @@ -541,7 +541,7 @@ This list contains 1585 plugins. :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest - :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI Jan 22, 2025 N/A pytest<8.0.0,>=7.2.1 + :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI Feb 21, 2025 N/A pytest<8.0.0,>=7.2.1 :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) @@ -629,12 +629,12 @@ This list contains 1585 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Jan 24, 2025 5 - Production/Stable pytest>=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Jan 30, 2025 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. Feb 20, 2025 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-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. Feb 14, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Feb 20, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -678,7 +678,7 @@ This list contains 1585 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Feb 15, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Feb 22, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -752,8 +752,8 @@ This list contains 1585 plugins. :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Feb 14, 2025 N/A pytest - :pypi:`pytest-ipywidgets` Jan 29, 2025 N/A pytest + :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Feb 19, 2025 N/A pytest + :pypi:`pytest-ipywidgets` Feb 18, 2025 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Dec 05, 2024 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) @@ -877,13 +877,13 @@ This list contains 1585 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Feb 14, 2025 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Feb 19, 2025 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A :pypi:`pytest-metadata` pytest plugin for test session metadata Feb 12, 2024 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 Nov 28, 2024 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Feb 20, 2025 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) @@ -1036,7 +1036,7 @@ This list contains 1585 plugins. :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-picked` Run the tests related to the changed files Nov 06, 2024 N/A pytest>=3.7.0 - :pypi:`pytest-pickle-cache` A pytest plugin for caching test results using pickle. Jan 18, 2025 N/A pytest>=7 + :pypi:`pytest-pickle-cache` A pytest plugin for caching test results using pickle. Feb 17, 2025 N/A pytest>=7 :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) :pypi:`pytest-pikachu` Show surprise when tests are passing Aug 05, 2021 5 - Production/Stable pytest :pypi:`pytest-pilot` Slice in your test base thanks to powerful markers. Oct 09, 2020 5 - Production/Stable N/A @@ -1046,6 +1046,7 @@ This list contains 1585 plugins. :pypi:`pytest-pinpoint` A pytest plugin which runs SBFL algorithms to detect faults. Sep 25, 2020 N/A pytest (>=4.4.0) :pypi:`pytest-pipeline` Pytest plugin for functional testing of data analysispipelines Jan 24, 2017 3 - Alpha N/A :pypi:`pytest-pitch` runs tests in an order such that coverage increases as fast as possible Nov 02, 2023 4 - Beta pytest >=7.3.1 + :pypi:`pytest-platform-adapter` Pytest集成自动化平台插件 Feb 18, 2025 5 - Production/Stable pytest>=6.2.5 :pypi:`pytest-platform-markers` Markers for pytest to skip tests on specific platforms Sep 09, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-play` pytest plugin that let you automate actions and assertions with test metrics reporting executing plain YAML files Jun 12, 2019 5 - Production/Stable N/A :pypi:`pytest-playbook` Pytest plugin for reading playbooks. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) @@ -1108,6 +1109,7 @@ This list contains 1585 plugins. :pypi:`pytest-pydev` py.test plugin to connect to a remote debug server with PyDev or PyCharm. Nov 15, 2017 3 - Alpha N/A :pypi:`pytest-pydocstyle` pytest plugin to run pydocstyle Oct 09, 2024 3 - Alpha pytest>=7.0 :pypi:`pytest-pylint` pytest plugin to check source code with pylint Oct 06, 2023 5 - Production/Stable pytest >=7.0 + :pypi:`pytest-pylyzer` A pytest plugin for pylyzer Feb 15, 2025 4 - Beta N/A :pypi:`pytest-pymysql-autorecord` Record PyMySQL queries and mock with the stored data. Sep 02, 2022 N/A N/A :pypi:`pytest-pyodide` Pytest plugin for testing applications that use Pyodide Nov 23, 2024 N/A pytest :pypi:`pytest-pypi` Easily test your HTTP library against a local copy of pypi Mar 04, 2018 3 - Alpha N/A @@ -1184,7 +1186,7 @@ This list contains 1585 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Feb 01, 2025 N/A pytest>=8.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Feb 19, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1259,7 +1261,7 @@ This list contains 1585 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 20, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1271,7 +1273,7 @@ This list contains 1585 plugins. :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 Feb 01, 2024 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. Feb 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Feb 20, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1470,7 +1472,7 @@ This list contains 1585 plugins. :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Mar 27, 2024 N/A N/A :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Jan 04, 2024 5 - Production/Stable pytest - :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Aug 29, 2024 4 - Beta pytest>=3.8.0 + :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Feb 18, 2025 4 - Beta pytest>=3.8.0 :pypi:`pytest-tipsi-django` Better fixtures for django Feb 05, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Feb 04, 2024 5 - Production/Stable pytest>=3.3.0 :pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0) @@ -1835,7 +1837,7 @@ This list contains 1585 plugins. A pytest plugin for verifying alembic migrations. :pypi:`pytest-alerts` - *last release*: Feb 01, 2025, + *last release*: Feb 21, 2025, *status*: 4 - Beta, *requires*: pytest>=7.4.0 @@ -2514,7 +2516,7 @@ This list contains 1585 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Feb 11, 2025, + *last release*: Feb 17, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -2934,8 +2936,8 @@ This list contains 1585 plugins. A pytest plugin to split your test suite into multiple parts :pypi:`pytest-celery` - *last release*: Sep 20, 2024, - *status*: 4 - Beta, + *last release*: Feb 21, 2025, + *status*: 5 - Production/Stable, *requires*: N/A Pytest plugin for Celery @@ -3214,7 +3216,7 @@ This list contains 1585 plugins. Distribute tests to cloud machines without fuss :pypi:`pytest-cmake` - *last release*: Feb 09, 2025, + *last release*: Feb 17, 2025, *status*: N/A, *requires*: pytest<9,>=4 @@ -4712,63 +4714,63 @@ This list contains 1585 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Feb 11, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -5174,7 +5176,7 @@ This list contains 1585 plugins. Additional pytest markers to dynamically enable/disable tests viia CLI flags :pypi:`pytest-f3ts` - *last release*: Jan 22, 2025, + *last release*: Feb 21, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.2.1 @@ -5790,7 +5792,7 @@ This list contains 1585 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Jan 30, 2025, + *last release*: Feb 20, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -5825,7 +5827,7 @@ This list contains 1585 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Feb 14, 2025, + *last release*: Feb 20, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6133,7 +6135,7 @@ This list contains 1585 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 15, 2025, + *last release*: Feb 22, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6651,14 +6653,14 @@ This list contains 1585 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipynb2` - *last release*: Feb 14, 2025, + *last release*: Feb 19, 2025, *status*: N/A, *requires*: pytest Pytest plugin to run tests in Jupyter Notebooks :pypi:`pytest-ipywidgets` - *last release*: Jan 29, 2025, + *last release*: Feb 18, 2025, *status*: N/A, *requires*: pytest @@ -7526,7 +7528,7 @@ This list contains 1585 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Feb 14, 2025, + *last release*: Feb 19, 2025, *status*: N/A, *requires*: N/A @@ -7568,7 +7570,7 @@ This list contains 1585 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Nov 28, 2024, + *last release*: Feb 20, 2025, *status*: N/A, *requires*: pytest @@ -8639,7 +8641,7 @@ This list contains 1585 plugins. Run the tests related to the changed files :pypi:`pytest-pickle-cache` - *last release*: Jan 18, 2025, + *last release*: Feb 17, 2025, *status*: N/A, *requires*: pytest>=7 @@ -8708,6 +8710,13 @@ This list contains 1585 plugins. runs tests in an order such that coverage increases as fast as possible + :pypi:`pytest-platform-adapter` + *last release*: Feb 18, 2025, + *status*: 5 - Production/Stable, + *requires*: pytest>=6.2.5 + + Pytest集成自动化平台插件 + :pypi:`pytest-platform-markers` *last release*: Sep 09, 2019, *status*: 4 - Beta, @@ -9142,6 +9151,13 @@ This list contains 1585 plugins. pytest plugin to check source code with pylint + :pypi:`pytest-pylyzer` + *last release*: Feb 15, 2025, + *status*: 4 - Beta, + *requires*: N/A + + A pytest plugin for pylyzer + :pypi:`pytest-pymysql-autorecord` *last release*: Sep 02, 2022, *status*: N/A, @@ -9675,7 +9691,7 @@ This list contains 1585 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Feb 01, 2025, + *last release*: Feb 19, 2025, *status*: N/A, *requires*: pytest>=8.0.0 @@ -10200,7 +10216,7 @@ This list contains 1585 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Feb 13, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10284,7 +10300,7 @@ This list contains 1585 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Feb 13, 2025, + *last release*: Feb 20, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -11677,7 +11693,7 @@ This list contains 1585 plugins. The companion pytest plugin for tiny-api-client :pypi:`pytest-tinybird` - *last release*: Aug 29, 2024, + *last release*: Feb 18, 2025, *status*: 4 - Beta, *requires*: pytest>=3.8.0 From 4f682c17a23d56fbfd85bcf628f24f6d89edecfc Mon Sep 17 00:00:00 2001 From: jakkdl Date: Mon, 24 Feb 2025 11:54:58 +0100 Subject: [PATCH 1132/1271] fix rtd --- src/_pytest/python_api.py | 9 ++++----- src/_pytest/raises_group.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index c8edce4274a..ecb28c2ca49 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -17,10 +17,9 @@ from typing import TYPE_CHECKING from typing import TypeVar -import _pytest._code from _pytest.outcomes import fail -from _pytest.raises_group import BaseExcT_co_default from _pytest.raises_group import RaisesExc +from pytest import ExceptionInfo if sys.version_info < (3, 11): @@ -797,7 +796,7 @@ def raises( expected_exception: type[E] | tuple[type[E], ...], *, match: str | re.Pattern[str] | None = ..., - check: Callable[[BaseExcT_co_default], bool] = ..., + check: Callable[[E], bool] = ..., ) -> RaisesExc[E]: ... @@ -820,14 +819,14 @@ def raises( func: Callable[..., Any], *args: Any, **kwargs: Any, -) -> _pytest._code.ExceptionInfo[E]: ... +) -> ExceptionInfo[E]: ... def raises( expected_exception: type[E] | tuple[type[E], ...] | None = None, *args: Any, **kwargs: Any, -) -> RaisesExc[BaseException] | _pytest._code.ExceptionInfo[E]: +) -> RaisesExc[BaseException] | ExceptionInfo[E]: r"""Assert that a code block/function call raises an exception type, or one of its subclasses. :param expected_exception: diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index f60bacb7184..b521e1962b4 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -17,10 +17,10 @@ from typing import TYPE_CHECKING import warnings -from _pytest._code import ExceptionInfo from _pytest._code.code import stringify_exception from _pytest.outcomes import fail from _pytest.warning_types import PytestWarning +from pytest import ExceptionInfo if TYPE_CHECKING: From 309030c0ace99a725f9cbe830ddad87fd3a20140 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Mon, 24 Feb 2025 12:41:26 +0100 Subject: [PATCH 1133/1271] fix import loop --- src/_pytest/python_api.py | 2 +- src/_pytest/raises_group.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index ecb28c2ca49..f59d7ea8ef4 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -17,9 +17,9 @@ from typing import TYPE_CHECKING from typing import TypeVar +from _pytest._code import ExceptionInfo from _pytest.outcomes import fail from _pytest.raises_group import RaisesExc -from pytest import ExceptionInfo if sys.version_info < (3, 11): diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index b521e1962b4..f60bacb7184 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -17,10 +17,10 @@ from typing import TYPE_CHECKING import warnings +from _pytest._code import ExceptionInfo from _pytest._code.code import stringify_exception from _pytest.outcomes import fail from _pytest.warning_types import PytestWarning -from pytest import ExceptionInfo if TYPE_CHECKING: From 9cf2cae94355cd83ad7e8d88f976c5a524c98cfb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 20:59:07 +0000 Subject: [PATCH 1134/1271] [pre-commit.ci] pre-commit autoupdate (#13251) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.6 → v0.9.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.6...v0.9.7) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d746af2e4e5..085ea59ca05 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.6" + rev: "v0.9.7" hooks: - id: ruff args: ["--fix"] From 22fe7b17faf97f8413a57c6482f3dbfeb9287839 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 28 Feb 2025 15:07:26 +0100 Subject: [PATCH 1135/1271] =?UTF-8?q?=F0=9F=93=A6=F0=9F=93=9D=20Allow=20mo?= =?UTF-8?q?dern=20Towncrier=20in=20docs=20builds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 has been resolved and the recent Towncrier versions are compatible with the `sphinxcontrib.towncrier` Sphinx extension project yet again. --- doc/en/broken-dep-constraints.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/en/broken-dep-constraints.txt b/doc/en/broken-dep-constraints.txt index 3a8d2c34b5a..1488e06fa23 100644 --- a/doc/en/broken-dep-constraints.txt +++ b/doc/en/broken-dep-constraints.txt @@ -1,6 +1,2 @@ # This file contains transitive dependencies that need to be pinned for some reason. # Eventually this file will be empty, but in this case keep it around for future use. - -# Pin towncrier temporarily due to incompatibility with sphinxcontrib-towncrier: -# https://github.com/sphinx-contrib/sphinxcontrib-towncrier/issues/92 -towncrier<24.7 From c51af71e635c1eafe421e61b5b9bf1647f6fd35b Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 28 Feb 2025 15:11:38 +0100 Subject: [PATCH 1136/1271] =?UTF-8?q?=F0=9F=93=9D=20Add=20a=20change=20not?= =?UTF-8?q?e=20for=20#13256?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelog/13256.contrib.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 changelog/13256.contrib.rst diff --git a/changelog/13256.contrib.rst b/changelog/13256.contrib.rst new file mode 100644 index 00000000000..fe3bac87ca1 --- /dev/null +++ b/changelog/13256.contrib.rst @@ -0,0 +1,2 @@ +Support for Towncier versions released in 2024 has been re-enabled +when building Sphinx docs -- by :user:`webknjaz`. From 611bb13108c249d2789014a631242f765efe1644 Mon Sep 17 00:00:00 2001 From: Anton Zhilin Date: Sat, 1 Mar 2025 16:06:40 +0300 Subject: [PATCH 1137/1271] Allow hiding a parameter set from test name (#13229) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #13228 --------- Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- AUTHORS | 1 + changelog/13228.feature.rst | 3 + doc/en/reference/reference.rst | 10 +++ src/_pytest/mark/__init__.py | 14 +++- src/_pytest/mark/structures.py | 22 ++++-- src/_pytest/python.py | 54 ++++++++++---- src/pytest/__init__.py | 2 + testing/python/metafunc.py | 125 +++++++++++++++++++++++++++++++++ testing/test_mark.py | 6 +- 9 files changed, 216 insertions(+), 21 deletions(-) create mode 100644 changelog/13228.feature.rst diff --git a/AUTHORS b/AUTHORS index e670571566a..e5c19cdca0d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -43,6 +43,7 @@ Anthony Shaw Anthony Sottile Anton Grinevich Anton Lodder +Anton Zhilin Antony Lee Arel Cordero Arias Emmanuel diff --git a/changelog/13228.feature.rst b/changelog/13228.feature.rst new file mode 100644 index 00000000000..c5d84182313 --- /dev/null +++ b/changelog/13228.feature.rst @@ -0,0 +1,3 @@ +:ref:`hidden-param` can now be used in ``id`` of :func:`pytest.param` or in +``ids`` of :py:func:`Metafunc.parametrize `. +It hides the parameter set from the test name. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 809e97b4747..267ab37b1b1 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -20,6 +20,16 @@ The current pytest version, as a string:: >>> pytest.__version__ '7.0.0' +.. _`hidden-param`: + +pytest.HIDDEN_PARAM +~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 8.4 + +Can be passed to ``ids`` of :py:func:`Metafunc.parametrize ` +or to ``id`` of :func:`pytest.param` to hide a parameter set from the test name. +Can only be used at most 1 time, as test names need to be unique. .. _`version-tuple`: diff --git a/src/_pytest/mark/__init__.py b/src/_pytest/mark/__init__.py index 488b562a298..068c7410a46 100644 --- a/src/_pytest/mark/__init__.py +++ b/src/_pytest/mark/__init__.py @@ -12,8 +12,10 @@ from .expression import Expression from .expression import ParseError +from .structures import _HiddenParam from .structures import EMPTY_PARAMETERSET_OPTION from .structures import get_empty_parameterset_mark +from .structures import HIDDEN_PARAM from .structures import Mark from .structures import MARK_GEN from .structures import MarkDecorator @@ -33,6 +35,7 @@ __all__ = [ + "HIDDEN_PARAM", "MARK_GEN", "Mark", "MarkDecorator", @@ -48,7 +51,7 @@ def param( *values: object, marks: MarkDecorator | Collection[MarkDecorator | Mark] = (), - id: str | None = None, + id: str | _HiddenParam | None = None, ) -> ParameterSet: """Specify a parameter in `pytest.mark.parametrize`_ calls or :ref:`parametrized fixtures `. @@ -72,7 +75,14 @@ def test_eval(test_input, expected): :ref:`pytest.mark.usefixtures ` cannot be added via this parameter. - :param id: The id to attribute to this parameter set. + :type id: str | Literal[pytest.HIDDEN_PARAM] | None + :param id: + The id to attribute to this parameter set. + + .. versionadded:: 8.4 + :ref:`hidden-param` means to hide the parameter set + from the test name. Can only be used at most 1 time, as + test names need to be unique. """ return ParameterSet.param(*values, marks=marks, id=id) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 1a0b3c5b5b8..a3290aed82e 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -10,6 +10,7 @@ from collections.abc import MutableMapping from collections.abc import Sequence import dataclasses +import enum import inspect from typing import Any from typing import final @@ -38,6 +39,16 @@ EMPTY_PARAMETERSET_OPTION = "empty_parameter_set_mark" +# Singleton type for HIDDEN_PARAM, as described in: +# https://www.python.org/dev/peps/pep-0484/#support-for-singleton-types-in-unions +class _HiddenParam(enum.Enum): + token = 0 + + +#: Can be used as a parameter set id to hide it from the test name. +HIDDEN_PARAM = _HiddenParam.token + + def istestfunc(func) -> bool: return callable(func) and getattr(func, "__name__", "") != "" @@ -68,14 +79,14 @@ def get_empty_parameterset_mark( class ParameterSet(NamedTuple): values: Sequence[object | NotSetType] marks: Collection[MarkDecorator | Mark] - id: str | None + id: str | _HiddenParam | None @classmethod def param( cls, *values: object, marks: MarkDecorator | Collection[MarkDecorator | Mark] = (), - id: str | None = None, + id: str | _HiddenParam | None = None, ) -> ParameterSet: if isinstance(marks, MarkDecorator): marks = (marks,) @@ -88,8 +99,11 @@ def param( ) if id is not None: - if not isinstance(id, str): - raise TypeError(f"Expected id to be a string, got {type(id)}: {id!r}") + if not isinstance(id, str) and id is not HIDDEN_PARAM: + raise TypeError( + "Expected id to be a string or a `pytest.HIDDEN_PARAM` sentinel, " + f"got {type(id)}: {id!r}", + ) return cls(values, marks, id) @classmethod diff --git a/src/_pytest/python.py b/src/_pytest/python.py index ef8a5f02b53..902bcfade9f 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -25,6 +25,7 @@ from typing import Any from typing import final from typing import Literal +from typing import NoReturn from typing import TYPE_CHECKING import warnings @@ -56,7 +57,9 @@ from _pytest.fixtures import get_scope_node from _pytest.main import Session from _pytest.mark import ParameterSet +from _pytest.mark.structures import _HiddenParam from _pytest.mark.structures import get_unpacked_marks +from _pytest.mark.structures import HIDDEN_PARAM from _pytest.mark.structures import Mark from _pytest.mark.structures import MarkDecorator from _pytest.mark.structures import normalize_mark_list @@ -473,7 +476,7 @@ def _genfunctions(self, name: str, funcobj) -> Iterator[Function]: fixtureinfo.prune_dependency_tree() for callspec in metafunc._calls: - subname = f"{name}[{callspec.id}]" + subname = f"{name}[{callspec.id}]" if callspec._idlist else name yield Function.from_parent( self, name=subname, @@ -884,7 +887,7 @@ class IdMaker: # Used only for clearer error messages. func_name: str | None - def make_unique_parameterset_ids(self) -> list[str]: + def make_unique_parameterset_ids(self) -> list[str | _HiddenParam]: """Make a unique identifier for each ParameterSet, that may be used to identify the parametrization in a node ID. @@ -905,6 +908,8 @@ def make_unique_parameterset_ids(self) -> list[str]: # Suffix non-unique IDs to make them unique. for index, id in enumerate(resolved_ids): if id_counts[id] > 1: + if id is HIDDEN_PARAM: + self._complain_multiple_hidden_parameter_sets() suffix = "" if id and id[-1].isdigit(): suffix = "_" @@ -919,15 +924,21 @@ def make_unique_parameterset_ids(self) -> list[str]: ) return resolved_ids - def _resolve_ids(self) -> Iterable[str]: + def _resolve_ids(self) -> Iterable[str | _HiddenParam]: """Resolve IDs for all ParameterSets (may contain duplicates).""" for idx, parameterset in enumerate(self.parametersets): if parameterset.id is not None: # ID provided directly - pytest.param(..., id="...") - yield _ascii_escaped_by_config(parameterset.id, self.config) + if parameterset.id is HIDDEN_PARAM: + yield HIDDEN_PARAM + else: + yield _ascii_escaped_by_config(parameterset.id, self.config) elif self.ids and idx < len(self.ids) and self.ids[idx] is not None: # ID provided in the IDs list - parametrize(..., ids=[...]). - yield self._idval_from_value_required(self.ids[idx], idx) + if self.ids[idx] is HIDDEN_PARAM: + yield HIDDEN_PARAM + else: + yield self._idval_from_value_required(self.ids[idx], idx) else: # ID not provided - generate it. yield "-".join( @@ -1001,12 +1012,7 @@ def _idval_from_value_required(self, val: object, idx: int) -> str: return id # Fail. - if self.func_name is not None: - prefix = f"In {self.func_name}: " - elif self.nodeid is not None: - prefix = f"In {self.nodeid}: " - else: - prefix = "" + prefix = self._make_error_prefix() msg = ( f"{prefix}ids contains unsupported value {saferepr(val)} (type: {type(val)!r}) at index {idx}. " "Supported types are: str, bytes, int, float, complex, bool, enum, regex or anything with a __name__." @@ -1019,6 +1025,21 @@ def _idval_from_argname(argname: str, idx: int) -> str: and the index of the ParameterSet.""" return str(argname) + str(idx) + def _complain_multiple_hidden_parameter_sets(self) -> NoReturn: + fail( + f"{self._make_error_prefix()}multiple instances of HIDDEN_PARAM " + "cannot be used in the same parametrize call, " + "because the tests names need to be unique." + ) + + def _make_error_prefix(self) -> str: + if self.func_name is not None: + return f"In {self.func_name}: " + elif self.nodeid is not None: + return f"In {self.nodeid}: " + else: + return "" + @final @dataclasses.dataclass(frozen=True) @@ -1047,7 +1068,7 @@ def setmulti( *, argnames: Iterable[str], valset: Iterable[object], - id: str, + id: str | _HiddenParam, marks: Iterable[Mark | MarkDecorator], scope: Scope, param_index: int, @@ -1065,7 +1086,7 @@ def setmulti( params=params, indices=indices, _arg2scope=arg2scope, - _idlist=[*self._idlist, id], + _idlist=self._idlist if id is HIDDEN_PARAM else [*self._idlist, id], marks=[*self.marks, *normalize_mark_list(marks)], ) @@ -1190,6 +1211,11 @@ def parametrize( They are mapped to the corresponding index in ``argvalues``. ``None`` means to use the auto-generated id. + .. versionadded:: 8.4 + :ref:`hidden-param` means to hide the parameter set + from the test name. Can only be used at most 1 time, as + test names need to be unique. + If it is a callable it will be called for each entry in ``argvalues``, and the return value is used as part of the auto-generated id for the whole set (where parts are joined with @@ -1322,7 +1348,7 @@ def _resolve_parameter_set_ids( ids: Iterable[object | None] | Callable[[Any], object | None] | None, parametersets: Sequence[ParameterSet], nodeid: str, - ) -> list[str]: + ) -> list[str | _HiddenParam]: """Resolve the actual ids for the given parameter sets. :param argnames: diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index 70096d6593e..f81b8cea1db 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -33,6 +33,7 @@ from _pytest.logging import LogCaptureFixture from _pytest.main import Dir from _pytest.main import Session +from _pytest.mark import HIDDEN_PARAM from _pytest.mark import Mark from _pytest.mark import MARK_GEN as mark from _pytest.mark import MarkDecorator @@ -89,6 +90,7 @@ __all__ = [ + "HIDDEN_PARAM", "Cache", "CallInfo", "CaptureFixture", diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index 4e7e441768c..e8b345aecc6 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -19,6 +19,7 @@ from _pytest.compat import getfuncargnames from _pytest.compat import NOTSET from _pytest.outcomes import fail +from _pytest.outcomes import Failed from _pytest.pytester import Pytester from _pytest.python import Function from _pytest.python import IdMaker @@ -2143,3 +2144,127 @@ def test_converted_to_str(a, b): "*= 6 passed in *", ] ) + + +class TestHiddenParam: + """Test that pytest.HIDDEN_PARAM works""" + + def test_parametrize_ids(self, pytester: Pytester) -> None: + items = pytester.getitems( + """ + import pytest + + @pytest.mark.parametrize( + ("foo", "bar"), + [ + ("a", "x"), + ("b", "y"), + ("c", "z"), + ], + ids=["paramset1", pytest.HIDDEN_PARAM, "paramset3"], + ) + def test_func(foo, bar): + pass + """ + ) + names = [item.name for item in items] + assert names == [ + "test_func[paramset1]", + "test_func", + "test_func[paramset3]", + ] + + def test_param_id(self, pytester: Pytester) -> None: + items = pytester.getitems( + """ + import pytest + + @pytest.mark.parametrize( + ("foo", "bar"), + [ + pytest.param("a", "x", id="paramset1"), + pytest.param("b", "y", id=pytest.HIDDEN_PARAM), + ("c", "z"), + ], + ) + def test_func(foo, bar): + pass + """ + ) + names = [item.name for item in items] + assert names == [ + "test_func[paramset1]", + "test_func", + "test_func[c-z]", + ] + + def test_multiple_hidden_param_is_forbidden(self, pytester: Pytester) -> None: + pytester.makepyfile( + """ + import pytest + + @pytest.mark.parametrize( + ("foo", "bar"), + [ + ("a", "x"), + ("b", "y"), + ], + ids=[pytest.HIDDEN_PARAM, pytest.HIDDEN_PARAM], + ) + def test_func(foo, bar): + pass + """ + ) + result = pytester.runpytest("--collect-only") + result.stdout.fnmatch_lines( + [ + "collected 0 items / 1 error", + "", + "*= ERRORS =*", + "*_ ERROR collecting test_multiple_hidden_param_is_forbidden.py _*", + "E Failed: In test_func: multiple instances of HIDDEN_PARAM cannot be used " + "in the same parametrize call, because the tests names need to be unique.", + "*! Interrupted: 1 error during collection !*", + "*= no tests collected, 1 error in *", + ] + ) + + def test_multiple_hidden_param_is_forbidden_idmaker(self) -> None: + id_maker = IdMaker( + ("foo", "bar"), + [pytest.param("a", "x"), pytest.param("b", "y")], + None, + [pytest.HIDDEN_PARAM, pytest.HIDDEN_PARAM], + None, + "some_node_id", + None, + ) + expected = "In some_node_id: multiple instances of HIDDEN_PARAM" + with pytest.raises(Failed, match=expected): + id_maker.make_unique_parameterset_ids() + + def test_multiple_parametrize(self, pytester: Pytester) -> None: + items = pytester.getitems( + """ + import pytest + + @pytest.mark.parametrize( + "bar", + ["x", "y"], + ) + @pytest.mark.parametrize( + "foo", + ["a", "b"], + ids=["a", pytest.HIDDEN_PARAM], + ) + def test_func(foo, bar): + pass + """ + ) + names = [item.name for item in items] + assert names == [ + "test_func[a-x]", + "test_func[a-y]", + "test_func[x]", + "test_func[y]", + ] diff --git a/testing/test_mark.py b/testing/test_mark.py index 7b76acf9990..1e51f9db18f 100644 --- a/testing/test_mark.py +++ b/testing/test_mark.py @@ -1170,7 +1170,11 @@ def test_pytest_param_id_requires_string() -> None: with pytest.raises(TypeError) as excinfo: pytest.param(id=True) # type: ignore[arg-type] (msg,) = excinfo.value.args - assert msg == "Expected id to be a string, got : True" + expected = ( + "Expected id to be a string or a `pytest.HIDDEN_PARAM` sentinel, " + "got : True" + ) + assert msg == expected @pytest.mark.parametrize("s", (None, "hello world")) From 9f3c4d11d9b162d0926e9a3ae57ec6f262362d73 Mon Sep 17 00:00:00 2001 From: "Vincent (Wen Yu) Ge" Date: Sat, 1 Mar 2025 09:23:13 -0500 Subject: [PATCH 1138/1271] Add more resources and studies to flaky tests page in docs (#13250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) Co-authored-by: Bruno Oliveira --- doc/en/explanation/flaky.rst | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/en/explanation/flaky.rst b/doc/en/explanation/flaky.rst index cb6c3983424..8369e1d9311 100644 --- a/doc/en/explanation/flaky.rst +++ b/doc/en/explanation/flaky.rst @@ -117,8 +117,11 @@ This is a limited list, please submit an issue or pull request to expand it! * Gao, Zebao, Yalan Liang, Myra B. Cohen, Atif M. Memon, and Zhen Wang. "Making system user interactive tests repeatable: When and what should we control?." In *Software Engineering (ICSE), 2015 IEEE/ACM 37th IEEE International Conference on*, vol. 1, pp. 55-65. IEEE, 2015. `PDF `__ * Palomba, Fabio, and Andy Zaidman. "Does refactoring of test smells induce fixing flaky tests?." In *Software Maintenance and Evolution (ICSME), 2017 IEEE International Conference on*, pp. 1-12. IEEE, 2017. `PDF in Google Drive `__ -* Bell, Jonathan, Owolabi Legunsen, Michael Hilton, Lamyaa Eloussi, Tifany Yung, and Darko Marinov. "DeFlaker: Automatically detecting flaky tests." In *Proceedings of the 2018 International Conference on Software Engineering*. 2018. `PDF `__ -* Dutta, Saikat and Shi, August and Choudhary, Rutvik and Zhang, Zhekun and Jain, Aryaman and Misailovic, Sasa. "Detecting flaky tests in probabilistic and machine learning applications." In *Proceedings of the 29th ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA)*, pp. 211-224. ACM, 2020. `PDF `__ +* Bell, Jonathan, Owolabi Legunsen, Michael Hilton, Lamyaa Eloussi, Tifany Yung, and Darko Marinov. "DeFlaker: Automatically detecting flaky tests." In *Proceedings of the 2018 International Conference on Software Engineering*. 2018. `PDF `__ +* Dutta, Saikat and Shi, August and Choudhary, Rutvik and Zhang, Zhekun and Jain, Aryaman and Misailovic, Sasa. "Detecting flaky tests in probabilistic and machine learning applications." In *Proceedings of the 29th ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA)*, pp. 211-224. ACM, 2020. `PDF `__ +* Habchi, Sarra and Haben, Guillaume and Sohn, Jeongju and Franci, Adriano and Papadakis, Mike and Cordy, Maxime and Le Traon, Yves. "What Made This Test Flake? Pinpointing Classes Responsible for Test Flakiness." In Proceedings of the 38th IEEE International Conference on Software Maintenance and Evolution (ICSME), IEEE, 2022. `PDF `__ +* Lamprou, Sokrates. "Non-deterministic tests and where to find them: Empirically investigating the relationship between flaky tests and test smells by examining test order dependency." Bachelor thesis, Department of Computer and Information Science, Linköping University, 2022. LIU-IDA/LITH-EX-G–19/056–SE. `PDF `__ +* Leinen, Fabian and Elsner, Daniel and Pretschner, Alexander and Stahlbauer, Andreas and Sailer, Michael and Jürgens, Elmar. "Cost of Flaky Tests in Continuous Integration: An Industrial Case Study." Technical University of Munich and CQSE GmbH, Munich, Germany, 2023. `PDF `__ Resources ^^^^^^^^^ @@ -137,5 +140,12 @@ Resources * `Flaky Tests at Google and How We Mitigate Them `_ by John Micco, 2016 * `Where do Google's flaky tests come from? `_ by Jeff Listfield, 2017 +* Dropbox: + * `Athena: Our automated build health management system `_ by Utsav Shah, 2019 + * `How To Manage Flaky Tests in your CI Workflows `_ by Li Haoyi, 2025 + +* Uber: + * `Handling Flaky Unit Tests in Java `_ by Uber Engineering, 2021 + * `Flaky Tests Overhaul at Uber `_ by Uber Engineering, 2024 .. _pytest-xdist: https://github.com/pytest-dev/pytest-xdist From 064638352d2c1f794fb494e52c0be522a6cb58c4 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sat, 1 Mar 2025 15:00:17 +0000 Subject: [PATCH 1139/1271] Copy docstrings to wrapped pdb methods (#12947) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bruno Oliveira Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- changelog/12946.bugfix.rst | 1 + src/_pytest/debugging.py | 20 +++++++---- testing/test_debugging.py | 68 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 changelog/12946.bugfix.rst diff --git a/changelog/12946.bugfix.rst b/changelog/12946.bugfix.rst new file mode 100644 index 00000000000..b11da09e7ae --- /dev/null +++ b/changelog/12946.bugfix.rst @@ -0,0 +1 @@ +Fixed missing help for :mod:`pdb` commands wrapped by pytest -- by :user:`adamchainz`. diff --git a/src/_pytest/debugging.py b/src/_pytest/debugging.py index 040e8994b37..de1b2688f76 100644 --- a/src/_pytest/debugging.py +++ b/src/_pytest/debugging.py @@ -159,6 +159,9 @@ def do_debug(self, arg): cls._recursive_debug -= 1 return ret + if hasattr(pdb_cls, "do_debug"): + do_debug.__doc__ = pdb_cls.do_debug.__doc__ + def do_continue(self, arg): ret = super().do_continue(arg) if cls._recursive_debug == 0: @@ -185,15 +188,17 @@ def do_continue(self, arg): self._continued = True return ret + if hasattr(pdb_cls, "do_continue"): + do_continue.__doc__ = pdb_cls.do_continue.__doc__ + do_c = do_cont = do_continue def do_quit(self, arg): - """Raise Exit outcome when quit command is used in pdb. - - This is a bit of a hack - it would be better if BdbQuit - could be handled, but this would require to wrap the - whole pytest run, and adjust the report etc. - """ + # Raise Exit outcome when quit command is used in pdb. + # + # This is a bit of a hack - it would be better if BdbQuit + # could be handled, but this would require to wrap the + # whole pytest run, and adjust the report etc. ret = super().do_quit(arg) if cls._recursive_debug == 0: @@ -201,6 +206,9 @@ def do_quit(self, arg): return ret + if hasattr(pdb_cls, "do_quit"): + do_quit.__doc__ = pdb_cls.do_quit.__doc__ + do_q = do_quit do_exit = do_quit diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 9588da8936f..45883568b11 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -52,6 +52,16 @@ def reset(self): def interaction(self, *args): called.append("interaction") + # Methods which we copy docstrings to. + def do_debug(self, *args): # pragma: no cover + pass + + def do_continue(self, *args): # pragma: no cover + pass + + def do_quit(self, *args): # pragma: no cover + pass + _pytest._CustomPdb = _CustomPdb # type: ignore return called @@ -75,6 +85,16 @@ def set_trace(self, frame): print("**CustomDebugger**") called.append("set_trace") + # Methods which we copy docstrings to. + def do_debug(self, *args): # pragma: no cover + pass + + def do_continue(self, *args): # pragma: no cover + pass + + def do_quit(self, *args): # pragma: no cover + pass + _pytest._CustomDebugger = _CustomDebugger # type: ignore yield called del _pytest._CustomDebugger # type: ignore @@ -965,6 +985,34 @@ def test_1(): child.sendeof() self.flush(child) + def test_pdb_wrapped_commands_docstrings(self, pytester: Pytester) -> None: + p1 = pytester.makepyfile( + """ + def test_1(): + assert False + """ + ) + + child = pytester.spawn_pytest(f"--pdb {p1}") + child.expect("Pdb") + + # Verify no undocumented commands + child.sendline("help") + child.expect("Documented commands") + assert "Undocumented commands" not in child.before.decode() + + child.sendline("help continue") + child.expect("Continue execution") + child.expect("Pdb") + + child.sendline("help debug") + child.expect("Enter a recursive debugger") + child.expect("Pdb") + + child.sendline("c") + child.sendeof() + self.flush(child) + class TestDebuggingBreakpoints: @pytest.mark.parametrize("arg", ["--pdb", ""]) @@ -1288,6 +1336,16 @@ def set_trace(self, *args): def runcall(self, *args, **kwds): print("runcall_called", args, kwds) + + # Methods which we copy the docstring over. + def do_debug(self, *args): + pass + + def do_continue(self, *args): + pass + + def do_quit(self, *args): + pass """, ) result = pytester.runpytest( @@ -1354,6 +1412,16 @@ def __init__(self, *args, **kwargs): def set_trace(self, *args): print("set_trace_called", args) + + # Methods which we copy the docstring over. + def do_debug(self, *args): + pass + + def do_continue(self, *args): + pass + + def do_quit(self, *args): + pass """, ) result = pytester.runpytest(str(p1), "--pdbcls=mypdb:MyPdb", syspathinsert=True) From d3adf46ad7a077233bc5f840f69d59fde5b4aa66 Mon Sep 17 00:00:00 2001 From: Andrew Pikul Date: Sat, 1 Mar 2025 10:37:16 -0500 Subject: [PATCH 1140/1271] Add capteesys capture fixture to bubble up output to `--capture` handler (#12854) The config dict is passed alongside the class that the fixture will eventually initialize. It can use the config dict for optional arguments to the implementation's constructor. --- AUTHORS | 1 + changelog/12081.feature.rst | 1 + doc/en/how-to/capture-stdout-stderr.rst | 10 ++++-- doc/en/reference/fixtures.rst | 4 +++ doc/en/reference/reference.rst | 10 ++++++ src/_pytest/capture.py | 41 +++++++++++++++++++++++-- testing/test_capture.py | 32 +++++++++++++++++++ 7 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 changelog/12081.feature.rst diff --git a/AUTHORS b/AUTHORS index e5c19cdca0d..ab72f4b7ed7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -32,6 +32,7 @@ Andras Tim Andrea Cimatoribus Andreas Motl Andreas Zeidler +Andrew Pikul Andrew Shapton Andrey Paramonov Andrzej Klajnert diff --git a/changelog/12081.feature.rst b/changelog/12081.feature.rst new file mode 100644 index 00000000000..6538fbf30f8 --- /dev/null +++ b/changelog/12081.feature.rst @@ -0,0 +1 @@ +Added :fixture:`capteesys` to capture AND pass output to next handler set by ``--capture=``. diff --git a/doc/en/how-to/capture-stdout-stderr.rst b/doc/en/how-to/capture-stdout-stderr.rst index d91bef736e7..e6affd80ea1 100644 --- a/doc/en/how-to/capture-stdout-stderr.rst +++ b/doc/en/how-to/capture-stdout-stderr.rst @@ -4,6 +4,12 @@ How to capture stdout/stderr output ========================================================= +Pytest intercepts stdout and stderr as configured by the ``--capture=`` +command-line argument or by using fixtures. The ``--capture=`` flag configures +reporting, whereas the fixtures offer more granular control and allows +inspection of output during testing. The reports can be customized with the +`-r flag <../reference/reference.html#command-line-flags>`_. + Default stdout/stderr/stdin capturing behaviour --------------------------------------------------------- @@ -106,8 +112,8 @@ of the failing function and hide the other one: Accessing captured output from a test function --------------------------------------------------- -The :fixture:`capsys`, :fixture:`capsysbinary`, :fixture:`capfd`, and :fixture:`capfdbinary` fixtures -allow access to ``stdout``/``stderr`` output created during test execution. +The :fixture:`capsys`, :fixture:`capteesys`, :fixture:`capsysbinary`, :fixture:`capfd`, and :fixture:`capfdbinary` +fixtures allow access to ``stdout``/``stderr`` output created during test execution. Here is an example test function that performs some output related checks: diff --git a/doc/en/reference/fixtures.rst b/doc/en/reference/fixtures.rst index dff93a035ef..566304d3330 100644 --- a/doc/en/reference/fixtures.rst +++ b/doc/en/reference/fixtures.rst @@ -32,6 +32,10 @@ Built-in fixtures :fixture:`capsys` Capture, as text, output to ``sys.stdout`` and ``sys.stderr``. + :fixture:`capteesys` + Capture in the same manner as :fixture:`capsys`, but also pass text + through according to ``--capture=``. + :fixture:`capsysbinary` Capture, as bytes, output to ``sys.stdout`` and ``sys.stderr``. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 267ab37b1b1..7e328f60939 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -412,6 +412,16 @@ capsys .. autoclass:: pytest.CaptureFixture() :members: +.. fixture:: capteesys + +capteesys +~~~~~~~~~ + +**Tutorial**: :ref:`captures` + +.. autofunction:: _pytest.capture.capteesys() + :no-auto-options: + .. fixture:: capsysbinary capsysbinary diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index d447d087031..3812d88176a 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -922,11 +922,13 @@ def __init__( captureclass: type[CaptureBase[AnyStr]], request: SubRequest, *, + config: dict[str, Any] | None = None, _ispytest: bool = False, ) -> None: check_ispytest(_ispytest) self.captureclass: type[CaptureBase[AnyStr]] = captureclass self.request = request + self._config = config if config else {} self._capture: MultiCapture[AnyStr] | None = None self._captured_out: AnyStr = self.captureclass.EMPTY_BUFFER self._captured_err: AnyStr = self.captureclass.EMPTY_BUFFER @@ -935,8 +937,8 @@ def _start(self) -> None: if self._capture is None: self._capture = MultiCapture( in_=None, - out=self.captureclass(1), - err=self.captureclass(2), + out=self.captureclass(1, **self._config), + err=self.captureclass(2, **self._config), ) self._capture.start_capturing() @@ -1022,6 +1024,41 @@ def test_output(capsys): capman.unset_fixture() +@fixture +def capteesys(request: SubRequest) -> Generator[CaptureFixture[str]]: + r"""Enable simultaneous text capturing and pass-through of writes + to ``sys.stdout`` and ``sys.stderr`` as defined by ``--capture=``. + + + The captured output is made available via ``capteesys.readouterr()`` method + calls, which return a ``(out, err)`` namedtuple. + ``out`` and ``err`` will be ``text`` objects. + + The output is also passed-through, allowing it to be "live-printed", + reported, or both as defined by ``--capture=``. + + Returns an instance of :class:`CaptureFixture[str] `. + + Example: + + .. code-block:: python + + def test_output(capsys): + print("hello") + captured = capteesys.readouterr() + assert captured.out == "hello\n" + """ + capman: CaptureManager = request.config.pluginmanager.getplugin("capturemanager") + capture_fixture = CaptureFixture( + SysCapture, request, config=dict(tee=True), _ispytest=True + ) + capman.set_fixture(capture_fixture) + capture_fixture._start() + yield capture_fixture + capture_fixture.close() + capman.unset_fixture() + + @fixture def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes]]: r"""Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. diff --git a/testing/test_capture.py b/testing/test_capture.py index a59273734c4..d9dacebd938 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -446,6 +446,38 @@ def test_hello(capsys): ) reprec.assertoutcome(passed=1) + def test_capteesys(self, pytester: Pytester) -> None: + p = pytester.makepyfile( + """\ + import sys + def test_one(capteesys): + print("sTdoUt") + print("sTdeRr", file=sys.stderr) + out, err = capteesys.readouterr() + assert out == "sTdoUt\\n" + assert err == "sTdeRr\\n" + """ + ) + # -rN and --capture=tee-sys means we'll read them on stdout/stderr, + # as opposed to both being reported on stdout + result = pytester.runpytest(p, "--quiet", "--quiet", "-rN", "--capture=tee-sys") + assert result.ret == ExitCode.OK + result.stdout.fnmatch_lines(["sTdoUt"]) # tee'd out + result.stderr.fnmatch_lines(["sTdeRr"]) # tee'd out + + result = pytester.runpytest(p, "--quiet", "--quiet", "-rA", "--capture=tee-sys") + assert result.ret == ExitCode.OK + result.stdout.fnmatch_lines( + ["sTdoUt", "sTdoUt", "sTdeRr"] + ) # tee'd out, the next two reported + result.stderr.fnmatch_lines(["sTdeRr"]) # tee'd out + + # -rA and --capture=sys means we'll read them on stdout. + result = pytester.runpytest(p, "--quiet", "--quiet", "-rA", "--capture=sys") + assert result.ret == ExitCode.OK + result.stdout.fnmatch_lines(["sTdoUt", "sTdeRr"]) # no tee, just reported + assert not result.stderr.lines + def test_capsyscapfd(self, pytester: Pytester) -> None: p = pytester.makepyfile( """\ From ca351458d85d0276ee4aa3079c8305feafe42b76 Mon Sep 17 00:00:00 2001 From: mwychung <145583690+mwychung@users.noreply.github.com> Date: Sun, 2 Mar 2025 00:00:57 +0800 Subject: [PATCH 1141/1271] Added dedicated page about using types with pytest #12842 (#12963) Fixes #12842 --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/12842.doc.rst | 3 ++ doc/en/explanation/index.rst | 1 + doc/en/explanation/types.rst | 89 ++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 changelog/12842.doc.rst create mode 100644 doc/en/explanation/types.rst diff --git a/AUTHORS b/AUTHORS index ab72f4b7ed7..95e6b13f11e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -265,6 +265,7 @@ lovetheguitar Lukas Bednar Luke Murphy Maciek Fijalkowski +Maggie Chung Maho Maik Figura Mandeep Bhutani diff --git a/changelog/12842.doc.rst b/changelog/12842.doc.rst new file mode 100644 index 00000000000..0a0f5c5bc23 --- /dev/null +++ b/changelog/12842.doc.rst @@ -0,0 +1,3 @@ +Added dedicated page about using types with pytest. + +See :ref:`types` for detailed usage. diff --git a/doc/en/explanation/index.rst b/doc/en/explanation/index.rst index 2edf60a5d8b..2606d7d4b34 100644 --- a/doc/en/explanation/index.rst +++ b/doc/en/explanation/index.rst @@ -12,5 +12,6 @@ Explanation fixtures goodpractices pythonpath + types ci flaky diff --git a/doc/en/explanation/types.rst b/doc/en/explanation/types.rst new file mode 100644 index 00000000000..827a2bf02b6 --- /dev/null +++ b/doc/en/explanation/types.rst @@ -0,0 +1,89 @@ +.. _types: + +Typing in pytest +================ + +.. note:: + This page assumes the reader is familiar with Python's typing system and its advantages. + + For more information, refer to `Python's Typing Documentation `_. + +Why type tests? +--------------- + +Typing tests provides significant advantages: + +- **Readability:** Clearly defines expected inputs and outputs, improving readability, especially in complex or parameterized tests. + +- **Refactoring:** This is the main benefit in typing tests, as it will greatly help with refactoring, letting the type checker point out the necessary changes in both production and tests, without needing to run the full test suite. + +For production code, typing also helps catching some bugs that might not be caught by tests at all (regardless of coverage), for example: + +.. code-block:: python + + def get_caption(target: int, items: list[tuple[int, str]]) -> str: + for value, caption in items: + if value == target: + return caption + + +The type checker will correctly error out that the function might return `None`, however even a full coverage test suite might miss that case: + +.. code-block:: python + + def test_get_caption() -> None: + assert get_caption(10, [(1, "foo"), (10, "bar")]) == "bar" + + +Note the code above has 100% coverage, but the bug is not caught (of course the example is "obvious", but serves to illustrate the point). + + + +Using typing in test suites +--------------------------- + +To type fixtures in pytest, just add normal types to the fixture functions -- there is nothing special that needs to be done just because of the `fixture` decorator. + +.. code-block:: python + + import pytest + + + @pytest.fixture + def sample_fixture() -> int: + return 38 + +In the same manner, the fixtures passed to test functions need be annotated with the fixture's return type: + +.. code-block:: python + + def test_sample_fixture(sample_fixture: int) -> None: + assert sample_fixture == 38 + +From the POV of the type checker, it does not matter that `sample_fixture` is actually a fixture managed by pytest, all it matters to it is that `sample_fixture` is a parameter of type `int`. + + +The same logic applies to :ref:`@pytest.mark.parametrize <@pytest.mark.parametrize>`: + +.. code-block:: python + + + @pytest.mark.parametrize("input_value, expected_output", [(1, 2), (5, 6), (10, 11)]) + def test_increment(input_value: int, expected_output: int) -> None: + assert input_value + 1 == expected_output + + +The same logic applies when typing fixture functions which receive other fixtures: + +.. code-block:: python + + @pytest.fixture + def mock_env_user(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setenv("USER", "TestingUser") + + +Conclusion +---------- + +Incorporating typing into pytest tests enhances **clarity**, improves **debugging** and **maintenance**, and ensures **type safety**. +These practices lead to a **robust**, **readable**, and **easily maintainable** test suite that is better equipped to handle future changes with minimal risk of errors. From 5bd393cf0151d5278ad18b508ce06b15bc95a499 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Sat, 1 Mar 2025 23:27:25 +0100 Subject: [PATCH 1142/1271] add --disable-plugin-autoload (#13253) * add --disable-plugin-autoload * update comments in test, don't check __spec__ on pypy (????), add changelog * pemdas except not * Apply suggestions from code review Co-authored-by: Florian Bruhin * add parens * Simplify plugin name in test_installed_plugin_rewrite * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Florian Bruhin Co-authored-by: Bruno Oliveira Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/13253.feature.rst | 1 + doc/en/how-to/plugins.rst | 27 ++++++++++++++- doc/en/reference/reference.rst | 7 ++-- src/_pytest/config/__init__.py | 26 +++++++++++---- src/_pytest/helpconfig.py | 9 ++++- testing/test_assertion.py | 51 +++++++++++++++++++++++----- testing/test_config.py | 61 +++++++++++++++++++++++++++------- 7 files changed, 151 insertions(+), 31 deletions(-) create mode 100644 changelog/13253.feature.rst diff --git a/changelog/13253.feature.rst b/changelog/13253.feature.rst new file mode 100644 index 00000000000..e497c207223 --- /dev/null +++ b/changelog/13253.feature.rst @@ -0,0 +1 @@ +New flag: :ref:`--disable-plugin-autoload ` which works as an alternative to :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD` when setting environment variables is inconvenient; and allows setting it in config files with :confval:`addopts`. diff --git a/doc/en/how-to/plugins.rst b/doc/en/how-to/plugins.rst index 7d5bcd85a31..fca8ab54e63 100644 --- a/doc/en/how-to/plugins.rst +++ b/doc/en/how-to/plugins.rst @@ -133,4 +133,29 @@ CI server), you can set ``PYTEST_ADDOPTS`` environment variable to See :ref:`findpluginname` for how to obtain the name of a plugin. -.. _`builtin plugins`: +.. _`disable_plugin_autoload`: + +Disabling plugins from autoloading +---------------------------------- + +If you want to disable plugins from loading automatically, instead of requiring you to +manually specify each plugin with ``-p`` or :envvar:`PYTEST_PLUGINS`, you can use ``--disable-plugin-autoload`` or :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD`. + +.. code-block:: bash + + export PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 + export PYTEST_PLUGINS=NAME,NAME2 + pytest + +.. code-block:: bash + + pytest --disable-plugin-autoload -p NAME,NAME2 + +.. code-block:: ini + + [pytest] + addopts = --disable-plugin-autoload -p NAME,NAME2 + +.. versionadded:: 8.4 + + The ``--disable-plugin-autoload`` command-line flag. diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index 7e328f60939..b42e69dfa23 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1181,8 +1181,9 @@ as discussed in :ref:`temporary directory location and retention`. .. envvar:: PYTEST_DISABLE_PLUGIN_AUTOLOAD When set, disables plugin auto-loading through :std:doc:`entry point packaging -metadata `. Only explicitly -specified plugins will be loaded. +metadata `. Only plugins +explicitly specified in :envvar:`PYTEST_PLUGINS` or with ``-p`` will be loaded. +See also :ref:`--disable-plugin-autoload `. .. envvar:: PYTEST_PLUGINS @@ -1192,6 +1193,8 @@ Contains comma-separated list of modules that should be loaded as plugins: export PYTEST_PLUGINS=mymodule.plugin,xdist +See also ``-p``. + .. envvar:: PYTEST_THEME Sets a `pygment style `_ to use for the code output. diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 02da5cf9229..56b04719641 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -70,6 +70,7 @@ if TYPE_CHECKING: + from _pytest.assertions.rewrite import AssertionRewritingHook from _pytest.cacheprovider import Cache from _pytest.terminal import TerminalReporter @@ -1271,6 +1272,10 @@ def _consider_importhook(self, args: Sequence[str]) -> None: """ ns, unknown_args = self._parser.parse_known_and_unknown_args(args) mode = getattr(ns, "assertmode", "plain") + + disable_autoload = getattr(ns, "disable_plugin_autoload", False) or bool( + os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD") + ) if mode == "rewrite": import _pytest.assertion @@ -1279,16 +1284,18 @@ def _consider_importhook(self, args: Sequence[str]) -> None: except SystemError: mode = "plain" else: - self._mark_plugins_for_rewrite(hook) + self._mark_plugins_for_rewrite(hook, disable_autoload) self._warn_about_missing_assertion(mode) - def _mark_plugins_for_rewrite(self, hook) -> None: + def _mark_plugins_for_rewrite( + self, hook: AssertionRewritingHook, disable_autoload: bool + ) -> None: """Given an importhook, mark for rewrite any top-level modules or packages in the distribution package for all pytest plugins.""" self.pluginmanager.rewrite_hook = hook - if os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD"): + if disable_autoload: # We don't autoload from distribution package entry points, # no need to continue. return @@ -1393,10 +1400,15 @@ def _preparse(self, args: list[str], addopts: bool = True) -> None: self._consider_importhook(args) self._configure_python_path() self.pluginmanager.consider_preparse(args, exclude_only=False) - if not os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD"): - # Don't autoload from distribution package entry point. Only - # explicitly specified plugins are going to be loaded. + if ( + not os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD") + and not self.known_args_namespace.disable_plugin_autoload + ): + # Autoloading from distribution package entry point has + # not been disabled. self.pluginmanager.load_setuptools_entrypoints("pytest11") + # Otherwise only plugins explicitly specified in PYTEST_PLUGINS + # are going to be loaded. self.pluginmanager.consider_env() self.known_args_namespace = self._parser.parse_known_args( @@ -1419,7 +1431,7 @@ def _preparse(self, args: list[str], addopts: bool = True) -> None: except ConftestImportFailure as e: if self.known_args_namespace.help or self.known_args_namespace.version: # we don't want to prevent --help/--version to work - # so just let is pass and print a warning at the end + # so just let it pass and print a warning at the end self.issue_config_time_warning( PytestConfigWarning(f"could not load initial conftests: {e.path}"), stacklevel=2, diff --git a/src/_pytest/helpconfig.py b/src/_pytest/helpconfig.py index 2b377c70f7b..b5ac0e6a50c 100644 --- a/src/_pytest/helpconfig.py +++ b/src/_pytest/helpconfig.py @@ -70,7 +70,14 @@ def pytest_addoption(parser: Parser) -> None: metavar="name", help="Early-load given plugin module name or entry point (multi-allowed). " "To avoid loading of plugins, use the `no:` prefix, e.g. " - "`no:doctest`.", + "`no:doctest`. See also --disable-plugin-autoload.", + ) + group.addoption( + "--disable-plugin-autoload", + action="store_true", + default=False, + help="Disable plugin auto-loading through entry point packaging metadata. " + "Only plugins explicitly specified in -p or env var PYTEST_PLUGINS will be loaded.", ) group.addoption( "--traceconfig", diff --git a/testing/test_assertion.py b/testing/test_assertion.py index e3d45478466..2c2830eb929 100644 --- a/testing/test_assertion.py +++ b/testing/test_assertion.py @@ -218,10 +218,36 @@ def test_foo(pytestconfig): assert result.ret == 0 @pytest.mark.parametrize("mode", ["plain", "rewrite"]) + @pytest.mark.parametrize("disable_plugin_autoload", ["env_var", "cli", ""]) + @pytest.mark.parametrize("explicit_specify", ["env_var", "cli", ""]) def test_installed_plugin_rewrite( - self, pytester: Pytester, mode, monkeypatch + self, + pytester: Pytester, + mode: str, + monkeypatch: pytest.MonkeyPatch, + disable_plugin_autoload: str, + explicit_specify: str, ) -> None: - monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False) + args = ["mainwrapper.py", "-s", f"--assert={mode}"] + if disable_plugin_autoload == "env_var": + monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1") + elif disable_plugin_autoload == "cli": + monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False) + args.append("--disable-plugin-autoload") + else: + assert disable_plugin_autoload == "" + monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False) + + name = "spamplugin" + + if explicit_specify == "env_var": + monkeypatch.setenv("PYTEST_PLUGINS", name) + elif explicit_specify == "cli": + args.append("-p") + args.append(name) + else: + assert explicit_specify == "" + # Make sure the hook is installed early enough so that plugins # installed via distribution package are rewritten. pytester.mkdir("hampkg") @@ -250,7 +276,7 @@ def check(values, value): import pytest class DummyEntryPoint(object): - name = 'spam' + name = 'spamplugin' module_name = 'spam.py' group = 'pytest11' @@ -275,20 +301,29 @@ def test(check_first): check_first([10, 30], 30) def test2(check_first2): - check_first([10, 30], 30) + check_first2([10, 30], 30) """, } pytester.makepyfile(**contents) - result = pytester.run( - sys.executable, "mainwrapper.py", "-s", f"--assert={mode}" - ) + result = pytester.run(sys.executable, *args) if mode == "plain": expected = "E AssertionError" elif mode == "rewrite": expected = "*assert 10 == 30*" else: assert 0 - result.stdout.fnmatch_lines([expected]) + + if not disable_plugin_autoload or explicit_specify: + result.assert_outcomes(failed=2) + result.stdout.fnmatch_lines([expected, expected]) + else: + result.assert_outcomes(errors=2) + result.stdout.fnmatch_lines( + [ + "E fixture 'check_first' not found", + "E fixture 'check_first2' not found", + ] + ) def test_rewrite_ast(self, pytester: Pytester) -> None: pytester.mkdir("pkg") diff --git a/testing/test_config.py b/testing/test_config.py index de07141238c..bb08c40fef4 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -6,6 +6,7 @@ import importlib.metadata import os from pathlib import Path +import platform import re import sys import textwrap @@ -1314,14 +1315,13 @@ def distributions(): ) -@pytest.mark.parametrize( - "parse_args,should_load", [(("-p", "mytestplugin"), True), ((), False)] -) +@pytest.mark.parametrize("disable_plugin_method", ["env_var", "flag", ""]) +@pytest.mark.parametrize("enable_plugin_method", ["env_var", "flag", ""]) def test_disable_plugin_autoload( pytester: Pytester, monkeypatch: MonkeyPatch, - parse_args: tuple[str, str] | tuple[()], - should_load: bool, + enable_plugin_method: str, + disable_plugin_method: str, ) -> None: class DummyEntryPoint: project_name = name = "mytestplugin" @@ -1342,23 +1342,60 @@ class PseudoPlugin: attrs_used = [] def __getattr__(self, name): - assert name == "__loader__" + assert name in ("__loader__", "__spec__") self.attrs_used.append(name) return object() def distributions(): return (Distribution(),) - monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1") + parse_args: list[str] = [] + + if disable_plugin_method == "env_var": + monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1") + elif disable_plugin_method == "flag": + monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD") + parse_args.append("--disable-plugin-autoload") + else: + assert disable_plugin_method == "" + monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD") + + if enable_plugin_method == "env_var": + monkeypatch.setenv("PYTEST_PLUGINS", "mytestplugin") + elif enable_plugin_method == "flag": + parse_args.extend(["-p", "mytestplugin"]) + else: + assert enable_plugin_method == "" + monkeypatch.setattr(importlib.metadata, "distributions", distributions) monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin()) config = pytester.parseconfig(*parse_args) + has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None - assert has_loaded == should_load - if should_load: - assert PseudoPlugin.attrs_used == ["__loader__"] - else: - assert PseudoPlugin.attrs_used == [] + # it should load if it's enabled, or we haven't disabled autoloading + assert has_loaded == (bool(enable_plugin_method) or not disable_plugin_method) + + # The reason for the discrepancy between 'has_loaded' and __loader__ being accessed + # appears to be the monkeypatching of importlib.metadata.distributions; where + # files being empty means that _mark_plugins_for_rewrite doesn't find the plugin. + # But enable_method==flag ends up in mark_rewrite being called and __loader__ + # being accessed. + assert ("__loader__" in PseudoPlugin.attrs_used) == ( + has_loaded + and not (enable_plugin_method in ("env_var", "") and not disable_plugin_method) + ) + + # __spec__ is accessed in AssertionRewritingHook.exec_module, which would be + # eventually called if we did a full pytest run; but it's only accessed with + # enable_plugin_method=="env_var" because that will early-load it. + # Except when autoloads aren't disabled, in which case PytestPluginManager.import_plugin + # bails out before importing it.. because it knows it'll be loaded later? + # The above seems a bit weird, but I *think* it's true. + if platform.python_implementation() != "PyPy": + assert ("__spec__" in PseudoPlugin.attrs_used) == bool( + enable_plugin_method == "env_var" and disable_plugin_method + ) + # __spec__ is present when testing locally on pypy, but not in CI ???? def test_plugin_loading_order(pytester: Pytester) -> None: From bc4abe4d4b4ee9256be020a28e1da4aef90e8105 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 2 Mar 2025 01:52:27 +0000 Subject: [PATCH 1143/1271] [automated] Update plugin list (#13261) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 128 ++++++++++++++++--------------- 1 file changed, 68 insertions(+), 60 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index b143608b6fd..59a73530796 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,14 +27,14 @@ please refer to `the update script =8.3 + :pypi:`databricks-labs-pytester` Python Testing for Databricks Feb 27, 2025 4 - Beta pytest>=8.3 :pypi:`logassert` Simple but powerful assertion and verification of logged lines Jan 29, 2025 5 - Production/Stable pytest; extra == "dev" :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 @@ -161,7 +161,7 @@ This list contains 1587 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Feb 17, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Feb 28, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -255,6 +255,7 @@ This list contains 1587 plugins. :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Nov 08, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Jan 30, 2025 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-cli2-ansible` Feb 28, 2025 N/A N/A :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Oct 23, 2024 N/A pytest>=3.9 @@ -466,7 +467,7 @@ This list contains 1587 plugins. :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A - :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Feb 01, 2025 5 - Production/Stable pytest>=6.0 + :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Feb 22, 2025 5 - Production/Stable pytest>=6.0 :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Nov 17, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Dec 03, 2024 5 - Production/Stable pytest>=7.0 @@ -527,7 +528,7 @@ This list contains 1587 plugins. :pypi:`pytest-exit-status` Enhance. Jan 25, 2025 N/A pytest>=8.0.0 :pypi:`pytest-expect` py.test plugin to store test expectations and mark tests based on them Apr 21, 2016 4 - Beta N/A :pypi:`pytest-expectdir` A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one Mar 19, 2023 5 - Production/Stable pytest (>=5.0) - :pypi:`pytest-expected` Record and play back your expectations Jan 14, 2025 N/A pytest + :pypi:`pytest-expected` Record and play back your expectations Feb 26, 2025 N/A pytest :pypi:`pytest-expecter` Better testing with expecter and pytest. Sep 18, 2022 5 - Production/Stable N/A :pypi:`pytest-expectr` This plugin is used to expect multiple assert using pytest framework. Oct 05, 2018 N/A pytest (>=2.4.2) :pypi:`pytest-expect-test` A fixture to support expect tests in pytest Apr 10, 2023 4 - Beta pytest (>=3.5.0) @@ -574,7 +575,7 @@ This list contains 1587 plugins. :pypi:`pytest-filter-subpackage` Pytest plugin for filtering based on sub-packages Mar 04, 2024 5 - Production/Stable pytest >=4.6 :pypi:`pytest-find-dependencies` A pytest plugin to find dependencies between tests Mar 16, 2024 4 - Beta pytest >=4.3.0 :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) - :pypi:`pytest-firefox` pytest plugin to manipulate firefox Aug 08, 2017 3 - Alpha pytest (>=3.0.2) + :pypi:`pytest-firefox` Feb 28, 2025 N/A N/A :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Feb 22, 2024 4 - Beta pytest >=3.5.0 :pypi:`pytest-fixture-config` Fixture configuration utils for py.test Oct 17, 2024 5 - Production/Stable pytest @@ -602,12 +603,11 @@ This list contains 1587 plugins. :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Aug 14, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-fly` pytest observer Dec 03, 2024 3 - Alpha pytest + :pypi:`pytest-fly` pytest observer Feb 28, 2025 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) :pypi:`pytest-forcefail` py.test plugin to make the test failing regardless of pytest.mark.xfail May 15, 2018 4 - Beta N/A - :pypi:`pytest-forks` Fork helper for pytest Mar 05, 2024 N/A N/A :pypi:`pytest-forward-compatability` A name to avoid typosquating pytest-foward-compatibility Sep 06, 2020 N/A N/A :pypi:`pytest-forward-compatibility` A pytest plugin to shim pytest commandline options for fowards compatibility Sep 29, 2020 N/A N/A :pypi:`pytest-frappe` Pytest Frappe Plugin - A set of pytest fixtures to test Frappe applications Jul 30, 2024 4 - Beta pytest>=7.0.0 @@ -619,7 +619,7 @@ This list contains 1587 plugins. :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 - :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Jan 31, 2025 N/A pytest + :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Feb 27, 2025 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A :pypi:`pytest-fxa-mte` pytest plugin for Firefox Accounts Oct 02, 2024 5 - Production/Stable N/A :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A @@ -678,7 +678,7 @@ This list contains 1587 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Feb 22, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 01, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -701,7 +701,7 @@ This list contains 1587 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace. Feb 11, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Jan 21, 2025 3 - Alpha N/A + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 24, 2025 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Dec 19, 2024 N/A pytest>=8.2.0 :pypi:`pytest-httpx` Send responses to httpx. Nov 28, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -755,7 +755,7 @@ This list contains 1587 plugins. :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Feb 19, 2025 N/A pytest :pypi:`pytest-ipywidgets` Feb 18, 2025 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest - :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Dec 05, 2024 4 - Beta pytest>=5 + :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Feb 24, 2025 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A :pypi:`pytest-item-dict` Get a hierarchical dict of session.items Nov 14, 2024 4 - Beta pytest>=8.3.0 @@ -805,6 +805,7 @@ This list contains 1587 plugins. :pypi:`pytest-lamp` Jan 06, 2017 3 - Alpha N/A :pypi:`pytest-langchain` Pytest-style test runner for langchain agents Feb 26, 2023 N/A pytest :pypi:`pytest-lark` Create fancy and clear HTML test reports. Nov 05, 2023 N/A N/A + :pypi:`pytest-latin-hypercube` Implementation of Latin Hypercube Sampling for pytest. Feb 27, 2025 N/A pytest :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) @@ -841,7 +842,7 @@ This list contains 1587 plugins. :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Jan 19, 2025 3 - Alpha pytest - :pypi:`pytest-logikal` Common testing environment Jan 31, 2025 5 - Production/Stable pytest==8.3.4 + :pypi:`pytest-logikal` Common testing environment Mar 02, 2025 5 - Production/Stable pytest==8.3.4 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" @@ -908,7 +909,7 @@ This list contains 1587 plugins. :pypi:`pytest-modifyjunit` Utility for adding additional properties to junit xml for IDM QE Jan 10, 2019 N/A N/A :pypi:`pytest-molecule` PyTest Molecule Plugin :: discover and run molecule tests Mar 29, 2022 5 - Production/Stable pytest (>=7.0.0) :pypi:`pytest-molecule-JC` PyTest Molecule Plugin :: discover and run molecule tests Jul 18, 2023 5 - Production/Stable pytest (>=7.0.0) - :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Mar 13, 2024 5 - Production/Stable pytest >=6.2 + :pypi:`pytest-mongo` MongoDB process and client fixtures plugin for Pytest. Feb 28, 2025 5 - Production/Stable pytest>=6.2 :pypi:`pytest-mongodb` pytest plugin for MongoDB fixtures May 16, 2023 5 - Production/Stable N/A :pypi:`pytest-mongodb-nono` pytest plugin for MongoDB Jan 07, 2025 N/A N/A :pypi:`pytest-mongodb-ry` pytest plugin for MongoDB Jan 21, 2025 N/A N/A @@ -958,7 +959,7 @@ This list contains 1587 plugins. :pypi:`pytest-nocustom` Run all tests without custom markers Aug 05, 2024 5 - Production/Stable N/A :pypi:`pytest-node-dependency` pytest plugin for controlling execution flow Apr 10, 2024 5 - Production/Stable N/A :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) - :pypi:`pytest-nogarbage` Ensure a test produces no garbage Aug 29, 2021 5 - Production/Stable pytest (>=4.6.0) + :pypi:`pytest-nogarbage` Ensure a test produces no garbage Feb 24, 2025 5 - Production/Stable pytest>=4.6.0 :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A :pypi:`pytest_notebook` A pytest plugin for testing Jupyter Notebooks. Nov 28, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-notice` Send pytest execution result email Nov 05, 2020 N/A N/A @@ -1076,14 +1077,14 @@ This list contains 1587 plugins. :pypi:`pytest-porcochu` Show surprise when tests are passing Nov 28, 2024 5 - Production/Stable N/A :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Sep 05, 2024 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Feb 23, 2025 5 - Production/Stable pytest>=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-powerpack` A plugin containing extra batteries for pytest Jan 04, 2025 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) :pypi:`pytest-pretty` pytest plugin for printing summary data as I want it Apr 05, 2023 5 - Production/Stable pytest>=7 :pypi:`pytest-pretty-terminal` pytest plugin for generating prettier terminal output Jan 31, 2022 N/A pytest (>=3.4.1) :pypi:`pytest-pride` Minitest-style test colors Apr 02, 2016 3 - Alpha N/A - :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Sep 17, 2024 5 - Production/Stable pytest>=8.3.2 + :pypi:`pytest-print` pytest-print adds the printer fixture you can use to print messages to the user (directly to the pytest runner, not stdout) Feb 25, 2025 5 - Production/Stable pytest>=8.3.2 :pypi:`pytest-priority` pytest plugin for add priority for tests Aug 19, 2024 N/A pytest :pypi:`pytest-proceed` Oct 01, 2024 N/A pytest :pypi:`pytest-profiles` pytest plugin for configuration profiles Dec 09, 2021 4 - Beta pytest (>=3.7.0) @@ -1192,7 +1193,7 @@ This list contains 1587 plugins. :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest :pypi:`pytest-report-me` A pytest plugin to generate report. Dec 31, 2020 N/A pytest :pypi:`pytest-report-parameters` pytest plugin for adding tests' parameters to junit report Jun 18, 2020 3 - Alpha pytest (>=2.4.2) - :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Dec 04, 2024 N/A pytest>=3.8.0 + :pypi:`pytest-reportportal` Agent for Reporting results of tests to the Report Portal Feb 28, 2025 N/A pytest>=4.6.10 :pypi:`pytest-report-stream` A pytest plugin which allows to stream test reports at runtime Oct 22, 2023 4 - Beta N/A :pypi:`pytest-repo-structure` Pytest Repo Structure Mar 18, 2024 1 - Planning N/A :pypi:`pytest-req` pytest requests plugin Aug 31, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.2 @@ -1200,7 +1201,7 @@ This list contains 1587 plugins. :pypi:`pytest-requests` A simple plugin to use with pytest Jun 24, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-requestselapsed` collect and show http requests elapsed time Aug 14, 2022 N/A N/A :pypi:`pytest-requests-futures` Pytest Plugin to Mock Requests Futures Jul 06, 2022 5 - Production/Stable pytest - :pypi:`pytest-requirements` pytest plugin for using custom markers to relate tests to requirements and usecases Nov 29, 2024 N/A pytest + :pypi:`pytest-requirements` pytest plugin for using custom markers to relate tests to requirements and usecases Feb 28, 2025 N/A pytest :pypi:`pytest-requires` A pytest plugin to elegantly skip tests with optional requirements Dec 21, 2021 4 - Beta pytest (>=3.5.0) :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) @@ -1209,7 +1210,7 @@ This list contains 1587 plugins. :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Nov 20, 2024 5 - Production/Stable pytest!=8.2.2,>=7.4 :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. Dec 22, 2024 4 - Beta pytest - :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Dec 16, 2024 N/A pytest~=7.0 + :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Feb 28, 2025 N/A pytest~=7.0 :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 @@ -1225,7 +1226,7 @@ This list contains 1587 plugins. :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Jan 19, 2025 N/A pytest>=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Nov 24, 2024 N/A pytest>=5.3 :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A - :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Dec 19, 2024 4 - Beta pytest>=7.0 + :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Feb 27, 2025 4 - Beta pytest<9,>=7.0 :pypi:`pytest-reverse` Pytest plugin to reverse test order. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Dec 12, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest @@ -1261,7 +1262,7 @@ This list contains 1587 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 26, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1273,12 +1274,12 @@ This list contains 1587 plugins. :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 Feb 01, 2024 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. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Feb 26, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 :pypi:`pytest-send-email` Send pytest execution result email Sep 02, 2024 N/A pytest - :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Nov 25, 2024 N/A pytest + :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Feb 24, 2025 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixtures for py.test Nov 29, 2024 5 - Production/Stable pytest @@ -1627,7 +1628,7 @@ This list contains 1587 plugins. :pypi:`databricks-labs-pytester` - *last release*: Feb 03, 2025, + *last release*: Feb 27, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3 @@ -2516,7 +2517,7 @@ This list contains 1587 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Feb 17, 2025, + *last release*: Feb 28, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3173,6 +3174,13 @@ This list contains 1587 plugins. A set of pytest fixtures to help with integration testing with Clerk. + :pypi:`pytest-cli2-ansible` + *last release*: Feb 28, 2025, + *status*: N/A, + *requires*: N/A + + + :pypi:`pytest-click` *last release*: Feb 11, 2022, *status*: 5 - Production/Stable, @@ -4651,7 +4659,7 @@ This list contains 1587 plugins. Pytest execution on EC2 instance :pypi:`pytest-echo` - *last release*: Feb 01, 2025, + *last release*: Feb 22, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6.0 @@ -5078,7 +5086,7 @@ This list contains 1587 plugins. A pytest plugin to provide initial/expected directories, and check a test transforms the initial directory to the expected one :pypi:`pytest-expected` - *last release*: Jan 14, 2025, + *last release*: Feb 26, 2025, *status*: N/A, *requires*: pytest @@ -5407,11 +5415,11 @@ This list contains 1587 plugins. A pytest plugin to treat non-assertion failures as test errors. :pypi:`pytest-firefox` - *last release*: Aug 08, 2017, - *status*: 3 - Alpha, - *requires*: pytest (>=3.0.2) + *last release*: Feb 28, 2025, + *status*: N/A, + *requires*: N/A + - pytest plugin to manipulate firefox :pypi:`pytest-fixture-classes` *last release*: Sep 02, 2023, @@ -5603,7 +5611,7 @@ This list contains 1587 plugins. A pytest plugin in order to provide logs via fluentbit :pypi:`pytest-fly` - *last release*: Dec 03, 2024, + *last release*: Feb 28, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -5637,13 +5645,6 @@ This list contains 1587 plugins. py.test plugin to make the test failing regardless of pytest.mark.xfail - :pypi:`pytest-forks` - *last release*: Mar 05, 2024, - *status*: N/A, - *requires*: N/A - - Fork helper for pytest - :pypi:`pytest-forward-compatability` *last release*: Sep 06, 2020, *status*: N/A, @@ -5722,7 +5723,7 @@ This list contains 1587 plugins. An alternative way to parametrize test cases. :pypi:`pytest-fv` - *last release*: Jan 31, 2025, + *last release*: Feb 27, 2025, *status*: N/A, *requires*: pytest @@ -6135,7 +6136,7 @@ This list contains 1587 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Feb 22, 2025, + *last release*: Mar 01, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6296,7 +6297,7 @@ This list contains 1587 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest_httpserver` - *last release*: Jan 21, 2025, + *last release*: Feb 24, 2025, *status*: 3 - Alpha, *requires*: N/A @@ -6674,7 +6675,7 @@ This list contains 1587 plugins. Run pytest tests in isolated subprocesses :pypi:`pytest-isolate-mpi` - *last release*: Dec 05, 2024, + *last release*: Feb 24, 2025, *status*: 4 - Beta, *requires*: pytest>=5 @@ -7023,6 +7024,13 @@ This list contains 1587 plugins. Create fancy and clear HTML test reports. + :pypi:`pytest-latin-hypercube` + *last release*: Feb 27, 2025, + *status*: N/A, + *requires*: pytest + + Implementation of Latin Hypercube Sampling for pytest. + :pypi:`pytest-launchable` *last release*: Apr 05, 2023, *status*: N/A, @@ -7276,7 +7284,7 @@ This list contains 1587 plugins. pytest fixture logging configured from packaged YAML :pypi:`pytest-logikal` - *last release*: Jan 31, 2025, + *last release*: Mar 02, 2025, *status*: 5 - Production/Stable, *requires*: pytest==8.3.4 @@ -7745,9 +7753,9 @@ This list contains 1587 plugins. PyTest Molecule Plugin :: discover and run molecule tests :pypi:`pytest-mongo` - *last release*: Mar 13, 2024, + *last release*: Feb 28, 2025, *status*: 5 - Production/Stable, - *requires*: pytest >=6.2 + *requires*: pytest>=6.2 MongoDB process and client fixtures plugin for Pytest. @@ -8095,9 +8103,9 @@ This list contains 1587 plugins. Test-driven source code search for Python. :pypi:`pytest-nogarbage` - *last release*: Aug 29, 2021, + *last release*: Feb 24, 2025, *status*: 5 - Production/Stable, - *requires*: pytest (>=4.6.0) + *requires*: pytest>=4.6.0 Ensure a test produces no garbage @@ -8921,7 +8929,7 @@ This list contains 1587 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: Sep 05, 2024, + *last release*: Feb 23, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6.2 @@ -8970,7 +8978,7 @@ This list contains 1587 plugins. Minitest-style test colors :pypi:`pytest-print` - *last release*: Sep 17, 2024, + *last release*: Feb 25, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=8.3.2 @@ -9733,9 +9741,9 @@ This list contains 1587 plugins. pytest plugin for adding tests' parameters to junit report :pypi:`pytest-reportportal` - *last release*: Dec 04, 2024, + *last release*: Feb 28, 2025, *status*: N/A, - *requires*: pytest>=3.8.0 + *requires*: pytest>=4.6.10 Agent for Reporting results of tests to the Report Portal @@ -9789,7 +9797,7 @@ This list contains 1587 plugins. Pytest Plugin to Mock Requests Futures :pypi:`pytest-requirements` - *last release*: Nov 29, 2024, + *last release*: Feb 28, 2025, *status*: N/A, *requires*: pytest @@ -9852,7 +9860,7 @@ This list contains 1587 plugins. Pytest fixture for recording and replaying serial port traffic. :pypi:`pytest-resilient-circuits` - *last release*: Dec 16, 2024, + *last release*: Feb 28, 2025, *status*: N/A, *requires*: pytest~=7.0 @@ -9964,9 +9972,9 @@ This list contains 1587 plugins. :pypi:`pytest-revealtype-injector` - *last release*: Dec 19, 2024, + *last release*: Feb 27, 2025, *status*: 4 - Beta, - *requires*: pytest>=7.0 + *requires*: pytest<9,>=7.0 Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. @@ -10216,7 +10224,7 @@ This list contains 1587 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Feb 20, 2025, + *last release*: Feb 26, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10300,7 +10308,7 @@ This list contains 1587 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Feb 20, 2025, + *last release*: Feb 26, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10335,7 +10343,7 @@ This list contains 1587 plugins. Send pytest execution result email :pypi:`pytest-sentry` - *last release*: Nov 25, 2024, + *last release*: Feb 24, 2025, *status*: N/A, *requires*: pytest From 79f0733f094ff336d839b2088b7f1bfd011b5f3f Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 2 Mar 2025 09:02:44 -0300 Subject: [PATCH 1144/1271] Fix prepare-release-pr script The script is [currently failing with](https://github.com/pytest-dev/pytest/actions/runs/13615071695/job/38057071681): ``` remote: Support for password authentication was removed on August 13, 2021. remote: Please see https://docs.github.com/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication. fatal: Authentication failed for 'https://github.com/pytest-dev/pytest.git/' ``` Decided to remove the usage of `github3` and use the `gh` command-line tool directly, which simplifies the script, integrates nicely with GH, and enables to run it locally seamlessly. --- .github/workflows/prepare-release-pr.yml | 9 ++++-- scripts/prepare-release-pr.py | 39 +++++++++--------------- tox.ini | 5 +-- 3 files changed, 21 insertions(+), 32 deletions(-) diff --git a/.github/workflows/prepare-release-pr.yml b/.github/workflows/prepare-release-pr.yml index b803ba8517b..b21ca70cb46 100644 --- a/.github/workflows/prepare-release-pr.yml +++ b/.github/workflows/prepare-release-pr.yml @@ -30,7 +30,8 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - persist-credentials: false + # persist-credentials is needed in order for us to push the release branch. + persist-credentials: true - name: Set up Python uses: actions/setup-python@v5 @@ -47,13 +48,15 @@ jobs: env: BRANCH: ${{ github.event.inputs.branch }} PRERELEASE: ${{ github.event.inputs.prerelease }} + GH_TOKEN: ${{ github.token }} run: | - tox -e prepare-release-pr -- "$BRANCH" ${{ github.token }} --prerelease="$PRERELEASE" + tox -e prepare-release-pr -- "$BRANCH" --prerelease="$PRERELEASE" - name: Prepare release PR (major release) if: github.event.inputs.major == 'yes' env: BRANCH: ${{ github.event.inputs.branch }} PRERELEASE: ${{ github.event.inputs.prerelease }} + GH_TOKEN: ${{ github.token }} run: | - tox -e prepare-release-pr -- "$BRANCH" ${{ github.token }} --major --prerelease="$PRERELEASE" + tox -e prepare-release-pr -- "$BRANCH" --major --prerelease="$PRERELEASE" diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index 49f8f8c431d..c420a80b3d2 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -10,8 +10,7 @@ After that, it will create a release using the `release` tox environment, and push a new PR. -**Token**: currently the token from the GitHub Actions is used, pushed with -`pytest bot ` commit author. +Note: the script uses the `gh` command-line tool, so `GH_TOKEN` must be set in the environment. """ from __future__ import annotations @@ -25,7 +24,6 @@ from colorama import Fore from colorama import init -from github3.repos import Repository class InvalidFeatureRelease(Exception): @@ -54,17 +52,7 @@ class InvalidFeatureRelease(Exception): """ -def login(token: str) -> Repository: - import github3 - - github = github3.login(token=token) - owner, repo = SLUG.split("/") - return github.repository(owner, repo) - - -def prepare_release_pr( - base_branch: str, is_major: bool, token: str, prerelease: str -) -> None: +def prepare_release_pr(base_branch: str, is_major: bool, prerelease: str) -> None: print() print(f"Processing release for branch {Fore.CYAN}{base_branch}") @@ -131,22 +119,25 @@ def prepare_release_pr( check=True, ) - oauth_url = f"https://{token}:x-oauth-basic@github.com/{SLUG}.git" run( - ["git", "push", oauth_url, f"HEAD:{release_branch}", "--force"], + ["git", "push", "origin", f"HEAD:{release_branch}", "--force"], check=True, ) print(f"Branch {Fore.CYAN}{release_branch}{Fore.RESET} pushed.") body = PR_BODY.format(version=version) - repo = login(token) - pr = repo.create_pull( - f"Prepare release {version}", - base=base_branch, - head=release_branch, - body=body, + run( + [ + "gh", + "pr", + "new", + f"--base={base_branch}", + f"--head={release_branch}", + f"--title=Release {version}", + f"--body={body}", + ], + check=True, ) - print(f"Pull request {Fore.CYAN}{pr.url}{Fore.RESET} created.") def find_next_version( @@ -174,14 +165,12 @@ def main() -> None: init(autoreset=True) parser = argparse.ArgumentParser() parser.add_argument("base_branch") - parser.add_argument("token") parser.add_argument("--major", action="store_true", default=False) parser.add_argument("--prerelease", default="") options = parser.parse_args() prepare_release_pr( base_branch=options.base_branch, is_major=options.major, - token=options.token, prerelease=options.prerelease, ) diff --git a/tox.ini b/tox.ini index 97a74dde937..850def411cb 100644 --- a/tox.ini +++ b/tox.ini @@ -188,11 +188,8 @@ usedevelop = True passenv = * deps = colorama - github3.py pre-commit>=2.9.3 - wheel - # https://github.com/twisted/towncrier/issues/340 - towncrier<21.3.0 + towncrier commands = python scripts/release.py {posargs} [testenv:prepare-release-pr] From 55db9236e0eb44be7d8a141a5ff8e72ec0920351 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 2 Mar 2025 09:53:56 -0300 Subject: [PATCH 1145/1271] Add deploy command-line to RELEASING.rst --- RELEASING.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASING.rst b/RELEASING.rst index 7ef907f2296..0ca63ee4fbf 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -137,6 +137,10 @@ Both automatic and manual processes described above follow the same steps from t in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml, using the ``release-MAJOR.MINOR.PATCH`` branch as source. + Using the command-line:: + + $ gh workflow run deploy.yml -R pytest-dev/pytest --ref=release-{VERSION} -f version={VERSION} + This job will require approval from ``pytest-dev/core``, after which it will publish to PyPI and tag the repository. From 87018dbfebe1aeaa03327509ea4b1d45d7f07d65 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 1 Dec 2024 10:03:14 -0300 Subject: [PATCH 1146/1271] Merge pull request #13018 from pytest-dev/release-8.3.4 Prepare release 8.3.4 (cherry picked from commit 4707416fa1607f0a48debc1aabbfd4917c7529e5) --- changelog/10558.doc.rst | 1 - changelog/10829.doc.rst | 1 - changelog/12497.contrib.rst | 1 - changelog/12592.bugfix.rst | 1 - changelog/12818.bugfix.rst | 1 - changelog/12849.bugfix.rst | 1 - changelog/12866.doc.rst | 1 - changelog/12966.doc.rst | 1 - changelog/9353.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.3.4.rst | 30 +++++++++++++++++++++ doc/en/builtin.rst | 36 +++++++++---------------- doc/en/changelog.rst | 41 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 ++--- doc/en/example/pythoncollection.rst | 4 +-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 17 files changed, 91 insertions(+), 40 deletions(-) delete mode 100644 changelog/10558.doc.rst delete mode 100644 changelog/10829.doc.rst delete mode 100644 changelog/12497.contrib.rst delete mode 100644 changelog/12592.bugfix.rst delete mode 100644 changelog/12818.bugfix.rst delete mode 100644 changelog/12849.bugfix.rst delete mode 100644 changelog/12866.doc.rst delete mode 100644 changelog/12966.doc.rst delete mode 100644 changelog/9353.bugfix.rst create mode 100644 doc/en/announce/release-8.3.4.rst diff --git a/changelog/10558.doc.rst b/changelog/10558.doc.rst deleted file mode 100644 index 1c242b9cf71..00000000000 --- a/changelog/10558.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Fix ambiguous docstring of :func:`pytest.Config.getoption`. diff --git a/changelog/10829.doc.rst b/changelog/10829.doc.rst deleted file mode 100644 index 1be45c7049d..00000000000 --- a/changelog/10829.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Improve documentation on the current handling of the ``--basetemp`` option and its lack of retention functionality (:ref:`temporary directory location and retention`). diff --git a/changelog/12497.contrib.rst b/changelog/12497.contrib.rst deleted file mode 100644 index ccf89731053..00000000000 --- a/changelog/12497.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed two failing pdb-related tests on Python 3.13. diff --git a/changelog/12592.bugfix.rst b/changelog/12592.bugfix.rst deleted file mode 100644 index 605783bcab4..00000000000 --- a/changelog/12592.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :class:`KeyError` crash when using ``--import-mode=importlib`` in a directory layout where a directory contains a child directory with the same name. diff --git a/changelog/12818.bugfix.rst b/changelog/12818.bugfix.rst deleted file mode 100644 index 9d74f2fda2a..00000000000 --- a/changelog/12818.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Assertion rewriting now preserves the source ranges of the original instructions, making it play well with tools that deal with the ``AST``, like `executing `__. diff --git a/changelog/12849.bugfix.rst b/changelog/12849.bugfix.rst deleted file mode 100644 index fb72263aadd..00000000000 --- a/changelog/12849.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -ANSI escape codes for colored output now handled correctly in :func:`pytest.fail` with `pytrace=False`. diff --git a/changelog/12866.doc.rst b/changelog/12866.doc.rst deleted file mode 100644 index 865b2bbc600..00000000000 --- a/changelog/12866.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Improved cross-references concerning the :fixture:`recwarn` fixture. diff --git a/changelog/12966.doc.rst b/changelog/12966.doc.rst deleted file mode 100644 index 8a440c2ec0f..00000000000 --- a/changelog/12966.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Clarify :ref:`filterwarnings` docs on filter precedence/order when using multiple :ref:`@pytest.mark.filterwarnings ` marks. diff --git a/changelog/9353.bugfix.rst b/changelog/9353.bugfix.rst deleted file mode 100644 index 414f5a007b6..00000000000 --- a/changelog/9353.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`pytest.approx` now uses strict equality when given booleans. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 61e4a772beb..8a38df7a2e1 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.3.4 release-8.3.3 release-8.3.2 release-8.3.1 diff --git a/doc/en/announce/release-8.3.4.rst b/doc/en/announce/release-8.3.4.rst new file mode 100644 index 00000000000..f76d60396dc --- /dev/null +++ b/doc/en/announce/release-8.3.4.rst @@ -0,0 +1,30 @@ +pytest-8.3.4 +======================================= + +pytest 8.3.4 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. To upgrade:: + + pip install --upgrade pytest + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Florian Bruhin +* Frank Hoffmann +* Jakob van Santen +* Leonardus Chen +* Pierre Sassoulas +* Pradeep Kumar +* Ran Benita +* Serge Smertin +* Stefaan Lippens +* Sviatoslav Sydorenko (Святослав Сидоренко) +* dongfangtianyu +* suspe + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 822ee48b3fb..85d280da50f 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -178,16 +178,11 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Return a :class:`pytest.TempdirFactory` instance for the test session. tmpdir -- .../_pytest/legacypath.py:305 - Return a temporary directory path object which is unique to each test - function invocation, created as a sub directory of the base temporary - directory. - - By default, a new base temporary directory is created each test session, - and old bases are removed after 3 sessions, to aid in debugging. If - ``--basetemp`` is used then it is cleared each session. See - :ref:`temporary directory location and retention`. - - The returned object is a `legacy_path`_ object. + Return a temporary directory (as `legacy_path`_ object) + which is unique to each test function invocation. + The temporary directory is created as a subdirectory + of the base temporary directory, with configurable retention, + as discussed in :ref:`temporary directory location and retention`. .. note:: These days, it is preferred to use ``tmp_path``. @@ -236,22 +231,15 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a See :ref:`warnings` for information on warning categories. - tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:242 + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:241 Return a :class:`pytest.TempPathFactory` instance for the test session. - tmp_path -- .../_pytest/tmpdir.py:257 - Return a temporary directory path object which is unique to each test - function invocation, created as a sub directory of the base temporary - directory. - - By default, a new base temporary directory is created each test session, - and old bases are removed after 3 sessions, to aid in debugging. - This behavior can be configured with :confval:`tmp_path_retention_count` and - :confval:`tmp_path_retention_policy`. - If ``--basetemp`` is used then it is cleared each session. See - :ref:`temporary directory location and retention`. - - The returned object is a :class:`pathlib.Path` object. + tmp_path -- .../_pytest/tmpdir.py:256 + Return a temporary directory (as :class:`pathlib.Path` object) + which is unique to each test function invocation. + The temporary directory is created as a subdirectory + of the base temporary directory, with configurable retention, + as discussed in :ref:`temporary directory location and retention`. ========================== no tests ran in 0.12s =========================== diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 0a32f88c6ff..58128763a49 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,47 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.3.4 (2024-12-01) +========================= + +Bug fixes +--------- + +- `#12592 `_: Fixed :class:`KeyError` crash when using ``--import-mode=importlib`` in a directory layout where a directory contains a child directory with the same name. + + +- `#12818 `_: Assertion rewriting now preserves the source ranges of the original instructions, making it play well with tools that deal with the ``AST``, like `executing `__. + + +- `#12849 `_: ANSI escape codes for colored output now handled correctly in :func:`pytest.fail` with `pytrace=False`. + + +- `#9353 `_: :func:`pytest.approx` now uses strict equality when given booleans. + + + +Improved documentation +---------------------- + +- `#10558 `_: Fix ambiguous docstring of :func:`pytest.Config.getoption`. + + +- `#10829 `_: Improve documentation on the current handling of the ``--basetemp`` option and its lack of retention functionality (:ref:`temporary directory location and retention`). + + +- `#12866 `_: Improved cross-references concerning the :fixture:`recwarn` fixture. + + +- `#12966 `_: Clarify :ref:`filterwarnings` docs on filter precedence/order when using multiple :ref:`@pytest.mark.filterwarnings ` marks. + + + +Contributor-facing changes +-------------------------- + +- `#12497 `_: Fixed two failing pdb-related tests on Python 3.13. + + pytest 8.3.3 (2024-09-09) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index fa43308d045..f1f7deb909c 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 42a603f114c..1d1ce07c10a 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index faf81154c48..d4308e5aab3 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.3.3 + pytest 8.3.4 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 4f6e8cbee06..9232c9e8449 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From 4603564f6437b544b7d34fec012e69016ce452f0 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sun, 2 Mar 2025 09:55:51 -0300 Subject: [PATCH 1147/1271] Merge pull request #13264 from pytest-dev/release-8.3.5 Release 8.3.5 (cherry picked from commit f004b11caf49fa6fbacc8648bbc9c650a2e08bec) --- changelog/11777.bugfix.rst | 1 - changelog/12842.doc.rst | 3 --- changelog/12888.bugfix.rst | 1 - changelog/13026.bugfix.rst | 1 - changelog/13053.bugfix.rst | 1 - changelog/13083.bugfix.rst | 1 - changelog/13112.contrib.rst | 1 - changelog/13256.contrib.rst | 2 -- doc/en/announce/index.rst | 1 + doc/en/announce/release-8.3.5.rst | 26 ++++++++++++++++++ doc/en/builtin.rst | 8 +++--- doc/en/changelog.rst | 41 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 15 ++++++----- doc/en/example/pythoncollection.rst | 4 +-- doc/en/example/reportingdemo.rst | 18 ++++++------- doc/en/example/simple.rst | 2 +- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- doc/en/reference/reference.rst | 14 +++++----- 19 files changed, 102 insertions(+), 42 deletions(-) delete mode 100644 changelog/11777.bugfix.rst delete mode 100644 changelog/12842.doc.rst delete mode 100644 changelog/12888.bugfix.rst delete mode 100644 changelog/13026.bugfix.rst delete mode 100644 changelog/13053.bugfix.rst delete mode 100644 changelog/13083.bugfix.rst delete mode 100644 changelog/13112.contrib.rst delete mode 100644 changelog/13256.contrib.rst create mode 100644 doc/en/announce/release-8.3.5.rst diff --git a/changelog/11777.bugfix.rst b/changelog/11777.bugfix.rst deleted file mode 100644 index 3f1ffc27a68..00000000000 --- a/changelog/11777.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed issue where sequences were still being shortened even with ``-vv`` verbosity. diff --git a/changelog/12842.doc.rst b/changelog/12842.doc.rst deleted file mode 100644 index 0a0f5c5bc23..00000000000 --- a/changelog/12842.doc.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added dedicated page about using types with pytest. - -See :ref:`types` for detailed usage. diff --git a/changelog/12888.bugfix.rst b/changelog/12888.bugfix.rst deleted file mode 100644 index 635e35a11ea..00000000000 --- a/changelog/12888.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed broken input when using Python 3.13+ and a ``libedit`` build of Python, such as on macOS or with uv-managed Python binaries from the ``python-build-standalone`` project. This could manifest e.g. by a broken prompt when using ``Pdb``, or seeing empty inputs with manual usage of ``input()`` and suspended capturing. diff --git a/changelog/13026.bugfix.rst b/changelog/13026.bugfix.rst deleted file mode 100644 index d10edbd111a..00000000000 --- a/changelog/13026.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed :class:`AttributeError` crash when using ``--import-mode=importlib`` when top-level directory same name as another module of the standard library. diff --git a/changelog/13053.bugfix.rst b/changelog/13053.bugfix.rst deleted file mode 100644 index b6744331394..00000000000 --- a/changelog/13053.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a regression in pytest 8.3.4 where, when using ``--import-mode=importlib``, a directory containing py file with the same name would cause an ``ImportError`` diff --git a/changelog/13083.bugfix.rst b/changelog/13083.bugfix.rst deleted file mode 100644 index fc4564755ba..00000000000 --- a/changelog/13083.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed issue where pytest could crash if one of the collected directories got removed during collection. diff --git a/changelog/13112.contrib.rst b/changelog/13112.contrib.rst deleted file mode 100644 index 5e59a736edb..00000000000 --- a/changelog/13112.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed selftest failures in ``test_terminal.py`` with Pygments >= 2.19.0 diff --git a/changelog/13256.contrib.rst b/changelog/13256.contrib.rst deleted file mode 100644 index fe3bac87ca1..00000000000 --- a/changelog/13256.contrib.rst +++ /dev/null @@ -1,2 +0,0 @@ -Support for Towncier versions released in 2024 has been re-enabled -when building Sphinx docs -- by :user:`webknjaz`. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 8a38df7a2e1..51edc964a0c 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.3.5 release-8.3.4 release-8.3.3 release-8.3.2 diff --git a/doc/en/announce/release-8.3.5.rst b/doc/en/announce/release-8.3.5.rst new file mode 100644 index 00000000000..3de02c1d7a4 --- /dev/null +++ b/doc/en/announce/release-8.3.5.rst @@ -0,0 +1,26 @@ +pytest-8.3.5 +======================================= + +pytest 8.3.5 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Florian Bruhin +* John Litborn +* Kenny Y +* Ran Benita +* Sadra Barikbin +* Vincent (Wen Yu) Ge +* delta87 +* dongfangtianyu +* mwychung +* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 85d280da50f..8aa6fef681c 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -33,7 +33,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1006 + capsysbinary -- .../_pytest/capture.py:1024 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -51,7 +51,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1034 + capfd -- .../_pytest/capture.py:1052 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -69,7 +69,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1062 + capfdbinary -- .../_pytest/capture.py:1080 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -87,7 +87,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - capsys -- .../_pytest/capture.py:978 + capsys -- .../_pytest/capture.py:996 Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsys.readouterr()`` method diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 58128763a49..3074124465a 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,47 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.3.5 (2025-03-02) +========================= + +Bug fixes +--------- + +- `#11777 `_: Fixed issue where sequences were still being shortened even with ``-vv`` verbosity. + + +- `#12888 `_: Fixed broken input when using Python 3.13+ and a ``libedit`` build of Python, such as on macOS or with uv-managed Python binaries from the ``python-build-standalone`` project. This could manifest e.g. by a broken prompt when using ``Pdb``, or seeing empty inputs with manual usage of ``input()`` and suspended capturing. + + +- `#13026 `_: Fixed :class:`AttributeError` crash when using ``--import-mode=importlib`` when top-level directory same name as another module of the standard library. + + +- `#13053 `_: Fixed a regression in pytest 8.3.4 where, when using ``--import-mode=importlib``, a directory containing py file with the same name would cause an ``ImportError`` + + +- `#13083 `_: Fixed issue where pytest could crash if one of the collected directories got removed during collection. + + + +Improved documentation +---------------------- + +- `#12842 `_: Added dedicated page about using types with pytest. + + See :ref:`types` for detailed usage. + + + +Contributor-facing changes +-------------------------- + +- `#13112 `_: Fixed selftest failures in ``test_terminal.py`` with Pygments >= 2.19.0 + + +- `#13256 `_: Support for Towncier versions released in 2024 has been re-enabled + when building Sphinx docs -- by :user:`webknjaz`. + + pytest 8.3.4 (2024-12-01) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index f1f7deb909c..69e715c9db1 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + @@ -503,11 +503,12 @@ Running it results in some skips if we don't have all the python interpreters in .. code-block:: pytest . $ pytest -rs -q multipython.py - ssssssssssss...ssssssssssss [100%] + sssssssssssssssssssssssssss [100%] ========================= short test summary info ========================== - SKIPPED [12] multipython.py:67: 'python3.9' not found - SKIPPED [12] multipython.py:67: 'python3.11' not found - 3 passed, 24 skipped in 0.12s + SKIPPED [9] multipython.py:67: 'python3.9' not found + SKIPPED [9] multipython.py:67: 'python3.10' not found + SKIPPED [9] multipython.py:67: 'python3.11' not found + 27 skipped in 0.12s Parametrization of optional implementations/imports --------------------------------------------------- diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 1d1ce07c10a..89d7ee42614 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 0da58d0490e..5e48815bbc9 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -568,12 +568,12 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + where False = ('456') E + where = '123'.startswith E + where '123' = .f at 0xdeadbeef0029>() - E + and '456' = .g at 0xdeadbeef002a>() + E + and '456' = .g at 0xdeadbeef0003>() failure_demo.py:237: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -584,18 +584,18 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:240: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - self = + self = def test_instance(self): self.x = 6 * 7 > assert self.x != 42 E assert 42 != 42 - E + where 42 = .x + E + where 42 = .x failure_demo.py:244: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -605,7 +605,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:247: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -616,7 +616,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:252: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -631,7 +631,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:263: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: @@ -650,7 +650,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:270: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index b50fbfed397..69d973e51d0 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -164,7 +164,7 @@ Now we'll get feedback on a bad argument: $ pytest -q --cmdopt=type3 ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...] - pytest: error: argument --cmdopt: invalid choice: 'type3' (choose from 'type1', 'type2') + pytest: error: argument --cmdopt: invalid choice: 'type3' (choose from type1, type2) If you need to provide more detailed error messages, you can use the diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index d4308e5aab3..5b9f38d7bf7 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.3.4 + pytest 8.3.5 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 9232c9e8449..8f84e4867a6 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1418,7 +1418,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index b42e69dfa23..631d45191a7 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2102,7 +2102,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: Show cache contents, don't perform collection or tests. Optional argument: glob (default: '*'). --cache-clear Remove all cache contents at start of test run - --lfnf={all,none}, --last-failed-no-failures={all,none} + --lfnf, --last-failed-no-failures={all,none} With ``--lf``, determines whether to execute tests when there are no previously (known) failures or when no cached ``lastfailed`` data was found. @@ -2148,11 +2148,13 @@ All the command-line flags can be obtained by running ``pytest --help``:: Whether code should be highlighted (only if --color is also enabled). Default: yes. --pastebin=mode Send failed|all info to bpaste.net pastebin service - --junit-xml=path Create junit-xml style report file at given path - --junit-prefix=str Prepend prefix to classnames in junit-xml output + --junitxml, --junit-xml=path + Create junit-xml style report file at given path + --junitprefix, --junit-prefix=str + Prepend prefix to classnames in junit-xml output pytest-warnings: - -W PYTHONWARNINGS, --pythonwarnings=PYTHONWARNINGS + -W, --pythonwarnings PYTHONWARNINGS Set which warnings to report, see -W option of Python itself --maxfail=num Exit after first num failures or errors @@ -2161,7 +2163,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: --strict-markers Markers not registered in the `markers` section of the configuration file raise errors --strict (Deprecated) alias to --strict-markers - -c FILE, --config-file=FILE + -c, --config-file FILE Load configuration from `FILE` instead of trying to locate one of the implicit configuration files. --continue-on-collection-errors @@ -2215,7 +2217,7 @@ All the command-line flags can be obtained by running ``pytest --help``:: Store internal tracing debug information in this log file. This file is opened with 'w' and truncated as a result, care advised. Default: pytestdebug.log. - -o OVERRIDE_INI, --override-ini=OVERRIDE_INI + -o, --override-ini OVERRIDE_INI Override ini option with "option=value" style, e.g. `-o xfail_strict=True -o cache_dir=cache`. --assert=MODE Control assertion debugging tools. From e18b245f0a07f03de889e9541242397e4d2ce388 Mon Sep 17 00:00:00 2001 From: Tony Narlock Date: Sun, 2 Mar 2025 10:12:28 -0600 Subject: [PATCH 1148/1271] chore(changelog) Minor typo fix (#13267) --- doc/en/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 3074124465a..c92cd7d4263 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -68,7 +68,7 @@ Contributor-facing changes - `#13112 `_: Fixed selftest failures in ``test_terminal.py`` with Pygments >= 2.19.0 -- `#13256 `_: Support for Towncier versions released in 2024 has been re-enabled +- `#13256 `_: Support for Towncrier versions released in 2024 has been re-enabled when building Sphinx docs -- by :user:`webknjaz`. From 4e9765203d61e2673f9d6c27e4e55811d000b424 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Mon, 3 Mar 2025 12:27:48 +0100 Subject: [PATCH 1149/1271] remove raises_group alias, doc fixes after review --- doc/en/how-to/assert.rst | 4 ++-- src/pytest/__init__.py | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index c01e59a7a0e..966ea8b38fc 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -225,9 +225,9 @@ Check the documentation on :class:`pytest.RaisesGroup` and :class:`pytest.Raises if very_unlucky(): excs.append(EXTREMELYBADERROR()) raise ExceptionGroup("", excs) - # this passes regardless of if there's other exceptions + # This passes regardless of if there's other exceptions. assert excinfo.group_contains(ValueError) - # you can't simply list all exceptions you *don't* want to get here + # You can't simply list all exceptions you *don't* want to get here. There is no good way of using :func:`excinfo.group_contains() ` to ensure you're not getting *any* other exceptions than the one you expected. diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index e3e782654fe..3e73605ce15 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -62,7 +62,6 @@ from _pytest.python_api import raises from _pytest.raises_group import RaisesExc from _pytest.raises_group import RaisesGroup -from _pytest.raises_group import RaisesGroup as raises_group from _pytest.recwarn import deprecated_call from _pytest.recwarn import WarningsRecorder from _pytest.recwarn import warns @@ -167,7 +166,6 @@ "mark", "param", "raises", - "raises_group", "register_assert_rewrite", "set_trace", "skip", From bfe0c83ed314741ee8e4b5aecaddaa84b44a3ec6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 15:40:29 +0100 Subject: [PATCH 1150/1271] build(deps): Bump peter-evans/create-pull-request from 7.0.6 to 7.0.7 (#13268) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.6 to 7.0.7. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/67ccf781d68cd99b580ae25a5c18a1cc84ffff1f...dd2324fc52d5d43c699a5636bcf19fceaa70c284) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index a4eeb4b0a36..3200cb174cc 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -48,7 +48,7 @@ jobs: - name: Create Pull Request id: pr - uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f + uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 410a052152720c572ec2e02ce6c034562b614c6f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 20:44:28 +0000 Subject: [PATCH 1151/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.7 → v0.9.9](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.7...v0.9.9) - [github.com/woodruffw/zizmor-pre-commit: v1.3.1 → v1.4.1](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.3.1...v1.4.1) - [github.com/tox-dev/pyproject-fmt: v2.5.0 → v2.5.1](https://github.com/tox-dev/pyproject-fmt/compare/v2.5.0...v2.5.1) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 085ea59ca05..26c5a7f5394 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.7" + rev: "v0.9.9" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.3.1 + rev: v1.4.1 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs @@ -48,7 +48,7 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.5.0" + rev: "v2.5.1" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version From be2600ea40708b709f50aa8706d83b1cda17663c Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 3 Mar 2025 22:28:13 +0100 Subject: [PATCH 1152/1271] [pylint] Noqa a false positive with dynamic exception handling --- src/_pytest/python_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index ddbf9b87251..5fd9c5124d5 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -1017,7 +1017,7 @@ def validate_exc(exc: type[E]) -> type[E]: raise TypeError(f"{func!r} object (type: {type(func)}) must be callable") try: func(*args[1:], **kwargs) - except expected_exceptions as e: + except expected_exceptions as e: # pylint: disable=catching-non-exception return _pytest._code.ExceptionInfo.from_exception(e) fail(message) From a7479ced6cad92fd5aee476efea748e65090e650 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 3 Mar 2025 22:28:43 +0100 Subject: [PATCH 1153/1271] [pyupgrade] Apply pyupgrade on new code manually --- testing/acceptance_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index ffd1dcce219..50ea4ff44d2 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -999,14 +999,14 @@ def test_calls_showall_durationsmin_verbose( def check_tests_in_output( lines: Sequence[str], *expected_test_numbers: int, number_of_tests: int = 3 ) -> None: - found_test_numbers = set( + found_test_numbers = { test_number for test_number in range(1, number_of_tests + 1) if any( line.endswith(f"test_{test_number}") and " call " in line for line in lines ) - ) + } assert found_test_numbers == set(expected_test_numbers) def test_with_deselected(self, pytester: Pytester, mock_timing) -> None: From d37e6d66d3ba33a41d4c1d09bc66fe934f79b175 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Wed, 5 Mar 2025 16:22:15 +0100 Subject: [PATCH 1154/1271] Update 11538.feature.rst --- changelog/11538.feature.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/11538.feature.rst b/changelog/11538.feature.rst index 60f191d05cb..d6473b8fe73 100644 --- a/changelog/11538.feature.rst +++ b/changelog/11538.feature.rst @@ -1 +1 @@ -Added :class:`pytest.RaisesGroup` (also export as ``pytest.raises_group``) and :class:`pytest.RaisesExc`, as an equivalent to :func:`pytest.raises` for expecting :exc:`ExceptionGroup`. It includes the ability to specify multiple different expected exceptions, the structure of nested exception groups, and flags for emulating :ref:`except* `. See :ref:`assert-matching-exception-groups` and docstrings for more information. +Added :class:`pytest.RaisesGroup` as an equivalent to :func:`pytest.raises` for expecting :exc:`ExceptionGroup`. Also adds :class:`pytest.RaisesExc` which is now the logic behind :func:`pytest.raises` and used as parameter to :class:`pytest.RaisesGroup`. ``RaisesGroup`` includes the ability to specify multiple different expected exceptions, the structure of nested exception groups, and flags for emulating :ref:`except* `. See :ref:`assert-matching-exception-groups` and docstrings for more information. From 4c6ded7b0c879221e54161cb4d712505b46a59d2 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Wed, 5 Mar 2025 16:34:49 +0100 Subject: [PATCH 1155/1271] docs fixes after removing the raises_group alias. --- doc/en/how-to/assert.rst | 20 ++++++++++---------- src/_pytest/_code/code.py | 2 +- src/_pytest/python_api.py | 5 ----- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 966ea8b38fc..6bc8f6fed33 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -148,14 +148,14 @@ Notes: Assertions about expected exception groups ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -When expecting a :exc:`BaseExceptionGroup` or :exc:`ExceptionGroup` you can use :class:`pytest.RaisesGroup`, also available as :class:`pytest.raises_group `: +When expecting a :exc:`BaseExceptionGroup` or :exc:`ExceptionGroup` you can use :class:`pytest.RaisesGroup`: .. code-block:: python def test_exception_in_group(): - with pytest.raises_group(ValueError): + with pytest.RaisesGroup(ValueError): raise ExceptionGroup("group msg", [ValueError("value msg")]) - with pytest.raises_group(ValueError, TypeError): + with pytest.RaisesGroup(ValueError, TypeError): raise ExceptionGroup("msg", [ValueError("foo"), TypeError("bar")]) @@ -164,9 +164,9 @@ It accepts a ``match`` parameter, that checks against the group message, and a ` .. code-block:: python def test_raisesgroup_match_and_check(): - with pytest.raises_group(BaseException, match="my group msg"): + with pytest.RaisesGroup(BaseException, match="my group msg"): raise BaseExceptionGroup("my group msg", [KeyboardInterrupt()]) - with pytest.raises_group( + with pytest.RaisesGroup( Exception, check=lambda eg: isinstance(eg.__cause__, ValueError) ): raise ExceptionGroup("", [TypeError()]) from ValueError() @@ -176,11 +176,11 @@ It is strict about structure and unwrapped exceptions, unlike :ref:`except* ` to ensure you're not getting *any* other exceptions than the one you expected. - You should instead use :class:`pytest.raises_group `, see :ref:`assert-matching-exception-groups`. + You should instead use :class:`pytest.RaisesGroup`, see :ref:`assert-matching-exception-groups`. You can also use the :func:`excinfo.group_contains() ` method to test for exceptions returned as part of an :class:`ExceptionGroup`: diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 0a5a20161e4..b57569dff98 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -840,7 +840,7 @@ def group_contains( This helper makes it easy to check for the presence of specific exceptions, but it is very bad for checking that the group does *not* contain *any other exceptions*. - You should instead consider using :class:`pytest.raises_group ` + You should instead consider using :class:`pytest.RaisesGroup` """ msg = "Captured exception is not an instance of `BaseExceptionGroup`" diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index f59d7ea8ef4..74ddd73005b 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -22,9 +22,6 @@ from _pytest.raises_group import RaisesExc -if sys.version_info < (3, 11): - pass - if TYPE_CHECKING: from numpy import ndarray @@ -771,8 +768,6 @@ def _as_numpy_array(obj: object) -> ndarray | None: Return an ndarray if the given object is implicitly convertible to ndarray, and numpy is already imported, otherwise None. """ - import sys - np: Any = sys.modules.get("numpy") if np is not None: # avoid infinite recursion on numpy scalars, which have __array__ From 94f4409a4fbd9aa02a671ada6f216949b6204668 Mon Sep 17 00:00:00 2001 From: jakkdl Date: Wed, 5 Mar 2025 17:34:06 +0100 Subject: [PATCH 1156/1271] require patches to be 100% coverage, instead of current project coverage% --- codecov.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 0841ab049ff..c37e5ec4a09 100644 --- a/codecov.yml +++ b/codecov.yml @@ -6,6 +6,8 @@ codecov: coverage: status: - patch: true + patch: + default: + target: 100% # require patches to be 100% project: false comment: false From 31d64fc53ba12905008241afa4010472aff13bae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 06:23:52 +0100 Subject: [PATCH 1157/1271] build(deps): Bump django in /testing/plugins_integration (#13276) Bumps [django](https://github.com/django/django) from 5.1.6 to 5.1.7. - [Commits](https://github.com/django/django/compare/5.1.6...5.1.7) --- updated-dependencies: - dependency-name: django dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 5562329e1de..437df4dc2d1 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[trio]==4.8.0 -django==5.1.6 +django==5.1.7 pytest-asyncio==0.25.3 pytest-bdd==8.1.0 pytest-cov==6.0.0 From a98d093a71a3a0cb13ff7d337366f364a54c2ba3 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Fri, 7 Mar 2025 20:04:46 +0100 Subject: [PATCH 1158/1271] improve raisesgroup code coverage (#13275) * improve raisesgroup code coverage * fix coverage of a weird branch in python_api, explicitify match in other test * remove comment --- src/_pytest/_code/code.py | 3 ++- src/_pytest/raises_group.py | 6 ------ testing/python/raises.py | 24 +++++++++++++++++++++--- testing/python/raises_group.py | 29 ++++++++++++++++++++--------- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index b57569dff98..2c872df3008 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -470,7 +470,8 @@ def stringify_exception( HTTPError = getattr(sys.modules.get("urllib.error", None), "HTTPError", ()) if sys.version_info < (3, 12) and isinstance(exc, HTTPError): notes = [] - else: + else: # pragma: no cover + # exception not related to above bug, reraise raise if not include_subexception_msg and isinstance(exc, BaseExceptionGroup): message = exc.message diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index f60bacb7184..51ab8aafaf4 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -213,7 +213,6 @@ def _parse_exc( self.is_baseexception = True return cast(type[BaseExcT_1], origin_exc) else: - # I kinda think this should be a TypeError... raise ValueError( f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` " f"are accepted as generic types but got `{exc}`. " @@ -424,11 +423,6 @@ def __enter__(self) -> ExceptionInfo[BaseExcT_co_default]: self.excinfo: ExceptionInfo[BaseExcT_co_default] = ExceptionInfo.for_later() return self.excinfo - def expected_type(self) -> str: - if self.expected_exceptions == (): - return "BaseException" - return _exception_type_name(self.expected_exceptions) - # TODO: move common code into superclass def __exit__( self, diff --git a/testing/python/raises.py b/testing/python/raises.py index 5dafef7a78d..333e273db6a 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -36,6 +36,19 @@ def test_raises_does_not_allow_none(self): # so we can ignore Mypy telling us that None is invalid. pytest.raises(expected_exception=None) # type: ignore + # it's unclear if this message is helpful, and if it is, should it trigger more + # liberally? Usually you'd get a TypeError here + def test_raises_false_and_arg(self): + with pytest.raises( + ValueError, + match=wrap_escape( + "Expected an exception type or a tuple of exception types, but got `False`. " + "Raising exceptions is already understood as failing the test, so you don't need " + "any special code to say 'this should never raise an exception'." + ), + ): + pytest.raises(False, int) # type: ignore[call-overload] + def test_raises_does_not_allow_empty_tuple(self): with pytest.raises( ValueError, @@ -219,7 +232,7 @@ def __call__(self): elif method == "with_group": with pytest.RaisesGroup(ValueError, allow_unwrapped=True): t() - else: + else: # pragma: no cover raise AssertionError("bad parametrization") # ensure both forms of pytest.raises don't leave exceptions in sys.exc_info() @@ -337,10 +350,15 @@ def __class__(self): def test_raises_context_manager_with_kwargs(self): with pytest.raises(expected_exception=ValueError): raise ValueError - with pytest.raises(TypeError) as excinfo: + with pytest.raises( + TypeError, + match=wrap_escape( + "Unexpected keyword arguments passed to pytest.raises: foo\n" + "Use context-manager form instead?" + ), + ): with pytest.raises(OSError, foo="bar"): # type: ignore[call-overload] pass - assert "Unexpected keyword arguments" in str(excinfo.value) def test_expected_exception_is_not_a_baseexception(self) -> None: with pytest.raises(TypeError) as excinfo: diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index 2619eb41c1d..0dc2a58a1da 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -458,12 +458,16 @@ def my_check(e: object) -> bool: # pragma: no cover assert RaisesGroup(ValueError, match="bar").matches(exc.value) -def test_RaisesGroup_matches() -> None: +def test_matches() -> None: rg = RaisesGroup(ValueError) assert not rg.matches(None) assert not rg.matches(ValueError()) assert rg.matches(ExceptionGroup("", (ValueError(),))) + re = RaisesExc(ValueError) + assert not re.matches(None) + assert re.matches(ValueError()) + def test_message() -> None: def check_message( @@ -884,11 +888,13 @@ def test_assert_message_nested() -> None: ) +# CI always runs with hypothesis, but this is not a critical test - it overlaps +# with several others @pytest.mark.skipif( "hypothesis" in sys.modules, reason="hypothesis may have monkeypatched _check_repr", ) -def test_check_no_patched_repr() -> None: +def test_check_no_patched_repr() -> None: # pragma: no cover # We make `_check_repr` monkeypatchable to avoid this very ugly and verbose # repr. The other tests that use `check` make use of `_check_repr` so they'll # continue passing in case it is patched - but we have this one test that @@ -1288,15 +1294,20 @@ def test_parametrizing_conditional_raisesgroup( def test_annotated_group() -> None: # repr depends on if exceptiongroup backport is being used or not t = repr(ExceptionGroup[ValueError]) - fail_msg = wrap_escape( - f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` are accepted as generic types but got `{t}`. As `raises` will catch all instances of the specified group regardless of the generic argument specific nested exceptions has to be checked with `RaisesGroup`." - ) + msg = "Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` are accepted as generic types but got `{}`. As `raises` will catch all instances of the specified group regardless of the generic argument specific nested exceptions has to be checked with `RaisesGroup`." + + fail_msg = wrap_escape(msg.format(t)) with pytest.raises(ValueError, match=fail_msg): - with RaisesGroup(ExceptionGroup[ValueError]): - ... # pragma: no cover + RaisesGroup(ExceptionGroup[ValueError]) with pytest.raises(ValueError, match=fail_msg): - with RaisesExc(ExceptionGroup[ValueError]): - ... # pragma: no cover + RaisesExc(ExceptionGroup[ValueError]) + with pytest.raises( + ValueError, + match=wrap_escape(msg.format(repr(BaseExceptionGroup[KeyboardInterrupt]))), + ): + with RaisesExc(BaseExceptionGroup[KeyboardInterrupt]): + raise BaseExceptionGroup("", [KeyboardInterrupt()]) + with RaisesGroup(ExceptionGroup[Exception]): raise ExceptionGroup( "", [ExceptionGroup("", [ValueError(), ValueError(), ValueError()])] From 72031556c790b253df76342afc98c054e2f22e70 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 8 Mar 2025 12:19:13 +0100 Subject: [PATCH 1159/1271] doc: Update trainings (#13280) --- doc/en/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 7f3dbdd800d..6e04dbb9ed0 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,7 @@ .. sidebar:: **Next Open Trainings and Events** - - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 4th -- 6th 2025**, Remote + - `pytest - simple, rapid and fun testing with Python `_, at `PyConDE `_, **April 24th** (1.5), Darmstadt, Germany Also see :doc:`previous talks and blogposts ` From 611f336b802366e662e5d35380dbed50b0c327e3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 9 Mar 2025 06:26:22 +0000 Subject: [PATCH 1160/1271] [automated] Update plugin list (#13282) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 98 +++++++++++++++++--------------- 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 59a73530796..e8dfcc68028 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Feb 10, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Mar 03, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -161,7 +161,7 @@ This list contains 1588 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Feb 28, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Mar 07, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -192,7 +192,7 @@ This list contains 1588 plugins. :pypi:`pytest-breakword` Use breakword with pytest Aug 04, 2021 N/A pytest (>=6.2.4,<7.0.0) :pypi:`pytest-breed-adapter` A simple plugin to connect with breed-server Nov 07, 2018 4 - Beta pytest (>=3.5.0) :pypi:`pytest-briefcase` A pytest plugin for running tests on a Briefcase project. Jun 14, 2020 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-broadcaster` Pytest plugin to broadcast pytest output to various destinations Apr 06, 2024 3 - Alpha pytest + :pypi:`pytest-broadcaster` Pytest plugin to broadcast pytest output to various destinations Mar 02, 2025 3 - Alpha pytest :pypi:`pytest-browser` A pytest plugin for console based browser test selection just after the collection phase Dec 10, 2016 3 - Alpha N/A :pypi:`pytest-browsermob-proxy` BrowserMob proxy plugin for py.test. Jun 11, 2013 4 - Beta N/A :pypi:`pytest_browserstack` Py.test plugin for BrowserStack Jan 27, 2016 4 - Beta N/A @@ -255,7 +255,7 @@ This list contains 1588 plugins. :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Nov 08, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Jan 30, 2025 N/A pytest<9.0.0,>=8.0.0 - :pypi:`pytest-cli2-ansible` Feb 28, 2025 N/A N/A + :pypi:`pytest-cli2-ansible` Mar 05, 2025 N/A N/A :pypi:`pytest-click` Pytest plugin for Click Feb 11, 2022 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-cli-fixtures` Automatically register fixtures for custom CLI arguments Jul 28, 2022 N/A pytest (~=7.0) :pypi:`pytest-clld` Oct 23, 2024 N/A pytest>=3.9 @@ -476,15 +476,15 @@ This list contains 1588 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 Jul 25, 2024 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. Feb 20, 2025 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Feb 20, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Feb 20, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Feb 20, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Feb 20, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Feb 20, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Feb 20, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Feb 20, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Feb 20, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Mar 03, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Mar 03, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Mar 03, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Mar 03, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Mar 03, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Mar 03, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Mar 03, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Mar 03, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Mar 03, 2025 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) @@ -678,7 +678,7 @@ This list contains 1588 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Mar 01, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 08, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -727,7 +727,7 @@ This list contains 1588 plugins. :pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A - :pypi:`pytest-infrahouse` A set of fixtures to use with pytest Dec 19, 2024 4 - Beta pytest~=8.3 + :pypi:`pytest-infrahouse` A set of fixtures to use with pytest Mar 06, 2025 4 - Beta pytest~=8.3 :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-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 @@ -747,12 +747,12 @@ This list contains 1588 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Feb 13, 2025 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Dec 02, 2024 5 - Production/Stable pytest<9.0.0,>=6 + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Mar 07, 2025 5 - Production/Stable pytest<9.0.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Feb 19, 2025 N/A pytest + :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Mar 03, 2025 N/A pytest :pypi:`pytest-ipywidgets` Feb 18, 2025 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Feb 24, 2025 4 - Beta pytest>=5 @@ -884,7 +884,7 @@ This list contains 1588 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 Feb 12, 2024 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 Feb 20, 2025 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin Mar 06, 2025 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) @@ -1262,7 +1262,7 @@ This list contains 1588 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Feb 26, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 07, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1274,7 +1274,7 @@ This list contains 1588 plugins. :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 Feb 01, 2024 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. Feb 26, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 07, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1356,7 +1356,7 @@ This list contains 1588 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 28, 2024 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons Mar 07, 2025 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jan 03, 2025 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 @@ -1365,6 +1365,7 @@ This list contains 1588 plugins. :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 19, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-sqlguard` Pytest fixture to record and check SQL Queries made by SQLAlchemy Mar 06, 2025 4 - Beta pytest>=7 :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest :pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A pytest>=6.2.0 :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest @@ -1581,7 +1582,7 @@ This list contains 1588 plugins. :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 - :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Jan 22, 2025 N/A pytest<8.0.0,>=7.4.2 + :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Mar 07, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 14, 2024 4 - Beta pytest>=8.2.1 @@ -2216,7 +2217,7 @@ This list contains 1588 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Feb 10, 2025, + *last release*: Mar 03, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2517,7 +2518,7 @@ This list contains 1588 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Feb 28, 2025, + *last release*: Mar 07, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -2734,7 +2735,7 @@ This list contains 1588 plugins. A pytest plugin for running tests on a Briefcase project. :pypi:`pytest-broadcaster` - *last release*: Apr 06, 2024, + *last release*: Mar 02, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3175,7 +3176,7 @@ This list contains 1588 plugins. A set of pytest fixtures to help with integration testing with Clerk. :pypi:`pytest-cli2-ansible` - *last release*: Feb 28, 2025, + *last release*: Mar 05, 2025, *status*: N/A, *requires*: N/A @@ -4722,63 +4723,63 @@ This list contains 1588 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Feb 20, 2025, + *last release*: Mar 03, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -6136,7 +6137,7 @@ This list contains 1588 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 01, 2025, + *last release*: Mar 08, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6479,7 +6480,7 @@ This list contains 1588 plugins. display more node ininformation. :pypi:`pytest-infrahouse` - *last release*: Dec 19, 2024, + *last release*: Mar 06, 2025, *status*: 4 - Beta, *requires*: pytest~=8.3 @@ -6619,7 +6620,7 @@ This list contains 1588 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Dec 02, 2024, + *last release*: Mar 07, 2025, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=6 @@ -6654,7 +6655,7 @@ This list contains 1588 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipynb2` - *last release*: Feb 19, 2025, + *last release*: Mar 03, 2025, *status*: N/A, *requires*: pytest @@ -7578,7 +7579,7 @@ This list contains 1588 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Feb 20, 2025, + *last release*: Mar 06, 2025, *status*: N/A, *requires*: pytest @@ -10224,7 +10225,7 @@ This list contains 1588 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Feb 26, 2025, + *last release*: Mar 07, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10308,7 +10309,7 @@ This list contains 1588 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Feb 26, 2025, + *last release*: Mar 07, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10882,7 +10883,7 @@ This list contains 1588 plugins. :pypi:`pytest-splunk-addon` - *last release*: Oct 28, 2024, + *last release*: Mar 07, 2025, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -10944,6 +10945,13 @@ This list contains 1588 plugins. A pytest plugin to use sqlfluff to enable format checking of sql files. + :pypi:`pytest-sqlguard` + *last release*: Mar 06, 2025, + *status*: 4 - Beta, + *requires*: pytest>=7 + + Pytest fixture to record and check SQL Queries made by SQLAlchemy + :pypi:`pytest-squadcast` *last release*: Feb 22, 2022, *status*: 5 - Production/Stable, @@ -12457,7 +12465,7 @@ This list contains 1588 plugins. A pytest plugin to list worker statistics after a xdist run. :pypi:`pytest-xdocker` - *last release*: Jan 22, 2025, + *last release*: Mar 07, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.2 From ada9977b2add3ca49ce2c55f906c4d1266927734 Mon Sep 17 00:00:00 2001 From: Anton Zhilin Date: Sun, 9 Mar 2025 23:35:11 +0300 Subject: [PATCH 1161/1271] Prevent parametrize with scope from breaking fixture dependencies (#13249) * Prevent parametrize with scope from breaking fixture dependencies * Add myself to AUTHORS * Fix the regression test * Assert fixture value inside the test --------- Co-authored-by: Bruno Oliveira --- changelog/13248.bugfix.rst | 2 ++ src/_pytest/fixtures.py | 7 ++++++- testing/python/fixtures.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 changelog/13248.bugfix.rst diff --git a/changelog/13248.bugfix.rst b/changelog/13248.bugfix.rst new file mode 100644 index 00000000000..2ebb102fd07 --- /dev/null +++ b/changelog/13248.bugfix.rst @@ -0,0 +1,2 @@ +Fixed an issue where passing a ``scope`` in :py:func:`Metafunc.parametrize ` with ``indirect=True`` +could result in other fixtures being unable to depend on the parametrized fixture. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index dcd06c3b40a..bb50b014dd1 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -605,7 +605,12 @@ def _get_active_fixturedef( param_index = 0 scope = fixturedef._scope self._check_fixturedef_without_param(fixturedef) - self._check_scope(fixturedef, scope) + # The parametrize invocation scope only controls caching behavior while + # allowing wider-scoped fixtures to keep depending on the parametrized + # fixture. Scope control is enforced for parametrized fixtures + # by recreating the whole fixture tree on parameter change. + # Hence `fixturedef._scope`, not `scope`. + self._check_scope(fixturedef, fixturedef._scope) subrequest = SubRequest( self, scope, param, param_index, fixturedef, _ispytest=True ) diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index dc69781095b..c8d1eb23838 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -5009,3 +5009,31 @@ def test_result(): ) result = pytester.runpytest() assert result.ret == 0 + + +def test_parametrized_fixture_scope_allowed(pytester: Pytester) -> None: + """ + Make sure scope from parametrize does not affect fixture's ability to be + depended upon. + + Regression test for #13248 + """ + pytester.makepyfile( + """ + import pytest + + @pytest.fixture(scope="session") + def my_fixture(request): + return getattr(request, "param", None) + + @pytest.fixture(scope="session") + def another_fixture(my_fixture): + return my_fixture + + @pytest.mark.parametrize("my_fixture", ["a value"], indirect=True, scope="function") + def test_foo(another_fixture): + assert another_fixture == "a value" + """ + ) + result = pytester.runpytest() + result.assert_outcomes(passed=1) From 03b5a79170679a017fb58894518b167ff9be463e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 07:14:46 +0100 Subject: [PATCH 1162/1271] build(deps): Bump peter-evans/create-pull-request from 7.0.7 to 7.0.8 (#13283) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7.0.7 to 7.0.8. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/dd2324fc52d5d43c699a5636bcf19fceaa70c284...271a8d0340265f705b14b6d32b9829c1cb33d45e) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/update-plugin-list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-plugin-list.yml b/.github/workflows/update-plugin-list.yml index 3200cb174cc..c10aefa3a55 100644 --- a/.github/workflows/update-plugin-list.yml +++ b/.github/workflows/update-plugin-list.yml @@ -48,7 +48,7 @@ jobs: - name: Create Pull Request id: pr - uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e with: commit-message: '[automated] Update plugin list' author: 'pytest bot ' From 338ef90968f14e6c008ff69188b88712e6019f14 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Mar 2025 22:19:49 +0100 Subject: [PATCH 1163/1271] [pre-commit.ci] pre-commit autoupdate (#13285) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.9 → v0.9.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.9...v0.9.10) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 26c5a7f5394..be0fa02399b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.9" + rev: "v0.9.10" hooks: - id: ruff args: ["--fix"] From d149ab353adcfa67693f692e3ee235888971e744 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 11 Mar 2025 09:14:36 +0100 Subject: [PATCH 1164/1271] assorted code updates and f string migrations (#12017) * chore: setuponly - migrate to f string * chore: MockTiming - move impl to _pytest.timing * chore: fixture tests: migrate to f-strings * chore: skipping tests: migrate to f-strings * chore: junitxml tests: add more type annotations * chore: junitxml tests: introduce more typesafe helpers * add changelog * test junitxml: split the DomNode type to express the Document/Element difference * fixup: undo accidential name-mangling in the junitxml test helpers * fixup: junitxml logging test - restore validation for expected output nodes * fixup: have fake config .getini use correct types * Update changelog/12017.improvement.rst Co-authored-by: Bruno Oliveira * use contrib category for changelog * use datetime.fromisoformat instead of strptime * post rebase ruff fixes * add extra coverage for junit test helpers --------- Co-authored-by: Bruno Oliveira --- changelog/12017.contrib.rst | 7 + src/_pytest/setuponly.py | 10 +- src/_pytest/timing.py | 36 ++++ testing/conftest.py | 21 +- testing/python/fixtures.py | 42 ++-- testing/test_junitxml.py | 405 ++++++++++++++++++++---------------- testing/test_skipping.py | 16 +- 7 files changed, 305 insertions(+), 232 deletions(-) create mode 100644 changelog/12017.contrib.rst diff --git a/changelog/12017.contrib.rst b/changelog/12017.contrib.rst new file mode 100644 index 00000000000..ec1861893b3 --- /dev/null +++ b/changelog/12017.contrib.rst @@ -0,0 +1,7 @@ +Mixed internal improvements: + +* Migrate formatting to f-strings in some tests. +* Use type-safe constructs in JUnitXML tests. +* Moved`` MockTiming`` into ``_pytest.timing``. + +-- by :user:`RonnyPfannschmidt` diff --git a/src/_pytest/setuponly.py b/src/_pytest/setuponly.py index 1e887a896f5..7e6b46bcdb4 100644 --- a/src/_pytest/setuponly.py +++ b/src/_pytest/setuponly.py @@ -73,13 +73,9 @@ def _show_fixture_action( # Use smaller indentation the higher the scope: Session = 0, Package = 1, etc. scope_indent = list(reversed(Scope)).index(fixturedef._scope) tw.write(" " * 2 * scope_indent) - tw.write( - "{step} {scope} {fixture}".format( # noqa: UP032 (Readability) - step=msg.ljust(8), # align the output to TEARDOWN - scope=fixturedef.scope[0].upper(), - fixture=fixturedef.argname, - ) - ) + + scopename = fixturedef.scope[0].upper() + tw.write(f"{msg:<8} {scopename} {fixturedef.argname}") if msg == "SETUP": deps = sorted(arg for arg in fixturedef.argnames if arg != "request") diff --git a/src/_pytest/timing.py b/src/_pytest/timing.py index b23c7f69e2d..4422037a9d9 100644 --- a/src/_pytest/timing.py +++ b/src/_pytest/timing.py @@ -8,9 +8,45 @@ from __future__ import annotations +import dataclasses +from datetime import datetime from time import perf_counter from time import sleep from time import time +from typing import TYPE_CHECKING + + +if TYPE_CHECKING: + from pytest import MonkeyPatch + + +@dataclasses.dataclass +class MockTiming: + """Mocks _pytest.timing with a known object that can be used to control timing in tests + deterministically. + + pytest itself should always use functions from `_pytest.timing` instead of `time` directly. + + This then allows us more control over time during testing, if testing code also + uses `_pytest.timing` functions. + + Time is static, and only advances through `sleep` calls, thus tests might sleep over large + numbers and obtain accurate time() calls at the end, making tests reliable and instant.""" + + _current_time: float = datetime(2020, 5, 22, 14, 20, 50).timestamp() + + def sleep(self, seconds: float) -> None: + self._current_time += seconds + + def time(self) -> float: + return self._current_time + + def patch(self, monkeypatch: MonkeyPatch) -> None: + from _pytest import timing # noqa: PLW0406 + + monkeypatch.setattr(timing, "sleep", self.sleep) + monkeypatch.setattr(timing, "time", self.time) + monkeypatch.setattr(timing, "perf_counter", self.time) __all__ = ["perf_counter", "sleep", "time"] diff --git a/testing/conftest.py b/testing/conftest.py index 45a47cbdbaa..251b430e9cd 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -2,7 +2,6 @@ from __future__ import annotations from collections.abc import Generator -import dataclasses import importlib.metadata import re import sys @@ -233,24 +232,8 @@ def mock_timing(monkeypatch: MonkeyPatch): Time is static, and only advances through `sleep` calls, thus tests might sleep over large numbers and obtain accurate time() calls at the end, making tests reliable and instant. """ - - @dataclasses.dataclass - class MockTiming: - _current_time: float = 1590150050.0 - - def sleep(self, seconds: float) -> None: - self._current_time += seconds - - def time(self) -> float: - return self._current_time - - def patch(self) -> None: - from _pytest import timing - - monkeypatch.setattr(timing, "sleep", self.sleep) - monkeypatch.setattr(timing, "time", self.time) - monkeypatch.setattr(timing, "perf_counter", self.time) + from _pytest.timing import MockTiming result = MockTiming() - result.patch() + result.patch(monkeypatch) return result diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index c8d1eb23838..32453739e8c 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -2315,14 +2315,14 @@ def test_ordering_dependencies_torndown_first( ) -> None: """#226""" pytester.makepyfile( - """ + f""" import pytest values = [] - @pytest.fixture(%(param1)s) + @pytest.fixture({param1}) def arg1(request): request.addfinalizer(lambda: values.append("fin1")) values.append("new1") - @pytest.fixture(%(param2)s) + @pytest.fixture({param2}) def arg2(request, arg1): request.addfinalizer(lambda: values.append("fin2")) values.append("new2") @@ -2331,8 +2331,7 @@ def test_arg(arg2): pass def test_check(): assert values == ["new1", "new2", "fin2", "fin1"] - """ # noqa: UP031 (python syntax issues) - % locals() + """ ) reprec = pytester.inline_run("-s") reprec.assertoutcome(passed=2) @@ -3212,21 +3211,21 @@ def test_finalizer_order_on_parametrization( ) -> None: """#246""" pytester.makepyfile( - """ + f""" import pytest values = [] - @pytest.fixture(scope=%(scope)r, params=["1"]) + @pytest.fixture(scope={scope!r}, params=["1"]) def fix1(request): return request.param - @pytest.fixture(scope=%(scope)r) + @pytest.fixture(scope={scope!r}) def fix2(request, base): def cleanup_fix2(): assert not values, "base should not have been finalized" request.addfinalizer(cleanup_fix2) - @pytest.fixture(scope=%(scope)r) + @pytest.fixture(scope={scope!r}) def base(request, fix1): def cleanup_base(): values.append("fin_base") @@ -3239,8 +3238,7 @@ def test_baz(base, fix2): pass def test_other(): pass - """ # noqa: UP031 (python syntax issues) - % {"scope": scope} + """ ) reprec = pytester.inline_run("-lvs") reprec.assertoutcome(passed=3) @@ -3426,42 +3424,40 @@ class TestRequestScopeAccess: def test_setup(self, pytester: Pytester, scope, ok, error) -> None: pytester.makepyfile( - """ + f""" import pytest - @pytest.fixture(scope=%r, autouse=True) + @pytest.fixture(scope={scope!r}, autouse=True) def myscoped(request): - for x in %r: + for x in {ok.split()}: assert hasattr(request, x) - for x in %r: + for x in {error.split()}: pytest.raises(AttributeError, lambda: getattr(request, x)) assert request.session assert request.config def test_func(): pass - """ # noqa: UP031 (python syntax issues) - % (scope, ok.split(), error.split()) + """ ) reprec = pytester.inline_run("-l") reprec.assertoutcome(passed=1) def test_funcarg(self, pytester: Pytester, scope, ok, error) -> None: pytester.makepyfile( - """ + f""" import pytest - @pytest.fixture(scope=%r) + @pytest.fixture(scope={scope!r}) def arg(request): - for x in %r: + for x in {ok.split()!r}: assert hasattr(request, x) - for x in %r: + for x in {error.split()!r}: pytest.raises(AttributeError, lambda: getattr(request, x)) assert request.session assert request.config def test_func(arg): pass - """ # noqa: UP031 (python syntax issues) - % (scope, ok.split(), error.split()) + """ ) reprec = pytester.inline_run() reprec.assertoutcome(passed=1) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 5de0e6a5d7a..4145f34ab14 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1,4 +1,3 @@ -# mypy: allow-untyped-defs from __future__ import annotations from datetime import datetime @@ -6,6 +5,7 @@ import os from pathlib import Path import platform +from typing import Any from typing import cast from typing import TYPE_CHECKING from xml.dom import minidom @@ -21,6 +21,7 @@ from _pytest.reports import BaseReport from _pytest.reports import TestReport from _pytest.stash import Stash +import _pytest.timing import pytest @@ -39,7 +40,7 @@ def __init__(self, pytester: Pytester, schema: xmlschema.XMLSchema) -> None: def __call__( self, *args: str | os.PathLike[str], family: str | None = "xunit1" - ) -> tuple[RunResult, DomNode]: + ) -> tuple[RunResult, DomDocument]: if family: args = ("-o", "junit_family=" + family, *args) xml_path = self.pytester.path.joinpath("junit.xml") @@ -48,7 +49,7 @@ def __call__( with xml_path.open(encoding="utf-8") as f: self.schema.validate(f) xmldoc = minidom.parse(str(xml_path)) - return result, DomNode(xmldoc) + return result, DomDocument(xmldoc) @pytest.fixture @@ -62,78 +63,129 @@ def run_and_parse(pytester: Pytester, schema: xmlschema.XMLSchema) -> RunAndPars return RunAndParse(pytester, schema) -def assert_attr(node, **kwargs): +def assert_attr(node: minidom.Element, **kwargs: object) -> None: __tracebackhide__ = True - def nodeval(node, name): + def nodeval(node: minidom.Element, name: str) -> str | None: anode = node.getAttributeNode(name) - if anode is not None: - return anode.value + return anode.value if anode is not None else None expected = {name: str(value) for name, value in kwargs.items()} on_node = {name: nodeval(node, name) for name in expected} assert on_node == expected -class DomNode: - def __init__(self, dom): - self.__node = dom +class DomDocument: + def __init__(self, dom: minidom.Document): + self._node = dom - def __repr__(self): - return self.__node.toxml() + _node: minidom.Document | minidom.Element - def find_first_by_tag(self, tag): + def find_first_by_tag(self, tag: str) -> DomNode | None: return self.find_nth_by_tag(tag, 0) - def _by_tag(self, tag): - return self.__node.getElementsByTagName(tag) + def get_first_by_tag(self, tag: str) -> DomNode: + maybe = self.find_first_by_tag(tag) + if maybe is None: + raise LookupError(tag) + else: + return maybe + + def find_nth_by_tag(self, tag: str, n: int) -> DomNode | None: + items = self._node.getElementsByTagName(tag) + try: + nth = items[n] + except IndexError: + return None + else: + return DomNode(nth) + + def find_by_tag(self, tag: str) -> list[DomNode]: + return [DomNode(x) for x in self._node.getElementsByTagName(tag)] @property - def children(self): - return [type(self)(x) for x in self.__node.childNodes] + def children(self) -> list[DomNode]: + return [DomNode(x) for x in self._node.childNodes] @property - def get_unique_child(self): + def get_unique_child(self) -> DomNode: children = self.children assert len(children) == 1 return children[0] - def find_nth_by_tag(self, tag, n): - items = self._by_tag(tag) - try: - nth = items[n] - except IndexError: - pass - else: - return type(self)(nth) + def toxml(self) -> str: + return self._node.toxml() + + +class DomNode(DomDocument): + _node: minidom.Element + + def __init__(self, dom: minidom.Element): + self._node = dom - def find_by_tag(self, tag): - t = type(self) - return [t(x) for x in self.__node.getElementsByTagName(tag)] + def __repr__(self) -> str: + return self.toxml() - def __getitem__(self, key): - node = self.__node.getAttributeNode(key) + def __getitem__(self, key: str) -> str: + node = self._node.getAttributeNode(key) if node is not None: - return node.value + return cast(str, node.value) + else: + raise KeyError(key) - def assert_attr(self, **kwargs): + def assert_attr(self, **kwargs: object) -> None: __tracebackhide__ = True - return assert_attr(self.__node, **kwargs) - - def toxml(self): - return self.__node.toxml() + return assert_attr(self._node, **kwargs) @property - def text(self): - return self.__node.childNodes[0].wholeText + def text(self) -> str: + return cast(str, self._node.childNodes[0].wholeText) @property - def tag(self): - return self.__node.tagName + def tag(self) -> str: + return self._node.tagName - @property - def next_sibling(self): - return type(self)(self.__node.nextSibling) + +class TestJunitHelpers: + """minimal test to increase coverage for methods that are used in debugging""" + + @pytest.fixture + def document(self) -> DomDocument: + doc = minidom.parseString(""" + + + + +""") + return DomDocument(doc) + + def test_uc_root(self, document: DomDocument) -> None: + assert document.get_unique_child.tag == "root" + + def test_node_assert_attr(self, document: DomDocument) -> None: + item = document.get_first_by_tag("item") + + item.assert_attr(name="a") + + with pytest.raises(AssertionError): + item.assert_attr(missing="foo") + + def test_node_getitem(self, document: DomDocument) -> None: + item = document.get_first_by_tag("item") + assert item["name"] == "a" + + with pytest.raises(KeyError, match="missing"): + item["missing"] + + def test_node_get_first_lookup(self, document: DomDocument) -> None: + with pytest.raises(LookupError, match="missing"): + document.get_first_by_tag("missing") + + def test_node_repr(self, document: DomDocument) -> None: + item = document.get_first_by_tag("item") + + assert repr(item) == item.toxml() + assert item.toxml() == '' parametrize_families = pytest.mark.parametrize("xunit_family", ["xunit1", "xunit2"]) @@ -163,7 +215,7 @@ def test_xpass(): ) result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(name="pytest", errors=0, failures=1, skipped=2, tests=5) @parametrize_families @@ -192,7 +244,7 @@ def test_xpass(): ) result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(name="pytest", errors=1, failures=2, skipped=1, tests=5) @parametrize_families @@ -206,7 +258,7 @@ def test_pass(): """ ) result, dom = run_and_parse(family=xunit_family) - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(hostname=platform.node()) @parametrize_families @@ -221,12 +273,15 @@ def test_pass(): ) start_time = datetime.now(timezone.utc) result, dom = run_and_parse(family=xunit_family) - node = dom.find_first_by_tag("testsuite") - timestamp = datetime.strptime(node["timestamp"], "%Y-%m-%dT%H:%M:%S.%f%z") + node = dom.get_first_by_tag("testsuite") + timestamp = datetime.fromisoformat(node["timestamp"]) assert start_time <= timestamp < datetime.now(timezone.utc) def test_timing_function( - self, pytester: Pytester, run_and_parse: RunAndParse, mock_timing + self, + pytester: Pytester, + run_and_parse: RunAndParse, + mock_timing: _pytest.timing.MockTiming, ) -> None: pytester.makepyfile( """ @@ -240,9 +295,10 @@ def test_sleep(): """ ) result, dom = run_and_parse() - node = dom.find_first_by_tag("testsuite") - tnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + tnode = node.get_first_by_tag("testcase") val = tnode["time"] + assert val is not None assert float(val) == 7.0 @pytest.mark.parametrize("duration_report", ["call", "total"]) @@ -256,7 +312,7 @@ def test_junit_duration_report( # mock LogXML.node_reporter so it always sets a known duration to each test report object original_node_reporter = LogXML.node_reporter - def node_reporter_wrapper(s, report): + def node_reporter_wrapper(s: Any, report: TestReport) -> Any: report.duration = 1.0 reporter = original_node_reporter(s, report) return reporter @@ -270,8 +326,8 @@ def test_foo(): """ ) result, dom = run_and_parse("-o", f"junit_duration_report={duration_report}") - node = dom.find_first_by_tag("testsuite") - tnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + tnode = node.get_first_by_tag("testcase") val = float(tnode["time"]) if duration_report == "total": assert val == 3.0 @@ -296,11 +352,11 @@ def test_function(arg): ) result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(errors=1, tests=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="test_setup_error", name="test_function") - fnode = tnode.find_first_by_tag("error") + fnode = tnode.get_first_by_tag("error") fnode.assert_attr(message='failed on setup with "ValueError: Error reason"') assert "ValueError" in fnode.toxml() @@ -322,10 +378,10 @@ def test_function(arg): ) result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") - tnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="test_teardown_error", name="test_function") - fnode = tnode.find_first_by_tag("error") + fnode = tnode.get_first_by_tag("error") fnode.assert_attr(message='failed on teardown with "ValueError: Error reason"') assert "ValueError" in fnode.toxml() @@ -347,15 +403,15 @@ def test_function(arg): ) result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(errors=1, failures=1, tests=1) first, second = dom.find_by_tag("testcase") assert first assert second assert first != second - fnode = first.find_first_by_tag("failure") + fnode = first.get_first_by_tag("failure") fnode.assert_attr(message="Exception: Call Exception") - snode = second.find_first_by_tag("error") + snode = second.get_first_by_tag("error") snode.assert_attr( message='failed on teardown with "Exception: Teardown Exception"' ) @@ -373,11 +429,11 @@ def test_skip(): ) result, dom = run_and_parse(family=xunit_family) assert result.ret == 0 - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(skipped=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="test_skip_contains_name_reason", name="test_skip") - snode = tnode.find_first_by_tag("skipped") + snode = tnode.get_first_by_tag("skipped") snode.assert_attr(type="pytest.skip", message="hello23") @parametrize_families @@ -394,13 +450,13 @@ def test_skip(): ) result, dom = run_and_parse(family=xunit_family) assert result.ret == 0 - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(skipped=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr( classname="test_mark_skip_contains_name_reason", name="test_skip" ) - snode = tnode.find_first_by_tag("skipped") + snode = tnode.get_first_by_tag("skipped") snode.assert_attr(type="pytest.skip", message="hello24") @parametrize_families @@ -418,13 +474,13 @@ def test_skip(): ) result, dom = run_and_parse(family=xunit_family) assert result.ret == 0 - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(skipped=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr( classname="test_mark_skipif_contains_name_reason", name="test_skip" ) - snode = tnode.find_first_by_tag("skipped") + snode = tnode.get_first_by_tag("skipped") snode.assert_attr(type="pytest.skip", message="hello25") @parametrize_families @@ -441,7 +497,7 @@ def test_skip(): ) result, dom = run_and_parse(family=xunit_family) assert result.ret == 0 - node_xml = dom.find_first_by_tag("testsuite").toxml() + node_xml = dom.get_first_by_tag("testsuite").toxml() assert "bar!" not in node_xml @parametrize_families @@ -457,9 +513,9 @@ def test_method(self): ) result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(failures=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr( classname="test_classname_instance.TestClass", name="test_method" ) @@ -472,9 +528,9 @@ def test_classname_nested_dir( p.write_text("def test_func(): 0/0", encoding="utf-8") result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(failures=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="sub.test_hello", name="test_func") @parametrize_families @@ -485,11 +541,11 @@ def test_internal_error( pytester.makepyfile("def test_function(): pass") result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(errors=1, tests=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="pytest", name="internal") - fnode = tnode.find_first_by_tag("error") + fnode = tnode.get_first_by_tag("error") fnode.assert_attr(message="internal error") assert "Division" in fnode.toxml() @@ -500,9 +556,9 @@ def test_internal_error( def test_failure_function( self, pytester: Pytester, - junit_logging, + junit_logging: str, run_and_parse: RunAndParse, - xunit_family, + xunit_family: str, ) -> None: pytester.makepyfile( """ @@ -522,22 +578,22 @@ def test_fail(): "-o", f"junit_logging={junit_logging}", family=xunit_family ) assert result.ret, "Expected ret > 0" - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(failures=1, tests=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="test_failure_function", name="test_fail") - fnode = tnode.find_first_by_tag("failure") + fnode = tnode.get_first_by_tag("failure") fnode.assert_attr(message="ValueError: 42") assert "ValueError" in fnode.toxml(), "ValueError not included" if junit_logging in ["log", "all"]: - logdata = tnode.find_first_by_tag("system-out") + logdata = tnode.get_first_by_tag("system-out") log_xml = logdata.toxml() assert logdata.tag == "system-out", "Expected tag: system-out" assert "info msg" not in log_xml, "Unexpected INFO message" assert "warning msg" in log_xml, "Missing WARN message" if junit_logging in ["system-out", "out-err", "all"]: - systemout = tnode.find_first_by_tag("system-out") + systemout = tnode.get_first_by_tag("system-out") systemout_xml = systemout.toxml() assert systemout.tag == "system-out", "Expected tag: system-out" assert "info msg" not in systemout_xml, "INFO message found in system-out" @@ -545,7 +601,7 @@ def test_fail(): "Missing 'hello-stdout' in system-out" ) if junit_logging in ["system-err", "out-err", "all"]: - systemerr = tnode.find_first_by_tag("system-err") + systemerr = tnode.get_first_by_tag("system-err") systemerr_xml = systemerr.toxml() assert systemerr.tag == "system-err", "Expected tag: system-err" assert "info msg" not in systemerr_xml, "INFO message found in system-err" @@ -576,9 +632,9 @@ def test_fail(): """ ) result, dom = run_and_parse(family=xunit_family) - node = dom.find_first_by_tag("testsuite") - tnode = node.find_first_by_tag("testcase") - fnode = tnode.find_first_by_tag("failure") + node = dom.get_first_by_tag("testsuite") + tnode = node.get_first_by_tag("testcase") + fnode = tnode.get_first_by_tag("failure") fnode.assert_attr(message="AssertionError: An error\nassert 0") @parametrize_families @@ -598,15 +654,15 @@ def test_func(arg1): "-o", "junit_logging=system-out", family=xunit_family ) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(failures=3, tests=3) - - for index, char in enumerate("<&'"): - tnode = node.find_nth_by_tag("testcase", index) + tnodes = node.find_by_tag("testcase") + assert len(tnodes) == 3 + for tnode, char in zip(tnodes, "<&'"): tnode.assert_attr( classname="test_failure_escape", name=f"test_func[{char}]" ) - sysout = tnode.find_first_by_tag("system-out") + sysout = tnode.get_first_by_tag("system-out") text = sysout.text assert f"{char}\n" in text @@ -625,11 +681,11 @@ def test_hello(self): ) result, dom = run_and_parse("--junitprefix=xyz", family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(failures=1, tests=2) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="xyz.test_junit_prefixing", name="test_func") - tnode = node.find_nth_by_tag("testcase", 1) + tnode = node.find_by_tag("testcase")[1] tnode.assert_attr( classname="xyz.test_junit_prefixing.TestHello", name="test_hello" ) @@ -647,11 +703,11 @@ def test_xfail(): ) result, dom = run_and_parse(family=xunit_family) assert not result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(skipped=1, tests=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="test_xfailure_function", name="test_xfail") - fnode = tnode.find_first_by_tag("skipped") + fnode = tnode.get_first_by_tag("skipped") fnode.assert_attr(type="pytest.xfail", message="42") @parametrize_families @@ -668,11 +724,11 @@ def test_xfail(): ) result, dom = run_and_parse(family=xunit_family) assert not result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(skipped=1, tests=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="test_xfailure_marker", name="test_xfail") - fnode = tnode.find_first_by_tag("skipped") + fnode = tnode.get_first_by_tag("skipped") fnode.assert_attr(type="pytest.xfail", message="42") @pytest.mark.parametrize( @@ -694,17 +750,17 @@ def test_fail(): """ ) result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") - node = dom.find_first_by_tag("testsuite") - tnode = node.find_first_by_tag("testcase") - if junit_logging in ["system-err", "out-err", "all"]: - assert len(tnode.find_by_tag("system-err")) == 1 - else: - assert len(tnode.find_by_tag("system-err")) == 0 + node = dom.get_first_by_tag("testsuite") + tnode = node.get_first_by_tag("testcase") - if junit_logging in ["log", "system-out", "out-err", "all"]: - assert len(tnode.find_by_tag("system-out")) == 1 - else: - assert len(tnode.find_by_tag("system-out")) == 0 + has_err_logging = junit_logging in ["system-err", "out-err", "all"] + expected_err_output_len = 1 if has_err_logging else 0 + assert len(tnode.find_by_tag("system-err")) == expected_err_output_len + + has_out_logigng = junit_logging in ("log", "system-out", "out-err", "all") + expected_out_output_len = 1 if has_out_logigng else 0 + + assert len(tnode.find_by_tag("system-out")) == expected_out_output_len @parametrize_families def test_xfailure_xpass( @@ -720,9 +776,9 @@ def test_xpass(): ) result, dom = run_and_parse(family=xunit_family) # assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(skipped=0, tests=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="test_xfailure_xpass", name="test_xpass") @parametrize_families @@ -739,11 +795,11 @@ def test_xpass(): ) result, dom = run_and_parse(family=xunit_family) # assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(skipped=0, tests=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(classname="test_xfailure_xpass_strict", name="test_xpass") - fnode = tnode.find_first_by_tag("failure") + fnode = tnode.get_first_by_tag("failure") fnode.assert_attr(message="[XPASS(strict)] This needs to fail!") @parametrize_families @@ -753,10 +809,10 @@ def test_collect_error( pytester.makepyfile("syntax error") result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(errors=1, tests=1) - tnode = node.find_first_by_tag("testcase") - fnode = tnode.find_first_by_tag("error") + tnode = node.get_first_by_tag("testcase") + fnode = tnode.get_first_by_tag("error") fnode.assert_attr(message="collection failure") assert "SyntaxError" in fnode.toxml() @@ -772,8 +828,8 @@ def test_hello(): ) result, dom = run_and_parse() assert result.ret == 1 - tnode = dom.find_first_by_tag("testcase") - fnode = tnode.find_first_by_tag("failure") + tnode = dom.get_first_by_tag("testcase") + fnode = tnode.get_first_by_tag("failure") assert "hx" in fnode.toxml() def test_assertion_binchars( @@ -804,14 +860,14 @@ def test_pass(): """ ) result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") - node = dom.find_first_by_tag("testsuite") - pnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + pnode = node.get_first_by_tag("testcase") if junit_logging == "no": assert not node.find_by_tag("system-out"), ( "system-out should not be generated" ) if junit_logging == "system-out": - systemout = pnode.find_first_by_tag("system-out") + systemout = pnode.get_first_by_tag("system-out") assert "hello-stdout" in systemout.toxml(), ( "'hello-stdout' should be in system-out" ) @@ -828,14 +884,14 @@ def test_pass(): """ ) result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") - node = dom.find_first_by_tag("testsuite") - pnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + pnode = node.get_first_by_tag("testcase") if junit_logging == "no": assert not node.find_by_tag("system-err"), ( "system-err should not be generated" ) if junit_logging == "system-err": - systemerr = pnode.find_first_by_tag("system-err") + systemerr = pnode.get_first_by_tag("system-err") assert "hello-stderr" in systemerr.toxml(), ( "'hello-stderr' should be in system-err" ) @@ -857,14 +913,14 @@ def test_function(arg): """ ) result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") - node = dom.find_first_by_tag("testsuite") - pnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + pnode = node.get_first_by_tag("testcase") if junit_logging == "no": assert not node.find_by_tag("system-out"), ( "system-out should not be generated" ) if junit_logging == "system-out": - systemout = pnode.find_first_by_tag("system-out") + systemout = pnode.get_first_by_tag("system-out") assert "hello-stdout" in systemout.toxml(), ( "'hello-stdout' should be in system-out" ) @@ -887,14 +943,14 @@ def test_function(arg): """ ) result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") - node = dom.find_first_by_tag("testsuite") - pnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + pnode = node.get_first_by_tag("testcase") if junit_logging == "no": assert not node.find_by_tag("system-err"), ( "system-err should not be generated" ) if junit_logging == "system-err": - systemerr = pnode.find_first_by_tag("system-err") + systemerr = pnode.get_first_by_tag("system-err") assert "hello-stderr" in systemerr.toxml(), ( "'hello-stderr' should be in system-err" ) @@ -918,14 +974,14 @@ def test_function(arg): """ ) result, dom = run_and_parse("-o", f"junit_logging={junit_logging}") - node = dom.find_first_by_tag("testsuite") - pnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + pnode = node.get_first_by_tag("testcase") if junit_logging == "no": assert not node.find_by_tag("system-out"), ( "system-out should not be generated" ) if junit_logging == "system-out": - systemout = pnode.find_first_by_tag("system-out") + systemout = pnode.get_first_by_tag("system-out") assert "hello-stdout call" in systemout.toxml() assert "hello-stdout teardown" in systemout.toxml() @@ -945,12 +1001,12 @@ class FakeConfig: if TYPE_CHECKING: workerinput = None - def __init__(self): + def __init__(self) -> None: self.pluginmanager = self self.option = self self.stash = Stash() - def getini(self, name): + def getini(self, name: str) -> str: return "pytest" junitprefix = None @@ -989,11 +1045,11 @@ def repr_failure(self, excinfo): pytester.path.joinpath("myfile.xyz").write_text("hello", encoding="utf-8") result, dom = run_and_parse(family=xunit_family) assert result.ret - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(errors=0, failures=1, skipped=0, tests=1) - tnode = node.find_first_by_tag("testcase") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(name="myfile.xyz") - fnode = tnode.find_first_by_tag("failure") + fnode = tnode.get_first_by_tag("failure") fnode.assert_attr(message="custom item runtest failed") assert "custom item runtest failed" in fnode.toxml() @@ -1134,7 +1190,7 @@ def test_func(char): ) result, dom = run_and_parse() assert result.ret == 0 - node = dom.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testcase") node.assert_attr(name="test_func[\\x00]") @@ -1151,7 +1207,7 @@ def test_func(param): ) result, dom = run_and_parse() assert result.ret == 0 - node = dom.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testcase") node.assert_attr(classname="test_double_colon_split_function_issue469") node.assert_attr(name="test_func[double::colon]") @@ -1170,7 +1226,7 @@ def test_func(self, param): ) result, dom = run_and_parse() assert result.ret == 0 - node = dom.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testcase") node.assert_attr(classname="test_double_colon_split_method_issue469.TestClass") node.assert_attr(name="test_func[double::colon]") @@ -1218,9 +1274,9 @@ def test_record(record_property, other): """ ) result, dom = run_and_parse() - node = dom.find_first_by_tag("testsuite") - tnode = node.find_first_by_tag("testcase") - psnode = tnode.find_first_by_tag("properties") + node = dom.get_first_by_tag("testsuite") + tnode = node.get_first_by_tag("testcase") + psnode = tnode.get_first_by_tag("properties") pnodes = psnode.find_by_tag("property") pnodes[0].assert_attr(name="bar", value="1") pnodes[1].assert_attr(name="foo", value="<1") @@ -1246,10 +1302,10 @@ def test_record(record_property, other): """ ) result, dom = run_and_parse() - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") tnodes = node.find_by_tag("testcase") for tnode in tnodes: - psnode = tnode.find_first_by_tag("properties") + psnode = tnode.get_first_by_tag("properties") assert psnode, f"testcase didn't had expected properties:\n{tnode}" pnodes = psnode.find_by_tag("property") pnodes[0].assert_attr(name="bar", value="1") @@ -1268,9 +1324,9 @@ def test_record_with_same_name(record_property): """ ) result, dom = run_and_parse() - node = dom.find_first_by_tag("testsuite") - tnode = node.find_first_by_tag("testcase") - psnode = tnode.find_first_by_tag("properties") + node = dom.get_first_by_tag("testsuite") + tnode = node.get_first_by_tag("testcase") + psnode = tnode.get_first_by_tag("properties") pnodes = psnode.find_by_tag("property") pnodes[0].assert_attr(name="foo", value="bar") pnodes[1].assert_attr(name="foo", value="baz") @@ -1310,8 +1366,8 @@ def test_record(record_xml_attribute, other): """ ) result, dom = run_and_parse() - node = dom.find_first_by_tag("testsuite") - tnode = node.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testsuite") + tnode = node.get_first_by_tag("testcase") tnode.assert_attr(bar="1") tnode.assert_attr(foo="<1") result.stdout.fnmatch_lines( @@ -1373,7 +1429,7 @@ def test_x(i): """ ) _, dom = run_and_parse("-n2") - suite_node = dom.find_first_by_tag("testsuite") + suite_node = dom.get_first_by_tag("testsuite") failed = [] for case_node in suite_node.find_by_tag("testcase"): if case_node.find_first_by_tag("failure"): @@ -1469,7 +1525,7 @@ def test_pass(): result.stdout.no_fnmatch_line("*INTERNALERROR*") items = sorted( - "%(classname)s %(name)s" % x # noqa: UP031 + f"{x['classname']} {x['name']}" # dom is a DomNode not a mapping, it's not possible to ** it. for x in dom.find_by_tag("testcase") ) @@ -1564,10 +1620,11 @@ def test_func2(record_testsuite_property): ) result, dom = run_and_parse(family=xunit_family) assert result.ret == 0 - node = dom.find_first_by_tag("testsuite") - properties_node = node.find_first_by_tag("properties") - p1_node = properties_node.find_nth_by_tag("property", 0) - p2_node = properties_node.find_nth_by_tag("property", 1) + node = dom.get_first_by_tag("testsuite") + properties_node = node.get_first_by_tag("properties") + p1_node, p2_node = properties_node.find_by_tag( + "property", + )[:2] p1_node.assert_attr(name="stats", value="all good") p2_node.assert_attr(name="stats", value="10") @@ -1627,7 +1684,7 @@ def test_func(): ) result, dom = run_and_parse(family=xunit_family) assert result.ret == 0 - node = dom.find_first_by_tag("testsuite") + node = dom.get_first_by_tag("testsuite") node.assert_attr(name=expected) @@ -1643,8 +1700,8 @@ def test_skip(): """ ) _, dom = run_and_parse() - node = dom.find_first_by_tag("testcase") - snode = node.find_first_by_tag("skipped") + node = dom.get_first_by_tag("testcase") + snode = node.get_first_by_tag("skipped") assert "1 <> 2" in snode.text snode.assert_attr(message="1 <> 2") @@ -1660,8 +1717,8 @@ def test_skip(): """ ) _, dom = run_and_parse() - node = dom.find_first_by_tag("testcase") - snode = node.find_first_by_tag("skipped") + node = dom.get_first_by_tag("testcase") + snode = node.get_first_by_tag("skipped") assert "#x1B[31;1mred#x1B[0m" in snode.text snode.assert_attr(message="#x1B[31;1mred#x1B[0m") @@ -1682,8 +1739,8 @@ def test_esc(my_setup): """ ) _, dom = run_and_parse() - node = dom.find_first_by_tag("testcase") - snode = node.find_first_by_tag("error") + node = dom.get_first_by_tag("testcase") + snode = node.get_first_by_tag("error") assert "#x1B[31mred#x1B[m" in snode["message"] assert "#x1B[31mred#x1B[m" in snode.text @@ -1714,7 +1771,7 @@ def test_func(): ) result, dom = run_and_parse(family=xunit_family) assert result.ret == 0 - node = dom.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testcase") assert len(node.find_by_tag("system-err")) == 0 assert len(node.find_by_tag("system-out")) == 0 @@ -1749,7 +1806,7 @@ def test_func(): "-o", f"junit_logging={junit_logging}", family=xunit_family ) assert result.ret == 1 - node = dom.find_first_by_tag("testcase") + node = dom.get_first_by_tag("testcase") if junit_logging == "system-out": assert len(node.find_by_tag("system-err")) == 0 assert len(node.find_by_tag("system-out")) == 1 diff --git a/testing/test_skipping.py b/testing/test_skipping.py index d1a63b1d920..57113ba93d5 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -602,13 +602,12 @@ def test_xfail_raises( self, expected, actual, matchline, pytester: Pytester ) -> None: p = pytester.makepyfile( - """ + f""" import pytest - @pytest.mark.xfail(raises=%s) + @pytest.mark.xfail(raises={expected}) def test_raises(): - raise %s() - """ # noqa: UP031 (python syntax issues) - % (expected, actual) + raise {actual}() + """ ) result = pytester.runpytest(p) result.stdout.fnmatch_lines([matchline]) @@ -900,13 +899,12 @@ def test_func(): ) def test_skipif_reporting(self, pytester: Pytester, params) -> None: p = pytester.makepyfile( - test_foo=""" + test_foo=f""" import pytest - @pytest.mark.skipif(%(params)s) + @pytest.mark.skipif({params}) def test_that(): assert 0 - """ # noqa: UP031 (python syntax issues) - % dict(params=params) + """ ) result = pytester.runpytest(p, "-s", "-rs") result.stdout.fnmatch_lines(["*SKIP*1*test_foo.py*platform*", "*1 skipped*"]) From b7854561993d00b8dddf3f43ce6b042b4111fa4c Mon Sep 17 00:00:00 2001 From: jakkdl Date: Wed, 12 Mar 2025 15:10:29 +0100 Subject: [PATCH 1165/1271] fix attrs==25.2.0 compatibility --- changelog/13291.bugfix.rst | 1 + src/_pytest/assertion/util.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/13291.bugfix.rst diff --git a/changelog/13291.bugfix.rst b/changelog/13291.bugfix.rst new file mode 100644 index 00000000000..03ce06b697a --- /dev/null +++ b/changelog/13291.bugfix.rst @@ -0,0 +1 @@ +Fixed ``repr`` of ``attrs`` objects in assertion failure messages when using ``attrs>=25.2``. diff --git a/src/_pytest/assertion/util.py b/src/_pytest/assertion/util.py index 30aee185d57..c545e6cd20c 100644 --- a/src/_pytest/assertion/util.py +++ b/src/_pytest/assertion/util.py @@ -169,7 +169,7 @@ def has_default_eq( code_filename = obj.__eq__.__code__.co_filename if isattrs(obj): - return "attrs generated eq" in code_filename + return "attrs generated " in code_filename return code_filename == "" # data class return True From fc115f06ea47daa7f6bea62930c78d1e896ce92b Mon Sep 17 00:00:00 2001 From: Guillaume Gauvrit Date: Sat, 15 Mar 2025 21:34:21 +0100 Subject: [PATCH 1166/1271] Update additional projects list --- scripts/update-plugin-list.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/update-plugin-list.py b/scripts/update-plugin-list.py index 347952cc7e4..61debb44043 100644 --- a/scripts/update-plugin-list.py +++ b/scripts/update-plugin-list.py @@ -67,6 +67,7 @@ "nuts", "flask_fixture", "databricks-labs-pytester", + "tursu", } From 23e496bf62f5e3acdfc205e268947b19a7901425 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 16 Mar 2025 09:26:43 +0000 Subject: [PATCH 1167/1271] [automated] Update plugin list (#13301) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 172 ++++++++++++++++++++----------- 1 file changed, 114 insertions(+), 58 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index e8dfcc68028..6d587217dc8 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Mar 03, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Mar 15, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -161,7 +161,7 @@ This list contains 1589 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Mar 07, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Mar 14, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -213,6 +213,7 @@ This list contains 1589 plugins. :pypi:`pytest-camel-collect` Enable CamelCase-aware pytest class collection Aug 02, 2020 N/A pytest (>=2.9) :pypi:`pytest-canonical-data` A plugin which allows to compare results with canonical results, based on previous runs May 08, 2020 2 - Pre-Alpha pytest (>=3.5.0) :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A + :pypi:`pytest-capsqlalchemy` Pytest plugin to allow capturing SQLAlchemy queries. Mar 14, 2025 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest :pypi:`pytest-case` A clean, modern, wrapper for pytest.mark.parametrize Nov 25, 2024 N/A pytest<9.0.0,>=8.3.3 @@ -251,6 +252,7 @@ This list contains 1589 plugins. :pypi:`pytest-clarity` A plugin providing an alternative, colourful diff output for failing assertions. Jun 11, 2021 N/A N/A :pypi:`pytest-class-fixtures` Class as PyTest fixtures (and BDD steps) Nov 15, 2024 N/A pytest<9.0.0,>=8.3.3 :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) + :pypi:`pytest-clean-database` A pytest plugin that cleans your database up after every test. Mar 14, 2025 3 - Alpha pytest<9,>=7.0 :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Nov 08, 2024 5 - Production/Stable N/A @@ -310,6 +312,7 @@ This list contains 1589 plugins. :pypi:`pytest-cram` Run cram tests with pytest. Aug 08, 2020 N/A N/A :pypi:`pytest-crate` Manages CrateDB instances during your integration tests May 28, 2019 3 - Alpha pytest (>=4.0) :pypi:`pytest-cratedb` Manage CrateDB instances for integration tests Oct 08, 2024 4 - Beta pytest<9 + :pypi:`pytest-cratedb-reporter` A pytest plugin for reporting test results to CrateDB Mar 11, 2025 N/A pytest>=6.0.0 :pypi:`pytest-crayons` A pytest plugin for colorful print statements Oct 08, 2023 N/A pytest :pypi:`pytest-create` pytest-create Feb 15, 2023 1 - Planning N/A :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest @@ -430,7 +433,7 @@ This list contains 1589 plugins. :pypi:`pytest-docker-registry-fixtures` Pytest fixtures for testing with docker registries. Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-service` pytest plugin to start docker container Jan 03, 2024 3 - Alpha pytest (>=7.1.3) :pypi:`pytest-docker-squid-fixtures` Pytest fixtures for testing with squid. Aug 12, 2024 4 - Beta pytest - :pypi:`pytest-docker-tools` Docker integration tests for pytest Feb 17, 2022 4 - Beta pytest (>=6.0.1) + :pypi:`pytest-docker-tools` Docker integration tests for pytest Mar 15, 2025 4 - Beta pytest>=6.0.1 :pypi:`pytest-docs` Documentation tool for pytest Nov 11, 2018 4 - Beta pytest (>=3.5.0) :pypi:`pytest-docstyle` pytest plugin to run pydocstyle Mar 23, 2020 3 - Alpha N/A :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A @@ -476,15 +479,15 @@ This list contains 1589 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 Jul 25, 2024 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. Mar 03, 2025 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Mar 03, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Mar 03, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Mar 03, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Mar 03, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Mar 03, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Mar 03, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Mar 03, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Mar 03, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Mar 13, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Mar 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Mar 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Mar 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Mar 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Mar 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Mar 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Mar 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Mar 13, 2025 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) @@ -537,6 +540,7 @@ This list contains 1589 plugins. :pypi:`pytest-exploratory` Interactive console for pytest. Sep 18, 2024 N/A pytest>=6.2 :pypi:`pytest-explorer` terminal ui for exploring and running tests Aug 01, 2023 N/A N/A :pypi:`pytest-ext` pytest plugin for automation test Mar 31, 2024 N/A pytest>=5.3 + :pypi:`pytest-extended-mock` a pytest extension for easy mock setup Mar 12, 2025 N/A pytest<9.0.0,>=8.3.5 :pypi:`pytest-extensions` A collection of helpers for pytest to ease testing Aug 17, 2022 4 - Beta pytest ; extra == 'testing' :pypi:`pytest-external-blockers` a special outcome for tests that are blocked for external reasons Oct 05, 2021 N/A pytest :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A @@ -603,7 +607,7 @@ This list contains 1589 plugins. :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Aug 14, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-fly` pytest observer Feb 28, 2025 3 - Alpha pytest + :pypi:`pytest-fly` pytest runner and observer Mar 13, 2025 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) @@ -678,7 +682,7 @@ This list contains 1589 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Mar 08, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 15, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -752,7 +756,7 @@ This list contains 1589 plugins. :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.0 :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A - :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Mar 03, 2025 N/A pytest + :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Mar 09, 2025 N/A pytest :pypi:`pytest-ipywidgets` Feb 18, 2025 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Feb 24, 2025 4 - Beta pytest>=5 @@ -848,11 +852,12 @@ This list contains 1589 plugins. :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 23, 2024 3 - Alpha pytest + :pypi:`pytest-lw-realtime-result` Pytest plugin to generate realtime test results to a file Mar 13, 2025 N/A pytest>=3.5.0 :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Nov 13, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) - :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Nov 28, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 13, 2025 N/A pytest>=7.0.0 :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Oct 30, 2024 4 - Beta pytest>=6.0 :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A @@ -878,7 +883,7 @@ This list contains 1589 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Feb 19, 2025 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Mar 14, 2025 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -900,7 +905,7 @@ This list contains 1589 plugins. :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest :pypi:`pytest-mockito` Base fixtures for mockito Jul 11, 2018 4 - Beta N/A :pypi:`pytest-mockredis` An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. Jan 02, 2018 2 - Pre-Alpha N/A - :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Sep 17, 2024 N/A pytest>=1.0 + :pypi:`pytest-mock-resources` A pytest plugin for easily instantiating reproducible mock resources. Mar 10, 2025 N/A pytest>=1.0 :pypi:`pytest-mock-server` Mock server plugin for pytest Jan 09, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-mockservers` A set of fixtures to test your requests to HTTP/UDP servers Mar 31, 2020 N/A pytest (>=4.3.0) :pypi:`pytest-mocktcp` A pytest plugin for testing TCP clients Oct 11, 2022 N/A pytest @@ -974,7 +979,7 @@ This list contains 1589 plugins. :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-odoo` py.test plugin to run Odoo tests Oct 08, 2024 5 - Production/Stable pytest>=8 + :pypi:`pytest-odoo` py.test plugin to run Odoo tests Mar 12, 2025 5 - Production/Stable pytest>=8 :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) @@ -1182,7 +1187,7 @@ This list contains 1589 plugins. :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest :pypi:`pytest_repeater` py.test plugin for repeating single test multiple times. Feb 09, 2018 1 - Planning N/A :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Feb 05, 2025 5 - Production/Stable pytest - :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Apr 17, 2023 3 - Alpha pytest + :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Mar 12, 2025 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A @@ -1219,8 +1224,10 @@ This list contains 1589 plugins. :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Oct 24, 2024 5 - Production/Stable pytest :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 + :pypi:`pytest-results` Easily spot regressions in your tests. Mar 14, 2025 4 - Beta pytest :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 17, 2024 N/A pytest>=8.3.4 + :pypi:`pytest-result-sender-lyt` Default template for PDM package Mar 14, 2025 N/A pytest>=8.3.5 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Jan 19, 2025 N/A pytest>=7.0.0 @@ -1262,7 +1269,7 @@ This list contains 1589 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 07, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 12, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1274,7 +1281,7 @@ This list contains 1589 plugins. :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 Feb 01, 2024 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. Mar 07, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 12, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1284,7 +1291,7 @@ This list contains 1589 plugins. :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixtures for py.test Nov 29, 2024 5 - Production/Stable pytest :pypi:`pytest-serverless` Automatically mocks resources from serverless.yml in pytest using moto. May 09, 2022 4 - Beta N/A - :pypi:`pytest-servers` pytest servers Dec 29, 2024 3 - Alpha pytest>=6.2 + :pypi:`pytest-servers` pytest servers Mar 12, 2025 3 - Alpha pytest>=6.2 :pypi:`pytest-service` Aug 06, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-services` Services plugin for pytest testing framework Oct 30, 2020 6 - Mature N/A :pypi:`pytest-session2file` pytest-session2file (aka: pytest-session_to_file for v0.1.0 - v0.1.2) is a py.test plugin for capturing and saving to file the stdout of py.test. Jan 26, 2021 3 - Alpha pytest @@ -1365,7 +1372,7 @@ This list contains 1589 plugins. :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 19, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest :pypi:`pytest-sqlfluff` A pytest plugin to use sqlfluff to enable format checking of sql files. Dec 21, 2022 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-sqlguard` Pytest fixture to record and check SQL Queries made by SQLAlchemy Mar 06, 2025 4 - Beta pytest>=7 + :pypi:`pytest-sqlguard` Pytest fixture to record and check SQL Queries made by SQLAlchemy Mar 11, 2025 4 - Beta pytest>=7 :pypi:`pytest-squadcast` Pytest report plugin for Squadcast Feb 22, 2022 5 - Production/Stable pytest :pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A pytest>=6.2.0 :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest @@ -1531,7 +1538,7 @@ This list contains 1589 plugins. :pypi:`pytest-unmarked` Run only unmarked tests Aug 27, 2019 5 - Production/Stable N/A :pypi:`pytest-unordered` Test equality of unordered collections in pytest Jul 05, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-unstable` Set a test as unstable to return 0 even if it failed Sep 27, 2022 4 - Beta N/A - :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Apr 08, 2024 4 - Beta pytest>7.3.2 + :pypi:`pytest-unused-fixtures` A pytest plugin to list unused fixtures after a test run. Mar 15, 2025 4 - Beta pytest>7.3.2 :pypi:`pytest-upload-report` pytest-upload-report is a plugin for pytest that upload your test report for test results. Jun 18, 2021 5 - Production/Stable N/A :pypi:`pytest-utils` Some helpers for pytest. Feb 02, 2023 4 - Beta pytest (>=7.0.0,<8.0.0) :pypi:`pytest-vagrant` A py.test plugin providing access to vagrant. Sep 07, 2021 5 - Production/Stable pytest @@ -1581,7 +1588,7 @@ This list contains 1589 plugins. :pypi:`pytest-xdist-debug-for-graingert` pytest xdist plugin for distributed testing and loop-on-failing modes Jul 24, 2019 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) - :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Apr 16, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Mar 15, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Mar 07, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A @@ -1597,7 +1604,7 @@ This list contains 1589 plugins. :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-xstress` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 - :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. May 29, 2023 4 - Beta pytest (>=2.8.1) + :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. Mar 12, 2025 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. Dec 15, 2024 4 - Beta pytest>=7.2.2 :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-fei` a pytest yaml allure package Feb 09, 2025 N/A pytest @@ -2217,7 +2224,7 @@ This list contains 1589 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Mar 03, 2025, + *last release*: Mar 15, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2518,7 +2525,7 @@ This list contains 1589 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Mar 07, 2025, + *last release*: Mar 14, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -2881,6 +2888,13 @@ This list contains 1589 plugins. A plugin that replays pRNG state on failure. + :pypi:`pytest-capsqlalchemy` + *last release*: Mar 14, 2025, + *status*: 4 - Beta, + *requires*: N/A + + Pytest plugin to allow capturing SQLAlchemy queries. + :pypi:`pytest-capture-deprecatedwarnings` *last release*: Apr 30, 2019, *status*: N/A, @@ -3147,6 +3161,13 @@ This list contains 1589 plugins. Easy quality control for CLDF datasets using pytest + :pypi:`pytest-clean-database` + *last release*: Mar 14, 2025, + *status*: 3 - Alpha, + *requires*: pytest<9,>=7.0 + + A pytest plugin that cleans your database up after every test. + :pypi:`pytest-cleanslate` *last release*: Sep 04, 2024, *status*: N/A, @@ -3560,6 +3581,13 @@ This list contains 1589 plugins. Manage CrateDB instances for integration tests + :pypi:`pytest-cratedb-reporter` + *last release*: Mar 11, 2025, + *status*: N/A, + *requires*: pytest>=6.0.0 + + A pytest plugin for reporting test results to CrateDB + :pypi:`pytest-crayons` *last release*: Oct 08, 2023, *status*: N/A, @@ -4401,9 +4429,9 @@ This list contains 1589 plugins. Pytest fixtures for testing with squid. :pypi:`pytest-docker-tools` - *last release*: Feb 17, 2022, + *last release*: Mar 15, 2025, *status*: 4 - Beta, - *requires*: pytest (>=6.0.1) + *requires*: pytest>=6.0.1 Docker integration tests for pytest @@ -4723,63 +4751,63 @@ This list contains 1589 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Mar 03, 2025, + *last release*: Mar 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -5149,6 +5177,13 @@ This list contains 1589 plugins. pytest plugin for automation test + :pypi:`pytest-extended-mock` + *last release*: Mar 12, 2025, + *status*: N/A, + *requires*: pytest<9.0.0,>=8.3.5 + + a pytest extension for easy mock setup + :pypi:`pytest-extensions` *last release*: Aug 17, 2022, *status*: 4 - Beta, @@ -5612,11 +5647,11 @@ This list contains 1589 plugins. A pytest plugin in order to provide logs via fluentbit :pypi:`pytest-fly` - *last release*: Feb 28, 2025, + *last release*: Mar 13, 2025, *status*: 3 - Alpha, *requires*: pytest - pytest observer + pytest runner and observer :pypi:`pytest-flyte` *last release*: May 03, 2021, @@ -6137,7 +6172,7 @@ This list contains 1589 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 08, 2025, + *last release*: Mar 15, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6655,7 +6690,7 @@ This list contains 1589 plugins. THIS PROJECT IS ABANDONED :pypi:`pytest-ipynb2` - *last release*: Mar 03, 2025, + *last release*: Mar 09, 2025, *status*: N/A, *requires*: pytest @@ -7326,6 +7361,13 @@ This list contains 1589 plugins. A pytest plugin for end-to-end testing of language servers + :pypi:`pytest-lw-realtime-result` + *last release*: Mar 13, 2025, + *status*: N/A, + *requires*: pytest>=3.5.0 + + Pytest plugin to generate realtime test results to a file + :pypi:`pytest-manual-marker` *last release*: Aug 04, 2022, *status*: 3 - Alpha, @@ -7355,7 +7397,7 @@ This list contains 1589 plugins. Test your markdown docs with pytest :pypi:`pytest-markdown-docs` - *last release*: Nov 28, 2024, + *last release*: Mar 13, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -7537,7 +7579,7 @@ This list contains 1589 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Feb 19, 2025, + *last release*: Mar 14, 2025, *status*: N/A, *requires*: N/A @@ -7691,7 +7733,7 @@ This list contains 1589 plugins. An in-memory mock of a Redis server that runs in a separate thread. This is to be used for unit-tests that require a Redis database. :pypi:`pytest-mock-resources` - *last release*: Sep 17, 2024, + *last release*: Mar 10, 2025, *status*: N/A, *requires*: pytest>=1.0 @@ -8209,7 +8251,7 @@ This list contains 1589 plugins. A pytest plugin for simplifying ODC database tests :pypi:`pytest-odoo` - *last release*: Oct 08, 2024, + *last release*: Mar 12, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=8 @@ -9665,7 +9707,7 @@ This list contains 1589 plugins. Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests :pypi:`pytest-repo-health` - *last release*: Apr 17, 2023, + *last release*: Mar 12, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -9923,6 +9965,13 @@ This list contains 1589 plugins. A pytest plugin that records the start, end, and result information of each use case in a log file + :pypi:`pytest-results` + *last release*: Mar 14, 2025, + *status*: 4 - Beta, + *requires*: pytest + + Easily spot regressions in your tests. + :pypi:`pytest-result-sender` *last release*: Apr 20, 2023, *status*: N/A, @@ -9937,6 +9986,13 @@ This list contains 1589 plugins. Default template for PDM package + :pypi:`pytest-result-sender-lyt` + *last release*: Mar 14, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + Default template for PDM package + :pypi:`pytest-resume` *last release*: Apr 22, 2023, *status*: 4 - Beta, @@ -10225,7 +10281,7 @@ This list contains 1589 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Mar 07, 2025, + *last release*: Mar 12, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10309,7 +10365,7 @@ This list contains 1589 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Mar 07, 2025, + *last release*: Mar 12, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10379,7 +10435,7 @@ This list contains 1589 plugins. Automatically mocks resources from serverless.yml in pytest using moto. :pypi:`pytest-servers` - *last release*: Dec 29, 2024, + *last release*: Mar 12, 2025, *status*: 3 - Alpha, *requires*: pytest>=6.2 @@ -10946,7 +11002,7 @@ This list contains 1589 plugins. A pytest plugin to use sqlfluff to enable format checking of sql files. :pypi:`pytest-sqlguard` - *last release*: Mar 06, 2025, + *last release*: Mar 11, 2025, *status*: 4 - Beta, *requires*: pytest>=7 @@ -12108,7 +12164,7 @@ This list contains 1589 plugins. Set a test as unstable to return 0 even if it failed :pypi:`pytest-unused-fixtures` - *last release*: Apr 08, 2024, + *last release*: Mar 15, 2025, *status*: 4 - Beta, *requires*: pytest>7.3.2 @@ -12458,7 +12514,7 @@ This list contains 1589 plugins. pytest plugin helps to reproduce failures for particular xdist node :pypi:`pytest-xdist-worker-stats` - *last release*: Apr 16, 2024, + *last release*: Mar 15, 2025, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -12570,9 +12626,9 @@ This list contains 1589 plugins. :pypi:`pytest-xvfb` - *last release*: May 29, 2023, + *last release*: Mar 12, 2025, *status*: 4 - Beta, - *requires*: pytest (>=2.8.1) + *requires*: pytest>=2.8.1 A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. From 21257689662aee77fe237fb070d006be9f4d6fe6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 06:49:22 +0100 Subject: [PATCH 1168/1271] build(deps): Bump anyio[trio] in /testing/plugins_integration (#13303) Bumps [anyio[trio]](https://github.com/agronholm/anyio) from 4.8.0 to 4.9.0. - [Release notes](https://github.com/agronholm/anyio/releases) - [Changelog](https://github.com/agronholm/anyio/blob/master/docs/versionhistory.rst) - [Commits](https://github.com/agronholm/anyio/compare/4.8.0...4.9.0) --- updated-dependencies: - dependency-name: anyio[trio] dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 437df4dc2d1..bf0a87129eb 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,4 +1,4 @@ -anyio[trio]==4.8.0 +anyio[trio]==4.9.0 django==5.1.7 pytest-asyncio==0.25.3 pytest-bdd==8.1.0 From 9666efad756bd9fa123d7ffc69ad34ef0b2f7c71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Mar 2025 06:50:00 +0100 Subject: [PATCH 1169/1271] build(deps): Bump pytest-xvfb in /testing/plugins_integration (#13302) Bumps [pytest-xvfb](https://github.com/The-Compiler/pytest-xvfb) from 3.0.0 to 3.1.1. - [Changelog](https://github.com/The-Compiler/pytest-xvfb/blob/master/CHANGELOG.rst) - [Commits](https://github.com/The-Compiler/pytest-xvfb/compare/v3.0.0...v3.1.1) --- updated-dependencies: - dependency-name: pytest-xvfb dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index bf0a87129eb..66ed13a4b8a 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -12,4 +12,4 @@ pytest-sugar==1.0.0 pytest-trio==0.8.0 pytest-twisted==1.14.3 twisted==24.11.0 -pytest-xvfb==3.0.0 +pytest-xvfb==3.1.1 From e34fc6205a7c3397378e0d9a35ee2e7cfd531d9b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 21 Mar 2025 13:31:58 +0100 Subject: [PATCH 1170/1271] [pre-commit.ci] pre-commit autoupdate (#13306) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.9.10 → v0.11.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.10...v0.11.0) - [github.com/woodruffw/zizmor-pre-commit: v1.4.1 → v1.5.1](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.4.1...v1.5.1) * [lint] Put noqa in pyproject.toml or locally if possible Co-authored-by: Pierre Sassoulas --- .pre-commit-config.yaml | 4 ++-- pyproject.toml | 4 ++++ src/_pytest/raises_group.py | 18 +++++++----------- testing/_py/test_local.py | 2 +- testing/code/test_source.py | 11 ++++------- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index be0fa02399b..56ee45b4c61 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.9.10" + rev: "v0.11.0" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.4.1 + rev: v1.5.1 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs diff --git a/pyproject.toml b/pyproject.toml index 263e0c23836..0cbf0a26027 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -167,6 +167,10 @@ lint.per-file-ignores."src/_pytest/_py/**/*.py" = [ lint.per-file-ignores."src/_pytest/_version.py" = [ "I001", ] +# can't be disabled on a line-by-line basis in file +lint.per-file-ignores."testing/code/test_source.py" = [ + "F841", +] lint.per-file-ignores."testing/python/approx.py" = [ "B015", ] diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises_group.py index 51ab8aafaf4..010b8b9f629 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises_group.py @@ -119,12 +119,9 @@ def _check_raw_type( def is_fully_escaped(s: str) -> bool: # we know we won't compile with re.VERBOSE, so whitespace doesn't need to be escaped metacharacters = "{}()+.*?^$[]" - - for i, c in enumerate(s): - if c in metacharacters and (i == 0 or s[i - 1] != "\\"): - return False - - return True + return not any( + c in metacharacters and (i == 0 or s[i - 1] != "\\") for (i, c) in enumerate(s) + ) def unescape(s: str) -> str: @@ -1198,8 +1195,7 @@ def possible_match(results: ResultHolder, used: set[int] | None = None) -> bool: curr_row = len(used) if curr_row == len(results.results): return True - - for i, val in enumerate(results.results[curr_row]): - if val is None and i not in used and possible_match(results, used | {i}): - return True - return False + return any( + val is None and i not in used and possible_match(results, used | {i}) + for (i, val) in enumerate(results.results[curr_row]) + ) diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 461b0b599c1..03a828c64f0 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -215,7 +215,7 @@ def test_visit_filterfunc_is_string(self, path1, fil): lst = [] for i in path1.visit(fil): lst.append(i.relto(path1)) - assert len(lst), 2 + assert len(lst), 2 # noqa: PLC1802,RUF040 assert "sampledir" in lst assert "otherdir" in lst diff --git a/testing/code/test_source.py b/testing/code/test_source.py index 843233fe21e..321372d4b59 100644 --- a/testing/code/test_source.py +++ b/testing/code/test_source.py @@ -1,21 +1,19 @@ # mypy: allow-untyped-defs -# flake8: noqa -# disable flake check on this file because some constructs are strange -# or redundant on purpose and can't be disable on a line-by-line basis +from __future__ import annotations + import inspect import linecache +from pathlib import Path import sys import textwrap -from pathlib import Path from typing import Any -from typing import Dict -import pytest from _pytest._code import Code from _pytest._code import Frame from _pytest._code import getfslineno from _pytest._code import Source from _pytest.pathlib import import_path +import pytest def test_source_str_function() -> None: @@ -464,7 +462,6 @@ def test_comment_in_statement() -> None: def test_source_with_decorator() -> None: """Test behavior with Source / Code().source with regard to decorators.""" - from _pytest.compat import get_real_func @pytest.mark.foo def deco_mark(): From 8e772b90d409729e38863dc2e3bbc23b1e1ae3f4 Mon Sep 17 00:00:00 2001 From: Nick Murphy Date: Sat, 22 Mar 2025 15:55:01 -0400 Subject: [PATCH 1171/1271] Specify minimum requirements for dependencies (#13317) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Specifies minimum allowed versions of `colorama`, `iniconfig`, and `packaging`, and bumps the minimum requirement of `exceptiongroup` to no longer be a release candidate. This specifies minimum allowed versions that are several years old, but these can be changed to be more recent. ## Motivation [`uv`](https://docs.astral.sh/uv/) has multiple dependency [resolution strategies](https://docs.astral.sh/uv/concepts/resolution/#resolution-strategy): - `lowest` will install the lowest allowed version for _all_ dependencies, both direct and indirect (transitive). - `lowest-direct` will use the lowest compatible versions for all _direct_ dependencies, while using the latest compatible versions for all other dependencies. Up until now, `pytest` has not specified the minimum allowed versions of multiple dependencies in `pyproject.toml`. When I ran `uv pip install pytest==8.3.5 --resolution=lowest` in a fresh virtual environment, it installed `packaging==14.0` (released in 2014 👀) and `iniconfig==0.1` (released in 2010 😅). It's a fairly common practice in the scientific pythoniverse to run tests against the oldest versions of dependencies. In practice, using `uv`'s `lowest` dependency resolution strategy results the first release of certain indirect dependencies being installed, like `v0.0.0.1`. Specifying lower bounds will make it a lot more practical for `pytest` users to test against the oldest allowed versions of both indirect and direct dependencies. --- changelog/13317.packaging.rst | 4 ++++ pyproject.toml | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 changelog/13317.packaging.rst diff --git a/changelog/13317.packaging.rst b/changelog/13317.packaging.rst new file mode 100644 index 00000000000..94171cb1ef3 --- /dev/null +++ b/changelog/13317.packaging.rst @@ -0,0 +1,4 @@ +Specified minimum allowed versions of ``colorama``, ``iniconfig``, +and ``packaging``; and bumped the minimum allowed version +of ``exceptiongroup`` for ``python_version<'3.11'`` from a release +candidate to a full release. diff --git a/pyproject.toml b/pyproject.toml index 0cbf0a26027..c7db5947cf4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,10 +46,10 @@ dynamic = [ "version", ] dependencies = [ - "colorama; sys_platform=='win32'", - "exceptiongroup>=1.0.0rc8; python_version<'3.11'", - "iniconfig", - "packaging", + "colorama>=0.4; sys_platform=='win32'", + "exceptiongroup>=1; python_version<'3.11'", + "iniconfig>=1", + "packaging>=20", "pluggy>=1.5,<2", "pygments>=2.7.2", "tomli>=1; python_version<'3.11'", From 252cf3bf8f568e5a7a8b97e7cf1c2b98824c64bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 23 Mar 2025 18:12:04 +0100 Subject: [PATCH 1172/1271] [automated] Update plugin list (#13323) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 200 ++++++++++++++++++++++++------- 1 file changed, 156 insertions(+), 44 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6d587217dc8..3e653676d69 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.2 :pypi:`pytest-argus` pyest results colection plugin Jun 24, 2021 5 - Production/Stable pytest (>=6.2.4) + :pypi:`pytest-argus-server` A plugin that provides a running Argus API server for tests Mar 20, 2025 4 - Beta pytest>=6.2.0 :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 Dec 20, 2023 4 - Beta N/A @@ -107,7 +108,7 @@ This list contains 1596 plugins. :pypi:`pytest-assertions` Pytest Assertions Apr 27, 2022 N/A N/A :pypi:`pytest-assertutil` pytest-assertutil May 10, 2019 N/A N/A :pypi:`pytest-assert-utils` Useful assertion utilities for use with pytest Apr 14, 2022 3 - Alpha N/A - :pypi:`pytest-assist` load testing library Jun 24, 2024 N/A pytest + :pypi:`pytest-assist` load testing library Mar 17, 2025 N/A pytest :pypi:`pytest-assume` A pytest plugin that allows multiple failures per test Jun 24, 2021 N/A pytest (>=2.7) :pypi:`pytest-assurka` A pytest plugin for Assurka Studio Aug 04, 2022 N/A N/A :pypi:`pytest-ast-back-to-python` A plugin for pytest devs to view how assertion rewriting recodes the AST Sep 29, 2019 4 - Beta N/A @@ -118,7 +119,7 @@ This list contains 1596 plugins. :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Jan 28, 2025 4 - Beta pytest<9,>=8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Mar 15, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Mar 16, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -161,7 +162,7 @@ This list contains 1596 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Mar 14, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Mar 22, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -213,7 +214,7 @@ This list contains 1596 plugins. :pypi:`pytest-camel-collect` Enable CamelCase-aware pytest class collection Aug 02, 2020 N/A pytest (>=2.9) :pypi:`pytest-canonical-data` A plugin which allows to compare results with canonical results, based on previous runs May 08, 2020 2 - Pre-Alpha pytest (>=3.5.0) :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A - :pypi:`pytest-capsqlalchemy` Pytest plugin to allow capturing SQLAlchemy queries. Mar 14, 2025 4 - Beta N/A + :pypi:`pytest-capsqlalchemy` Pytest plugin to allow capturing SQLAlchemy queries. Mar 19, 2025 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest :pypi:`pytest-case` A clean, modern, wrapper for pytest.mark.parametrize Nov 25, 2024 N/A pytest<9.0.0,>=8.3.3 @@ -231,7 +232,7 @@ This list contains 1596 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Feb 13, 2025 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Mar 18, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-checkdocs` check the README when running tests Apr 30, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -239,9 +240,11 @@ This list contains 1596 plugins. :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<9,>=7.0 :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Jun 10, 2024 N/A N/A :pypi:`pytest-check-mk` pytest plugin to test Check_MK checks Nov 19, 2015 4 - Beta pytest + :pypi:`pytest-checkpoint` Restore a checkpoint in pytest Mar 22, 2025 N/A pytest>=8.3.5 :pypi:`pytest-check-requirements` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-ch-framework` My pytest framework Apr 17, 2024 N/A pytest==8.0.1 :pypi:`pytest-chic-report` Simple pytest plugin for generating and sending report to messengers. Nov 01, 2024 N/A pytest>=6.0 + :pypi:`pytest-chinesereport` Mar 19, 2025 4 - Beta pytest>=3.5.0 :pypi:`pytest-choose` Provide the pytest with the ability to collect use cases based on rules in text files Feb 04, 2024 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_cid` Compare data structures containing matching CIDs of different versions and encoding Sep 01, 2023 4 - Beta pytest >= 5.0, < 7.0 @@ -268,6 +271,7 @@ This list contains 1596 plugins. :pypi:`pytest-cmake-presets` Execute CMake Presets via pytest Dec 26, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) + :pypi:`pytest-cocotb` Pytest plugin to integrate Cocotb Mar 15, 2025 5 - Production/Stable pytest; extra == "test" :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A @@ -433,7 +437,7 @@ This list contains 1596 plugins. :pypi:`pytest-docker-registry-fixtures` Pytest fixtures for testing with docker registries. Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-service` pytest plugin to start docker container Jan 03, 2024 3 - Alpha pytest (>=7.1.3) :pypi:`pytest-docker-squid-fixtures` Pytest fixtures for testing with squid. Aug 12, 2024 4 - Beta pytest - :pypi:`pytest-docker-tools` Docker integration tests for pytest Mar 15, 2025 4 - Beta pytest>=6.0.1 + :pypi:`pytest-docker-tools` Docker integration tests for pytest Mar 16, 2025 4 - Beta pytest>=6.0.1 :pypi:`pytest-docs` Documentation tool for pytest Nov 11, 2018 4 - Beta pytest (>=3.5.0) :pypi:`pytest-docstyle` pytest plugin to run pydocstyle Mar 23, 2020 3 - Alpha N/A :pypi:`pytest-doctest-custom` A py.test plugin for customizing string representations of doctest results. Jul 25, 2016 4 - Beta N/A @@ -460,7 +464,7 @@ This list contains 1596 plugins. :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A - :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Sep 11, 2024 5 - Production/Stable pytest>=4.6 + :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Mar 18, 2025 5 - Production/Stable pytest>=4.6 :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A @@ -607,7 +611,7 @@ This list contains 1596 plugins. :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Aug 14, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-fly` pytest runner and observer Mar 13, 2025 3 - Alpha pytest + :pypi:`pytest-fly` pytest runner and observer Mar 20, 2025 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) @@ -622,6 +626,7 @@ This list contains 1596 plugins. :pypi:`pytest-freeze-reqs` Check if requirement files are frozen Apr 29, 2021 N/A N/A :pypi:`pytest-frozen-uuids` Deterministically frozen UUID's for your tests Apr 17, 2022 N/A pytest (>=3.0) :pypi:`pytest-func-cov` Pytest plugin for measuring function coverage Apr 15, 2021 3 - Alpha pytest (>=5) + :pypi:`pytest-funcnodes` Testing plugin for funcnodes Mar 19, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-funparam` An alternative way to parametrize test cases. Dec 02, 2021 4 - Beta pytest >=4.6.0 :pypi:`pytest-fv` pytest extensions to support running functional-verification jobs Feb 27, 2025 N/A pytest :pypi:`pytest-fxa` pytest plugin for Firefox Accounts Aug 28, 2018 5 - Production/Stable N/A @@ -638,7 +643,7 @@ This list contains 1596 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Feb 20, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Mar 21, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -682,7 +687,7 @@ This list contains 1596 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Mar 15, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 22, 2025 3 - Alpha pytest==8.3.4 :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` Sep 23, 2024 N/A N/A @@ -731,7 +736,7 @@ This list contains 1596 plugins. :pypi:`pytest-info-collector` pytest plugin to collect information from tests May 26, 2019 3 - Alpha N/A :pypi:`pytest-info-plugin` Get executed interface information in pytest interface automation framework Sep 14, 2023 N/A N/A :pypi:`pytest-informative-node` display more node ininformation. Apr 25, 2019 4 - Beta N/A - :pypi:`pytest-infrahouse` A set of fixtures to use with pytest Mar 06, 2025 4 - Beta pytest~=8.3 + :pypi:`pytest-infrahouse` A set of fixtures to use with pytest Mar 18, 2025 4 - Beta pytest~=8.3 :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-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 @@ -818,6 +823,7 @@ This list contains 1596 plugins. :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-leo-interface` Pytest extension tool for leo projects. Mar 19, 2025 N/A N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Oct 01, 2024 4 - Beta N/A @@ -831,6 +837,7 @@ This list contains 1596 plugins. :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. Nov 23, 2023 4 - Beta pytest >=6.1 :pypi:`pytest-live` Live results for pytest Mar 08, 2020 N/A pytest + :pypi:`pytest-llmeval` A pytest plugin to evaluate/benchmark LLM prompts Mar 19, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-local-badge` Generate local badges (shields) reporting your test suite status. Jan 15, 2023 N/A pytest (>=6.1.0) :pypi:`pytest-localftpserver` A PyTest plugin which provides an FTP fixture for your tests May 19, 2024 5 - Production/Stable pytest :pypi:`pytest-localserver` pytest plugin to test server connections locally. Oct 06, 2024 4 - Beta N/A @@ -853,6 +860,7 @@ This list contains 1596 plugins. :pypi:`pytest-loop` pytest plugin for looping tests Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 23, 2024 3 - Alpha pytest :pypi:`pytest-lw-realtime-result` Pytest plugin to generate realtime test results to a file Mar 13, 2025 N/A pytest>=3.5.0 + :pypi:`pytest-manifest` PyTest plugin for recording and asserting against a manifest file Mar 18, 2025 N/A pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Nov 13, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) @@ -957,7 +965,7 @@ This list contains 1596 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Nov 28, 2024 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Mar 21, 2025 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Aug 05, 2024 N/A N/A @@ -1041,6 +1049,7 @@ This list contains 1596 plugins. :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) + :pypi:`pytest-phoenix-interface` Pytest extension tool for phoenix projects. Mar 19, 2025 N/A N/A :pypi:`pytest-picked` Run the tests related to the changed files Nov 06, 2024 N/A pytest>=3.7.0 :pypi:`pytest-pickle-cache` A pytest plugin for caching test results using pickle. Feb 17, 2025 N/A pytest>=7 :pypi:`pytest-pigeonhole` Jun 25, 2018 5 - Production/Stable pytest (>=3.4) @@ -1082,7 +1091,7 @@ This list contains 1596 plugins. :pypi:`pytest-porcochu` Show surprise when tests are passing Nov 28, 2024 5 - Production/Stable N/A :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Feb 23, 2025 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 19, 2025 5 - Production/Stable pytest>=6.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-powerpack` A plugin containing extra batteries for pytest Jan 04, 2025 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) @@ -1136,7 +1145,7 @@ This list contains 1596 plugins. :pypi:`pytest-pyvenv` A package for create venv in tests Feb 27, 2024 N/A pytest ; extra == 'test' :pypi:`pytest-pyvista` Pytest-pyvista package Sep 29, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-qanova` A pytest plugin to collect test information Sep 05, 2024 3 - Alpha pytest - :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Feb 11, 2025 5 - Production/Stable pytest<9.0.0,>=7.2.2 + :pypi:`pytest-qaseio` Pytest plugin for Qase.io integration Mar 18, 2025 5 - Production/Stable pytest<9.0.0,>=7.2.2 :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 14, 2024 5 - Production/Stable pytest>=6.0 @@ -1192,7 +1201,7 @@ This list contains 1596 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Feb 19, 2025 N/A pytest>=8.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Mar 20, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1228,12 +1237,13 @@ This list contains 1596 plugins. :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 17, 2024 N/A pytest>=8.3.4 :pypi:`pytest-result-sender-lyt` Default template for PDM package Mar 14, 2025 N/A pytest>=8.3.5 + :pypi:`pytest-result-sender-misszhang` Default template for PDM package Mar 21, 2025 N/A pytest>=8.3.5 :pypi:`pytest-resume` A Pytest plugin to resuming from the last run test Apr 22, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-rethinkdb` A RethinkDB plugin for pytest. Jul 24, 2016 4 - Beta N/A :pypi:`pytest-retry` Adds the ability to retry flaky tests in CI environments Jan 19, 2025 N/A pytest>=7.0.0 :pypi:`pytest-retry-class` A pytest plugin to rerun entire class on failure Nov 24, 2024 N/A pytest>=5.3 :pypi:`pytest-reusable-testcases` Apr 28, 2023 N/A N/A - :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Feb 27, 2025 4 - Beta pytest<9,>=7.0 + :pypi:`pytest-revealtype-injector` Pytest plugin for replacing reveal_type() calls inside test functions with static and runtime type checking result comparison, for confirming type annotation validity. Mar 18, 2025 4 - Beta pytest<9,>=7.0 :pypi:`pytest-reverse` Pytest plugin to reverse test order. Oct 25, 2024 5 - Production/Stable pytest :pypi:`pytest-rich` Leverage rich for richer test session output Dec 12, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-richer` Pytest plugin providing a Rich based reporter. Oct 27, 2023 3 - Alpha pytest @@ -1266,10 +1276,11 @@ This list contains 1596 plugins. :pypi:`pytest-salt-runtests-bridge` Simple PyTest Plugin For Salt's Test Suite Specifically Dec 05, 2019 4 - Beta pytest (>=4.1) :pypi:`pytest-sample-argvalues` A utility function to help choose a random sample from your argvalues in pytest. May 07, 2024 N/A pytest :pypi:`pytest-sanic` a pytest plugin for Sanic Oct 25, 2021 N/A pytest (>=5.2) + :pypi:`pytest-sanitizer` A pytest plugin to sanitize output for LLMs (personal tool, no warranty or liability) Mar 16, 2025 3 - Alpha pytest>=6.0.0 :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 12, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 22, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1281,7 +1292,7 @@ This list contains 1596 plugins. :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 Feb 01, 2024 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. Mar 12, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 22, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1323,7 +1334,7 @@ This list contains 1596 plugins. :pypi:`pytest-slow` A pytest plugin to skip \`@pytest.mark.slow\` tests by default. Sep 28, 2021 N/A N/A :pypi:`pytest-slowest-first` Sort tests by their last duration, slowest first Dec 11, 2022 4 - Beta N/A :pypi:`pytest-slow-first` Prioritize running the slowest tests first. Jan 30, 2024 4 - Beta pytest >=3.5.0 - :pypi:`pytest-slow-last` Run tests in order of execution time (faster tests first) Dec 10, 2022 4 - Beta pytest (>=3.5.0) + :pypi:`pytest-slow-last` Run tests in order of execution time (faster tests first) Mar 16, 2025 4 - Beta pytest>=3.5.0 :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A @@ -1349,7 +1360,7 @@ This list contains 1596 plugins. :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest - :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Feb 23, 2020 4 - Beta pytest + :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Mar 21, 2025 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. Aug 04, 2024 N/A pytest; extra == "test" :pypi:`pytest-spec2md` Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. Apr 10, 2024 N/A pytest>7.0 @@ -1364,7 +1375,7 @@ This list contains 1596 plugins. :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 Mar 07, 2025 N/A pytest<8,>5.4.0 - :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Jan 03, 2025 N/A N/A + :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 19, 2025 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 @@ -1447,6 +1458,7 @@ This list contains 1596 plugins. :pypi:`pytest-testpluggy` set your encoding Jan 07, 2022 N/A pytest :pypi:`pytest-testrail` pytest plugin for creating TestRail runs and adding results Aug 27, 2020 N/A pytest (>=3.6) :pypi:`pytest-testrail2` A pytest plugin to upload results to TestRail. Feb 10, 2023 N/A pytest (<8.0,>=7.2.0) + :pypi:`pytest-testrail-api` TestRail Api Python Client Mar 17, 2025 N/A pytest :pypi:`pytest-testrail-api-client` TestRail Api Python Client Dec 14, 2021 N/A pytest :pypi:`pytest-testrail-appetize` pytest plugin for creating TestRail runs and adding results Sep 29, 2021 N/A N/A :pypi:`pytest-testrail-client` pytest plugin for Testrail Sep 29, 2020 5 - Production/Stable N/A @@ -1581,6 +1593,7 @@ This list contains 1596 plugins. :pypi:`pytest-win32consoletitle` Pytest progress in console title (Win32 only) Aug 08, 2021 N/A N/A :pypi:`pytest-winnotify` Windows tray notifications for py.test results. Apr 22, 2016 N/A N/A :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-wiretap` \`pytest\` plugin for recording call stacks Mar 18, 2025 N/A pytest :pypi:`pytest-with-docker` pytest with docker helpers. Nov 09, 2021 N/A pytest :pypi:`pytest-workaround-12888` forces an import of readline early in the process to work around pytest bug #12888 Jan 15, 2025 N/A N/A :pypi:`pytest-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Mar 18, 2024 5 - Production/Stable pytest >=7.0.0 @@ -1630,6 +1643,7 @@ This list contains 1596 plugins. :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest :pypi:`pytest-zy` 接口自动化测试框架 Mar 24, 2024 N/A pytest~=7.2.0 + :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Mar 22, 2025 4 - Beta pytest>=8.3.5 =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -2090,6 +2104,13 @@ This list contains 1596 plugins. pyest results colection plugin + :pypi:`pytest-argus-server` + *last release*: Mar 20, 2025, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A plugin that provides a running Argus API server for tests + :pypi:`pytest-arraydiff` *last release*: Nov 27, 2023, *status*: 4 - Beta, @@ -2147,7 +2168,7 @@ This list contains 1596 plugins. Useful assertion utilities for use with pytest :pypi:`pytest-assist` - *last release*: Jun 24, 2024, + *last release*: Mar 17, 2025, *status*: N/A, *requires*: pytest @@ -2224,7 +2245,7 @@ This list contains 1596 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Mar 15, 2025, + *last release*: Mar 16, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2525,7 +2546,7 @@ This list contains 1596 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Mar 14, 2025, + *last release*: Mar 22, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -2889,7 +2910,7 @@ This list contains 1596 plugins. A plugin that replays pRNG state on failure. :pypi:`pytest-capsqlalchemy` - *last release*: Mar 14, 2025, + *last release*: Mar 19, 2025, *status*: 4 - Beta, *requires*: N/A @@ -3015,7 +3036,7 @@ This list contains 1596 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Feb 13, 2025, + *last release*: Mar 18, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -3070,6 +3091,13 @@ This list contains 1596 plugins. pytest plugin to test Check_MK checks + :pypi:`pytest-checkpoint` + *last release*: Mar 22, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + Restore a checkpoint in pytest + :pypi:`pytest-check-requirements` *last release*: Feb 20, 2024, *status*: N/A, @@ -3091,6 +3119,13 @@ This list contains 1596 plugins. Simple pytest plugin for generating and sending report to messengers. + :pypi:`pytest-chinesereport` + *last release*: Mar 19, 2025, + *status*: 4 - Beta, + *requires*: pytest>=3.5.0 + + + :pypi:`pytest-choose` *last release*: Feb 04, 2024, *status*: N/A, @@ -3273,6 +3308,13 @@ This list contains 1596 plugins. PyTest plugin for testing Smart Contracts for Ethereum blockchain. + :pypi:`pytest-cocotb` + *last release*: Mar 15, 2025, + *status*: 5 - Production/Stable, + *requires*: pytest; extra == "test" + + Pytest plugin to integrate Cocotb + :pypi:`pytest_codeblocks` *last release*: Sep 17, 2023, *status*: 5 - Production/Stable, @@ -4429,7 +4471,7 @@ This list contains 1596 plugins. Pytest fixtures for testing with squid. :pypi:`pytest-docker-tools` - *last release*: Mar 15, 2025, + *last release*: Mar 16, 2025, *status*: 4 - Beta, *requires*: pytest>=6.0.1 @@ -4618,7 +4660,7 @@ This list contains 1596 plugins. :pypi:`pytest-durations` - *last release*: Sep 11, 2024, + *last release*: Mar 18, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=4.6 @@ -5647,7 +5689,7 @@ This list contains 1596 plugins. A pytest plugin in order to provide logs via fluentbit :pypi:`pytest-fly` - *last release*: Mar 13, 2025, + *last release*: Mar 20, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -5751,6 +5793,13 @@ This list contains 1596 plugins. Pytest plugin for measuring function coverage + :pypi:`pytest-funcnodes` + *last release*: Mar 19, 2025, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + Testing plugin for funcnodes + :pypi:`pytest-funparam` *last release*: Dec 02, 2021, *status*: 4 - Beta, @@ -5864,7 +5913,7 @@ This list contains 1596 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Feb 20, 2025, + *last release*: Mar 21, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6172,7 +6221,7 @@ This list contains 1596 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 15, 2025, + *last release*: Mar 22, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.4 @@ -6515,7 +6564,7 @@ This list contains 1596 plugins. display more node ininformation. :pypi:`pytest-infrahouse` - *last release*: Mar 06, 2025, + *last release*: Mar 18, 2025, *status*: 4 - Beta, *requires*: pytest~=8.3 @@ -7123,6 +7172,13 @@ This list contains 1596 plugins. A simple plugin to use with pytest + :pypi:`pytest-leo-interface` + *last release*: Mar 19, 2025, + *status*: N/A, + *requires*: N/A + + Pytest extension tool for leo projects. + :pypi:`pytest-level` *last release*: Oct 21, 2019, *status*: N/A, @@ -7214,6 +7270,13 @@ This list contains 1596 plugins. Live results for pytest + :pypi:`pytest-llmeval` + *last release*: Mar 19, 2025, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + A pytest plugin to evaluate/benchmark LLM prompts + :pypi:`pytest-local-badge` *last release*: Jan 15, 2023, *status*: N/A, @@ -7368,6 +7431,13 @@ This list contains 1596 plugins. Pytest plugin to generate realtime test results to a file + :pypi:`pytest-manifest` + *last release*: Mar 18, 2025, + *status*: N/A, + *requires*: pytest + + PyTest plugin for recording and asserting against a manifest file + :pypi:`pytest-manual-marker` *last release*: Aug 04, 2022, *status*: 3 - Alpha, @@ -8097,7 +8167,7 @@ This list contains 1596 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Nov 28, 2024, + *last release*: Mar 21, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -8684,6 +8754,13 @@ This list contains 1596 plugins. pytest plugin to test Python examples in Markdown using phmdoctest. + :pypi:`pytest-phoenix-interface` + *last release*: Mar 19, 2025, + *status*: N/A, + *requires*: N/A + + Pytest extension tool for phoenix projects. + :pypi:`pytest-picked` *last release*: Nov 06, 2024, *status*: N/A, @@ -8972,7 +9049,7 @@ This list contains 1596 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: Feb 23, 2025, + *last release*: Mar 19, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6.2 @@ -9350,7 +9427,7 @@ This list contains 1596 plugins. A pytest plugin to collect test information :pypi:`pytest-qaseio` - *last release*: Feb 11, 2025, + *last release*: Mar 18, 2025, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=7.2.2 @@ -9742,7 +9819,7 @@ This list contains 1596 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Feb 19, 2025, + *last release*: Mar 20, 2025, *status*: N/A, *requires*: pytest>=8.0.0 @@ -9993,6 +10070,13 @@ This list contains 1596 plugins. Default template for PDM package + :pypi:`pytest-result-sender-misszhang` + *last release*: Mar 21, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + Default template for PDM package + :pypi:`pytest-resume` *last release*: Apr 22, 2023, *status*: 4 - Beta, @@ -10029,7 +10113,7 @@ This list contains 1596 plugins. :pypi:`pytest-revealtype-injector` - *last release*: Feb 27, 2025, + *last release*: Mar 18, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=7.0 @@ -10259,6 +10343,13 @@ This list contains 1596 plugins. a pytest plugin for Sanic + :pypi:`pytest-sanitizer` + *last release*: Mar 16, 2025, + *status*: 3 - Alpha, + *requires*: pytest>=6.0.0 + + A pytest plugin to sanitize output for LLMs (personal tool, no warranty or liability) + :pypi:`pytest-sanity` *last release*: Dec 07, 2020, *status*: N/A, @@ -10281,7 +10372,7 @@ This list contains 1596 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Mar 12, 2025, + *last release*: Mar 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10365,7 +10456,7 @@ This list contains 1596 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Mar 12, 2025, + *last release*: Mar 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10659,9 +10750,9 @@ This list contains 1596 plugins. Prioritize running the slowest tests first. :pypi:`pytest-slow-last` - *last release*: Dec 10, 2022, + *last release*: Mar 16, 2025, *status*: 4 - Beta, - *requires*: pytest (>=3.5.0) + *requires*: pytest>=3.5.0 Run tests in order of execution time (faster tests first) @@ -10841,7 +10932,7 @@ This list contains 1596 plugins. Test-ordering plugin for pytest :pypi:`pytest-spark` - *last release*: Feb 23, 2020, + *last release*: Mar 21, 2025, *status*: 4 - Beta, *requires*: pytest @@ -10946,7 +11037,7 @@ This list contains 1596 plugins. A Dynamic test tool for Splunk Apps and Add-ons :pypi:`pytest-splunk-addon-ui-smartx` - *last release*: Jan 03, 2025, + *last release*: Mar 19, 2025, *status*: N/A, *requires*: N/A @@ -11526,6 +11617,13 @@ This list contains 1596 plugins. A pytest plugin to upload results to TestRail. + :pypi:`pytest-testrail-api` + *last release*: Mar 17, 2025, + *status*: N/A, + *requires*: pytest + + TestRail Api Python Client + :pypi:`pytest-testrail-api-client` *last release*: Dec 14, 2021, *status*: N/A, @@ -12464,6 +12562,13 @@ This list contains 1596 plugins. A pytest plugin for programmatically using wiremock in integration tests + :pypi:`pytest-wiretap` + *last release*: Mar 18, 2025, + *status*: N/A, + *requires*: pytest + + \`pytest\` plugin for recording call stacks + :pypi:`pytest-with-docker` *last release*: Nov 09, 2021, *status*: N/A, @@ -12806,3 +12911,10 @@ This list contains 1596 plugins. *requires*: pytest~=7.2.0 接口自动化测试框架 + + :pypi:`tursu` + *last release*: Mar 22, 2025, + *status*: 4 - Beta, + *requires*: pytest>=8.3.5 + + 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. From 544f58995d03580e74890a8668802b285082a901 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Mar 2025 22:11:36 +0100 Subject: [PATCH 1173/1271] [pre-commit.ci] pre-commit autoupdate (#13325) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.0 → v0.11.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.0...v0.11.2) - [github.com/woodruffw/zizmor-pre-commit: v1.5.1 → v1.5.2](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.5.1...v1.5.2) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 56ee45b4c61..3741df6f51b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.0" + rev: "v0.11.2" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.5.1 + rev: v1.5.2 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs From 134b759e5def7fd2fd4c74bd2a4f00a4b56e5425 Mon Sep 17 00:00:00 2001 From: John Litborn <11260241+jakkdl@users.noreply.github.com> Date: Sat, 29 Mar 2025 14:08:12 +0100 Subject: [PATCH 1174/1271] raisesgroup followups (#13279) * raisesgroup followups * renames src/_pytest/raises_group.py to src/_pytest/raises.py * moves pytest.raises from src/_pytest/python_api.py to src/_pytest/raises.py * adds several newsfragments that should've been bundled with #13192 * add more detailed error message if you try to do RaisesGroup((ValueError, TypeError)) * mess around with ValueError vs TypeError on invalid expected exception * revert change in behaviour if raises has a type mismatch * add check example to raises, fix test after behaviour revert * made args to AbstractMatcher, RaisesExc and RaisesGroup pos/kw-only --------- Co-authored-by: Ran Benita Co-authored-by: Bruno Oliveira Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/13192.feature.1.rst | 1 + changelog/13192.feature.2.rst | 1 + changelog/13192.feature.rst | 1 + src/_pytest/mark/structures.py | 2 +- src/_pytest/python_api.py | 237 ------------ src/_pytest/{raises_group.py => raises.py} | 396 +++++++++++++++++++-- src/_pytest/skipping.py | 2 +- src/pytest/__init__.py | 6 +- testing/code/test_excinfo.py | 5 +- testing/python/raises.py | 30 +- testing/python/raises_group.py | 41 ++- testing/test_warning_types.py | 2 +- testing/typing_raises_group.py | 10 +- 13 files changed, 425 insertions(+), 309 deletions(-) create mode 100644 changelog/13192.feature.1.rst create mode 100644 changelog/13192.feature.2.rst create mode 100644 changelog/13192.feature.rst rename src/_pytest/{raises_group.py => raises.py} (75%) diff --git a/changelog/13192.feature.1.rst b/changelog/13192.feature.1.rst new file mode 100644 index 00000000000..71fb06f7d70 --- /dev/null +++ b/changelog/13192.feature.1.rst @@ -0,0 +1 @@ +:func:`pytest.raises` will now print a helpful string diff if matching fails and the match parameter has ``^`` and ``$`` and is otherwise escaped. diff --git a/changelog/13192.feature.2.rst b/changelog/13192.feature.2.rst new file mode 100644 index 00000000000..0ffa0e1496a --- /dev/null +++ b/changelog/13192.feature.2.rst @@ -0,0 +1 @@ +You can now pass :func:`with pytest.raises(check=fn): `, where ``fn`` is a function which takes a raised exception and returns a boolean. The ``raises`` fails if no exception was raised (as usual), passes if an exception is raised and ``fn`` returns ``True`` (as well as ``match`` and the type matching, if specified, which are checked before), and propagates the exception if ``fn`` returns ``False`` (which likely also fails the test). diff --git a/changelog/13192.feature.rst b/changelog/13192.feature.rst new file mode 100644 index 00000000000..97f31ce233c --- /dev/null +++ b/changelog/13192.feature.rst @@ -0,0 +1 @@ +:func:`pytest.raises` will now raise a warning when passing an empty string to ``match``, as this will match against any value. Use ``match="^$"`` if you want to check that an exception has no message. diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 81fed875ca0..7a49b1a9b0c 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -28,7 +28,7 @@ from _pytest.deprecated import check_ispytest from _pytest.deprecated import MARKED_FIXTURE from _pytest.outcomes import fail -from _pytest.raises_group import AbstractRaises +from _pytest.raises import AbstractRaises from _pytest.scope import _ScopeName from _pytest.warning_types import PytestUnknownMarkWarning diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 74ddd73005b..af078e25256 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -1,7 +1,6 @@ # mypy: allow-untyped-defs from __future__ import annotations -from collections.abc import Callable from collections.abc import Collection from collections.abc import Mapping from collections.abc import Sequence @@ -10,23 +9,14 @@ import math from numbers import Complex import pprint -import re import sys from typing import Any -from typing import overload from typing import TYPE_CHECKING -from typing import TypeVar - -from _pytest._code import ExceptionInfo -from _pytest.outcomes import fail -from _pytest.raises_group import RaisesExc if TYPE_CHECKING: from numpy import ndarray - E = TypeVar("E", bound=BaseException, default=BaseException) - def _compare_approx( full_object: object, @@ -778,230 +768,3 @@ def _as_numpy_array(obj: object) -> ndarray | None: elif hasattr(obj, "__array__") or hasattr("obj", "__array_interface__"): return np.asarray(obj) return None - - -# builtin pytest.raises helper -# FIXME: This should probably me moved to 'src/_pytest.raises_group.py' -# (and rename the file to 'raises.py') -# since it's much more closely tied to those than to the other stuff in this file. - - -@overload -def raises( - expected_exception: type[E] | tuple[type[E], ...], - *, - match: str | re.Pattern[str] | None = ..., - check: Callable[[E], bool] = ..., -) -> RaisesExc[E]: ... - - -@overload -def raises( - *, - match: str | re.Pattern[str], - # If exception_type is not provided, check() must do any typechecks itself. - check: Callable[[BaseException], bool] = ..., -) -> RaisesExc[BaseException]: ... - - -@overload -def raises(*, check: Callable[[BaseException], bool]) -> RaisesExc[BaseException]: ... - - -@overload -def raises( - expected_exception: type[E] | tuple[type[E], ...], - func: Callable[..., Any], - *args: Any, - **kwargs: Any, -) -> ExceptionInfo[E]: ... - - -def raises( - expected_exception: type[E] | tuple[type[E], ...] | None = None, - *args: Any, - **kwargs: Any, -) -> RaisesExc[BaseException] | ExceptionInfo[E]: - r"""Assert that a code block/function call raises an exception type, or one of its subclasses. - - :param expected_exception: - The expected exception type, or a tuple if one of multiple possible - exception types are expected. Note that subclasses of the passed exceptions - will also match. - - :kwparam str | re.Pattern[str] | None match: - If specified, a string containing a regular expression, - or a regular expression object, that is tested against the string - representation of the exception and its :pep:`678` `__notes__` - using :func:`re.search`. - - To match a literal string that may contain :ref:`special characters - `, the pattern can first be escaped with :func:`re.escape`. - - (This is only used when ``pytest.raises`` is used as a context manager, - and passed through to the function otherwise. - When using ``pytest.raises`` as a function, you can use: - ``pytest.raises(Exc, func, match="passed on").match("my pattern")``.) - - Use ``pytest.raises`` as a context manager, which will capture the exception of the given - type, or any of its subclasses:: - - >>> import pytest - >>> with pytest.raises(ZeroDivisionError): - ... 1/0 - - If the code block does not raise the expected exception (:class:`ZeroDivisionError` in the example - above), or no exception at all, the check will fail instead. - - You can also use the keyword argument ``match`` to assert that the - exception matches a text or regex:: - - >>> with pytest.raises(ValueError, match='must be 0 or None'): - ... raise ValueError("value must be 0 or None") - - >>> with pytest.raises(ValueError, match=r'must be \d+$'): - ... raise ValueError("value must be 42") - - The ``match`` argument searches the formatted exception string, which includes any - `PEP-678 `__ ``__notes__``: - - >>> with pytest.raises(ValueError, match=r"had a note added"): # doctest: +SKIP - ... e = ValueError("value must be 42") - ... e.add_note("had a note added") - ... raise e - - The context manager produces an :class:`ExceptionInfo` object which can be used to inspect the - details of the captured exception:: - - >>> with pytest.raises(ValueError) as exc_info: - ... raise ValueError("value must be 42") - >>> assert exc_info.type is ValueError - >>> assert exc_info.value.args[0] == "value must be 42" - - .. warning:: - - Given that ``pytest.raises`` matches subclasses, be wary of using it to match :class:`Exception` like this:: - - # Careful, this will catch ANY exception raised. - with pytest.raises(Exception): - some_function() - - Because :class:`Exception` is the base class of almost all exceptions, it is easy for this to hide - real bugs, where the user wrote this expecting a specific exception, but some other exception is being - raised due to a bug introduced during a refactoring. - - Avoid using ``pytest.raises`` to catch :class:`Exception` unless certain that you really want to catch - **any** exception raised. - - .. note:: - - When using ``pytest.raises`` as a context manager, it's worthwhile to - note that normal context manager rules apply and that the exception - raised *must* be the final line in the scope of the context manager. - Lines of code after that, within the scope of the context manager will - not be executed. For example:: - - >>> value = 15 - >>> with pytest.raises(ValueError) as exc_info: - ... if value > 10: - ... raise ValueError("value must be <= 10") - ... assert exc_info.type is ValueError # This will not execute. - - Instead, the following approach must be taken (note the difference in - scope):: - - >>> with pytest.raises(ValueError) as exc_info: - ... if value > 10: - ... raise ValueError("value must be <= 10") - ... - >>> assert exc_info.type is ValueError - - **Expecting exception groups** - - When expecting exceptions wrapped in :exc:`BaseExceptionGroup` or - :exc:`ExceptionGroup`, you should instead use :class:`pytest.RaisesGroup`. - - **Using with** ``pytest.mark.parametrize`` - - When using :ref:`pytest.mark.parametrize ref` - it is possible to parametrize tests such that - some runs raise an exception and others do not. - - See :ref:`parametrizing_conditional_raising` for an example. - - .. seealso:: - - :ref:`assertraises` for more examples and detailed discussion. - - **Legacy form** - - It is possible to specify a callable by passing a to-be-called lambda:: - - >>> raises(ZeroDivisionError, lambda: 1/0) - - - or you can specify an arbitrary callable with arguments:: - - >>> def f(x): return 1/x - ... - >>> raises(ZeroDivisionError, f, 0) - - >>> raises(ZeroDivisionError, f, x=0) - - - The form above is fully supported but discouraged for new code because the - context manager form is regarded as more readable and less error-prone. - - .. note:: - Similar to caught exception objects in Python, explicitly clearing - local references to returned ``ExceptionInfo`` objects can - help the Python interpreter speed up its garbage collection. - - Clearing those references breaks a reference cycle - (``ExceptionInfo`` --> caught exception --> frame stack raising - the exception --> current frame stack --> local variables --> - ``ExceptionInfo``) which makes Python keep all objects referenced - from that cycle (including all local variables in the current - frame) alive until the next cyclic garbage collection run. - More detailed information can be found in the official Python - documentation for :ref:`the try statement `. - """ - __tracebackhide__ = True - - if not args: - if set(kwargs) - {"match", "check", "expected_exception"}: - msg = "Unexpected keyword arguments passed to pytest.raises: " - msg += ", ".join(sorted(kwargs)) - msg += "\nUse context-manager form instead?" - raise TypeError(msg) - - if expected_exception is None: - return RaisesExc(**kwargs) - return RaisesExc(expected_exception, **kwargs) - - if not expected_exception: - raise ValueError( - f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. " - f"Raising exceptions is already understood as failing the test, so you don't need " - f"any special code to say 'this should never raise an exception'." - ) - func = args[0] - if not callable(func): - raise TypeError(f"{func!r} object (type: {type(func)}) must be callable") - with RaisesExc(expected_exception) as excinfo: - func(*args[1:], **kwargs) - try: - return excinfo - finally: - del excinfo - - -# note: RaisesExc/RaisesGroup uses fail() internally, so this alias -# indicates (to [internal] plugins?) that `pytest.raises` will -# raise `_pytest.outcomes.Failed`, where -# `outcomes.Failed is outcomes.fail.Exception is raises.Exception` -# note: this is *not* the same as `_pytest.main.Failed` -# note: mypy does not recognize this attribute, and it's not possible -# to use a protocol/decorator like the others in outcomes due to -# https://github.com/python/mypy/issues/18715 -raises.Exception = fail.Exception # type: ignore[attr-defined] diff --git a/src/_pytest/raises_group.py b/src/_pytest/raises.py similarity index 75% rename from src/_pytest/raises_group.py rename to src/_pytest/raises.py index 010b8b9f629..2eba53bf10b 100644 --- a/src/_pytest/raises_group.py +++ b/src/_pytest/raises.py @@ -43,6 +43,9 @@ default=BaseException, covariant=True, ) + + # Use short name because it shows up in docs. + E = TypeVar("E", bound=BaseException, default=BaseException) else: from typing import TypeVar @@ -66,6 +69,248 @@ _REGEX_NO_FLAGS = re.compile(r"").flags +# pytest.raises helper +@overload +def raises( + expected_exception: type[E] | tuple[type[E], ...], + *, + match: str | re.Pattern[str] | None = ..., + check: Callable[[E], bool] = ..., +) -> RaisesExc[E]: ... + + +@overload +def raises( + *, + match: str | re.Pattern[str], + # If exception_type is not provided, check() must do any typechecks itself. + check: Callable[[BaseException], bool] = ..., +) -> RaisesExc[BaseException]: ... + + +@overload +def raises(*, check: Callable[[BaseException], bool]) -> RaisesExc[BaseException]: ... + + +@overload +def raises( + expected_exception: type[E] | tuple[type[E], ...], + func: Callable[..., Any], + *args: Any, + **kwargs: Any, +) -> ExceptionInfo[E]: ... + + +def raises( + expected_exception: type[E] | tuple[type[E], ...] | None = None, + *args: Any, + **kwargs: Any, +) -> RaisesExc[BaseException] | ExceptionInfo[E]: + r"""Assert that a code block/function call raises an exception type, or one of its subclasses. + + :param expected_exception: + The expected exception type, or a tuple if one of multiple possible + exception types are expected. Note that subclasses of the passed exceptions + will also match. + + This is not a required parameter, you may opt to only use ``match`` and/or + ``check`` for verifying the raised exception. + + :kwparam str | re.Pattern[str] | None match: + If specified, a string containing a regular expression, + or a regular expression object, that is tested against the string + representation of the exception and its :pep:`678` `__notes__` + using :func:`re.search`. + + To match a literal string that may contain :ref:`special characters + `, the pattern can first be escaped with :func:`re.escape`. + + (This is only used when ``pytest.raises`` is used as a context manager, + and passed through to the function otherwise. + When using ``pytest.raises`` as a function, you can use: + ``pytest.raises(Exc, func, match="passed on").match("my pattern")``.) + + :kwparam Callable[[BaseException], bool] check: + + .. versionadded:: 8.4 + + If specified, a callable that will be called with the exception as a parameter + after checking the type and the match regex if specified. + If it returns ``True`` it will be considered a match, if not it will + be considered a failed match. + + + Use ``pytest.raises`` as a context manager, which will capture the exception of the given + type, or any of its subclasses:: + + >>> import pytest + >>> with pytest.raises(ZeroDivisionError): + ... 1/0 + + If the code block does not raise the expected exception (:class:`ZeroDivisionError` in the example + above), or no exception at all, the check will fail instead. + + You can also use the keyword argument ``match`` to assert that the + exception matches a text or regex:: + + >>> with pytest.raises(ValueError, match='must be 0 or None'): + ... raise ValueError("value must be 0 or None") + + >>> with pytest.raises(ValueError, match=r'must be \d+$'): + ... raise ValueError("value must be 42") + + The ``match`` argument searches the formatted exception string, which includes any + `PEP-678 `__ ``__notes__``: + + >>> with pytest.raises(ValueError, match=r"had a note added"): # doctest: +SKIP + ... e = ValueError("value must be 42") + ... e.add_note("had a note added") + ... raise e + + The ``check`` argument, if provided, must return True when passed the raised exception + for the match to be successful, otherwise an :exc:`AssertionError` is raised. + + >>> import errno + >>> with pytest.raises(OSError, check=lambda e: e.errno == errno.EACCES): + ... raise OSError(errno.EACCES, "no permission to view") + + The context manager produces an :class:`ExceptionInfo` object which can be used to inspect the + details of the captured exception:: + + >>> with pytest.raises(ValueError) as exc_info: + ... raise ValueError("value must be 42") + >>> assert exc_info.type is ValueError + >>> assert exc_info.value.args[0] == "value must be 42" + + .. warning:: + + Given that ``pytest.raises`` matches subclasses, be wary of using it to match :class:`Exception` like this:: + + # Careful, this will catch ANY exception raised. + with pytest.raises(Exception): + some_function() + + Because :class:`Exception` is the base class of almost all exceptions, it is easy for this to hide + real bugs, where the user wrote this expecting a specific exception, but some other exception is being + raised due to a bug introduced during a refactoring. + + Avoid using ``pytest.raises`` to catch :class:`Exception` unless certain that you really want to catch + **any** exception raised. + + .. note:: + + When using ``pytest.raises`` as a context manager, it's worthwhile to + note that normal context manager rules apply and that the exception + raised *must* be the final line in the scope of the context manager. + Lines of code after that, within the scope of the context manager will + not be executed. For example:: + + >>> value = 15 + >>> with pytest.raises(ValueError) as exc_info: + ... if value > 10: + ... raise ValueError("value must be <= 10") + ... assert exc_info.type is ValueError # This will not execute. + + Instead, the following approach must be taken (note the difference in + scope):: + + >>> with pytest.raises(ValueError) as exc_info: + ... if value > 10: + ... raise ValueError("value must be <= 10") + ... + >>> assert exc_info.type is ValueError + + **Expecting exception groups** + + When expecting exceptions wrapped in :exc:`BaseExceptionGroup` or + :exc:`ExceptionGroup`, you should instead use :class:`pytest.RaisesGroup`. + + **Using with** ``pytest.mark.parametrize`` + + When using :ref:`pytest.mark.parametrize ref` + it is possible to parametrize tests such that + some runs raise an exception and others do not. + + See :ref:`parametrizing_conditional_raising` for an example. + + .. seealso:: + + :ref:`assertraises` for more examples and detailed discussion. + + **Legacy form** + + It is possible to specify a callable by passing a to-be-called lambda:: + + >>> raises(ZeroDivisionError, lambda: 1/0) + + + or you can specify an arbitrary callable with arguments:: + + >>> def f(x): return 1/x + ... + >>> raises(ZeroDivisionError, f, 0) + + >>> raises(ZeroDivisionError, f, x=0) + + + The form above is fully supported but discouraged for new code because the + context manager form is regarded as more readable and less error-prone. + + .. note:: + Similar to caught exception objects in Python, explicitly clearing + local references to returned ``ExceptionInfo`` objects can + help the Python interpreter speed up its garbage collection. + + Clearing those references breaks a reference cycle + (``ExceptionInfo`` --> caught exception --> frame stack raising + the exception --> current frame stack --> local variables --> + ``ExceptionInfo``) which makes Python keep all objects referenced + from that cycle (including all local variables in the current + frame) alive until the next cyclic garbage collection run. + More detailed information can be found in the official Python + documentation for :ref:`the try statement `. + """ + __tracebackhide__ = True + + if not args: + if set(kwargs) - {"match", "check", "expected_exception"}: + msg = "Unexpected keyword arguments passed to pytest.raises: " + msg += ", ".join(sorted(kwargs)) + msg += "\nUse context-manager form instead?" + raise TypeError(msg) + + if expected_exception is None: + return RaisesExc(**kwargs) + return RaisesExc(expected_exception, **kwargs) + + if not expected_exception: + raise ValueError( + f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. " + f"Raising exceptions is already understood as failing the test, so you don't need " + f"any special code to say 'this should never raise an exception'." + ) + func = args[0] + if not callable(func): + raise TypeError(f"{func!r} object (type: {type(func)}) must be callable") + with RaisesExc(expected_exception) as excinfo: + func(*args[1:], **kwargs) + try: + return excinfo + finally: + del excinfo + + +# note: RaisesExc/RaisesGroup uses fail() internally, so this alias +# indicates (to [internal] plugins?) that `pytest.raises` will +# raise `_pytest.outcomes.Failed`, where +# `outcomes.Failed is outcomes.fail.Exception is raises.Exception` +# note: this is *not* the same as `_pytest.main.Failed` +# note: mypy does not recognize this attribute, and it's not possible +# to use a protocol/decorator like the others in outcomes due to +# https://github.com/python/mypy/issues/18715 +raises.Exception = fail.Exception # type: ignore[attr-defined] + + def _match_pattern(match: Pattern[str]) -> str | Pattern[str]: """Helper function to remove redundant `re.compile` calls when printing regex""" return match.pattern if match.flags == _REGEX_NO_FLAGS else match @@ -139,6 +384,7 @@ class AbstractRaises(ABC, Generic[BaseExcT_co]): def __init__( self, + *, match: str | Pattern[str] | None, check: Callable[[BaseExcT_co], bool] | None, ) -> None: @@ -217,9 +463,13 @@ def _parse_exc( f"generic argument specific nested exceptions has to be checked " f"with `RaisesGroup`." ) - not_a = exc.__name__ if isinstance(exc, type) else type(exc).__name__ - msg = f"expected exception must be {expected}, not {not_a}" - raise TypeError(msg) + # unclear if the Type/ValueError distinction is even helpful here + msg = f"expected exception must be {expected}, not " + if isinstance(exc, type): + raise ValueError(msg + f"{exc.__name__!r}") + if isinstance(exc, BaseException): + raise TypeError(msg + f"an exception instance ({type(exc).__name__})") + raise TypeError(msg + repr(type(exc).__name__)) @property def fail_reason(self) -> str | None: @@ -294,13 +544,29 @@ class RaisesExc(AbstractRaises[BaseExcT_co_default]): """ .. versionadded:: 8.4 - Helper class to be used together with RaisesGroup when you want to specify requirements on sub-exceptions. + + This is the class constructed when calling :func:`pytest.raises`, but may be used + directly as a helper class with :class:`RaisesGroup` when you want to specify + requirements on sub-exceptions. You don't need this if you only want to specify the type, since :class:`RaisesGroup` accepts ``type[BaseException]``. - The type is checked with :func:`isinstance`, and does not need to be an exact match. - If that is wanted you can use the ``check`` parameter. + :param type[BaseException] | tuple[type[BaseException]] | None expected_exception: + The expected type, or one of several possible types. + May be ``None`` in order to only make use of ``match`` and/or ``check`` + + The type is checked with :func:`isinstance`, and does not need to be an exact match. + If that is wanted you can use the ``check`` parameter. + + :kwparam str | Pattern[str] match + A regex to match. + + :kwparam Callable[[BaseException], bool] check: + If specified, a callable that will be called with the exception as a parameter + after checking the type and the match regex if specified. + If it returns ``True`` it will be considered a match, if not it will + be considered a failed match. :meth:`RaisesExc.matches` can also be used standalone to check individual exceptions. @@ -326,6 +592,8 @@ def __init__( expected_exception: ( type[BaseExcT_co_default] | tuple[type[BaseExcT_co_default], ...] ), + /, + *, match: str | Pattern[str] | None = ..., check: Callable[[BaseExcT_co_default], bool] | None = ..., ) -> None: ... @@ -333,6 +601,7 @@ def __init__( @overload def __init__( self: RaisesExc[BaseException], # Give E a value. + /, *, match: str | Pattern[str] | None, # If exception_type is not provided, check() must do any typechecks itself. @@ -340,17 +609,19 @@ def __init__( ) -> None: ... @overload - def __init__(self, *, check: Callable[[BaseException], bool]) -> None: ... + def __init__(self, /, *, check: Callable[[BaseException], bool]) -> None: ... def __init__( self, expected_exception: ( type[BaseExcT_co_default] | tuple[type[BaseExcT_co_default], ...] | None ) = None, + /, + *, match: str | Pattern[str] | None = None, check: Callable[[BaseExcT_co_default], bool] | None = None, ): - super().__init__(match, check) + super().__init__(match=match, check=check) if isinstance(expected_exception, tuple): expected_exceptions = expected_exception elif expected_exception is None: @@ -366,6 +637,8 @@ def __init__( for e in expected_exceptions ) + self._just_propagate = False + def matches( self, exception: BaseException | None, @@ -388,10 +661,12 @@ def matches( assert re.search("foo", str(excinfo.value.__cause__) """ + self._just_propagate = False if exception is None: self._fail_reason = "exception is None" return False if not self._check_type(exception): + self._just_propagate = True return False if not self._check_match(exception): @@ -441,6 +716,8 @@ def __exit__( ) if not self.matches(exc_val): + if self._just_propagate: + return False raise AssertionError(self._fail_reason) # Cast to narrow the exception type now that it's verified.... @@ -463,49 +740,77 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): :meth:`ExceptionInfo.group_contains` also tries to handle exception groups, but it is very bad at checking that you *didn't* get unexpected exceptions. - The catching behaviour differs from :ref:`except* `, being much stricter about the structure by default. By using ``allow_unwrapped=True`` and ``flatten_subgroups=True`` you can match :ref:`except* ` fully when expecting a single exception. - #. All specified exceptions must be present, *and no others*. - - * If you expect a variable number of exceptions you need to use - :func:`pytest.raises(ExceptionGroup) ` and manually check - the contained exceptions. Consider making use of :meth:`RaisesExc.matches`. - - #. It will only catch exceptions wrapped in an exceptiongroup by default. - - * With ``allow_unwrapped=True`` you can specify a single expected exception (or :class:`RaisesExc`) and it will - match the exception even if it is not inside an :exc:`ExceptionGroup`. - If you expect one of several different exception types you need to use a :class:`RaisesExc` object. - - #. By default it cares about the full structure with nested :exc:`ExceptionGroup`'s. You can specify nested - :exc:`ExceptionGroup`'s by passing :class:`RaisesGroup` objects as expected exceptions. - - * With ``flatten_subgroups=True`` it will "flatten" the raised :exc:`ExceptionGroup`, - extracting all exceptions inside any nested :exc:`ExceptionGroup`, before matching. - - It does not care about the order of the exceptions, so - ``RaisesGroup(ValueError, TypeError)`` - is equivalent to - ``RaisesGroup(TypeError, ValueError)``. + :param args: + Any number of exception types, :class:`RaisesGroup` or :class:`RaisesExc` + to specify the exceptions contained in this exception. + All specified exceptions must be present in the raised group, *and no others*. + + If you expect a variable number of exceptions you need to use + :func:`pytest.raises(ExceptionGroup) ` and manually check + the contained exceptions. Consider making use of :meth:`RaisesExc.matches`. + + It does not care about the order of the exceptions, so + ``RaisesGroup(ValueError, TypeError)`` + is equivalent to + ``RaisesGroup(TypeError, ValueError)``. + :kwparam str | re.Pattern[str] | None match: + If specified, a string containing a regular expression, + or a regular expression object, that is tested against the string + representation of the exception group and its :pep:`678` `__notes__` + using :func:`re.search`. + + To match a literal string that may contain :ref:`special characters + `, the pattern can first be escaped with :func:`re.escape`. + + Note that " (5 subgroups)" will be stripped from the ``repr`` before matching. + :kwparam Callable[[E], bool] check: + If specified, a callable that will be called with the group as a parameter + after successfully matching the expected exceptions. If it returns ``True`` + it will be considered a match, if not it will be considered a failed match. + :kwparam bool allow_unwrapped: + If expecting a single exception or :class:`RaisesExc` it will match even + if the exception is not inside an exceptiongroup. + + Using this together with ``match``, ``check`` or expecting multiple exceptions + will raise an error. + :kwparam bool flatten_subgroups: + "flatten" any groups inside the raised exception group, extracting all exceptions + inside any nested groups, before matching. Without this it expects you to + fully specify the nesting structure by passing :class:`RaisesGroup` as expected + parameter. Examples:: with RaisesGroup(ValueError): raise ExceptionGroup("", (ValueError(),)) + # match with RaisesGroup( - ValueError, ValueError, RaisesExc(TypeError, match="expected int") + ValueError, + ValueError, + RaisesExc(TypeError, match="^expected int$"), + match="^my group$", ): - ... + raise ExceptionGroup( + "my group", + [ + ValueError(), + TypeError("expected int"), + ValueError(), + ], + ) + # check with RaisesGroup( KeyboardInterrupt, - match="hello", - check=lambda x: type(x) is BaseExceptionGroup, + match="^hello$", + check=lambda x: isinstance(x.__cause__, ValueError), ): - ... + raise BaseExceptionGroup("hello", [KeyboardInterrupt()]) from ValueError + # nested groups with RaisesGroup(RaisesGroup(ValueError)): raise ExceptionGroup("", (ExceptionGroup("", (ValueError(),)),)) @@ -544,6 +849,7 @@ class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]): def __init__( self, expected_exception: type[BaseExcT_co] | RaisesExc[BaseExcT_co], + /, *, allow_unwrapped: Literal[True], flatten_subgroups: bool = False, @@ -554,6 +860,7 @@ def __init__( def __init__( self, expected_exception: type[BaseExcT_co] | RaisesExc[BaseExcT_co], + /, *other_exceptions: type[BaseExcT_co] | RaisesExc[BaseExcT_co], flatten_subgroups: Literal[True], match: str | Pattern[str] | None = None, @@ -569,6 +876,7 @@ def __init__( def __init__( self: RaisesGroup[ExcT_1], expected_exception: type[ExcT_1] | RaisesExc[ExcT_1], + /, *other_exceptions: type[ExcT_1] | RaisesExc[ExcT_1], match: str | Pattern[str] | None = None, check: Callable[[ExceptionGroup[ExcT_1]], bool] | None = None, @@ -578,6 +886,7 @@ def __init__( def __init__( self: RaisesGroup[ExceptionGroup[ExcT_2]], expected_exception: RaisesGroup[ExcT_2], + /, *other_exceptions: RaisesGroup[ExcT_2], match: str | Pattern[str] | None = None, check: Callable[[ExceptionGroup[ExceptionGroup[ExcT_2]]], bool] | None = None, @@ -587,6 +896,7 @@ def __init__( def __init__( self: RaisesGroup[ExcT_1 | ExceptionGroup[ExcT_2]], expected_exception: type[ExcT_1] | RaisesExc[ExcT_1] | RaisesGroup[ExcT_2], + /, *other_exceptions: type[ExcT_1] | RaisesExc[ExcT_1] | RaisesGroup[ExcT_2], match: str | Pattern[str] | None = None, check: ( @@ -599,6 +909,7 @@ def __init__( def __init__( self: RaisesGroup[BaseExcT_1], expected_exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1], + /, *other_exceptions: type[BaseExcT_1] | RaisesExc[BaseExcT_1], match: str | Pattern[str] | None = None, check: Callable[[BaseExceptionGroup[BaseExcT_1]], bool] | None = None, @@ -608,6 +919,7 @@ def __init__( def __init__( self: RaisesGroup[BaseExceptionGroup[BaseExcT_2]], expected_exception: RaisesGroup[BaseExcT_2], + /, *other_exceptions: RaisesGroup[BaseExcT_2], match: str | Pattern[str] | None = None, check: ( @@ -621,6 +933,7 @@ def __init__( expected_exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], + /, *other_exceptions: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], @@ -639,6 +952,7 @@ def __init__( expected_exception: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], + /, *other_exceptions: type[BaseExcT_1] | RaisesExc[BaseExcT_1] | RaisesGroup[BaseExcT_2], @@ -660,7 +974,7 @@ def __init__( "], bool]", check, ) - super().__init__(match, check) + super().__init__(match=match, check=check) self.allow_unwrapped = allow_unwrapped self.flatten_subgroups: bool = flatten_subgroups self.is_baseexception = False @@ -724,8 +1038,14 @@ def _parse_excgroup( self.is_baseexception |= exc.is_baseexception exc._nested = True return exc + elif isinstance(exc, tuple): + raise TypeError( + f"expected exception must be {expected}, not {type(exc).__name__!r}.\n" + "RaisesGroup does not support tuples of exception types when expecting one of " + "several possible exception types like RaisesExc.\n" + "If you meant to expect a group with multiple exceptions, list them as separate arguments." + ) else: - # validate_exc transforms GenericAlias ExceptionGroup[Exception] -> type[ExceptionGroup] return super()._parse_exc(exc, expected) @overload diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 20efefb84df..96281faec97 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -20,7 +20,7 @@ from _pytest.outcomes import fail from _pytest.outcomes import skip from _pytest.outcomes import xfail -from _pytest.raises_group import AbstractRaises +from _pytest.raises import AbstractRaises from _pytest.reports import BaseReport from _pytest.reports import TestReport from _pytest.runner import CallInfo diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index e5098fe6e61..e36d3e704c1 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -60,9 +60,9 @@ from _pytest.python import Module from _pytest.python import Package from _pytest.python_api import approx -from _pytest.python_api import raises -from _pytest.raises_group import RaisesExc -from _pytest.raises_group import RaisesGroup +from _pytest.raises import raises +from _pytest.raises import RaisesExc +from _pytest.raises import RaisesGroup from _pytest.recwarn import deprecated_call from _pytest.recwarn import WarningsRecorder from _pytest.recwarn import warns diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 438a5259f20..89088576980 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -481,9 +481,8 @@ def test_raises_exception_escapes_generic_group() -> None: try: with pytest.raises(ExceptionGroup[Exception]): raise ValueError("my value error") - except AssertionError as e: - assert str(e) == "`ValueError()` is not an instance of `ExceptionGroup`" - assert str(e.__context__) == "my value error" + except ValueError as e: + assert str(e) == "my value error" else: pytest.fail("Expected ValueError to be raised") diff --git a/testing/python/raises.py b/testing/python/raises.py index 333e273db6a..3da260d1837 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -108,7 +108,7 @@ def test_noraise(): int() def test_raise_wrong_exception_passes_by(): - with pytest.raises(AssertionError): + with pytest.raises(ZeroDivisionError): with pytest.raises(ValueError): 1/0 """ @@ -310,8 +310,8 @@ def test_raises_match_wrong_type(self): really relevant if we got a different exception. """ with pytest.raises( - AssertionError, - match=wrap_escape("`ValueError()` is not an instance of `IndexError`"), + ValueError, + match=wrap_escape("invalid literal for int() with base 10: 'asdf'"), ): with pytest.raises(IndexError, match="nomatch"): int("asdf") @@ -361,23 +361,35 @@ def test_raises_context_manager_with_kwargs(self): pass def test_expected_exception_is_not_a_baseexception(self) -> None: - with pytest.raises(TypeError) as excinfo: + with pytest.raises( + TypeError, + match=wrap_escape( + "expected exception must be a BaseException type, not 'str'" + ), + ): with pytest.raises("hello"): # type: ignore[call-overload] pass # pragma: no cover - assert "must be a BaseException type, not str" in str(excinfo.value) class NotAnException: pass - with pytest.raises(TypeError) as excinfo: + with pytest.raises( + ValueError, + match=wrap_escape( + "expected exception must be a BaseException type, not 'NotAnException'" + ), + ): with pytest.raises(NotAnException): # type: ignore[type-var] pass # pragma: no cover - assert "must be a BaseException type, not NotAnException" in str(excinfo.value) - with pytest.raises(TypeError) as excinfo: + with pytest.raises( + TypeError, + match=wrap_escape( + "expected exception must be a BaseException type, not 'str'" + ), + ): with pytest.raises(("hello", NotAnException)): # type: ignore[arg-type] pass # pragma: no cover - assert "must be a BaseException type, not str" in str(excinfo.value) def test_issue_11872(self) -> None: """Regression test for #11872. diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index 0dc2a58a1da..04979c32e98 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -10,9 +10,9 @@ from _pytest._code import ExceptionInfo from _pytest.outcomes import Failed from _pytest.pytester import Pytester -from _pytest.raises_group import RaisesExc -from _pytest.raises_group import RaisesGroup -from _pytest.raises_group import repr_callable +from _pytest.raises import RaisesExc +from _pytest.raises import RaisesGroup +from _pytest.raises import repr_callable import pytest @@ -34,11 +34,21 @@ def fails_raises_group(msg: str, add_prefix: bool = True) -> RaisesExc[Failed]: def test_raises_group() -> None: + with pytest.raises( + TypeError, + match=wrap_escape("expected exception must be a BaseException type, not 'int'"), + ): + RaisesExc(5) # type: ignore[call-overload] + with pytest.raises( + ValueError, + match=wrap_escape("expected exception must be a BaseException type, not 'int'"), + ): + RaisesExc(int) # type: ignore[type-var] with pytest.raises( TypeError, # TODO: bad sentence structure match=wrap_escape( - "expected exception must be a BaseException type, RaisesExc, or RaisesGroup, not ValueError", + "expected exception must be a BaseException type, RaisesExc, or RaisesGroup, not an exception instance (ValueError)", ), ): RaisesGroup(ValueError()) # type: ignore[call-overload] @@ -499,7 +509,7 @@ def check_message( # RaisesExc check_message( "ExceptionGroup(RaisesExc(ValueError, match='my_str'))", - RaisesGroup(RaisesExc(ValueError, "my_str")), + RaisesGroup(RaisesExc(ValueError, match="my_str")), ) check_message( "ExceptionGroup(RaisesExc(match='my_str'))", @@ -1067,9 +1077,9 @@ def test_raisesexc() -> None: ): RaisesExc() # type: ignore[call-overload] with pytest.raises( - TypeError, + ValueError, match=wrap_escape( - "expected exception must be a BaseException type, not object" + "expected exception must be a BaseException type, not 'object'" ), ): RaisesExc(object) # type: ignore[type-var] @@ -1110,14 +1120,14 @@ def test_raisesexc() -> None: # currently RaisesGroup says "Raised exception did not match" but RaisesExc doesn't... with pytest.raises( AssertionError, - match=wrap_escape("`TypeError()` is not an instance of `ValueError`"), + match=wrap_escape("Regex pattern did not match.\n Regex: 'foo'\n Input: 'bar'"), ): - with RaisesExc(ValueError): - raise TypeError + with RaisesExc(TypeError, match="foo"): + raise TypeError("bar") def test_raisesexc_match() -> None: - with RaisesGroup(RaisesExc(ValueError, "foo")): + with RaisesGroup(RaisesExc(ValueError, match="foo")): raise ExceptionGroup("", (ValueError("foo"),)) with ( fails_raises_group( @@ -1125,7 +1135,7 @@ def test_raisesexc_match() -> None: " Regex: 'foo'\n" " Input: 'bar'" ), - RaisesGroup(RaisesExc(ValueError, "foo")), + RaisesGroup(RaisesExc(ValueError, match="foo")), ): raise ExceptionGroup("", (ValueError("bar"),)) @@ -1328,6 +1338,11 @@ def test_tuples() -> None: # RaisesGroup(ValueError, TypeError), and the former might be interpreted as the latter. with pytest.raises( TypeError, - match="expected exception must be a BaseException type, RaisesExc, or RaisesGroup, not tuple", + match=wrap_escape( + "expected exception must be a BaseException type, RaisesExc, or RaisesGroup, not 'tuple'.\n" + "RaisesGroup does not support tuples of exception types when expecting one of " + "several possible exception types like RaisesExc.\n" + "If you meant to expect a group with multiple exceptions, list them as separate arguments." + ), ): RaisesGroup((ValueError, IndexError)) # type: ignore[call-overload] diff --git a/testing/test_warning_types.py b/testing/test_warning_types.py index 19fe0f8a272..7cbc4703c26 100644 --- a/testing/test_warning_types.py +++ b/testing/test_warning_types.py @@ -43,7 +43,7 @@ def test(): @pytest.mark.filterwarnings("error") def test_warn_explicit_for_annotates_errors_with_location(): - with pytest.raises(Warning, match="(?m)test\n at .*python_api.py:\\d+"): + with pytest.raises(Warning, match="(?m)test\n at .*raises.py:\\d+"): warning_types.warn_explicit_for( pytest.raises, # type: ignore[arg-type] warning_types.PytestWarning("test"), diff --git a/testing/typing_raises_group.py b/testing/typing_raises_group.py index f27943e3a58..c7dd16991ac 100644 --- a/testing/typing_raises_group.py +++ b/testing/typing_raises_group.py @@ -70,9 +70,8 @@ def check_exc(exc: BaseException) -> bool: # At least 1 arg must be provided. RaisesExc() # type: ignore RaisesExc(ValueError) - RaisesExc(ValueError, "regex") - RaisesExc(ValueError, "regex", check_exc) - RaisesExc(expected_exception=ValueError) + RaisesExc(ValueError, match="regex") + RaisesExc(ValueError, match="regex", check=check_exc) RaisesExc(match="regex") RaisesExc(check=check_exc) RaisesExc(ValueError, match="regex") @@ -87,6 +86,11 @@ def check_filenotfound(exc: FileNotFoundError) -> bool: RaisesExc(check=check_filenotfound) # type: ignore RaisesExc(FileNotFoundError, match="regex", check=check_filenotfound) + # exceptions are pos-only + RaisesExc(expected_exception=ValueError) # type: ignore + # match and check are kw-only + RaisesExc(ValueError, "regex") # type: ignore + def raisesgroup_check_type_narrowing() -> None: """Check type narrowing on the `check` argument to `RaisesGroup`. From 88164320f517277d81a3a337fd5dbb60622691ae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 30 Mar 2025 10:59:58 +0200 Subject: [PATCH 1175/1271] [automated] Update plugin list (#13335) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 128 ++++++++++++++++++------------- 1 file changed, 76 insertions(+), 52 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 3e653676d69..de1ae7f7595 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =7.2 :pypi:`pytest-argus` pyest results colection plugin Jun 24, 2021 5 - Production/Stable pytest (>=6.2.4) - :pypi:`pytest-argus-server` A plugin that provides a running Argus API server for tests Mar 20, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-argus-server` A plugin that provides a running Argus API server for tests Mar 24, 2025 4 - Beta pytest>=6.2.0 :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 Dec 20, 2023 4 - Beta N/A @@ -118,7 +118,7 @@ This list contains 1610 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Jan 28, 2025 4 - Beta pytest<9,>=8.2 + :pypi:`pytest-asyncio` Pytest support for asyncio Mar 25, 2025 4 - Beta pytest<9,>=8.2 :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Mar 16, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 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) @@ -162,7 +162,7 @@ This list contains 1610 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Mar 22, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Mar 27, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -275,7 +275,7 @@ This list contains 1610 plugins. :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A - :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Dec 11, 2024 4 - Beta pytest>=4.6.0 + :pypi:`pytest-codecov` Pytest plugin for uploading pytest-cov results to codecov.io Mar 25, 2025 4 - Beta pytest>=4.6.0 :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A @@ -338,7 +338,7 @@ This list contains 1610 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Feb 11, 2025 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Mar 23, 2025 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Feb 07, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -466,7 +466,7 @@ This list contains 1610 plugins. :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Mar 18, 2025 5 - Production/Stable pytest>=4.6 :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A - :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Oct 25, 2024 5 - Production/Stable pytest + :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Mar 23, 2025 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Feb 16, 2024 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A @@ -520,7 +520,7 @@ This list contains 1610 plugins. :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Nov 20, 2024 N/A pytest>=7 + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Mar 23, 2025 N/A pytest>=7 :pypi:`pytest-exasol-backend` Feb 11, 2025 N/A pytest<9,>=7 :pypi:`pytest-exasol-extension` Feb 11, 2025 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Nov 22, 2024 N/A pytest<9,>=7 @@ -643,7 +643,7 @@ This list contains 1610 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Mar 21, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Mar 28, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -687,7 +687,7 @@ This list contains 1610 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Mar 22, 2025 3 - Alpha pytest==8.3.4 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Mar 29, 2025 3 - Alpha pytest==8.3.5 :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` Sep 23, 2024 N/A N/A @@ -852,7 +852,7 @@ This list contains 1610 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Jan 19, 2025 3 - Alpha pytest + :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Mar 23, 2025 3 - Alpha pytest :pypi:`pytest-logikal` Common testing environment Mar 02, 2025 5 - Production/Stable pytest==8.3.4 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 @@ -891,7 +891,7 @@ This list contains 1610 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Mar 14, 2025 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Mar 27, 2025 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -945,7 +945,7 @@ This list contains 1610 plugins. :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-my-plugin` A pytest plugin that does awesome things Jan 27, 2025 N/A pytest>=6.0 - :pypi:`pytest-mypy` Mypy static type checker plugin for Pytest Dec 18, 2022 4 - Beta pytest (>=6.2) ; python_version >= "3.10" + :pypi:`pytest-mypy` A Pytest Plugin for Mypy Mar 28, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Dec 21, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Feb 14, 2025 N/A pytest>=6.0.0 @@ -998,7 +998,7 @@ This list contains 1610 plugins. :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Jun 05, 2024 3 - Alpha pytest>=4.6 :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Nov 22, 2024 N/A pytest - :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Sep 05, 2024 5 - Production/Stable pytest>=5.0 + :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Mar 22, 2025 5 - Production/Stable pytest>=5.0 :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest :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) @@ -1013,6 +1013,7 @@ This list contains 1610 plugins. :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A :pypi:`pytest-owner` Add owner mark for tests Aug 19, 2024 N/A pytest :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A + :pypi:`pytest-pagerduty` Pytest plugin for PagerDuty integration via automation testing. Mar 22, 2025 N/A pytest<9.0.0,>=7.4.0 :pypi:`pytest-pahrametahrize` Parametrize your tests with a Boston accent. Nov 24, 2021 4 - Beta pytest (>=6.0,<7.0) :pypi:`pytest-parallel` a pytest plugin for parallel and concurrent testing Oct 10, 2021 3 - Alpha pytest (>=3.0.0) :pypi:`pytest-parallel-39` a pytest plugin for parallel and concurrent testing Jul 12, 2021 3 - Alpha pytest (>=3.0.0) @@ -1068,11 +1069,13 @@ This list contains 1610 plugins. :pypi:`pytest-playwright` A pytest wrapper with fixtures for Playwright to automate web browsers Jan 31, 2025 N/A pytest<9.0.0,>=6.2.4 :pypi:`pytest_playwright_async` ASYNC Pytest plugin for Playwright Sep 28, 2024 N/A N/A :pypi:`pytest-playwright-asyncio` A pytest wrapper with async fixtures for Playwright to automate web browsers Jan 31, 2025 N/A pytest<9.0.0,>=6.2.4 + :pypi:`pytest-playwright-axe` An axe-core integration for accessibility testing using Playwright Python. Mar 27, 2025 4 - Beta N/A :pypi:`pytest-playwright-enhanced` A pytest plugin for playwright python Mar 24, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A - :pypi:`pytest-plone` Pytest plugin to test Plone addons May 15, 2024 3 - Alpha pytest<8.0.0 + :pypi:`pytest-playwright-visual-snapshot` Easy pytest visual regression testing using playwright Mar 25, 2025 N/A N/A + :pypi:`pytest-plone` Pytest plugin to test Plone addons Mar 27, 2025 3 - Alpha pytest<8.0.0 :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Feb 02, 2025 5 - Production/Stable pytest>=7.4.2 @@ -1253,7 +1256,7 @@ This list contains 1610 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Oct 15, 2024 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 28, 2025 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1280,19 +1283,19 @@ This list contains 1610 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 29, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 - :pypi:`pytest-scim2-server` SCIM2 server fixture for Pytest Jan 27, 2025 N/A pytest>=8.3.4 + :pypi:`pytest-scim2-server` SCIM2 server fixture for Pytest Mar 28, 2025 N/A pytest>=8.3.4 :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-scrutinize` Scrutinize your pytest test suites for slow fixtures, tests and more. Aug 19, 2024 4 - Beta pytest>=6 :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 Feb 01, 2024 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. Mar 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Mar 29, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1338,7 +1341,7 @@ This list contains 1610 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A - :pypi:`pytest-smoke` Pytest plugin for smoke testing Jan 30, 2025 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-smoke` Pytest plugin for smoke testing Mar 25, 2025 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -1356,7 +1359,7 @@ This list contains 1610 plugins. :pypi:`pytest-soft-assertions` May 05, 2020 3 - Alpha pytest :pypi:`pytest-solidity` A PyTest library plugin for Solidity language. Jan 15, 2022 1 - Planning pytest (<7,>=6.0.1) ; extra == 'tests' :pypi:`pytest-solr` Solr process and client fixtures for py.test. May 11, 2020 3 - Alpha pytest (>=3.0.0) - :pypi:`pytest-sort` Tools for sorting test cases Jan 07, 2024 N/A pytest >=7.4.0 + :pypi:`pytest-sort` Tools for sorting test cases Mar 22, 2025 N/A pytest>=7.4.0 :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest @@ -1444,7 +1447,7 @@ This list contains 1610 plugins. :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) - :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Nov 14, 2024 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Mar 28, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-testinfra` Test infrastructures May 26, 2024 5 - Production/Stable pytest>=6 :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 @@ -1543,7 +1546,7 @@ This list contains 1610 plugins. :pypi:`pytest-uncollect-if` A plugin to uncollect pytests tests rather than using skipif Dec 26, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unflakable` Unflakable plugin for PyTest Apr 30, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-unhandled-exception-exit-code` Plugin for py.test set a different exit code on uncaught exceptions Jun 22, 2020 5 - Production/Stable pytest (>=2.3) - :pypi:`pytest-unique` Pytest fixture to generate unique values. Jan 03, 2025 N/A pytest<8.0.0,>=7.4.2 + :pypi:`pytest-unique` Pytest fixture to generate unique values. Mar 23, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-unittest-filter` A pytest plugin for filtering unittest-based test classes Jan 12, 2019 4 - Beta pytest (>=3.1.0) :pypi:`pytest-unittest-id-runner` A pytest plugin to run tests using unittest-style test IDs Feb 09, 2025 N/A pytest>=6.0.0 :pypi:`pytest-unmagic` Pytest fixtures with conventional import semantics Oct 22, 2024 5 - Production/Stable pytest @@ -1602,7 +1605,7 @@ This list contains 1610 plugins. :pypi:`pytest-xdist-forked` forked from pytest-xdist Feb 10, 2020 5 - Production/Stable pytest (>=4.4.0) :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Mar 15, 2025 4 - Beta pytest>=7.0.0 - :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Mar 07, 2025 N/A pytest<8.0.0,>=7.4.2 + :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Mar 23, 2025 N/A pytest<8.0.0,>=7.4.2 :pypi:`pytest-xfaillist` Maintain a xfaillist in an additional file to avoid merge-conflicts. Sep 17, 2021 N/A pytest (>=6.2.2,<7.0.0) :pypi:`pytest-xfiles` Pytest fixtures providing data read from function, module or package related (x)files. Feb 27, 2018 N/A N/A :pypi:`pytest-xflaky` A simple plugin to use with pytest Oct 14, 2024 4 - Beta pytest>=8.2.1 @@ -2105,7 +2108,7 @@ This list contains 1610 plugins. pyest results colection plugin :pypi:`pytest-argus-server` - *last release*: Mar 20, 2025, + *last release*: Mar 24, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2238,7 +2241,7 @@ This list contains 1610 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Jan 28, 2025, + *last release*: Mar 25, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=8.2 @@ -2546,7 +2549,7 @@ This list contains 1610 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Mar 22, 2025, + *last release*: Mar 27, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3337,7 +3340,7 @@ This list contains 1610 plugins. pytest plugin to add source code sanity checks (pep8 and friends) :pypi:`pytest-codecov` - *last release*: Dec 11, 2024, + *last release*: Mar 25, 2025, *status*: 4 - Beta, *requires*: pytest>=4.6.0 @@ -3778,7 +3781,7 @@ This list contains 1610 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Feb 11, 2025, + *last release*: Mar 23, 2025, *status*: 4 - Beta, *requires*: pytest @@ -4674,7 +4677,7 @@ This list contains 1610 plugins. A pytest plugin to rerun tests dynamically based off of test outcome and output. :pypi:`pytest-dynamodb` - *last release*: Oct 25, 2024, + *last release*: Mar 23, 2025, *status*: 5 - Production/Stable, *requires*: pytest @@ -5052,7 +5055,7 @@ This list contains 1610 plugins. Parse queries in Lucene and Elasticsearch syntaxes :pypi:`pytest-examples` - *last release*: Nov 20, 2024, + *last release*: Mar 23, 2025, *status*: N/A, *requires*: pytest>=7 @@ -5913,7 +5916,7 @@ This list contains 1610 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Mar 21, 2025, + *last release*: Mar 28, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6221,9 +6224,9 @@ This list contains 1610 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 22, 2025, + *last release*: Mar 29, 2025, *status*: 3 - Alpha, - *requires*: pytest==8.3.4 + *requires*: pytest==8.3.5 Experimental package to automatically extract test plugins for Home Assistant custom components @@ -7376,7 +7379,7 @@ This list contains 1610 plugins. :pypi:`pytest-logging-strict` - *last release*: Jan 19, 2025, + *last release*: Mar 23, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -7649,7 +7652,7 @@ This list contains 1610 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Mar 14, 2025, + *last release*: Mar 27, 2025, *status*: N/A, *requires*: N/A @@ -8027,11 +8030,11 @@ This list contains 1610 plugins. A pytest plugin that does awesome things :pypi:`pytest-mypy` - *last release*: Dec 18, 2022, - *status*: 4 - Beta, - *requires*: pytest (>=6.2) ; python_version >= "3.10" + *last release*: Mar 28, 2025, + *status*: 5 - Production/Stable, + *requires*: pytest>=7.0 - Mypy static type checker plugin for Pytest + A Pytest Plugin for Mypy :pypi:`pytest-mypyd` *last release*: Aug 20, 2019, @@ -8398,7 +8401,7 @@ This list contains 1610 plugins. A pytest plugin for instrumenting test runs via OpenTelemetry :pypi:`pytest-opentmi` - *last release*: Sep 05, 2024, + *last release*: Mar 22, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=5.0 @@ -8502,6 +8505,13 @@ This list contains 1610 plugins. A simple plugin to use with pytest + :pypi:`pytest-pagerduty` + *last release*: Mar 22, 2025, + *status*: N/A, + *requires*: pytest<9.0.0,>=7.4.0 + + Pytest plugin for PagerDuty integration via automation testing. + :pypi:`pytest-pahrametahrize` *last release*: Nov 24, 2021, *status*: 4 - Beta, @@ -8887,6 +8897,13 @@ This list contains 1610 plugins. A pytest wrapper with async fixtures for Playwright to automate web browsers + :pypi:`pytest-playwright-axe` + *last release*: Mar 27, 2025, + *status*: 4 - Beta, + *requires*: N/A + + An axe-core integration for accessibility testing using Playwright Python. + :pypi:`pytest-playwright-enhanced` *last release*: Mar 24, 2024, *status*: N/A, @@ -8915,8 +8932,15 @@ This list contains 1610 plugins. A pytest fixture for visual testing with Playwright + :pypi:`pytest-playwright-visual-snapshot` + *last release*: Mar 25, 2025, + *status*: N/A, + *requires*: N/A + + Easy pytest visual regression testing using playwright + :pypi:`pytest-plone` - *last release*: May 15, 2024, + *last release*: Mar 27, 2025, *status*: 3 - Alpha, *requires*: pytest<8.0.0 @@ -10183,7 +10207,7 @@ This list contains 1610 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Oct 15, 2024, + *last release*: Mar 28, 2025, *status*: N/A, *requires*: pytest<9,>=7 @@ -10372,7 +10396,7 @@ This list contains 1610 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Mar 22, 2025, + *last release*: Mar 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10407,7 +10431,7 @@ This list contains 1610 plugins. 👍 Validate return values against a schema-like object in testing :pypi:`pytest-scim2-server` - *last release*: Jan 27, 2025, + *last release*: Mar 28, 2025, *status*: N/A, *requires*: pytest>=8.3.4 @@ -10456,7 +10480,7 @@ This list contains 1610 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Mar 22, 2025, + *last release*: Mar 29, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10778,7 +10802,7 @@ This list contains 1610 plugins. Automated bad smell detection tool for Pytest :pypi:`pytest-smoke` - *last release*: Jan 30, 2025, + *last release*: Mar 25, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 @@ -10904,9 +10928,9 @@ This list contains 1610 plugins. Solr process and client fixtures for py.test. :pypi:`pytest-sort` - *last release*: Jan 07, 2024, + *last release*: Mar 22, 2025, *status*: N/A, - *requires*: pytest >=7.4.0 + *requires*: pytest>=7.4.0 Tools for sorting test cases @@ -11520,7 +11544,7 @@ This list contains 1610 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-test-groups` - *last release*: Nov 14, 2024, + *last release*: Mar 28, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -12213,7 +12237,7 @@ This list contains 1610 plugins. Plugin for py.test set a different exit code on uncaught exceptions :pypi:`pytest-unique` - *last release*: Jan 03, 2025, + *last release*: Mar 23, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.2 @@ -12626,7 +12650,7 @@ This list contains 1610 plugins. A pytest plugin to list worker statistics after a xdist run. :pypi:`pytest-xdocker` - *last release*: Mar 07, 2025, + *last release*: Mar 23, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.2 From 33e2e262d688ed2951ec5174e51545fda918e6f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Mar 2025 06:26:06 +0200 Subject: [PATCH 1176/1271] build(deps): Bump pytest-asyncio in /testing/plugins_integration (#13336) Bumps [pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio) from 0.25.3 to 0.26.0. - [Release notes](https://github.com/pytest-dev/pytest-asyncio/releases) - [Commits](https://github.com/pytest-dev/pytest-asyncio/compare/v0.25.3...v0.26.0) --- updated-dependencies: - dependency-name: pytest-asyncio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 66ed13a4b8a..05565fe89d4 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,6 +1,6 @@ anyio[trio]==4.9.0 django==5.1.7 -pytest-asyncio==0.25.3 +pytest-asyncio==0.26.0 pytest-bdd==8.1.0 pytest-cov==6.0.0 pytest-django==4.10.0 From 9eacaef044dcf2162b3c3396ffc755f7f1e83b3c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 1 Apr 2025 08:33:12 -0300 Subject: [PATCH 1177/1271] Enable GitHub Sponsors in FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 5f2d1cf09c8..2db4a7f7e57 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,5 +1,6 @@ # info: # * https://help.github.com/en/articles/displaying-a-sponsor-button-in-your-repository # * https://tidelift.com/subscription/how-to-connect-tidelift-with-github +github: pytest-dev tidelift: pypi/pytest open_collective: pytest From 7ca1bc90400e10bd6f6968b16c39b3098ec8e450 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 1 Apr 2025 08:36:41 -0300 Subject: [PATCH 1178/1271] Enable thanks.dev in FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 2db4a7f7e57..88049407b45 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -4,3 +4,4 @@ github: pytest-dev tidelift: pypi/pytest open_collective: pytest +thanks_dev: u/gh/pytest-dev From 0c454979cc2038bc193eb037e80f658a9183641f Mon Sep 17 00:00:00 2001 From: Bahram Farahmand Date: Wed, 2 Apr 2025 13:31:53 +0300 Subject: [PATCH 1179/1271] Fix `approx` when mixing numpy.bool and bool (#13338) Fix #13047 --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/13047.bugfix.rst | 17 +++++++++++++++++ src/_pytest/python_api.py | 20 ++++++++++++++++---- testing/python/approx.py | 9 +++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 changelog/13047.bugfix.rst diff --git a/AUTHORS b/AUTHORS index 95e6b13f11e..9004008bfa5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -58,6 +58,7 @@ Ashley Whetter Aviral Verma Aviv Palivoda Babak Keyvani +Bahram Farahmand Barney Gale Ben Brown Ben Gartner diff --git a/changelog/13047.bugfix.rst b/changelog/13047.bugfix.rst new file mode 100644 index 00000000000..399e860505c --- /dev/null +++ b/changelog/13047.bugfix.rst @@ -0,0 +1,17 @@ +Restore :func:`pytest.approx` handling of equality checks between `bool` and `numpy.bool_` types. + +Comparing `bool` and `numpy.bool_` using :func:`pytest.approx` accidentally changed in version `8.3.4` and `8.3.5` to no longer match: + +.. code-block:: pycon + + >>> import numpy as np + >>> from pytest import approx + >>> [np.True_, np.True_] == pytest.approx([True, True]) + False + +This has now been fixed: + +.. code-block:: pycon + + >>> [np.True_, np.True_] == pytest.approx([True, True]) + True diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index af078e25256..3f899a24ea8 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -421,14 +421,26 @@ def __repr__(self) -> str: def __eq__(self, actual) -> bool: """Return whether the given value is equal to the expected value within the pre-specified tolerance.""" + + def is_bool(val: Any) -> bool: + # Check if `val` is a native bool or numpy bool. + if isinstance(val, bool): + return True + try: + import numpy as np + + return isinstance(val, np.bool_) + except ImportError: + return False + asarray = _as_numpy_array(actual) if asarray is not None: # Call ``__eq__()`` manually to prevent infinite-recursion with # numpy<1.13. See #3748. return all(self.__eq__(a) for a in asarray.flat) - # Short-circuit exact equality, except for bool - if isinstance(self.expected, bool) and not isinstance(actual, bool): + # Short-circuit exact equality, except for bool and np.bool_ + if is_bool(self.expected) and not is_bool(actual): return False elif actual == self.expected: return True @@ -436,8 +448,8 @@ def __eq__(self, actual) -> bool: # If either type is non-numeric, fall back to strict equality. # NB: we need Complex, rather than just Number, to ensure that __abs__, # __sub__, and __float__ are defined. Also, consider bool to be - # nonnumeric, even though it has the required arithmetic. - if isinstance(self.expected, bool) or not ( + # non-numeric, even though it has the required arithmetic. + if is_bool(self.expected) or not ( isinstance(self.expected, (Complex, Decimal)) and isinstance(actual, (Complex, Decimal)) ): diff --git a/testing/python/approx.py b/testing/python/approx.py index 7eba4755c01..01b58782cdb 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -647,6 +647,15 @@ def test_expecting_bool(self) -> None: assert True != approx(False, abs=2) # noqa: E712 assert 1 != approx(True) + def test_expecting_bool_numpy(self) -> None: + """Check approx comparing with numpy.bool (#13047).""" + np = pytest.importorskip("numpy") + assert np.False_ != approx(True) + assert np.True_ != approx(False) + assert np.True_ == approx(True) + assert np.False_ == approx(False) + assert np.True_ != approx(False, abs=2) + def test_list(self): actual = [1 + 1e-7, 2 + 1e-8] expected = [1, 2] From 682013d200764b27659dd5eb60963bbb18779964 Mon Sep 17 00:00:00 2001 From: Harmin Parra Rueda Date: Wed, 2 Apr 2025 13:15:58 +0200 Subject: [PATCH 1180/1271] Make wasxfail consistent (#13328) Previously, xfailed tests via the marker would have a special `"reason: "` string prefixed to it. Removed the prefix so the `wasxfail` attribute is now consistent regardless the method used. Fix #11067 --------- Co-authored-by: Bruno Oliveira --- changelog/11067.bugfix.rst | 3 +++ src/_pytest/skipping.py | 2 +- testing/test_skipping.py | 8 ++++---- 3 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 changelog/11067.bugfix.rst diff --git a/changelog/11067.bugfix.rst b/changelog/11067.bugfix.rst new file mode 100644 index 00000000000..4e3cb8e7dd7 --- /dev/null +++ b/changelog/11067.bugfix.rst @@ -0,0 +1,3 @@ +The test report is now consistent regardless if the test xfailed via :ref:`pytest.mark.xfail ` or :func:`pytest.fail`. + +Previously, *xfailed* tests via the marker would have the string ``"reason: "`` prefixed to the message, while those *xfailed* via the function did not. The prefix has been removed. diff --git a/src/_pytest/skipping.py b/src/_pytest/skipping.py index 96281faec97..ec118f2c92f 100644 --- a/src/_pytest/skipping.py +++ b/src/_pytest/skipping.py @@ -278,7 +278,7 @@ def pytest_runtest_makereport( pass # don't interfere elif call.excinfo and isinstance(call.excinfo.value, xfail.Exception): assert call.excinfo.value.msg is not None - rep.wasxfail = "reason: " + call.excinfo.value.msg + rep.wasxfail = call.excinfo.value.msg rep.outcome = "skipped" elif not rep.skipped and xfailed: if call.excinfo: diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 57113ba93d5..9a6c2c4b6aa 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -448,8 +448,8 @@ def test_this_false(): result = pytester.runpytest(p, "-rx") result.stdout.fnmatch_lines( [ - "*test_one*test_this - reason: *NOTRUN* noway", - "*test_one*test_this_true - reason: *NOTRUN* condition: True", + "*test_one*test_this - *NOTRUN* noway", + "*test_one*test_this_true - *NOTRUN* condition: True", "*1 passed*", ] ) @@ -492,7 +492,7 @@ def test_this(): result = pytester.runpytest(p) result.stdout.fnmatch_lines(["*1 xfailed*"]) result = pytester.runpytest(p, "-rx") - result.stdout.fnmatch_lines(["*XFAIL*test_this*reason:*hello*"]) + result.stdout.fnmatch_lines(["*XFAIL*test_this*hello*"]) result = pytester.runpytest(p, "--runxfail") result.stdout.fnmatch_lines(["*1 pass*"]) @@ -510,7 +510,7 @@ def test_this(): result = pytester.runpytest(p) result.stdout.fnmatch_lines(["*1 xfailed*"]) result = pytester.runpytest(p, "-rx") - result.stdout.fnmatch_lines(["*XFAIL*test_this*reason:*hello*"]) + result.stdout.fnmatch_lines(["*XFAIL*test_this*hello*"]) result = pytester.runpytest(p, "--runxfail") result.stdout.fnmatch_lines( """ From 9a7dbd8a394bb47ee43be51d60ec3c4f4759789e Mon Sep 17 00:00:00 2001 From: Callum Scott <134177091+callummscott@users.noreply.github.com> Date: Thu, 3 Apr 2025 13:53:43 +0100 Subject: [PATCH 1181/1271] Add title and change spelling for use of approx with non-numerics (#13343) * Added title to draw attention to the easily-missed information on non-numeric types for approx. * Changed spelling of all cases of "nonnumeric" to "non-numeric" within docstrings for clarity and consistency with .rst files. Related to #13218 --- src/_pytest/python_api.py | 10 ++++++---- testing/python/approx.py | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 3f899a24ea8..655f53fd8ef 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -632,8 +632,10 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: >>> 1 + 1e-8 == approx(1, rel=1e-6, abs=1e-12) True - You can also use ``approx`` to compare nonnumeric types, or dicts and - sequences containing nonnumeric types, in which case it falls back to + **Non-numeric types** + + You can also use ``approx`` to compare non-numeric types, or dicts and + sequences containing non-numeric types, in which case it falls back to strict equality. This can be useful for comparing dicts and sequences that can contain optional values:: @@ -708,10 +710,10 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: .. versionchanged:: 3.7.1 ``approx`` raises ``TypeError`` when it encounters a dict value or - sequence element of nonnumeric type. + sequence element of non-numeric type. .. versionchanged:: 6.1.0 - ``approx`` falls back to strict equality for nonnumeric types instead + ``approx`` falls back to strict equality for non-numeric types instead of raising ``TypeError``. """ # Delegate the comparison to a class that knows how to deal with the type diff --git a/testing/python/approx.py b/testing/python/approx.py index 01b58782cdb..75b57b6965c 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -939,7 +939,7 @@ def test_nonnumeric_okay_if_equal(self, x): ], ) def test_nonnumeric_false_if_unequal(self, x): - """For nonnumeric types, x != pytest.approx(y) reduces to x != y""" + """For non-numeric types, x != pytest.approx(y) reduces to x != y""" assert "ab" != approx("abc") assert ["ab"] != approx(["abc"]) # in particular, both of these should return False From 40564337c789ec713dab38f83dea1b43620f5c61 Mon Sep 17 00:00:00 2001 From: Andy Freeland Date: Thu, 3 Apr 2025 06:07:08 -0700 Subject: [PATCH 1182/1271] Fix type hints for `TestReport.when` and `TestReport.location` (#13345) These are set in `TestReport.__init__` but weren't being picked up by type checkers because of the annotations on `BaseReport`. Fixes #12941. --- changelog/13345.bugfix.rst | 1 + src/_pytest/reports.py | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 changelog/13345.bugfix.rst diff --git a/changelog/13345.bugfix.rst b/changelog/13345.bugfix.rst new file mode 100644 index 00000000000..5010888aa08 --- /dev/null +++ b/changelog/13345.bugfix.rst @@ -0,0 +1 @@ +Fix type hints for :attr:`pytest.TestReport.when` and :attr:`pytest.TestReport.location`. diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index 746512285b4..c85bf78594f 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -260,6 +260,9 @@ class TestReport(BaseReport): """ __test__ = False + + when: Literal["setup", "call", "teardown"] + location: tuple[str, int | None, str] # Defined by skipping plugin. # xfail reason if xfailed, otherwise not defined. Use hasattr to distinguish. wasxfail: str From 636d956cdc117603b2e5f8c9cd558a207fdffc8c Mon Sep 17 00:00:00 2001 From: Andy Freeland Date: Thu, 3 Apr 2025 13:09:37 -0700 Subject: [PATCH 1183/1271] Clean up type hints and add a test (#13348) Based on discussion in #13345. --- src/_pytest/reports.py | 4 +--- testing/typing_checks.py | 8 ++++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/_pytest/reports.py b/src/_pytest/reports.py index c85bf78594f..480ffae1f9c 100644 --- a/src/_pytest/reports.py +++ b/src/_pytest/reports.py @@ -261,8 +261,6 @@ class TestReport(BaseReport): __test__ = False - when: Literal["setup", "call", "teardown"] - location: tuple[str, int | None, str] # Defined by skipping plugin. # xfail reason if xfailed, otherwise not defined. Use hasattr to distinguish. wasxfail: str @@ -307,7 +305,7 @@ def __init__( self.longrepr = longrepr #: One of 'setup', 'call', 'teardown' to indicate runtest phase. - self.when = when + self.when: Literal["setup", "call", "teardown"] = when #: User properties is a list of tuples (name, value) that holds user #: defined properties of the test. diff --git a/testing/typing_checks.py b/testing/typing_checks.py index d4d6a97aea6..8a316580a25 100644 --- a/testing/typing_checks.py +++ b/testing/typing_checks.py @@ -8,12 +8,14 @@ from __future__ import annotations import contextlib +from typing import Literal from typing import Optional from typing_extensions import assert_type import pytest from pytest import MonkeyPatch +from pytest import TestReport # Issue #7488. @@ -51,3 +53,9 @@ def check_raises_is_a_context_manager(val: bool) -> None: with pytest.raises(RuntimeError) if val else contextlib.nullcontext() as excinfo: pass assert_type(excinfo, Optional[pytest.ExceptionInfo[RuntimeError]]) + + +# Issue #12941. +def check_testreport_attributes(report: TestReport) -> None: + assert_type(report.when, Literal["setup", "call", "teardown"]) + assert_type(report.location, tuple[str, Optional[int], str]) From 6964cf105e6256682271e5bc1ad32c08a58df4bc Mon Sep 17 00:00:00 2001 From: Natalia Mokeeva <91160475+natmokval@users.noreply.github.com> Date: Fri, 4 Apr 2025 16:53:37 +0200 Subject: [PATCH 1184/1271] Doc: clarify `approx` behavior regarding int and bools (#13341) Fixes #13218 --- changelog/13218.doc.rst | 1 + src/_pytest/python_api.py | 9 +++++++++ 2 files changed, 10 insertions(+) create mode 100644 changelog/13218.doc.rst diff --git a/changelog/13218.doc.rst b/changelog/13218.doc.rst new file mode 100644 index 00000000000..907a817e895 --- /dev/null +++ b/changelog/13218.doc.rst @@ -0,0 +1 @@ +Pointed out in the :func:`pytest.approx` documentation that it considers booleans unequal to numeric zero or one. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 655f53fd8ef..77b0edc0ac5 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -692,6 +692,15 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: from the `re_assert package `_. + + .. note:: + + Unlike built-in equality, this function considers + booleans unequal to numeric zero or one. For example:: + + >>> 1 == approx(True) + False + .. warning:: .. versionchanged:: 3.2 From be83aa618c68ebb9080b537bbd8b19b97a7f4eb8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 6 Apr 2025 09:20:04 +0200 Subject: [PATCH 1185/1271] [automated] Update plugin list (#13356) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 144 ++++++++++++++++++------------- 1 file changed, 84 insertions(+), 60 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index de1ae7f7595..406ebe75dce 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) :pypi:`pytest-annotated` Pytest plugin to allow use of Annotated in tests to resolve fixtures Sep 30, 2024 N/A pytest>=8.3.3 - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Jan 21, 2025 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Apr 01, 2025 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -142,7 +142,7 @@ This list contains 1613 plugins. :pypi:`pytest-aws` pytest plugin for testing AWS resource configurations Oct 04, 2017 4 - Beta N/A :pypi:`pytest-aws-apigateway` pytest plugin for AWS ApiGateway May 24, 2024 4 - Beta pytest :pypi:`pytest-aws-config` Protect your AWS credentials in unit tests May 28, 2021 N/A N/A - :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Oct 07, 2024 N/A pytest<9.0.0,>=8.0.0 + :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Apr 04, 2025 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest @@ -162,7 +162,7 @@ This list contains 1613 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Mar 27, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Apr 01, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -232,7 +232,7 @@ This list contains 1613 plugins. :pypi:`pytest-change-report` turn . into √,turn F into x Sep 14, 2020 N/A pytest :pypi:`pytest-change-xds` turn . into √,turn F into x Apr 16, 2022 N/A pytest :pypi:`pytest-chdir` A pytest fixture for changing current working directory Jan 28, 2020 N/A pytest (>=5.0.0,<6.0.0) - :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Mar 18, 2025 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-check` A pytest plugin that allows multiple failures per test. Apr 04, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-checkdocs` check the README when running tests Apr 30, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "testing" :pypi:`pytest-checkipdb` plugin to check if there are ipdb debugs left Dec 04, 2023 5 - Production/Stable pytest >=2.9.2 :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A @@ -240,7 +240,7 @@ This list contains 1613 plugins. :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<9,>=7.0 :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Jun 10, 2024 N/A N/A :pypi:`pytest-check-mk` pytest plugin to test Check_MK checks Nov 19, 2015 4 - Beta pytest - :pypi:`pytest-checkpoint` Restore a checkpoint in pytest Mar 22, 2025 N/A pytest>=8.3.5 + :pypi:`pytest-checkpoint` Restore a checkpoint in pytest Mar 30, 2025 N/A pytest>=8.0.0 :pypi:`pytest-check-requirements` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-ch-framework` My pytest framework Apr 17, 2024 N/A pytest==8.0.1 :pypi:`pytest-chic-report` Simple pytest plugin for generating and sending report to messengers. Nov 01, 2024 N/A pytest>=6.0 @@ -304,7 +304,7 @@ This list contains 1613 plugins. :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A - :pypi:`pytest-cov` Pytest plugin for measuring coverage. Oct 29, 2024 5 - Production/Stable pytest>=4.6 + :pypi:`pytest-cov` Pytest plugin for measuring coverage. Apr 05, 2025 5 - Production/Stable pytest>=4.6 :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A @@ -396,7 +396,7 @@ This list contains 1613 plugins. :pypi:`pytest-ditto` Snapshot testing pytest plugin with minimal ceremony and flexible persistence formats. Jun 09, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-ditto-pandas` pytest-ditto plugin for pandas snapshots. May 29, 2024 4 - Beta pytest>=3.5.0 :pypi:`pytest-ditto-pyarrow` pytest-ditto plugin for pyarrow tables. Jun 09, 2024 4 - Beta pytest>=3.5.0 - :pypi:`pytest-django` A Django plugin for pytest. Feb 10, 2025 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-django` A Django plugin for pytest. Apr 03, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-django-ahead` A Django plugin for pytest. Oct 27, 2016 5 - Production/Stable pytest (>=2.9) :pypi:`pytest-djangoapp` Nice pytest plugin to help you with Django pluggable application testing. May 19, 2023 4 - Beta pytest :pypi:`pytest-django-cache-xdist` A djangocachexdist plugin for pytest May 12, 2020 4 - Beta N/A @@ -466,7 +466,7 @@ This list contains 1613 plugins. :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Mar 18, 2025 5 - Production/Stable pytest>=4.6 :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A - :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Mar 23, 2025 5 - Production/Stable pytest + :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Apr 04, 2025 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Feb 16, 2024 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A @@ -474,7 +474,7 @@ This list contains 1613 plugins. :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A - :pypi:`pytest-echo` pytest plugin with mechanisms for echoing environment variables, package version and generic attributes Feb 22, 2025 5 - Production/Stable pytest>=6.0 + :pypi:`pytest-echo` pytest plugin that allows to dump environment variables, package version and generic attributes Apr 01, 2025 5 - Production/Stable pytest>=8.3.3 :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Nov 17, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Dec 03, 2024 5 - Production/Stable pytest>=7.0 @@ -634,6 +634,7 @@ This list contains 1613 plugins. :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A :pypi:`pytest-fzf` fzf-based test selector for pytest Jan 06, 2025 4 - Beta pytest>=6.0.0 :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A + :pypi:`pytest-gak` A Pytest plugin and command line tool for interactive testing with Pytest Mar 29, 2025 N/A N/A :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Aug 18, 2024 N/A pytest>=7.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 @@ -643,7 +644,7 @@ This list contains 1613 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Mar 28, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 04, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -687,7 +688,7 @@ This list contains 1613 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Mar 29, 2025 3 - Alpha pytest==8.3.5 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 05, 2025 3 - Alpha pytest==8.3.5 :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` Sep 23, 2024 N/A N/A @@ -718,7 +719,7 @@ This list contains 1613 plugins. :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Jul 25, 2024 4 - Beta pytest>=7.0.0 + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Apr 04, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Feb 06, 2025 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A @@ -756,7 +757,7 @@ This list contains 1613 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Feb 13, 2025 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Mar 07, 2025 5 - Production/Stable pytest<9.0.0,>=6 + :pypi:`pytest-invenio` Pytest fixtures for Invenio. Apr 02, 2025 5 - Production/Stable pytest<9.0.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.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 @@ -853,20 +854,20 @@ This list contains 1613 plugins. :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Mar 23, 2025 3 - Alpha pytest - :pypi:`pytest-logikal` Common testing environment Mar 02, 2025 5 - Production/Stable pytest==8.3.4 + :pypi:`pytest-logikal` Common testing environment Apr 02, 2025 5 - Production/Stable pytest==8.3.5 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" :pypi:`pytest-loop` pytest plugin for looping tests Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 23, 2024 3 - Alpha pytest :pypi:`pytest-lw-realtime-result` Pytest plugin to generate realtime test results to a file Mar 13, 2025 N/A pytest>=3.5.0 - :pypi:`pytest-manifest` PyTest plugin for recording and asserting against a manifest file Mar 18, 2025 N/A pytest + :pypi:`pytest-manifest` PyTest plugin for recording and asserting against a manifest file Apr 01, 2025 N/A pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Nov 13, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 13, 2025 N/A pytest>=7.0.0 - :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Jan 09, 2020 N/A N/A + :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Apr 02, 2025 5 - Production/Stable pytest>=2.2.4 :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Oct 30, 2024 4 - Beta pytest>=6.0 :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A :pypi:`pytest-mark-manage` 用例标签化管理 Aug 15, 2024 N/A pytest @@ -891,7 +892,7 @@ This list contains 1613 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Mar 27, 2025 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Mar 31, 2025 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -945,7 +946,7 @@ This list contains 1613 plugins. :pypi:`pytest-mutagen` Add the mutation testing feature to pytest Jul 24, 2020 N/A pytest (>=5.4) :pypi:`pytest-my-cool-lib` Nov 02, 2023 N/A pytest (>=7.1.3,<8.0.0) :pypi:`pytest-my-plugin` A pytest plugin that does awesome things Jan 27, 2025 N/A pytest>=6.0 - :pypi:`pytest-mypy` A Pytest Plugin for Mypy Mar 28, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-mypy` A Pytest Plugin for Mypy Apr 02, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-mypyd` Mypy static type checker plugin for Pytest Aug 20, 2019 4 - Beta pytest (<4.7,>=2.8) ; python_version < "3.5" :pypi:`pytest-mypy-plugins` pytest plugin for writing tests for mypy plugins Dec 21, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-mypy-plugins-shim` Substitute for "pytest-mypy-plugins" for Python implementations which aren't supported by mypy. Feb 14, 2025 N/A pytest>=6.0.0 @@ -965,7 +966,7 @@ This list contains 1613 plugins. :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) - :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Mar 21, 2025 N/A pytest<9.0.0,>=8.2.0 + :pypi:`pytest-nhsd-apim` Pytest plugin accessing NHSDigital's APIM proxies Apr 01, 2025 N/A pytest<9.0.0,>=8.2.0 :pypi:`pytest-nice` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-nice-parametrize` A small snippet for nicer PyTest's Parametrize Apr 17, 2021 5 - Production/Stable N/A :pypi:`pytest_nlcov` Pytest plugin to get the coverage of the new lines (based on git diff) only Aug 05, 2024 N/A N/A @@ -997,6 +998,7 @@ This list contains 1613 plugins. :pypi:`pytest-oof` A Pytest plugin providing structured, programmatic access to a test run's results Dec 11, 2023 4 - Beta N/A :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Jun 05, 2024 3 - Alpha pytest>=4.6 + :pypi:`pytest-open-html` Auto-open HTML reports after pytest runs Mar 31, 2025 N/A pytest>=6.0 :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Nov 22, 2024 N/A pytest :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Mar 22, 2025 5 - Production/Stable pytest>=5.0 :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest @@ -1047,7 +1049,7 @@ This list contains 1613 plugins. :pypi:`pytest-performancetotal` A performance plugin for pytest Feb 01, 2025 5 - Production/Stable N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Aug 21, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 21, 2024 5 - Production/Stable pytest>=6.0.0 + :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker Apr 03, 2025 5 - Production/Stable pytest>=8.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-phoenix-interface` Pytest extension tool for phoenix projects. Mar 19, 2025 N/A N/A @@ -1175,7 +1177,7 @@ This list contains 1613 plugins. :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jan 14, 2025 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A - :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Jan 09, 2025 N/A N/A + :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Mar 31, 2025 N/A N/A :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 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-record-video` 用例执行过程中录制视频 Oct 31, 2024 N/A N/A @@ -1204,7 +1206,7 @@ This list contains 1613 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A - :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Mar 20, 2025 N/A pytest>=8.0.0 + :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Apr 04, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-reportlog` Replacement for the --resultlog option, focused in simplicity and extensibility May 22, 2023 3 - Alpha pytest @@ -1283,7 +1285,7 @@ This list contains 1613 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Mar 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 04, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1295,7 +1297,7 @@ This list contains 1613 plugins. :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 Feb 01, 2024 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. Mar 29, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 04, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1328,6 +1330,7 @@ This list contains 1613 plugins. :pypi:`pytest-simple-plugin` Simple pytest plugin Nov 27, 2019 N/A N/A :pypi:`pytest-simple-settings` simple-settings plugin for pytest Nov 17, 2020 4 - Beta pytest :pypi:`pytest-single-file-logging` Allow for multiple processes to log to a single file May 05, 2016 4 - Beta pytest (>=2.8.1) + :pypi:`pytest-skip` A pytest plugin which allows to (de-)select or skip tests from a file. Apr 04, 2025 3 - Alpha pytest :pypi:`pytest-skip-markers` Pytest Salt Plugin Aug 09, 2024 5 - Production/Stable pytest>=7.1.0 :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) @@ -1448,7 +1451,7 @@ This list contains 1613 plugins. :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Mar 28, 2025 5 - Production/Stable pytest>=7.0.0 - :pypi:`pytest-testinfra` Test infrastructures May 26, 2024 5 - Production/Stable pytest>=6 + :pypi:`pytest-testinfra` Test infrastructures Mar 30, 2025 5 - Production/Stable pytest>=6 :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-testit-parametrize` A pytest plugin for uploading parameterized tests parameters into TMS TestIT Dec 04, 2024 4 - Beta pytest>=8.3.3 @@ -1646,7 +1649,7 @@ This list contains 1613 plugins. :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest :pypi:`pytest-zy` 接口自动化测试框架 Mar 24, 2024 N/A pytest~=7.2.0 - :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Mar 22, 2025 4 - Beta pytest>=8.3.5 + :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Apr 05, 2025 4 - Beta pytest>=8.3.5 =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -1975,7 +1978,7 @@ This list contains 1613 plugins. Pytest plugin to allow use of Annotated in tests to resolve fixtures :pypi:`pytest-ansible` - *last release*: Jan 21, 2025, + *last release*: Apr 01, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2409,7 +2412,7 @@ This list contains 1613 plugins. Protect your AWS credentials in unit tests :pypi:`pytest-aws-fixtures` - *last release*: Oct 07, 2024, + *last release*: Apr 04, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -2549,7 +2552,7 @@ This list contains 1613 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Mar 27, 2025, + *last release*: Apr 01, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3039,7 +3042,7 @@ This list contains 1613 plugins. A pytest fixture for changing current working directory :pypi:`pytest-check` - *last release*: Mar 18, 2025, + *last release*: Apr 04, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -3095,9 +3098,9 @@ This list contains 1613 plugins. pytest plugin to test Check_MK checks :pypi:`pytest-checkpoint` - *last release*: Mar 22, 2025, + *last release*: Mar 30, 2025, *status*: N/A, - *requires*: pytest>=8.3.5 + *requires*: pytest>=8.0.0 Restore a checkpoint in pytest @@ -3543,7 +3546,7 @@ This list contains 1613 plugins. count erros and send email :pypi:`pytest-cov` - *last release*: Oct 29, 2024, + *last release*: Apr 05, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=4.6 @@ -4187,7 +4190,7 @@ This list contains 1613 plugins. pytest-ditto plugin for pyarrow tables. :pypi:`pytest-django` - *last release*: Feb 10, 2025, + *last release*: Apr 03, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -4677,7 +4680,7 @@ This list contains 1613 plugins. A pytest plugin to rerun tests dynamically based off of test outcome and output. :pypi:`pytest-dynamodb` - *last release*: Mar 23, 2025, + *last release*: Apr 04, 2025, *status*: 5 - Production/Stable, *requires*: pytest @@ -4733,11 +4736,11 @@ This list contains 1613 plugins. Pytest execution on EC2 instance :pypi:`pytest-echo` - *last release*: Feb 22, 2025, + *last release*: Apr 01, 2025, *status*: 5 - Production/Stable, - *requires*: pytest>=6.0 + *requires*: pytest>=8.3.3 - pytest plugin with mechanisms for echoing environment variables, package version and generic attributes + pytest plugin that allows to dump environment variables, package version and generic attributes :pypi:`pytest-edit` *last release*: Nov 17, 2024, @@ -5852,6 +5855,13 @@ This list contains 1613 plugins. pytest plugin for apps written with Google's AppEngine + :pypi:`pytest-gak` + *last release*: Mar 29, 2025, + *status*: N/A, + *requires*: N/A + + A Pytest plugin and command line tool for interactive testing with Pytest + :pypi:`pytest-gather-fixtures` *last release*: Aug 18, 2024, *status*: N/A, @@ -5916,7 +5926,7 @@ This list contains 1613 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Mar 28, 2025, + *last release*: Apr 04, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6224,7 +6234,7 @@ This list contains 1613 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Mar 29, 2025, + *last release*: Apr 05, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.5 @@ -6441,7 +6451,7 @@ This list contains 1613 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Jul 25, 2024, + *last release*: Apr 04, 2025, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -6707,7 +6717,7 @@ This list contains 1613 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Mar 07, 2025, + *last release*: Apr 02, 2025, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=6 @@ -7386,9 +7396,9 @@ This list contains 1613 plugins. pytest fixture logging configured from packaged YAML :pypi:`pytest-logikal` - *last release*: Mar 02, 2025, + *last release*: Apr 02, 2025, *status*: 5 - Production/Stable, - *requires*: pytest==8.3.4 + *requires*: pytest==8.3.5 Common testing environment @@ -7435,7 +7445,7 @@ This list contains 1613 plugins. Pytest plugin to generate realtime test results to a file :pypi:`pytest-manifest` - *last release*: Mar 18, 2025, + *last release*: Apr 01, 2025, *status*: N/A, *requires*: pytest @@ -7477,9 +7487,9 @@ This list contains 1613 plugins. Run markdown code fences through pytest :pypi:`pytest-marker-bugzilla` - *last release*: Jan 09, 2020, - *status*: N/A, - *requires*: N/A + *last release*: Apr 02, 2025, + *status*: 5 - Production/Stable, + *requires*: pytest>=2.2.4 py.test bugzilla integration plugin, using markers @@ -7652,7 +7662,7 @@ This list contains 1613 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Mar 27, 2025, + *last release*: Mar 31, 2025, *status*: N/A, *requires*: N/A @@ -8030,7 +8040,7 @@ This list contains 1613 plugins. A pytest plugin that does awesome things :pypi:`pytest-mypy` - *last release*: Mar 28, 2025, + *last release*: Apr 02, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -8170,7 +8180,7 @@ This list contains 1613 plugins. pytest ngs fixtures :pypi:`pytest-nhsd-apim` - *last release*: Mar 21, 2025, + *last release*: Apr 01, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=8.2.0 @@ -8393,6 +8403,13 @@ This list contains 1613 plugins. Pytest plugin for detecting inadvertent open file handles + :pypi:`pytest-open-html` + *last release*: Mar 31, 2025, + *status*: N/A, + *requires*: pytest>=6.0 + + Auto-open HTML reports after pytest runs + :pypi:`pytest-opentelemetry` *last release*: Nov 22, 2024, *status*: N/A, @@ -8744,9 +8761,9 @@ This list contains 1613 plugins. Pytest pexpect plugin. :pypi:`pytest-pg` - *last release*: May 21, 2024, + *last release*: Apr 03, 2025, *status*: 5 - Production/Stable, - *requires*: pytest>=6.0.0 + *requires*: pytest>=8.0.0 A tiny plugin for pytest which runs PostgreSQL in Docker @@ -9640,7 +9657,7 @@ This list contains 1613 plugins. Pytest fixtures for REANA. :pypi:`pytest-recorder` - *last release*: Jan 09, 2025, + *last release*: Mar 31, 2025, *status*: N/A, *requires*: N/A @@ -9843,7 +9860,7 @@ This list contains 1613 plugins. A basic HTML report for pytest using Jinja2 template engine. :pypi:`pytest-report-extras` - *last release*: Mar 20, 2025, + *last release*: Apr 04, 2025, *status*: N/A, *requires*: pytest>=8.0.0 @@ -10396,7 +10413,7 @@ This list contains 1613 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Mar 29, 2025, + *last release*: Apr 04, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10480,7 +10497,7 @@ This list contains 1613 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Mar 29, 2025, + *last release*: Apr 04, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10710,6 +10727,13 @@ This list contains 1613 plugins. Allow for multiple processes to log to a single file + :pypi:`pytest-skip` + *last release*: Apr 04, 2025, + *status*: 3 - Alpha, + *requires*: pytest + + A pytest plugin which allows to (de-)select or skip tests from a file. + :pypi:`pytest-skip-markers` *last release*: Aug 09, 2024, *status*: 5 - Production/Stable, @@ -11551,7 +11575,7 @@ This list contains 1613 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-testinfra` - *last release*: May 26, 2024, + *last release*: Mar 30, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -12937,7 +12961,7 @@ This list contains 1613 plugins. 接口自动化测试框架 :pypi:`tursu` - *last release*: Mar 22, 2025, + *last release*: Apr 05, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3.5 From 3f463206f7b484074910e71732d4f03449130320 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 06:18:23 +0200 Subject: [PATCH 1186/1271] build(deps): Bump pytest-django in /testing/plugins_integration (#13357) Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.10.0 to 4.11.1. - [Release notes](https://github.com/pytest-dev/pytest-django/releases) - [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst) - [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.10.0...v4.11.1) --- updated-dependencies: - dependency-name: pytest-django dependency-version: 4.11.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 05565fe89d4..fc604e1888d 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -3,7 +3,7 @@ django==5.1.7 pytest-asyncio==0.26.0 pytest-bdd==8.1.0 pytest-cov==6.0.0 -pytest-django==4.10.0 +pytest-django==4.11.1 pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.14.0 From 18439f52fd00bfa42a7ad1d66ca862bc62e36c59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 04:53:01 +0000 Subject: [PATCH 1187/1271] build(deps): Bump pytest-cov in /testing/plugins_integration (#13358) Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 6.0.0 to 6.1.1. - [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-cov/compare/v6.0.0...v6.1.1) --- updated-dependencies: - dependency-name: pytest-cov dependency-version: 6.1.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index fc604e1888d..93e3dc7d0b1 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -2,7 +2,7 @@ anyio[trio]==4.9.0 django==5.1.7 pytest-asyncio==0.26.0 pytest-bdd==8.1.0 -pytest-cov==6.0.0 +pytest-cov==6.1.1 pytest-django==4.11.1 pytest-flakes==4.0.5 pytest-html==4.1.1 From 46c94ee82ddbb4a541f5bd4fecd0b4071e1972ae Mon Sep 17 00:00:00 2001 From: Bahram Farahmand Date: Mon, 7 Apr 2025 14:02:21 +0300 Subject: [PATCH 1188/1271] Add note on using mixin classes for abstract test classes in documentation (#13346) --- changelog/8612.doc.rst | 5 +++++ doc/en/example/pythoncollection.rst | 27 +++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 changelog/8612.doc.rst diff --git a/changelog/8612.doc.rst b/changelog/8612.doc.rst new file mode 100644 index 00000000000..6ab4102ace4 --- /dev/null +++ b/changelog/8612.doc.rst @@ -0,0 +1,5 @@ +Add a recipe for handling abstract test classes in the documentation. + +A new example has been added to the documentation to demonstrate how to use a mixin class to handle abstract +test classes without manually setting the ``__test__`` attribute for subclasses. +This ensures that subclasses of abstract test classes are automatically collected by pytest. diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 89d7ee42614..6a3b143d580 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -325,3 +325,30 @@ with ``Test`` by setting a boolean ``__test__`` attribute to ``False``. # Will not be discovered as a test class TestClass: __test__ = False + +.. note:: + + If you are working with abstract test classes and want to avoid manually setting + the ``__test__`` attribute for subclasses, you can use a mixin class to handle + this automatically. For example: + + .. code-block:: python + + # Mixin to handle abstract test classes + class NotATest: + def __init_subclass__(cls): + cls.__test__ = NotATest not in cls.__bases__ + + + # Abstract test class + class AbstractTest(NotATest): + pass + + + # Subclass that will be collected as a test + class RealTest(AbstractTest): + def test_example(self): + assert 1 + 1 == 2 + + This approach ensures that subclasses of abstract test classes are automatically + collected without needing to explicitly set the ``__test__`` attribute. From 0286f64602f4b3a5d64bdfd832595cecbe1738d1 Mon Sep 17 00:00:00 2001 From: TobiMcNamobi Date: Mon, 7 Apr 2025 20:33:28 +0200 Subject: [PATCH 1189/1271] Fix test suite when PYTEST_PLUGINS is set Fixes #12647 --- changelog/12647.contrib.rst | 1 + testing/test_helpconfig.py | 2 ++ testing/test_terminal.py | 1 + 3 files changed, 4 insertions(+) create mode 100644 changelog/12647.contrib.rst diff --git a/changelog/12647.contrib.rst b/changelog/12647.contrib.rst new file mode 100644 index 00000000000..1d7a3181778 --- /dev/null +++ b/changelog/12647.contrib.rst @@ -0,0 +1 @@ +Fixed running the test suite with the ``hypothesis`` pytest plugin. diff --git a/testing/test_helpconfig.py b/testing/test_helpconfig.py index 7fcf5804ace..dc7e709b65d 100644 --- a/testing/test_helpconfig.py +++ b/testing/test_helpconfig.py @@ -8,6 +8,7 @@ def test_version_verbose(pytester: Pytester, pytestconfig, monkeypatch) -> None: monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD") + monkeypatch.delenv("PYTEST_PLUGINS", raising=False) result = pytester.runpytest("--version", "--version") assert result.ret == 0 result.stdout.fnmatch_lines([f"*pytest*{pytest.__version__}*imported from*"]) @@ -17,6 +18,7 @@ def test_version_verbose(pytester: Pytester, pytestconfig, monkeypatch) -> None: def test_version_less_verbose(pytester: Pytester, pytestconfig, monkeypatch) -> None: monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD") + monkeypatch.delenv("PYTEST_PLUGINS", raising=False) result = pytester.runpytest("--version") assert result.ret == 0 result.stdout.fnmatch_lines([f"pytest {pytest.__version__}"]) diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 42638f2edd7..86feb33b3ec 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -859,6 +859,7 @@ def test_header_trailer_info( self, monkeypatch: MonkeyPatch, pytester: Pytester, request ) -> None: monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD") + monkeypatch.delenv("PYTEST_PLUGINS", raising=False) pytester.makepyfile( """ def test_passes(): From 9d7bf4e544f6e9d43ab0dd390a820d4dae140a53 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 8 Apr 2025 06:18:52 +0200 Subject: [PATCH 1190/1271] [pre-commit.ci] pre-commit autoupdate (#13362) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.2 → v0.11.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.2...v0.11.4) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3741df6f51b..3573c876d9e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.2" + rev: "v0.11.4" hooks: - id: ruff args: ["--fix"] From b72f9a2d02f50b458970b8367b7d18de5baf0108 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 13 Apr 2025 04:48:41 +0000 Subject: [PATCH 1191/1271] [automated] Update plugin list (#13372) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 150 +++++++++++++++++++------------ 1 file changed, 91 insertions(+), 59 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 406ebe75dce..6690ad5196a 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.0.0 + :pypi:`pytest-aws-fixtures` A series of fixtures to use in integration tests involving actual AWS services. Apr 06, 2025 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-axe` pytest plugin for axe-selenium-python Nov 12, 2018 N/A pytest (>=3.0.0) :pypi:`pytest-axe-playwright-snapshot` A pytest plugin that runs Axe-core on Playwright pages and takes snapshots of the results. Jul 25, 2023 N/A pytest :pypi:`pytest-azure` Pytest utilities and mocks for Azure Jan 18, 2023 3 - Alpha pytest @@ -184,6 +184,7 @@ This list contains 1616 plugins. :pypi:`pytest-blue` A pytest plugin that adds a \`blue\` fixture for printing stuff in blue. Sep 05, 2022 N/A N/A :pypi:`pytest-board` Local continuous test runner with pytest and watchdog. Jan 20, 2019 N/A N/A :pypi:`pytest-boilerplate` The pytest plugin for your Django Boilerplate. Sep 12, 2024 5 - Production/Stable pytest>=4.0.0 + :pypi:`pytest-bonsai` Apr 08, 2025 N/A pytest>=6 :pypi:`pytest-boost-xml` Plugin for pytest to generate boost xml reports Nov 30, 2022 4 - Beta N/A :pypi:`pytest-bootstrap` Mar 04, 2022 N/A N/A :pypi:`pytest-boto-mock` Thin-wrapper around the mock package for easier use with pytest Jul 16, 2024 5 - Production/Stable pytest>=8.2.0 @@ -256,7 +257,7 @@ This list contains 1616 plugins. :pypi:`pytest-class-fixtures` Class as PyTest fixtures (and BDD steps) Nov 15, 2024 N/A pytest<9.0.0,>=8.3.3 :pypi:`pytest-cldf` Easy quality control for CLDF datasets using pytest Nov 07, 2022 N/A pytest (>=3.6) :pypi:`pytest-clean-database` A pytest plugin that cleans your database up after every test. Mar 14, 2025 3 - Alpha pytest<9,>=7.0 - :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Sep 04, 2024 N/A pytest + :pypi:`pytest-cleanslate` Collects and executes pytest tests separately Apr 10, 2025 N/A pytest :pypi:`pytest_cleanup` Automated, comprehensive and well-organised pytest test cases. Jan 28, 2020 N/A N/A :pypi:`pytest-cleanuptotal` A cleanup plugin for pytest Nov 08, 2024 5 - Production/Stable N/A :pypi:`pytest-clerk` A set of pytest fixtures to help with integration testing with Clerk. Jan 30, 2025 N/A pytest<9.0.0,>=8.0.0 @@ -300,7 +301,7 @@ This list contains 1616 plugins. :pypi:`pytest-contexts` A plugin to run tests written with the Contexts framework using pytest May 19, 2021 4 - Beta N/A :pypi:`pytest-continuous` A pytest plugin to run tests continuously until failure or interruption. Apr 23, 2024 N/A N/A :pypi:`pytest-cookies` The pytest plugin for your Cookiecutter templates. 🍪 Mar 22, 2023 5 - Production/Stable pytest (>=3.9.0) - :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Jan 31, 2025 3 - Alpha pytest + :pypi:`pytest-copie` The pytest plugin for your copier templates 📒 Apr 09, 2025 3 - Alpha pytest :pypi:`pytest-copier` A pytest plugin to help testing Copier templates Dec 11, 2023 4 - Beta pytest>=7.3.2 :pypi:`pytest-couchdbkit` py.test extension for per-test couchdb databases using couchdbkit Apr 17, 2012 N/A N/A :pypi:`pytest-count` count erros and send email Jan 12, 2018 4 - Beta N/A @@ -338,7 +339,7 @@ This list contains 1616 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Mar 23, 2025 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 06, 2025 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Feb 07, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -421,7 +422,7 @@ This list contains 1616 plugins. :pypi:`pytest-doc` A documentation plugin for py.test. Jun 28, 2015 5 - Production/Stable N/A :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A - :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Feb 06, 2025 N/A pytest<9.0,>=4.0 + :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Apr 07, 2025 N/A pytest<9.0,>=4.0 :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) @@ -634,7 +635,7 @@ This list contains 1616 plugins. :pypi:`pytest-fxtest` Oct 27, 2020 N/A N/A :pypi:`pytest-fzf` fzf-based test selector for pytest Jan 06, 2025 4 - Beta pytest>=6.0.0 :pypi:`pytest_gae` pytest plugin for apps written with Google's AppEngine Aug 03, 2016 3 - Alpha N/A - :pypi:`pytest-gak` A Pytest plugin and command line tool for interactive testing with Pytest Mar 29, 2025 N/A N/A + :pypi:`pytest-gak` A Pytest plugin and command line tool for interactive testing with Pytest Apr 10, 2025 N/A N/A :pypi:`pytest-gather-fixtures` set up asynchronous pytest fixtures concurrently Aug 18, 2024 N/A pytest>=7.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 @@ -644,7 +645,7 @@ This list contains 1616 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 04, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 08, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -711,7 +712,7 @@ This list contains 1616 plugins. :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace. Feb 11, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A - :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Feb 24, 2025 3 - Alpha N/A + :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Apr 10, 2025 3 - Alpha N/A :pypi:`pytest-httptesting` http_testing framework on top of pytest Dec 19, 2024 N/A pytest>=8.2.0 :pypi:`pytest-httpx` Send responses to httpx. Nov 28, 2024 5 - Production/Stable pytest==8.* :pypi:`pytest-httpx-blockage` Disable httpx requests during a test run Feb 16, 2023 N/A pytest (>=7.2.1) @@ -742,9 +743,9 @@ This list contains 1616 plugins. :pypi:`pytest-ini` Reuse pytest.ini to store env variables Apr 26, 2022 N/A N/A :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-inline` A pytest plugin for writing inline tests Oct 24, 2024 4 - Beta pytest<9.0,>=7.0 - :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Oct 10, 2024 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Jan 17, 2025 5 - Production/Stable N/A - :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Dec 13, 2024 5 - Production/Stable N/A + :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Apr 09, 2025 5 - Production/Stable pytest + :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 10, 2025 5 - Production/Stable N/A + :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Apr 09, 2025 5 - Production/Stable N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Nov 23, 2024 N/A pytest @@ -853,7 +854,7 @@ This list contains 1616 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Mar 23, 2025 3 - Alpha pytest + :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Apr 09, 2025 3 - Alpha pytest :pypi:`pytest-logikal` Common testing environment Apr 02, 2025 5 - Production/Stable pytest==8.3.5 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 @@ -861,12 +862,12 @@ This list contains 1616 plugins. :pypi:`pytest-loop` pytest plugin for looping tests Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-lsp` A pytest plugin for end-to-end testing of language servers Nov 23, 2024 3 - Alpha pytest :pypi:`pytest-lw-realtime-result` Pytest plugin to generate realtime test results to a file Mar 13, 2025 N/A pytest>=3.5.0 - :pypi:`pytest-manifest` PyTest plugin for recording and asserting against a manifest file Apr 01, 2025 N/A pytest + :pypi:`pytest-manifest` PyTest plugin for recording and asserting against a manifest file Apr 07, 2025 N/A pytest :pypi:`pytest-manual-marker` pytest marker for marking manual tests Aug 04, 2022 3 - Alpha pytest>=7 :pypi:`pytest-mark-count` Get a count of the number of tests marked, unmarked, and unique tests if tests have multiple markers Nov 13, 2024 4 - Beta pytest>=8.0.0 :pypi:`pytest-markdoctest` A pytest plugin to doctest your markdown files Jul 22, 2022 4 - Beta pytest (>=6) :pypi:`pytest-markdown` Test your markdown docs with pytest Jan 15, 2021 4 - Beta pytest (>=6.0.1,<7.0.0) - :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Mar 13, 2025 N/A pytest>=7.0.0 + :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Apr 09, 2025 N/A pytest>=7.0.0 :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Apr 02, 2025 5 - Production/Stable pytest>=2.2.4 :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Oct 30, 2024 4 - Beta pytest>=6.0 :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A @@ -892,7 +893,7 @@ This list contains 1616 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Mar 31, 2025 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify Apr 10, 2025 N/A N/A :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A @@ -900,12 +901,14 @@ This list contains 1616 plugins. :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest :pypi:`pytest-mh` Pytest multihost plugin Mar 06, 2025 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) + :pypi:`pytest-mimic` Easily record function calls while testing Apr 11, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Aug 27, 2024 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-missing-modules` Pytest plugin to easily fake missing modules Sep 03, 2024 N/A pytest>=8.3.2 :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Nov 13, 2024 N/A pytest>=7.0 + :pypi:`pytest-mitmproxy-plugin` Use MITM Proxy in autotests with full control from code Apr 10, 2025 4 - Beta pytest>=7.2.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Mar 21, 2024 5 - Production/Stable pytest>=6.2.5 @@ -958,7 +961,7 @@ This list contains 1616 plugins. :pypi:`pytest-neo` pytest-neo is a plugin for pytest that shows tests like screen of Matrix. Jan 08, 2022 3 - Alpha pytest (>=6.2.0) :pypi:`pytest-neos` Pytest plugin for neos Sep 10, 2024 5 - Production/Stable pytest<8.0,>=7.2; extra == "dev" :pypi:`pytest-netconf` A pytest plugin that provides a mock NETCONF (RFC6241/RFC6242) server for local testing. Jan 06, 2025 N/A N/A - :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Jul 05, 2024 N/A pytest<7.3,>=3.5.0 + :pypi:`pytest-netdut` "Automated software testing for switches using pytest" Apr 11, 2025 N/A pytest>=3.5.0 :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) @@ -974,6 +977,7 @@ This list contains 1616 plugins. :pypi:`pytest-node-dependency` pytest plugin for controlling execution flow Apr 10, 2024 5 - Production/Stable N/A :pypi:`pytest-nodev` Test-driven source code search for Python. Jul 21, 2016 4 - Beta pytest (>=2.8.1) :pypi:`pytest-nogarbage` Ensure a test produces no garbage Feb 24, 2025 5 - Production/Stable pytest>=4.6.0 + :pypi:`pytest-no-problem` Pytest plugin to tell you when there's no problem Apr 05, 2025 N/A pytest>=7.0 :pypi:`pytest-nose-attrib` pytest plugin to use nose @attrib marks decorators and pick tests based on attributes and partially uses nose-attrib plugin approach Aug 13, 2023 N/A N/A :pypi:`pytest_notebook` A pytest plugin for testing Jupyter Notebooks. Nov 28, 2023 4 - Beta pytest>=3.5.0 :pypi:`pytest-notice` Send pytest execution result email Nov 05, 2020 N/A N/A @@ -1021,7 +1025,6 @@ This list contains 1616 plugins. :pypi:`pytest-parallel-39` a pytest plugin for parallel and concurrent testing Jul 12, 2021 3 - Alpha pytest (>=3.0.0) :pypi:`pytest-parallelize-tests` pytest plugin that parallelizes test execution across multiple hosts Jan 27, 2023 4 - Beta N/A :pypi:`pytest-param` pytest plugin to test all, first, last or random params Sep 11, 2016 4 - Beta pytest (>=2.6.0) - :pypi:`pytest-paramark` Configure pytest fixtures using a combination of"parametrize" and markers Jan 10, 2020 4 - Beta pytest (>=4.5.0) :pypi:`pytest-parametrization` Simpler PyTest parametrization May 22, 2022 5 - Production/Stable N/A :pypi:`pytest-parametrization-annotation` A pytest library for parametrizing tests using type hints. Dec 10, 2024 5 - Production/Stable pytest>=7 :pypi:`pytest-parametrize` pytest decorator for parametrizing test cases in a dict-way Nov 10, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 @@ -1049,7 +1052,7 @@ This list contains 1616 plugins. :pypi:`pytest-performancetotal` A performance plugin for pytest Feb 01, 2025 5 - Production/Stable N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Aug 21, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker Apr 03, 2025 5 - Production/Stable pytest>=8.0.0 + :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker Apr 11, 2025 5 - Production/Stable pytest>=8.0.0 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-phoenix-interface` Pytest extension tool for phoenix projects. Mar 19, 2025 N/A N/A @@ -1174,7 +1177,7 @@ This list contains 1616 plugins. :pypi:`pytest-randomness` Pytest plugin about random seed management May 30, 2019 3 - Alpha N/A :pypi:`pytest-random-num` Randomise the order in which pytest tests are run with some control over the randomness Oct 19, 2020 5 - Production/Stable N/A :pypi:`pytest-random-order` Randomise the order in which pytest tests are run with some control over the randomness Jan 20, 2024 5 - Production/Stable pytest >=3.0.0 - :pypi:`pytest-ranking` A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection Jan 14, 2025 4 - Beta pytest>=7.4.3 + :pypi:`pytest-ranking` A Pytest plugin for faster fault detection via regression test prioritization Apr 08, 2025 4 - Beta pytest>=7.4.3 :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Mar 31, 2025 N/A N/A @@ -1198,7 +1201,7 @@ This list contains 1616 plugins. :pypi:`pytest-remote-response` Pytest plugin for capturing and mocking connection requests. Apr 26, 2023 5 - Production/Stable pytest (>=4.6) :pypi:`pytest-remove-stale-bytecode` py.test plugin to remove stale byte code files. Jul 07, 2023 4 - Beta pytest :pypi:`pytest-reorder` Reorder tests depending on their paths and names. May 31, 2018 4 - Beta pytest - :pypi:`pytest-repeat` pytest plugin for repeating tests Oct 09, 2023 5 - Production/Stable pytest + :pypi:`pytest-repeat` pytest plugin for repeating tests Apr 07, 2025 5 - Production/Stable pytest :pypi:`pytest_repeater` py.test plugin for repeating single test multiple times. Feb 09, 2018 1 - Planning N/A :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Feb 05, 2025 5 - Production/Stable pytest :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Mar 12, 2025 3 - Alpha pytest @@ -1285,7 +1288,7 @@ This list contains 1616 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 04, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 10, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1297,7 +1300,7 @@ This list contains 1616 plugins. :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 Feb 01, 2024 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. Apr 04, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 10, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1432,7 +1435,7 @@ This list contains 1616 plugins. :pypi:`pytest-tap` Test Anything Protocol (TAP) reporting plugin for pytest Jan 30, 2025 5 - Production/Stable pytest>=3.0 :pypi:`pytest-tape` easy assertion with expected results saved to yaml files Mar 17, 2021 4 - Beta N/A :pypi:`pytest-target` Pytest plugin for remote target orchestration. Jan 21, 2021 3 - Alpha pytest (>=6.1.2,<7.0.0) - :pypi:`pytest-taskgraph` Add your description here Dec 12, 2024 N/A pytest + :pypi:`pytest-taskgraph` Add your description here Apr 09, 2025 N/A pytest :pypi:`pytest-tblineinfo` tblineinfo is a py.test plugin that insert the node id in the final py.test report when --tb=line option is used Dec 01, 2015 3 - Alpha pytest (>=2.0) :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A @@ -1533,6 +1536,7 @@ This list contains 1616 plugins. :pypi:`pytest-tst` Customize pytest options, output and exit code to make it compatible with tst Apr 27, 2022 N/A pytest (>=5.0.0) :pypi:`pytest-tstcls` Test Class Base Mar 23, 2020 5 - Production/Stable N/A :pypi:`pytest-tui` Text User Interface (TUI) and HTML report for Pytest test runs Dec 08, 2023 4 - Beta N/A + :pypi:`pytest-tuitest` pytest plugin for testing TUI and regular command-line applications. Apr 11, 2025 N/A pytest>=7.4.0 :pypi:`pytest-tutorials` Mar 11, 2023 N/A N/A :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A :pypi:`pytest-twisted` A twisted plugin for pytest. Sep 10, 2024 5 - Production/Stable pytest>=2.3 @@ -1634,7 +1638,7 @@ This list contains 1616 plugins. :pypi:`pytest-yapf` Run yapf Jul 06, 2017 4 - Beta pytest (>=3.1.1) :pypi:`pytest-yapf3` Validate your Python file format with yapf Mar 29, 2023 5 - Production/Stable pytest (>=7) :pypi:`pytest-yield` PyTest plugin to run tests concurrently, each \`yield\` switch context to other one Jan 23, 2019 N/A N/A - :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Oct 18, 2024 N/A pytest<9.0.0,>=8.3.3 + :pypi:`pytest-yls` Pytest plugin to test the YLS as a whole. Apr 09, 2025 N/A pytest<9.0.0,>=8.3.3 :pypi:`pytest-youqu-playwright` pytest-youqu-playwright Jun 12, 2024 N/A pytest :pypi:`pytest-yuk` Display tests you are uneasy with, using 🤢/🤮 for pass/fail of tests marked with yuk. Mar 26, 2021 N/A pytest>=5.0.0 :pypi:`pytest-zafira` A Zafira plugin for pytest Sep 18, 2019 5 - Production/Stable pytest (==4.1.1) @@ -1649,7 +1653,7 @@ This list contains 1616 plugins. :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest :pypi:`pytest-zy` 接口自动化测试框架 Mar 24, 2024 N/A pytest~=7.2.0 - :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Apr 05, 2025 4 - Beta pytest>=8.3.5 + :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Apr 10, 2025 4 - Beta pytest>=8.3.5 =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -2412,7 +2416,7 @@ This list contains 1616 plugins. Protect your AWS credentials in unit tests :pypi:`pytest-aws-fixtures` - *last release*: Apr 04, 2025, + *last release*: Apr 06, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=8.0.0 @@ -2705,6 +2709,13 @@ This list contains 1616 plugins. The pytest plugin for your Django Boilerplate. + :pypi:`pytest-bonsai` + *last release*: Apr 08, 2025, + *status*: N/A, + *requires*: pytest>=6 + + + :pypi:`pytest-boost-xml` *last release*: Nov 30, 2022, *status*: 4 - Beta, @@ -3210,7 +3221,7 @@ This list contains 1616 plugins. A pytest plugin that cleans your database up after every test. :pypi:`pytest-cleanslate` - *last release*: Sep 04, 2024, + *last release*: Apr 10, 2025, *status*: N/A, *requires*: pytest @@ -3518,7 +3529,7 @@ This list contains 1616 plugins. The pytest plugin for your Cookiecutter templates. 🍪 :pypi:`pytest-copie` - *last release*: Jan 31, 2025, + *last release*: Apr 09, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3784,7 +3795,7 @@ This list contains 1616 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Mar 23, 2025, + *last release*: Apr 06, 2025, *status*: 4 - Beta, *requires*: pytest @@ -4365,7 +4376,7 @@ This list contains 1616 plugins. An RST Documentation Generator for pytest-based test suites :pypi:`pytest-docker` - *last release*: Feb 06, 2025, + *last release*: Apr 07, 2025, *status*: N/A, *requires*: pytest<9.0,>=4.0 @@ -5856,7 +5867,7 @@ This list contains 1616 plugins. pytest plugin for apps written with Google's AppEngine :pypi:`pytest-gak` - *last release*: Mar 29, 2025, + *last release*: Apr 10, 2025, *status*: N/A, *requires*: N/A @@ -5926,7 +5937,7 @@ This list contains 1616 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Apr 04, 2025, + *last release*: Apr 08, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6395,7 +6406,7 @@ This list contains 1616 plugins. A thin wrapper of HTTPretty for pytest :pypi:`pytest_httpserver` - *last release*: Feb 24, 2025, + *last release*: Apr 10, 2025, *status*: 3 - Alpha, *requires*: N/A @@ -6612,21 +6623,21 @@ This list contains 1616 plugins. A pytest plugin for writing inline tests :pypi:`pytest-inmanta` - *last release*: Oct 10, 2024, + *last release*: Apr 09, 2025, *status*: 5 - Production/Stable, *requires*: pytest A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Jan 17, 2025, + *last release*: Apr 10, 2025, *status*: 5 - Production/Stable, *requires*: N/A Inmanta tests package :pypi:`pytest-inmanta-lsm` - *last release*: Dec 13, 2024, + *last release*: Apr 09, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -7389,7 +7400,7 @@ This list contains 1616 plugins. :pypi:`pytest-logging-strict` - *last release*: Mar 23, 2025, + *last release*: Apr 09, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -7445,7 +7456,7 @@ This list contains 1616 plugins. Pytest plugin to generate realtime test results to a file :pypi:`pytest-manifest` - *last release*: Apr 01, 2025, + *last release*: Apr 07, 2025, *status*: N/A, *requires*: pytest @@ -7480,7 +7491,7 @@ This list contains 1616 plugins. Test your markdown docs with pytest :pypi:`pytest-markdown-docs` - *last release*: Mar 13, 2025, + *last release*: Apr 09, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -7662,7 +7673,7 @@ This list contains 1616 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Mar 31, 2025, + *last release*: Apr 10, 2025, *status*: N/A, *requires*: N/A @@ -7717,6 +7728,13 @@ This list contains 1616 plugins. Mimesis integration with the pytest test runner + :pypi:`pytest-mimic` + *last release*: Apr 11, 2025, + *status*: 4 - Beta, + *requires*: pytest>=6.2.0 + + Easily record function calls while testing + :pypi:`pytest-minecraft` *last release*: Apr 06, 2022, *status*: N/A, @@ -7759,6 +7777,13 @@ This list contains 1616 plugins. pytest plugin for mitmproxy tests + :pypi:`pytest-mitmproxy-plugin` + *last release*: Apr 10, 2025, + *status*: 4 - Beta, + *requires*: pytest>=7.2.0 + + Use MITM Proxy in autotests with full control from code + :pypi:`pytest-ml` *last release*: May 04, 2019, *status*: 4 - Beta, @@ -8124,9 +8149,9 @@ This list contains 1616 plugins. A pytest plugin that provides a mock NETCONF (RFC6241/RFC6242) server for local testing. :pypi:`pytest-netdut` - *last release*: Jul 05, 2024, + *last release*: Apr 11, 2025, *status*: N/A, - *requires*: pytest<7.3,>=3.5.0 + *requires*: pytest>=3.5.0 "Automated software testing for switches using pytest" @@ -8235,6 +8260,13 @@ This list contains 1616 plugins. Ensure a test produces no garbage + :pypi:`pytest-no-problem` + *last release*: Apr 05, 2025, + *status*: N/A, + *requires*: pytest>=7.0 + + Pytest plugin to tell you when there's no problem + :pypi:`pytest-nose-attrib` *last release*: Aug 13, 2023, *status*: N/A, @@ -8564,13 +8596,6 @@ This list contains 1616 plugins. pytest plugin to test all, first, last or random params - :pypi:`pytest-paramark` - *last release*: Jan 10, 2020, - *status*: 4 - Beta, - *requires*: pytest (>=4.5.0) - - Configure pytest fixtures using a combination of"parametrize" and markers - :pypi:`pytest-parametrization` *last release*: May 22, 2022, *status*: 5 - Production/Stable, @@ -8761,7 +8786,7 @@ This list contains 1616 plugins. Pytest pexpect plugin. :pypi:`pytest-pg` - *last release*: Apr 03, 2025, + *last release*: Apr 11, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=8.0.0 @@ -9636,11 +9661,11 @@ This list contains 1616 plugins. Randomise the order in which pytest tests are run with some control over the randomness :pypi:`pytest-ranking` - *last release*: Jan 14, 2025, + *last release*: Apr 08, 2025, *status*: 4 - Beta, *requires*: pytest>=7.4.3 - A Pytest plugin for automatically prioritizing/ranking tests to speed up failure detection + A Pytest plugin for faster fault detection via regression test prioritization :pypi:`pytest-readme` *last release*: Sep 02, 2022, @@ -9804,7 +9829,7 @@ This list contains 1616 plugins. Reorder tests depending on their paths and names. :pypi:`pytest-repeat` - *last release*: Oct 09, 2023, + *last release*: Apr 07, 2025, *status*: 5 - Production/Stable, *requires*: pytest @@ -10413,7 +10438,7 @@ This list contains 1616 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Apr 04, 2025, + *last release*: Apr 10, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10497,7 +10522,7 @@ This list contains 1616 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Apr 04, 2025, + *last release*: Apr 10, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -11442,7 +11467,7 @@ This list contains 1616 plugins. Pytest plugin for remote target orchestration. :pypi:`pytest-taskgraph` - *last release*: Dec 12, 2024, + *last release*: Apr 09, 2025, *status*: N/A, *requires*: pytest @@ -12148,6 +12173,13 @@ This list contains 1616 plugins. Text User Interface (TUI) and HTML report for Pytest test runs + :pypi:`pytest-tuitest` + *last release*: Apr 11, 2025, + *status*: N/A, + *requires*: pytest>=7.4.0 + + pytest plugin for testing TUI and regular command-line applications. + :pypi:`pytest-tutorials` *last release*: Mar 11, 2023, *status*: N/A, @@ -12856,7 +12888,7 @@ This list contains 1616 plugins. PyTest plugin to run tests concurrently, each \`yield\` switch context to other one :pypi:`pytest-yls` - *last release*: Oct 18, 2024, + *last release*: Apr 09, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=8.3.3 @@ -12961,7 +12993,7 @@ This list contains 1616 plugins. 接口自动化测试框架 :pypi:`tursu` - *last release*: Apr 05, 2025, + *last release*: Apr 10, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3.5 From 103b2b67b015b5f677eef471c3d34706b5efedaa Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 21:34:23 -0300 Subject: [PATCH 1192/1271] [pre-commit.ci] pre-commit autoupdate (#13375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.4 → v0.11.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.4...v0.11.5) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3573c876d9e..a9d59e15551 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.4" + rev: "v0.11.5" hooks: - id: ruff args: ["--fix"] From 61c204a0355c89946cb0f3202820c5a0ec85e13d Mon Sep 17 00:00:00 2001 From: Stefan Zimmermann Date: Fri, 18 Apr 2025 23:18:36 +0200 Subject: [PATCH 1193/1271] Fix handling of positional-only parameters in test methods (#13377) Fixes #13376 --- changelog/13377.bugfix.rst | 12 ++++++++++++ src/_pytest/compat.py | 10 +++++----- testing/python/fixtures.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 changelog/13377.bugfix.rst diff --git a/changelog/13377.bugfix.rst b/changelog/13377.bugfix.rst new file mode 100644 index 00000000000..15755481f7f --- /dev/null +++ b/changelog/13377.bugfix.rst @@ -0,0 +1,12 @@ +Fixed handling of test methods with positional-only parameter syntax. + +Now, methods are supported that formally define ``self`` as positional-only +and/or fixture parameters as keyword-only, e.g.: + +.. code-block:: python + + class TestClass: + + def test_method(self, /, *, fixture): ... + +Before, this caused an internal error in pytest. diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 2cbb17eca38..f113a2197f3 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -122,7 +122,7 @@ def getfuncargnames( # creates a tuple of the names of the parameters that don't have # defaults. try: - parameters = signature(function).parameters + parameters = signature(function).parameters.values() except (ValueError, TypeError) as e: from _pytest.outcomes import fail @@ -133,7 +133,7 @@ def getfuncargnames( arg_names = tuple( p.name - for p in parameters.values() + for p in parameters if ( p.kind is Parameter.POSITIONAL_OR_KEYWORD or p.kind is Parameter.KEYWORD_ONLY @@ -144,9 +144,9 @@ def getfuncargnames( name = function.__name__ # If this function should be treated as a bound method even though - # it's passed as an unbound method or function, remove the first - # parameter name. - if ( + # it's passed as an unbound method or function, and its first parameter + # wasn't defined as positional only, remove the first parameter name. + if not any(p.kind is Parameter.POSITIONAL_ONLY for p in parameters) and ( # Not using `getattr` because we don't want to resolve the staticmethod. # Not using `cls.__dict__` because we want to check the entire MRO. cls diff --git a/testing/python/fixtures.py b/testing/python/fixtures.py index 32453739e8c..fb76fe6cf96 100644 --- a/testing/python/fixtures.py +++ b/testing/python/fixtures.py @@ -48,7 +48,23 @@ class A: def f(self, arg1, arg2="hello"): raise NotImplementedError() + def g(self, /, arg1, arg2="hello"): + raise NotImplementedError() + + def h(self, *, arg1, arg2="hello"): + raise NotImplementedError() + + def j(self, arg1, *, arg2, arg3="hello"): + raise NotImplementedError() + + def k(self, /, arg1, *, arg2, arg3="hello"): + raise NotImplementedError() + assert getfuncargnames(A().f) == ("arg1",) + assert getfuncargnames(A().g) == ("arg1",) + assert getfuncargnames(A().h) == ("arg1",) + assert getfuncargnames(A().j) == ("arg1", "arg2") + assert getfuncargnames(A().k) == ("arg1", "arg2") def test_getfuncargnames_staticmethod(): @@ -5033,3 +5049,22 @@ def test_foo(another_fixture): ) result = pytester.runpytest() result.assert_outcomes(passed=1) + + +def test_collect_positional_only(pytester: Pytester) -> None: + """Support the collection of tests with positional-only arguments (#13376).""" + pytester.makepyfile( + """ + import pytest + + class Test: + @pytest.fixture + def fix(self): + return 1 + + def test_method(self, /, fix): + assert fix == 1 + """ + ) + result = pytester.runpytest() + result.assert_outcomes(passed=1) From 7e93d83df30478e0243c6887d998575d4bff4ce5 Mon Sep 17 00:00:00 2001 From: Peter Gessler Date: Sat, 19 Apr 2025 16:34:09 -0500 Subject: [PATCH 1194/1271] Fix `ExceptionGroup` traceback filtering of pytest internals (#13380) * init * + author * fix * Simplify the code a bit * Small refactor * Import functions from `traceback` directly, to allow free use of `traceback` as a variable name. * Extract `_filtered_traceback` into a function. * Inline `_repr_exception_group_traceback` given it is used only in one place. * Make a type alias for the type of `tbfilter`. * action rerun * + comment * fix docs * Revert "fix docs" This reverts commit fc505cbaecb1131f52f1db6e3b0614054d3cba9a. * fix --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/13380.improvement.rst | 1 + src/_pytest/_code/code.py | 64 +++++++++++++++++++++------------ testing/code/test_excinfo.py | 3 ++ 4 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 changelog/13380.improvement.rst diff --git a/AUTHORS b/AUTHORS index 9004008bfa5..e19a0ae5871 100644 --- a/AUTHORS +++ b/AUTHORS @@ -346,6 +346,7 @@ Pavel Karateev Pavel Zhukov Paweł Adamczak Pedro Algarvio +Peter Gessler Petter Strandmark Philipp Loose Pierre Sassoulas diff --git a/changelog/13380.improvement.rst b/changelog/13380.improvement.rst new file mode 100644 index 00000000000..51f374fbf01 --- /dev/null +++ b/changelog/13380.improvement.rst @@ -0,0 +1 @@ +Fix :class:`ExceptionGroup` traceback filtering to exclude pytest internals. diff --git a/src/_pytest/_code/code.py b/src/_pytest/_code/code.py index 2c872df3008..f1241f14136 100644 --- a/src/_pytest/_code/code.py +++ b/src/_pytest/_code/code.py @@ -15,8 +15,10 @@ from pathlib import Path import re import sys -import traceback +from traceback import extract_tb +from traceback import format_exception from traceback import format_exception_only +from traceback import FrameSummary from types import CodeType from types import FrameType from types import TracebackType @@ -28,6 +30,7 @@ from typing import Literal from typing import overload from typing import SupportsIndex +from typing import TYPE_CHECKING from typing import TypeVar from typing import Union @@ -208,10 +211,10 @@ def with_repr_style( def lineno(self) -> int: return self._rawentry.tb_lineno - 1 - def get_python_framesummary(self) -> traceback.FrameSummary: + def get_python_framesummary(self) -> FrameSummary: # Python's built-in traceback module implements all the nitty gritty # details to get column numbers of out frames. - stack_summary = traceback.extract_tb(self._rawentry, limit=1) + stack_summary = extract_tb(self._rawentry, limit=1) return stack_summary[0] # Column and end line numbers introduced in python 3.11 @@ -694,8 +697,7 @@ def getrepr( showlocals: bool = False, style: TracebackStyle = "long", abspath: bool = False, - tbfilter: bool - | Callable[[ExceptionInfo[BaseException]], _pytest._code.code.Traceback] = True, + tbfilter: bool | Callable[[ExceptionInfo[BaseException]], Traceback] = True, funcargs: bool = False, truncate_locals: bool = True, truncate_args: bool = True, @@ -742,7 +744,7 @@ def getrepr( if style == "native": return ReprExceptionInfo( reprtraceback=ReprTracebackNative( - traceback.format_exception( + format_exception( self.type, self.value, self.traceback[0]._rawentry if self.traceback else None, @@ -851,6 +853,17 @@ def group_contains( return self._group_contains(self.value, expected_exception, match, depth) +if TYPE_CHECKING: + from typing_extensions import TypeAlias + + # Type alias for the `tbfilter` setting: + # bool: If True, it should be filtered using Traceback.filter() + # callable: A callable that takes an ExceptionInfo and returns the filtered traceback. + TracebackFilter: TypeAlias = Union[ + bool, Callable[[ExceptionInfo[BaseException]], Traceback] + ] + + @dataclasses.dataclass class FormattedExcinfo: """Presenting information about failing Functions and Generators.""" @@ -862,7 +875,7 @@ class FormattedExcinfo: showlocals: bool = False style: TracebackStyle = "long" abspath: bool = True - tbfilter: bool | Callable[[ExceptionInfo[BaseException]], Traceback] = True + tbfilter: TracebackFilter = True funcargs: bool = False truncate_locals: bool = True truncate_args: bool = True @@ -1100,11 +1113,7 @@ def _makepath(self, path: Path | str) -> str: return str(path) def repr_traceback(self, excinfo: ExceptionInfo[BaseException]) -> ReprTraceback: - traceback = excinfo.traceback - if callable(self.tbfilter): - traceback = self.tbfilter(excinfo) - elif self.tbfilter: - traceback = traceback.filter(excinfo) + traceback = filter_excinfo_traceback(self.tbfilter, excinfo) if isinstance(excinfo.value, RecursionError): traceback, extraline = self._truncate_recursive_traceback(traceback) @@ -1178,14 +1187,15 @@ def repr_excinfo(self, excinfo: ExceptionInfo[BaseException]) -> ExceptionChainR # Fall back to native traceback as a temporary workaround until # full support for exception groups added to ExceptionInfo. # See https://github.com/pytest-dev/pytest/issues/9159 + reprtraceback: ReprTraceback | ReprTracebackNative if isinstance(e, BaseExceptionGroup): - reprtraceback: ReprTracebackNative | ReprTraceback = ( - ReprTracebackNative( - traceback.format_exception( - type(excinfo_.value), - excinfo_.value, - excinfo_.traceback[0]._rawentry, - ) + # don't filter any sub-exceptions since they shouldn't have any internal frames + traceback = filter_excinfo_traceback(self.tbfilter, excinfo) + reprtraceback = ReprTracebackNative( + format_exception( + type(excinfo.value), + excinfo.value, + traceback[0]._rawentry, ) ) else: @@ -1194,9 +1204,7 @@ def repr_excinfo(self, excinfo: ExceptionInfo[BaseException]) -> ExceptionChainR else: # Fallback to native repr if the exception doesn't have a traceback: # ExceptionInfo objects require a full traceback to work. - reprtraceback = ReprTracebackNative( - traceback.format_exception(type(e), e, None) - ) + reprtraceback = ReprTracebackNative(format_exception(type(e), e, None)) reprcrash = None repr_chain += [(reprtraceback, reprcrash, descr)] @@ -1545,3 +1553,15 @@ def filter_traceback(entry: TracebackEntry) -> bool: return False return True + + +def filter_excinfo_traceback( + tbfilter: TracebackFilter, excinfo: ExceptionInfo[BaseException] +) -> Traceback: + """Filter the exception traceback in ``excinfo`` according to ``tbfilter``.""" + if callable(tbfilter): + return tbfilter(excinfo) + elif tbfilter: + return excinfo.traceback.filter(excinfo) + else: + return excinfo.traceback diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 89088576980..555645030fc 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1797,6 +1797,9 @@ def test(): rf"FAILED test_excgroup.py::test - {pre_catch}BaseExceptionGroup: Oops \(2.*" ) result.stdout.re_match_lines(match_lines) + # Check for traceback filtering of pytest internals. + result.stdout.no_fnmatch_line("*, line *, in pytest_pyfunc_call") + result.stdout.no_fnmatch_line("*, line *, in pytest_runtest_call") @pytest.mark.skipif( From 33b26e429817935af8eb0202aa1e5ef0476e1cad Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 20 Apr 2025 05:03:23 +0000 Subject: [PATCH 1195/1271] [automated] Update plugin list (#13385) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 78 +++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6690ad5196a..6b5f7c7457a 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =6.0 - :pypi:`pytest-chinesereport` Mar 19, 2025 4 - Beta pytest>=3.5.0 + :pypi:`pytest-chinesereport` Apr 16, 2025 4 - Beta pytest>=3.5.0 :pypi:`pytest-choose` Provide the pytest with the ability to collect use cases based on rules in text files Feb 04, 2024 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_cid` Compare data structures containing matching CIDs of different versions and encoding Sep 01, 2023 4 - Beta pytest >= 5.0, < 7.0 @@ -462,6 +462,7 @@ This list contains 1620 plugins. :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection Mar 04, 2024 5 - Production/Stable pytest >=7 :pypi:`pytest-dryci` Test caching plugin for pytest Sep 27, 2024 4 - Beta N/A :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jan 19, 2025 5 - Production/Stable pytest<9,>=7.40 + :pypi:`pytest-dsl` A DSL testing framework based on pytest Apr 14, 2025 N/A pytest>=7.0.0 :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A @@ -480,6 +481,7 @@ This list contains 1620 plugins. :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Dec 03, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-elasticsearch-test` Elasticsearch fixtures and fixture factories for Pytest. Aug 21, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-elbase` Elbase pytest plugin Apr 15, 2025 N/A N/A :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jul 25, 2024 4 - Beta pytest>=3.5.0 @@ -645,7 +647,7 @@ This list contains 1620 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 08, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 16, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -689,7 +691,7 @@ This list contains 1620 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Apr 05, 2025 3 - Alpha pytest==8.3.5 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 13, 2025 3 - Alpha pytest==8.3.5 :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` Sep 23, 2024 N/A N/A @@ -764,7 +766,7 @@ This list contains 1620 plugins. :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Mar 09, 2025 N/A pytest - :pypi:`pytest-ipywidgets` Feb 18, 2025 N/A pytest + :pypi:`pytest-ipywidgets` Apr 15, 2025 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Feb 24, 2025 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) @@ -778,7 +780,7 @@ This list contains 1620 plugins. :pypi:`pytest-jelastic` Pytest plugin defining the necessary command-line options to pass to pytests testing a Jelastic environment. Nov 16, 2022 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-jest` A custom jest-pytest oriented Pytest reporter May 22, 2018 4 - Beta pytest (>=3.3.2) :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) - :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 30, 2024 3 - Alpha N/A + :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 15, 2025 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jul 09, 2024 N/A pytest>=7.2.0 :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Oct 27, 2024 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) @@ -827,6 +829,7 @@ This list contains 1620 plugins. :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-leo-interface` Pytest extension tool for leo projects. Mar 19, 2025 N/A N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest + :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. Apr 16, 2025 N/A pytest>=8.3.5 :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Oct 01, 2024 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest @@ -1007,7 +1010,7 @@ This list contains 1620 plugins. :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Mar 22, 2025 5 - Production/Stable pytest>=5.0 :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest :pypi:`pytest-optional` include/exclude values of fixtures in pytest Oct 07, 2015 N/A N/A - :pypi:`pytest-optional-tests` Easy declaration of optional tests (i.e., that are not run by default) Jul 09, 2019 4 - Beta pytest (>=4.5.0) + :pypi:`pytest-optional-tests` Easy declaration of optional tests (i.e., that are not run by default) Apr 15, 2025 4 - Beta pytest; extra == "dev" :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 Aug 22, 2024 5 - Production/Stable pytest>=5.0; python_version < "3.10" :pypi:`pytest-ordered` Declare the order in which tests should run in your pytest.ini Oct 07, 2024 N/A pytest>=6.2.0 @@ -1079,7 +1082,7 @@ This list contains 1620 plugins. :pypi:`pytest-playwrights` A pytest wrapper with fixtures for Playwright to automate web browsers Dec 02, 2021 N/A N/A :pypi:`pytest-playwright-snapshot` A pytest wrapper for snapshot testing with playwright Aug 19, 2021 N/A N/A :pypi:`pytest-playwright-visual` A pytest fixture for visual testing with Playwright Apr 28, 2022 N/A N/A - :pypi:`pytest-playwright-visual-snapshot` Easy pytest visual regression testing using playwright Mar 25, 2025 N/A N/A + :pypi:`pytest-playwright-visual-snapshot` Easy pytest visual regression testing using playwright Apr 15, 2025 N/A N/A :pypi:`pytest-plone` Pytest plugin to test Plone addons Mar 27, 2025 3 - Alpha pytest<8.0.0 :pypi:`pytest-plt` Fixtures for quickly making Matplotlib plots in tests Jan 17, 2024 5 - Production/Stable pytest :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) @@ -1261,7 +1264,7 @@ This list contains 1620 plugins. :pypi:`pytest-rmsis` Sycronise pytest results to Jira RMsis Aug 10, 2022 N/A pytest (>=5.3.5) :pypi:`pytest-rng` Fixtures for seeding tests and making randomness reproducible Aug 08, 2019 5 - Production/Stable pytest :pypi:`pytest-roast` pytest plugin for ROAST configuration override and fixtures Nov 09, 2022 5 - Production/Stable pytest - :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Mar 28, 2025 N/A pytest<9,>=7 + :pypi:`pytest_robotframework` a pytest plugin that can run both python and robotframework tests while generating robot reports for them Apr 13, 2025 N/A pytest<9,>=7 :pypi:`pytest-rocketchat` Pytest to Rocket.Chat reporting plugin Apr 18, 2021 5 - Production/Stable N/A :pypi:`pytest-rotest` Pytest integration with rotest Sep 08, 2019 N/A pytest (>=3.5.0) :pypi:`pytest-rpc` Extend py.test for RPC OpenStack testing. Feb 22, 2019 4 - Beta pytest (~=3.6) @@ -1271,7 +1274,7 @@ This list contains 1620 plugins. :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 21, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A - :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Feb 05, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Apr 17, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 @@ -1387,7 +1390,7 @@ This list contains 1620 plugins. :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 19, 2025 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 + :pypi:`pytest-sqlalchemy` pytest plugin with sqlalchemy related fixtures Apr 19, 2025 3 - Alpha pytest>=8.0 :pypi:`pytest-sqlalchemy-mock` pytest sqlalchemy plugin for mock Aug 10, 2024 3 - Alpha pytest>=7.0.0 :pypi:`pytest-sqlalchemy-session` A pytest plugin for preserving test isolation that use SQLAlchemy. May 19, 2023 4 - Beta pytest (>=7.0) :pypi:`pytest-sql-bigquery` Yet another SQL-testing framework for BigQuery provided by pytest plugin Dec 19, 2019 N/A pytest @@ -1440,7 +1443,7 @@ This list contains 1620 plugins. :pypi:`pytest-tcpclient` A pytest plugin for testing TCP clients Nov 16, 2022 N/A pytest (<8,>=7.1.3) :pypi:`pytest-tdd` run pytest on a python module Aug 18, 2023 4 - Beta N/A :pypi:`pytest-teamcity-logblock` py.test plugin to introduce block structure in teamcity build log, if output is not captured May 15, 2018 4 - Beta N/A - :pypi:`pytest-teardown` Feb 03, 2025 N/A pytest<9.0.0,>=7.4.1 + :pypi:`pytest-teardown` Apr 15, 2025 N/A pytest<9.0.0,>=7.4.1 :pypi:`pytest-telegram` Pytest to Telegram reporting plugin Apr 25, 2024 5 - Production/Stable N/A :pypi:`pytest-telegram-notifier` Telegram notification plugin for Pytest Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-tempdir` Predictable and repeatable tempdir support. Oct 11, 2019 4 - Beta pytest (>=2.8.1) @@ -1653,7 +1656,7 @@ This list contains 1620 plugins. :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest :pypi:`pytest-zy` 接口自动化测试框架 Mar 24, 2024 N/A pytest~=7.2.0 - :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Apr 10, 2025 4 - Beta pytest>=8.3.5 + :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Apr 17, 2025 4 - Beta pytest>=8.3.5 =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -3137,7 +3140,7 @@ This list contains 1620 plugins. Simple pytest plugin for generating and sending report to messengers. :pypi:`pytest-chinesereport` - *last release*: Mar 19, 2025, + *last release*: Apr 16, 2025, *status*: 4 - Beta, *requires*: pytest>=3.5.0 @@ -4655,6 +4658,13 @@ This list contains 1620 plugins. A Pytest plugin to ignore tests during collection without reporting them in the test summary. + :pypi:`pytest-dsl` + *last release*: Apr 14, 2025, + *status*: N/A, + *requires*: pytest>=7.0.0 + + A DSL testing framework based on pytest + :pypi:`pytest-dummynet` *last release*: Dec 15, 2021, *status*: 5 - Production/Stable, @@ -4781,6 +4791,13 @@ This list contains 1620 plugins. Elasticsearch fixtures and fixture factories for Pytest. + :pypi:`pytest-elbase` + *last release*: Apr 15, 2025, + *status*: N/A, + *requires*: N/A + + Elbase pytest plugin + :pypi:`pytest-elements` *last release*: Jan 13, 2021, *status*: N/A, @@ -5937,7 +5954,7 @@ This list contains 1620 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Apr 08, 2025, + *last release*: Apr 16, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6245,7 +6262,7 @@ This list contains 1620 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 05, 2025, + *last release*: Apr 13, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.5 @@ -6770,7 +6787,7 @@ This list contains 1620 plugins. Pytest plugin to run tests in Jupyter Notebooks :pypi:`pytest-ipywidgets` - *last release*: Feb 18, 2025, + *last release*: Apr 15, 2025, *status*: N/A, *requires*: pytest @@ -6868,7 +6885,7 @@ This list contains 1620 plugins. A plugin to generate customizable jinja-based HTML reports in pytest :pypi:`pytest-jira` - *last release*: Apr 30, 2024, + *last release*: Apr 15, 2025, *status*: 3 - Alpha, *requires*: N/A @@ -7210,6 +7227,13 @@ This list contains 1620 plugins. Select tests of a given level or lower + :pypi:`pytest-lf-skip` + *last release*: Apr 16, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. + :pypi:`pytest-libfaketime` *last release*: Apr 12, 2024, *status*: 4 - Beta, @@ -8471,9 +8495,9 @@ This list contains 1620 plugins. include/exclude values of fixtures in pytest :pypi:`pytest-optional-tests` - *last release*: Jul 09, 2019, + *last release*: Apr 15, 2025, *status*: 4 - Beta, - *requires*: pytest (>=4.5.0) + *requires*: pytest; extra == "dev" Easy declaration of optional tests (i.e., that are not run by default) @@ -8975,7 +8999,7 @@ This list contains 1620 plugins. A pytest fixture for visual testing with Playwright :pypi:`pytest-playwright-visual-snapshot` - *last release*: Mar 25, 2025, + *last release*: Apr 15, 2025, *status*: N/A, *requires*: N/A @@ -10249,7 +10273,7 @@ This list contains 1620 plugins. pytest plugin for ROAST configuration override and fixtures :pypi:`pytest_robotframework` - *last release*: Mar 28, 2025, + *last release*: Apr 13, 2025, *status*: N/A, *requires*: pytest<9,>=7 @@ -10319,7 +10343,7 @@ This list contains 1620 plugins. implement a --failed option for pytest :pypi:`pytest-run-parallel` - *last release*: Feb 05, 2025, + *last release*: Apr 17, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -11131,9 +11155,9 @@ This list contains 1620 plugins. sqitch for pytest :pypi:`pytest-sqlalchemy` - *last release*: Mar 13, 2018, + *last release*: Apr 19, 2025, *status*: 3 - Alpha, - *requires*: N/A + *requires*: pytest>=8.0 pytest plugin with sqlalchemy related fixtures @@ -11502,7 +11526,7 @@ This list contains 1620 plugins. py.test plugin to introduce block structure in teamcity build log, if output is not captured :pypi:`pytest-teardown` - *last release*: Feb 03, 2025, + *last release*: Apr 15, 2025, *status*: N/A, *requires*: pytest<9.0.0,>=7.4.1 @@ -12993,7 +13017,7 @@ This list contains 1620 plugins. 接口自动化测试框架 :pypi:`tursu` - *last release*: Apr 10, 2025, + *last release*: Apr 17, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3.5 From ca3a1328075e5acf4e8816d08ae4a1bb0df54889 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 27 Apr 2025 09:05:34 -0300 Subject: [PATCH 1196/1271] [automated] Update plugin list (#13398) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 148 ++++++++++++++++++------------- 1 file changed, 86 insertions(+), 62 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 6b5f7c7457a..b5b9ac659d0 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.2 :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Mar 16, 2025 4 - Beta pytest>=6.2.0 - :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Jul 04, 2024 N/A N/A + :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Apr 26, 2025 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) @@ -162,7 +162,7 @@ This list contains 1623 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Apr 01, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Apr 25, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -339,7 +339,7 @@ This list contains 1623 plugins. :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 06, 2025 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 21, 2025 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest :pypi:`pytest-datadir` pytest plugin for test data directories and files Feb 07, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) @@ -480,21 +480,21 @@ This list contains 1623 plugins. :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Nov 17, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Dec 03, 2024 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-elasticsearch-test` Elasticsearch fixtures and fixture factories for Pytest. Aug 21, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-elasticsearch-test` Elasticsearch fixtures and fixture factories for Pytest. Apr 20, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-elbase` Elbase pytest plugin Apr 15, 2025 N/A N/A :pypi:`pytest-elements` Tool to help automate user interfaces Jan 13, 2021 N/A pytest (>=5.4,<6.0) :pypi:`pytest-eliot` An eliot plugin for pytest. Aug 31, 2022 1 - Planning pytest (>=5.4.0) :pypi:`pytest-elk-reporter` A simple plugin to use with pytest Jul 25, 2024 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. Mar 13, 2025 5 - Production/Stable pytest>=7.0 - :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Mar 13, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Mar 13, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Mar 13, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Mar 13, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Mar 13, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Mar 13, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Mar 13, 2025 5 - Production/Stable N/A - :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Mar 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded` A pytest plugin that designed for embedded testing. Apr 22, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-embedded-arduino` Make pytest-embedded plugin work with Arduino. Apr 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-idf` Make pytest-embedded plugin work with ESP-IDF. Apr 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-jtag` Make pytest-embedded plugin work with JTAG. Apr 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-nuttx` Make pytest-embedded plugin work with NuttX. Apr 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-qemu` Make pytest-embedded plugin work with QEMU. Apr 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial` Make pytest-embedded plugin work with Serial. Apr 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-serial-esp` Make pytest-embedded plugin work with Espressif target boards. Apr 22, 2025 5 - Production/Stable N/A + :pypi:`pytest-embedded-wokwi` Make pytest-embedded plugin work with the Wokwi CLI. Apr 22, 2025 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) @@ -647,7 +647,7 @@ This list contains 1623 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 16, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 24, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -691,7 +691,7 @@ This list contains 1623 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Apr 13, 2025 3 - Alpha pytest==8.3.5 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components Apr 26, 2025 3 - Alpha pytest==8.3.5 :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` Sep 23, 2024 N/A N/A @@ -722,7 +722,7 @@ This list contains 1623 plugins. :pypi:`pytest-hue` Visualise PyTest status via your Phillips Hue lights May 09, 2019 N/A N/A :pypi:`pytest-hylang` Pytest plugin to allow running tests written in hylang Mar 28, 2021 N/A pytest :pypi:`pytest-hypo-25` help hypo module for pytest Jan 12, 2020 3 - Alpha N/A - :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite Apr 04, 2025 4 - Beta pytest>=7.0.0 + :pypi:`pytest-iam` A fully functional OAUTH2 / OpenID Connect (OIDC) / SCIM server to be used in your testsuite Apr 24, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-ibutsu` A plugin to sent pytest results to an Ibutsu server Feb 06, 2025 4 - Beta pytest>=7.1 :pypi:`pytest-icdiff` use icdiff for better error messages in pytest assertions Dec 05, 2023 4 - Beta pytest :pypi:`pytest-idapro` A pytest plugin for idapython. Allows a pytest setup to run tests outside and inside IDA in an automated manner by runnig pytest inside IDA and by mocking idapython api Nov 03, 2018 N/A N/A @@ -748,6 +748,7 @@ This list contains 1623 plugins. :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Apr 09, 2025 5 - Production/Stable pytest :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 10, 2025 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Apr 09, 2025 5 - Production/Stable N/A + :pypi:`pytest-inmanta-srlinux` Pytest library to facilitate end to end testing of inmanta projects Apr 22, 2025 3 - Alpha N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest :pypi:`pytest-Inomaly` A simple image diff plugin for pytest Feb 13, 2018 4 - Beta N/A :pypi:`pytest-in-robotframework` The extension enables easy execution of pytest tests within the Robot Framework environment. Nov 23, 2024 N/A pytest @@ -766,8 +767,8 @@ This list contains 1623 plugins. :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Mar 09, 2025 N/A pytest - :pypi:`pytest-ipywidgets` Apr 15, 2025 N/A pytest - :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Jan 16, 2025 4 - Beta pytest + :pypi:`pytest-ipywidgets` Apr 25, 2025 N/A pytest + :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Apr 22, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Feb 24, 2025 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -792,8 +793,9 @@ This list contains 1623 plugins. :pypi:`pytest-jsonlint` UNKNOWN Aug 04, 2016 N/A N/A :pypi:`pytest-json-report` A pytest plugin to report test results as JSON files Mar 15, 2022 4 - Beta pytest (>=3.8.0) :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 - :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Mar 27, 2024 4 - Beta pytest>=6.2.0 + :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Apr 20, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Jul 21, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-jubilant` Add your description here Apr 25, 2025 N/A pytest>=8.3.5 :pypi:`pytest-junit-xray-xml` Export test results in an augmented JUnit format for usage with Xray () Jan 01, 2025 4 - Beta pytest :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest @@ -829,7 +831,7 @@ This list contains 1623 plugins. :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-leo-interface` Pytest extension tool for leo projects. Mar 19, 2025 N/A N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest - :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. Apr 16, 2025 N/A pytest>=8.3.5 + :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. Apr 25, 2025 N/A pytest>=8.3.5 :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Oct 01, 2024 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest @@ -904,7 +906,7 @@ This list contains 1623 plugins. :pypi:`pytest-metrics` Custom metrics report for pytest Apr 04, 2020 N/A pytest :pypi:`pytest-mh` Pytest multihost plugin Mar 06, 2025 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) - :pypi:`pytest-mimic` Easily record function calls while testing Apr 11, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-mimic` Easily record function calls while testing Apr 24, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Aug 27, 2024 N/A pytest>=5.0.0 @@ -1006,7 +1008,7 @@ This list contains 1623 plugins. :pypi:`pytest-oot` Run object-oriented tests in a simple format Sep 18, 2016 4 - Beta N/A :pypi:`pytest-openfiles` Pytest plugin for detecting inadvertent open file handles Jun 05, 2024 3 - Alpha pytest>=4.6 :pypi:`pytest-open-html` Auto-open HTML reports after pytest runs Mar 31, 2025 N/A pytest>=6.0 - :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Nov 22, 2024 N/A pytest + :pypi:`pytest-opentelemetry` A pytest plugin for instrumenting test runs via OpenTelemetry Apr 25, 2025 N/A pytest :pypi:`pytest-opentmi` pytest plugin for publish results to opentmi Mar 22, 2025 5 - Production/Stable pytest>=5.0 :pypi:`pytest-operator` Fixtures for Operators Sep 28, 2022 N/A pytest :pypi:`pytest-optional` include/exclude values of fixtures in pytest Oct 07, 2015 N/A N/A @@ -1018,7 +1020,7 @@ This list contains 1623 plugins. :pypi:`pytest-order-modify` 新增run_marker 来自定义用例的执行顺序 Nov 04, 2022 N/A N/A :pypi:`pytest-osxnotify` OS X notifications for py.test results. May 15, 2015 N/A N/A :pypi:`pytest-ot` A pytest plugin for instrumenting test runs via OpenTelemetry Mar 21, 2024 N/A pytest; extra == "dev" - :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Feb 10, 2025 N/A pytest==8.3.4 + :pypi:`pytest-otel` OpenTelemetry plugin for Pytest Apr 24, 2025 N/A pytest==8.3.5 :pypi:`pytest-override-env-var` Pytest mark to override a value of an environment variable. Feb 25, 2023 N/A N/A :pypi:`pytest-owner` Add owner mark for tests Aug 19, 2024 N/A pytest :pypi:`pytest-pact` A simple plugin to use with pytest Jan 07, 2019 4 - Beta N/A @@ -1184,7 +1186,7 @@ This list contains 1623 plugins. :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Mar 31, 2025 N/A N/A - :pypi:`pytest-recording` A pytest plugin that allows you recording of network interactions via VCR.py Jul 09, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-recording` A pytest plugin powered by VCR.py to record and replay HTTP traffic Apr 24, 2025 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-record-video` 用例执行过程中录制视频 Oct 31, 2024 N/A N/A :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Nov 27, 2024 5 - Production/Stable pytest>=6.2 @@ -1211,7 +1213,7 @@ This list contains 1623 plugins. :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A - :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Jan 22, 2023 N/A N/A + :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Apr 26, 2025 N/A N/A :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Apr 04, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) @@ -1274,7 +1276,7 @@ This list contains 1623 plugins. :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 21, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A - :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Apr 17, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Apr 22, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 @@ -1291,7 +1293,7 @@ This list contains 1623 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 10, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 25, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1303,7 +1305,7 @@ This list contains 1623 plugins. :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 Feb 01, 2024 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. Apr 10, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. Apr 25, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1613,6 +1615,7 @@ This list contains 1623 plugins. :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Apr 28, 2024 5 - Production/Stable pytest>=7.0.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-lock` Extension for pytest-xdist adding test and resource group locks for local and distributed runs Apr 26, 2025 N/A pytest>=6.0 :pypi:`pytest-xdist-tracker` pytest plugin helps to reproduce failures for particular xdist node Nov 18, 2021 3 - Alpha pytest (>=3.5.1) :pypi:`pytest-xdist-worker-stats` A pytest plugin to list worker statistics after a xdist run. Mar 15, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-xdocker` Pytest fixture to run docker across test runs. Mar 23, 2025 N/A pytest<8.0.0,>=7.4.2 @@ -1656,7 +1659,7 @@ This list contains 1623 plugins. :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest :pypi:`pytest-zy` 接口自动化测试框架 Mar 24, 2024 N/A pytest~=7.2.0 - :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Apr 17, 2025 4 - Beta pytest>=8.3.5 + :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Apr 25, 2025 4 - Beta pytest>=8.3.5 =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -2265,7 +2268,7 @@ This list contains 1623 plugins. Pytest plugin to execute python async tests concurrently. :pypi:`pytest-asyncio-cooperative` - *last release*: Jul 04, 2024, + *last release*: Apr 26, 2025, *status*: N/A, *requires*: N/A @@ -2559,7 +2562,7 @@ This list contains 1623 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Apr 01, 2025, + *last release*: Apr 25, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3798,7 +3801,7 @@ This list contains 1623 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Apr 06, 2025, + *last release*: Apr 21, 2025, *status*: 4 - Beta, *requires*: pytest @@ -4785,7 +4788,7 @@ This list contains 1623 plugins. Elasticsearch fixtures and fixture factories for Pytest. :pypi:`pytest-elasticsearch-test` - *last release*: Aug 21, 2024, + *last release*: Apr 20, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -4827,63 +4830,63 @@ This list contains 1623 plugins. Send execution result email :pypi:`pytest-embedded` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 A pytest plugin that designed for embedded testing. :pypi:`pytest-embedded-arduino` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Arduino. :pypi:`pytest-embedded-idf` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with ESP-IDF. :pypi:`pytest-embedded-jtag` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with JTAG. :pypi:`pytest-embedded-nuttx` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with NuttX. :pypi:`pytest-embedded-qemu` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with QEMU. :pypi:`pytest-embedded-serial` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Serial. :pypi:`pytest-embedded-serial-esp` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A Make pytest-embedded plugin work with Espressif target boards. :pypi:`pytest-embedded-wokwi` - *last release*: Mar 13, 2025, + *last release*: Apr 22, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -5954,7 +5957,7 @@ This list contains 1623 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Apr 16, 2025, + *last release*: Apr 24, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6262,7 +6265,7 @@ This list contains 1623 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 13, 2025, + *last release*: Apr 26, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.5 @@ -6479,11 +6482,11 @@ This list contains 1623 plugins. help hypo module for pytest :pypi:`pytest-iam` - *last release*: Apr 04, 2025, + *last release*: Apr 24, 2025, *status*: 4 - Beta, *requires*: pytest>=7.0.0 - A fully functional OAUTH2 / OpenID Connect (OIDC) server to be used in your testsuite + A fully functional OAUTH2 / OpenID Connect (OIDC) / SCIM server to be used in your testsuite :pypi:`pytest-ibutsu` *last release*: Feb 06, 2025, @@ -6660,6 +6663,13 @@ This list contains 1623 plugins. Common fixtures for inmanta LSM related modules + :pypi:`pytest-inmanta-srlinux` + *last release*: Apr 22, 2025, + *status*: 3 - Alpha, + *requires*: N/A + + Pytest library to facilitate end to end testing of inmanta projects + :pypi:`pytest-inmanta-yang` *last release*: Feb 22, 2024, *status*: 4 - Beta, @@ -6787,14 +6797,14 @@ This list contains 1623 plugins. Pytest plugin to run tests in Jupyter Notebooks :pypi:`pytest-ipywidgets` - *last release*: Apr 15, 2025, + *last release*: Apr 25, 2025, *status*: N/A, *requires*: pytest :pypi:`pytest-isolate` - *last release*: Jan 16, 2025, + *last release*: Apr 22, 2025, *status*: 4 - Beta, *requires*: pytest @@ -6969,7 +6979,7 @@ This list contains 1623 plugins. A pytest plugin to report test results as JSON files :pypi:`pytest-jsonschema` - *last release*: Mar 27, 2024, + *last release*: Apr 20, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -6982,6 +6992,13 @@ This list contains 1623 plugins. pytest plugin supporting json test report output + :pypi:`pytest-jubilant` + *last release*: Apr 25, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + Add your description here + :pypi:`pytest-junit-xray-xml` *last release*: Jan 01, 2025, *status*: 4 - Beta, @@ -7228,7 +7245,7 @@ This list contains 1623 plugins. Select tests of a given level or lower :pypi:`pytest-lf-skip` - *last release*: Apr 16, 2025, + *last release*: Apr 25, 2025, *status*: N/A, *requires*: pytest>=8.3.5 @@ -7753,7 +7770,7 @@ This list contains 1623 plugins. Mimesis integration with the pytest test runner :pypi:`pytest-mimic` - *last release*: Apr 11, 2025, + *last release*: Apr 24, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -8467,7 +8484,7 @@ This list contains 1623 plugins. Auto-open HTML reports after pytest runs :pypi:`pytest-opentelemetry` - *last release*: Nov 22, 2024, + *last release*: Apr 25, 2025, *status*: N/A, *requires*: pytest @@ -8551,9 +8568,9 @@ This list contains 1623 plugins. A pytest plugin for instrumenting test runs via OpenTelemetry :pypi:`pytest-otel` - *last release*: Feb 10, 2025, + *last release*: Apr 24, 2025, *status*: N/A, - *requires*: pytest==8.3.4 + *requires*: pytest==8.3.5 OpenTelemetry plugin for Pytest @@ -9713,11 +9730,11 @@ This list contains 1623 plugins. Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. :pypi:`pytest-recording` - *last release*: Jul 09, 2024, + *last release*: Apr 24, 2025, *status*: 4 - Beta, *requires*: pytest>=3.5.0 - A pytest plugin that allows you recording of network interactions via VCR.py + A pytest plugin powered by VCR.py to record and replay HTTP traffic :pypi:`pytest-recordings` *last release*: Aug 13, 2020, @@ -9902,7 +9919,7 @@ This list contains 1623 plugins. A basic HTML report template for Pytest :pypi:`pytest-reporter-html-dots` - *last release*: Jan 22, 2023, + *last release*: Apr 26, 2025, *status*: N/A, *requires*: N/A @@ -10343,7 +10360,7 @@ This list contains 1623 plugins. implement a --failed option for pytest :pypi:`pytest-run-parallel` - *last release*: Apr 17, 2025, + *last release*: Apr 22, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -10462,7 +10479,7 @@ This list contains 1623 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Apr 10, 2025, + *last release*: Apr 25, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10546,7 +10563,7 @@ This list contains 1623 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Apr 10, 2025, + *last release*: Apr 25, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -12715,6 +12732,13 @@ This list contains 1623 plugins. forked from pytest-xdist + :pypi:`pytest-xdist-lock` + *last release*: Apr 26, 2025, + *status*: N/A, + *requires*: pytest>=6.0 + + Extension for pytest-xdist adding test and resource group locks for local and distributed runs + :pypi:`pytest-xdist-tracker` *last release*: Nov 18, 2021, *status*: 3 - Alpha, @@ -13017,7 +13041,7 @@ This list contains 1623 plugins. 接口自动化测试框架 :pypi:`tursu` - *last release*: Apr 17, 2025, + *last release*: Apr 25, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3.5 From 8173aa812253aa263b43cd52c80d605470d0c13f Mon Sep 17 00:00:00 2001 From: Deysha Rivera <50204868+rivtechprojects@users.noreply.github.com> Date: Sun, 27 Apr 2025 08:19:55 -0400 Subject: [PATCH 1197/1271] Replace explicit time() calls with _pytest.timing (#13394) Fix #13384 --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/13384.bugfix.rst | 1 + src/_pytest/junitxml.py | 5 +++-- src/_pytest/pytester.py | 8 ++++---- src/_pytest/terminal.py | 8 ++++---- testing/_py/test_local.py | 8 ++++---- testing/test_pytester.py | 6 +++--- 7 files changed, 20 insertions(+), 17 deletions(-) create mode 100644 changelog/13384.bugfix.rst diff --git a/AUTHORS b/AUTHORS index e19a0ae5871..7f742fb4083 100644 --- a/AUTHORS +++ b/AUTHORS @@ -130,6 +130,7 @@ Daw-Ran Liou Debi Mishra Denis Kirisov Denivy Braiam Rück +Deysha Rivera Dheeraj C K Dhiren Serai Diego Russo diff --git a/changelog/13384.bugfix.rst b/changelog/13384.bugfix.rst new file mode 100644 index 00000000000..e93d01dcab0 --- /dev/null +++ b/changelog/13384.bugfix.rst @@ -0,0 +1 @@ +Fixed an issue where pytest could report negative durations. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index d129cd295e7..06cab961ef5 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -637,6 +637,7 @@ def pytest_internalerror(self, excrepr: ExceptionRepr) -> None: def pytest_sessionstart(self) -> None: self.suite_start_time = timing.time() + self.suite_start_perf = timing.perf_counter() def pytest_sessionfinish(self) -> None: dirname = os.path.dirname(os.path.abspath(self.logfile)) @@ -644,8 +645,8 @@ def pytest_sessionfinish(self) -> None: os.makedirs(dirname, exist_ok=True) with open(self.logfile, "w", encoding="utf-8") as logfile: - suite_stop_time = timing.time() - suite_time_delta = suite_stop_time - self.suite_start_time + suite_stop_perf = timing.perf_counter() + suite_time_delta = suite_stop_perf - self.suite_start_perf numtests = ( self.stats["passed"] diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 59839562031..bb5f6a5787e 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1150,7 +1150,7 @@ def runpytest_inprocess( if syspathinsert: self.syspathinsert() - now = timing.time() + now = timing.perf_counter() capture = _get_multicapture("sys") capture.start_capturing() try: @@ -1180,7 +1180,7 @@ class reprec: # type: ignore assert reprec.ret is not None res = RunResult( - reprec.ret, out.splitlines(), err.splitlines(), timing.time() - now + reprec.ret, out.splitlines(), err.splitlines(), timing.perf_counter() - now ) res.reprec = reprec # type: ignore return res @@ -1408,7 +1408,7 @@ def run( print(" in:", Path.cwd()) with p1.open("w", encoding="utf8") as f1, p2.open("w", encoding="utf8") as f2: - now = timing.time() + now = timing.perf_counter() popen = self.popen( cmdargs, stdin=stdin, @@ -1445,7 +1445,7 @@ def handle_timeout() -> None: with contextlib.suppress(ValueError): ret = ExitCode(ret) - return RunResult(ret, out, err, timing.time() - now) + return RunResult(ret, out, err, timing.perf_counter() - now) def _dump_lines(self, lines, fp): try: diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 3297c38e848..8415912e9ac 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -769,7 +769,7 @@ def pytest_collection(self) -> None: if self.isatty: if self.config.option.verbose >= 0: self.write("collecting ... ", flush=True, bold=True) - self._collect_report_last_write = timing.time() + self._collect_report_last_write = timing.perf_counter() elif self.config.option.verbose >= 1: self.write("collecting ... ", flush=True, bold=True) @@ -789,7 +789,7 @@ def report_collect(self, final: bool = False) -> None: if not final: # Only write "collecting" report every 0.5s. - t = timing.time() + t = timing.perf_counter() if ( self._collect_report_last_write is not None and self._collect_report_last_write > t - REPORT_COLLECTING_RESOLUTION @@ -823,7 +823,7 @@ def report_collect(self, final: bool = False) -> None: @hookimpl(trylast=True) def pytest_sessionstart(self, session: Session) -> None: self._session = session - self._sessionstarttime = timing.time() + self._sessionstarttime = timing.perf_counter() if not self.showheader: return self.write_sep("=", "test session starts", bold=True) @@ -1202,7 +1202,7 @@ def summary_stats(self) -> None: if self.verbosity < -1: return - session_duration = timing.time() - self._sessionstarttime + session_duration = timing.perf_counter() - self._sessionstarttime (parts, main_color) = self.build_summary_stats_line() line_parts = [] diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 03a828c64f0..e4b011a9727 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -12,6 +12,7 @@ from py import error from py.path import local +import _pytest.timing import pytest @@ -738,7 +739,6 @@ def test_dump(self, tmpdir, bin): def test_setmtime(self): import tempfile - import time try: fd, name = tempfile.mkstemp() @@ -747,7 +747,7 @@ def test_setmtime(self): name = tempfile.mktemp() open(name, "w").close() try: - mtime = int(time.time()) - 100 + mtime = int(_pytest.timing.time()) - 100 path = local(name) assert path.mtime() != mtime path.setmtime(mtime) @@ -1405,7 +1405,7 @@ def test_atime(self, tmpdir): import time path = tmpdir.ensure("samplefile") - now = time.time() + now = _pytest.timing.perf_counter() atime1 = path.atime() # we could wait here but timer resolution is very # system dependent @@ -1413,7 +1413,7 @@ def test_atime(self, tmpdir): time.sleep(ATIME_RESOLUTION) atime2 = path.atime() time.sleep(ATIME_RESOLUTION) - duration = time.time() - now + duration = _pytest.timing.perf_counter() - now assert (atime2 - atime1) <= duration def test_commondir(self, path1): diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 87714b4708f..555d73f9eaa 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -4,7 +4,6 @@ import os import subprocess import sys -import time from types import ModuleType from _pytest.config import ExitCode @@ -16,6 +15,7 @@ from _pytest.pytester import Pytester from _pytest.pytester import SysModulesSnapshot from _pytest.pytester import SysPathsSnapshot +import _pytest.timing import pytest @@ -451,9 +451,9 @@ def test_pytester_run_with_timeout(pytester: Pytester) -> None: timeout = 120 - start = time.time() + start = _pytest.timing.perf_counter() result = pytester.runpytest_subprocess(testfile, timeout=timeout) - end = time.time() + end = _pytest.timing.perf_counter() duration = end - start assert result.ret == ExitCode.OK From 20c51f70c99ecaa4745d622a69bbe93fbf59ad16 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Tue, 29 Apr 2025 08:00:08 -0300 Subject: [PATCH 1198/1271] Add `Instant` class to conveniently track elapsed and start/end times (#13397) Throughout the codebase we often need to track elapsed times, using a performance clock, and also start/end times that given seconds since epoch (via `time.time()`). `Instant` encapsulates both functionalities to simplify the code and ensure we are using the correct functions from `_pytest.timing`, which we can mock in tests for reliability. --- src/_pytest/junitxml.py | 14 ++++--------- src/_pytest/pytester.py | 8 ++++---- src/_pytest/runner.py | 14 +++++-------- src/_pytest/terminal.py | 18 ++++++++--------- src/_pytest/timing.py | 42 +++++++++++++++++++++++++++++++++++++++ testing/_py/test_local.py | 9 +++++---- testing/test_pytester.py | 7 +++---- 7 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index 06cab961ef5..ec9922ee7bd 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -11,8 +11,6 @@ from __future__ import annotations from collections.abc import Callable -from datetime import datetime -from datetime import timezone import functools import os import platform @@ -636,8 +634,7 @@ def pytest_internalerror(self, excrepr: ExceptionRepr) -> None: reporter._add_simple("error", "internal error", str(excrepr)) def pytest_sessionstart(self) -> None: - self.suite_start_time = timing.time() - self.suite_start_perf = timing.perf_counter() + self.suite_start = timing.Instant() def pytest_sessionfinish(self) -> None: dirname = os.path.dirname(os.path.abspath(self.logfile)) @@ -645,8 +642,7 @@ def pytest_sessionfinish(self) -> None: os.makedirs(dirname, exist_ok=True) with open(self.logfile, "w", encoding="utf-8") as logfile: - suite_stop_perf = timing.perf_counter() - suite_time_delta = suite_stop_perf - self.suite_start_perf + duration = self.suite_start.elapsed() numtests = ( self.stats["passed"] @@ -664,10 +660,8 @@ def pytest_sessionfinish(self) -> None: failures=str(self.stats["failure"]), skipped=str(self.stats["skipped"]), tests=str(numtests), - time=f"{suite_time_delta:.3f}", - timestamp=datetime.fromtimestamp(self.suite_start_time, timezone.utc) - .astimezone() - .isoformat(), + time=f"{duration.seconds:.3f}", + timestamp=self.suite_start.as_utc().astimezone().isoformat(), hostname=platform.node(), ) global_properties = self._get_global_properties_node() diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index bb5f6a5787e..11127a88bb8 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1150,7 +1150,7 @@ def runpytest_inprocess( if syspathinsert: self.syspathinsert() - now = timing.perf_counter() + instant = timing.Instant() capture = _get_multicapture("sys") capture.start_capturing() try: @@ -1180,7 +1180,7 @@ class reprec: # type: ignore assert reprec.ret is not None res = RunResult( - reprec.ret, out.splitlines(), err.splitlines(), timing.perf_counter() - now + reprec.ret, out.splitlines(), err.splitlines(), instant.elapsed().seconds ) res.reprec = reprec # type: ignore return res @@ -1408,7 +1408,7 @@ def run( print(" in:", Path.cwd()) with p1.open("w", encoding="utf8") as f1, p2.open("w", encoding="utf8") as f2: - now = timing.perf_counter() + instant = timing.Instant() popen = self.popen( cmdargs, stdin=stdin, @@ -1445,7 +1445,7 @@ def handle_timeout() -> None: with contextlib.suppress(ValueError): ret = ExitCode(ret) - return RunResult(ret, out, err, timing.perf_counter() - now) + return RunResult(ret, out, err, instant.elapsed().seconds) def _dump_lines(self, lines, fp): try: diff --git a/src/_pytest/runner.py b/src/_pytest/runner.py index f0543289267..26e4e838b77 100644 --- a/src/_pytest/runner.py +++ b/src/_pytest/runner.py @@ -339,8 +339,7 @@ def from_call( function, instead of being wrapped in the CallInfo. """ excinfo = None - start = timing.time() - precise_start = timing.perf_counter() + instant = timing.Instant() try: result: TResult | None = func() except BaseException: @@ -348,14 +347,11 @@ def from_call( if reraise is not None and isinstance(excinfo.value, reraise): raise result = None - # use the perf counter - precise_stop = timing.perf_counter() - duration = precise_stop - precise_start - stop = timing.time() + duration = instant.elapsed() return cls( - start=start, - stop=stop, - duration=duration, + start=duration.start.time, + stop=duration.stop.time, + duration=duration.seconds, when=when, result=result, excinfo=excinfo, diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 8415912e9ac..d5ccc4e4900 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -391,7 +391,7 @@ def __init__(self, config: Config, file: TextIO | None = None) -> None: self._progress_nodeids_reported: set[str] = set() self._timing_nodeids_reported: set[str] = set() self._show_progress_info = self._determine_show_progress_info() - self._collect_report_last_write: float | None = None + self._collect_report_last_write = timing.Instant() self._already_displayed_warnings: int | None = None self._keyboardinterrupt_memo: ExceptionRepr | None = None @@ -769,7 +769,6 @@ def pytest_collection(self) -> None: if self.isatty: if self.config.option.verbose >= 0: self.write("collecting ... ", flush=True, bold=True) - self._collect_report_last_write = timing.perf_counter() elif self.config.option.verbose >= 1: self.write("collecting ... ", flush=True, bold=True) @@ -788,14 +787,13 @@ def report_collect(self, final: bool = False) -> None: return if not final: - # Only write "collecting" report every 0.5s. - t = timing.perf_counter() + # Only write the "collecting" report every `REPORT_COLLECTING_RESOLUTION`. if ( - self._collect_report_last_write is not None - and self._collect_report_last_write > t - REPORT_COLLECTING_RESOLUTION + self._collect_report_last_write.elapsed().seconds + < REPORT_COLLECTING_RESOLUTION ): return - self._collect_report_last_write = t + self._collect_report_last_write = timing.Instant() errors = len(self.stats.get("error", [])) skipped = len(self.stats.get("skipped", [])) @@ -823,7 +821,7 @@ def report_collect(self, final: bool = False) -> None: @hookimpl(trylast=True) def pytest_sessionstart(self, session: Session) -> None: self._session = session - self._sessionstarttime = timing.perf_counter() + self._session_start = timing.Instant() if not self.showheader: return self.write_sep("=", "test session starts", bold=True) @@ -1202,7 +1200,7 @@ def summary_stats(self) -> None: if self.verbosity < -1: return - session_duration = timing.perf_counter() - self._sessionstarttime + session_duration = self._session_start.elapsed() (parts, main_color) = self.build_summary_stats_line() line_parts = [] @@ -1217,7 +1215,7 @@ def summary_stats(self) -> None: msg = ", ".join(line_parts) main_markup = {main_color: True} - duration = f" in {format_session_duration(session_duration)}" + duration = f" in {format_session_duration(session_duration.seconds)}" duration_with_markup = self._tw.markup(duration, **main_markup) if display_sep: fullwidth += len(duration_with_markup) - len(duration) diff --git a/src/_pytest/timing.py b/src/_pytest/timing.py index 4422037a9d9..221eeffc4fd 100644 --- a/src/_pytest/timing.py +++ b/src/_pytest/timing.py @@ -10,6 +10,7 @@ import dataclasses from datetime import datetime +from datetime import timezone from time import perf_counter from time import sleep from time import time @@ -20,6 +21,47 @@ from pytest import MonkeyPatch +@dataclasses.dataclass(frozen=True) +class Instant: + """ + Represents an instant in time, used to both get the timestamp value and to measure + the duration of a time span. + + Inspired by Rust's `std::time::Instant`. + """ + + # Creation time of this instant, using time.time(), to measure actual time. + # Note: using a `lambda` to correctly get the mocked time via `MockTiming`. + time: float = dataclasses.field(default_factory=lambda: time(), init=False) + + # Performance counter tick of the instant, used to measure precise elapsed time. + # Note: using a `lambda` to correctly get the mocked time via `MockTiming`. + perf_count: float = dataclasses.field( + default_factory=lambda: perf_counter(), init=False + ) + + def elapsed(self) -> Duration: + """Measure the duration since `Instant` was created.""" + return Duration(start=self, stop=Instant()) + + def as_utc(self) -> datetime: + """Instant as UTC datetime.""" + return datetime.fromtimestamp(self.time, timezone.utc) + + +@dataclasses.dataclass(frozen=True) +class Duration: + """A span of time as measured by `Instant.elapsed()`.""" + + start: Instant + stop: Instant + + @property + def seconds(self) -> float: + """Elapsed time of the duration in seconds, measured using a performance counter for precise timing.""" + return self.stop.perf_count - self.start.perf_count + + @dataclasses.dataclass class MockTiming: """Mocks _pytest.timing with a known object that can be used to control timing in tests diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index e4b011a9727..7064d1daa9b 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -12,7 +12,6 @@ from py import error from py.path import local -import _pytest.timing import pytest @@ -747,7 +746,8 @@ def test_setmtime(self): name = tempfile.mktemp() open(name, "w").close() try: - mtime = int(_pytest.timing.time()) - 100 + # Do not use _pytest.timing here, as we do not want time mocking to affect this test. + mtime = int(time.time()) - 100 path = local(name) assert path.mtime() != mtime path.setmtime(mtime) @@ -1405,7 +1405,8 @@ def test_atime(self, tmpdir): import time path = tmpdir.ensure("samplefile") - now = _pytest.timing.perf_counter() + # Do not use _pytest.timing here, as we do not want time mocking to affect this test. + now = time.time() atime1 = path.atime() # we could wait here but timer resolution is very # system dependent @@ -1413,7 +1414,7 @@ def test_atime(self, tmpdir): time.sleep(ATIME_RESOLUTION) atime2 = path.atime() time.sleep(ATIME_RESOLUTION) - duration = _pytest.timing.perf_counter() - now + duration = time.time() - now assert (atime2 - atime1) <= duration def test_commondir(self, path1): diff --git a/testing/test_pytester.py b/testing/test_pytester.py index 555d73f9eaa..721e8c19d8b 100644 --- a/testing/test_pytester.py +++ b/testing/test_pytester.py @@ -451,13 +451,12 @@ def test_pytester_run_with_timeout(pytester: Pytester) -> None: timeout = 120 - start = _pytest.timing.perf_counter() + instant = _pytest.timing.Instant() result = pytester.runpytest_subprocess(testfile, timeout=timeout) - end = _pytest.timing.perf_counter() - duration = end - start + duration = instant.elapsed() assert result.ret == ExitCode.OK - assert duration < timeout + assert duration.seconds < timeout def test_pytester_run_timeout_expires(pytester: Pytester) -> None: From a0f8a697fcafb7432d753784cc55860ebb939182 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 2 May 2025 17:54:14 +0200 Subject: [PATCH 1199/1271] doc: Update trainings --- doc/en/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index 6e04dbb9ed0..fb5d0482c0d 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,8 @@ .. sidebar:: **Next Open Trainings and Events** - - `pytest - simple, rapid and fun testing with Python `_, at `PyConDE `_, **April 24th** (1.5), Darmstadt, Germany + - `pytest - simple, rapid and fun testing with Python `_, at `EuroPython 2025 `_, **July 14th** (3h), Prague, Czech Republic + - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 3th -- 5th 2026**, Leipzig (DE) / Remote Also see :doc:`previous talks and blogposts ` From 7746f4f21044627e77d9bf34d27238c1a4eb16b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Augustyn=C3=B3w?= <105516855+Alcares@users.noreply.github.com> Date: Fri, 2 May 2025 19:22:25 +0200 Subject: [PATCH 1200/1271] Add `name` attribute to `testsuites` root tag in junitxml (#13404) Fixes #12736 --------- Co-authored-by: maugu Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/12736.improvement.rst | 3 +++ src/_pytest/junitxml.py | 1 + testing/test_junitxml.py | 1 + 4 files changed, 6 insertions(+) create mode 100644 changelog/12736.improvement.rst diff --git a/AUTHORS b/AUTHORS index 7f742fb4083..1dfa55b131f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -275,6 +275,7 @@ Manuel Krebber Marc Mueller Marc Schlaich Marcelo Duarte Trevisani +Marcin Augustynów Marcin Bachry Marc Bresson Marco Gorelli diff --git a/changelog/12736.improvement.rst b/changelog/12736.improvement.rst new file mode 100644 index 00000000000..5fdb14e2ef5 --- /dev/null +++ b/changelog/12736.improvement.rst @@ -0,0 +1,3 @@ +Added a new attribute `name` with the fixed value `"pytest tests"` to the root tag `testsuites` of the junit-xml generated by pytest. + +This attribute is part of many junit-xml specifications and is even part of the `junit-10.xsd` specification that pytest's implementation is based on. diff --git a/src/_pytest/junitxml.py b/src/_pytest/junitxml.py index ec9922ee7bd..dc35e3aac15 100644 --- a/src/_pytest/junitxml.py +++ b/src/_pytest/junitxml.py @@ -670,6 +670,7 @@ def pytest_sessionfinish(self) -> None: for node_reporter in self.node_reporters_ordered: suite_node.append(node_reporter.to_xml()) testsuites = ET.Element("testsuites") + testsuites.set("name", "pytest tests") testsuites.append(suite_node) logfile.write(ET.tostring(testsuites, encoding="unicode")) diff --git a/testing/test_junitxml.py b/testing/test_junitxml.py index 4145f34ab14..504e4969039 100644 --- a/testing/test_junitxml.py +++ b/testing/test_junitxml.py @@ -1451,6 +1451,7 @@ def test_x(): _, dom = run_and_parse(family=xunit_family) root = dom.get_unique_child assert root.tag == "testsuites" + root.assert_attr(name="pytest tests") suite_node = root.get_unique_child assert suite_node.tag == "testsuite" From 89b84cb56295c46e1d8834b599e858bc65c15a5b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 4 May 2025 05:41:56 +0000 Subject: [PATCH 1201/1271] [automated] Update plugin list (#13407) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 114 ++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 41 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index b5b9ac659d0..bb34208872b 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) :pypi:`pytest-annotated` Pytest plugin to allow use of Annotated in tests to resolve fixtures Sep 30, 2024 N/A pytest>=8.3.3 - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Apr 01, 2025 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Apr 28, 2025 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -119,7 +119,7 @@ This list contains 1626 plugins. :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio Mar 25, 2025 4 - Beta pytest<9,>=8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Mar 16, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Apr 29, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Apr 26, 2025 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) @@ -162,7 +162,7 @@ This list contains 1626 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests Apr 25, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 02, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -273,6 +273,7 @@ This list contains 1626 plugins. :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest-cocotb` Pytest plugin to integrate Cocotb Mar 15, 2025 5 - Production/Stable pytest; extra == "test" + :pypi:`pytest-codeblock` Pytest plugin to collect and test code blocks in reStructuredText and Markdown files. May 02, 2025 4 - Beta pytest :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A @@ -409,7 +410,7 @@ This list contains 1626 plugins. :pypi:`pytest-django-filefield` Replaces FileField.storage with something you can patch globally. May 09, 2022 5 - Production/Stable pytest >= 5.2 :pypi:`pytest-django-gcir` A Django plugin for pytest. Mar 06, 2018 5 - Production/Stable N/A :pypi:`pytest-django-haystack` Cleanup your Haystack indexes between tests Sep 03, 2017 5 - Production/Stable pytest (>=2.3.4) - :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Aug 27, 2023 5 - Production/Stable N/A + :pypi:`pytest-django-ifactory` A model instance factory for pytest-django Apr 30, 2025 5 - Production/Stable N/A :pypi:`pytest-django-lite` The bare minimum to integrate py.test with Django. Jan 30, 2014 N/A N/A :pypi:`pytest-django-liveserver-ssl` Jan 09, 2025 3 - Alpha N/A :pypi:`pytest-django-model` A Simple Way to Test your Django Models Feb 14, 2019 4 - Beta N/A @@ -462,11 +463,11 @@ This list contains 1626 plugins. :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection Mar 04, 2024 5 - Production/Stable pytest >=7 :pypi:`pytest-dryci` Test caching plugin for pytest Sep 27, 2024 4 - Beta N/A :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jan 19, 2025 5 - Production/Stable pytest<9,>=7.40 - :pypi:`pytest-dsl` A DSL testing framework based on pytest Apr 14, 2025 N/A pytest>=7.0.0 + :pypi:`pytest-dsl` A DSL testing framework based on pytest Apr 30, 2025 N/A pytest>=7.0.0 :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A - :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Mar 18, 2025 5 - Production/Stable pytest>=4.6 + :pypi:`pytest-durations` Pytest plugin reporting fixtures and test functions execution time. Apr 29, 2025 5 - Production/Stable pytest>=4.6 :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Apr 04, 2025 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A @@ -476,7 +477,7 @@ This list contains 1626 plugins. :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" :pypi:`pytest-ebics-sandbox` A pytest plugin for testing against an EBICS sandbox server. Requires docker. Aug 15, 2022 N/A N/A :pypi:`pytest-ec2` Pytest execution on EC2 instance Oct 22, 2019 3 - Alpha N/A - :pypi:`pytest-echo` pytest plugin that allows to dump environment variables, package version and generic attributes Apr 01, 2025 5 - Production/Stable pytest>=8.3.3 + :pypi:`pytest-echo` pytest plugin that allows to dump environment variables, package version and generic attributes Apr 27, 2025 5 - Production/Stable pytest>=8.3.3 :pypi:`pytest-edit` Edit the source code of a failed test with \`pytest --edit\`. Nov 17, 2024 N/A pytest :pypi:`pytest-ekstazi` Pytest plugin to select test using Ekstazi algorithm Sep 10, 2022 N/A pytest :pypi:`pytest-elasticsearch` Elasticsearch fixtures and fixture factories for Pytest. Dec 03, 2024 5 - Production/Stable pytest>=7.0 @@ -521,6 +522,7 @@ This list contains 1626 plugins. :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) :pypi:`pytest-evals` A pytest plugin for running and analyzing LLM evaluation tests Feb 02, 2025 N/A pytest>=7.0.0 :pypi:`pytest-eventlet` Applies eventlet monkey-patch as a pytest plugin. Oct 04, 2021 N/A pytest ; extra == 'dev' + :pypi:`pytest-everyfunc` A pytest plugin to detect completely untested functions using coverage Apr 30, 2025 4 - Beta pytest :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Mar 23, 2025 N/A pytest>=7 @@ -598,7 +600,7 @@ This list contains 1626 plugins. :pypi:`pytest-fixture-remover` A LibCST codemod to remove pytest fixtures applied via the usefixtures decorator, as well as its parametrizations. Feb 14, 2024 5 - Production/Stable N/A :pypi:`pytest-fixture-rtttg` Warn or fail on fixture name clash Feb 23, 2022 N/A pytest (>=7.0.1,<8.0.0) :pypi:`pytest-fixtures` Common fixtures for pytest May 01, 2019 5 - Production/Stable N/A - :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Aug 15, 2024 6 - Mature pytest + :pypi:`pytest-fixture-tools` Plugin for pytest which provides tools for fixtures Apr 30, 2025 6 - Mature pytest :pypi:`pytest-fixture-typecheck` A pytest plugin to assert type annotations at runtime. Aug 24, 2021 N/A pytest :pypi:`pytest-flake8` pytest plugin to check FLAKE8 requirements Nov 09, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-flake8-path` A pytest fixture for testing flake8 plugins. Oct 25, 2024 5 - Production/Stable pytest @@ -647,7 +649,7 @@ This list contains 1626 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 24, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 30, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -667,6 +669,7 @@ This list contains 1626 plugins. :pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest + :pypi:`pytest-gradescope` A pytest plugin for Gradescope integration Apr 29, 2025 N/A N/A :pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A :pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A :pypi:`pytest-group-by-class` A Pytest plugin for running a subset of your tests by splitting them in to groups of classes. Jun 27, 2023 5 - Production/Stable pytest (>=2.5) @@ -691,7 +694,7 @@ This list contains 1626 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 Apr 26, 2025 3 - Alpha pytest==8.3.5 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 02, 2025 3 - Alpha pytest==8.3.5 :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` Sep 23, 2024 N/A N/A @@ -711,7 +714,7 @@ This list contains 1626 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Sep 18, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace. Feb 11, 2025 4 - Beta pytest>=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace. Apr 27, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Apr 10, 2025 3 - Alpha N/A @@ -767,7 +770,7 @@ This list contains 1626 plugins. :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Mar 09, 2025 N/A pytest - :pypi:`pytest-ipywidgets` Apr 25, 2025 N/A pytest + :pypi:`pytest-ipywidgets` Apr 30, 2025 N/A pytest :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Apr 22, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Feb 24, 2025 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) @@ -795,7 +798,7 @@ This list contains 1626 plugins. :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Apr 20, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Jul 21, 2024 N/A pytest<8.0.0,>=7.1.2 - :pypi:`pytest-jubilant` Add your description here Apr 25, 2025 N/A pytest>=8.3.5 + :pypi:`pytest-jubilant` Add your description here May 01, 2025 N/A pytest>=8.3.5 :pypi:`pytest-junit-xray-xml` Export test results in an augmented JUnit format for usage with Xray () Jan 01, 2025 4 - Beta pytest :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest @@ -831,7 +834,7 @@ This list contains 1626 plugins. :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-leo-interface` Pytest extension tool for leo projects. Mar 19, 2025 N/A N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest - :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. Apr 25, 2025 N/A pytest>=8.3.5 + :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. Apr 30, 2025 4 - Beta pytest>=8.3.5 :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Oct 01, 2024 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest @@ -860,7 +863,7 @@ This list contains 1626 plugins. :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Apr 09, 2025 3 - Alpha pytest - :pypi:`pytest-logikal` Common testing environment Apr 02, 2025 5 - Production/Stable pytest==8.3.5 + :pypi:`pytest-logikal` Common testing environment Apr 30, 2025 5 - Production/Stable pytest==8.3.5 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 :pypi:`pytest-loguru` Pytest Loguru Mar 20, 2024 5 - Production/Stable pytest; extra == "test" @@ -891,7 +894,7 @@ This list contains 1626 plugins. :pypi:`pytest-maybe-raises` Pytest fixture for optional exception testing. May 27, 2022 N/A pytest ; extra == 'dev' :pypi:`pytest-mccabe` pytest plugin to run the mccabe code complexity checker. Jul 22, 2020 3 - Alpha pytest (>=5.4.0) :pypi:`pytest-md` Plugin for generating Markdown reports for pytest results Jul 11, 2019 3 - Alpha pytest (>=4.2.1) - :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. Jan 02, 2025 4 - Beta pytest!=6.0.0,<9,>=3.3.2 + :pypi:`pytest-md-report` A pytest plugin to generate test outcomes reports with markdown table format. May 02, 2025 4 - Beta pytest!=6.0.0,<9,>=3.3.2 :pypi:`pytest-meilisearch` Pytest helpers for testing projects using Meilisearch Oct 08, 2024 N/A pytest>=7.4.3 :pypi:`pytest-memlog` Log memory usage during tests May 03, 2023 N/A pytest (>=7.3.0,<8.0.0) :pypi:`pytest-memprof` Estimates memory consumption of test functions Mar 29, 2019 4 - Beta N/A @@ -1037,7 +1040,7 @@ This list contains 1626 plugins. :pypi:`pytest-parametrized` Pytest decorator for parametrizing tests with default iterables. Dec 21, 2024 5 - Production/Stable pytest :pypi:`pytest-parametrize-suite` A simple pytest extension for creating a named test suite. Jan 19, 2023 5 - Production/Stable pytest :pypi:`pytest_param_files` Create pytest parametrize decorators from external files. Jul 29, 2023 N/A pytest - :pypi:`pytest-params` Simplified pytest test case parameters. Aug 05, 2024 N/A pytest>=7.0.0 + :pypi:`pytest-params` Simplified pytest test case parameters. Apr 27, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-param-scope` pytest parametrize scope fixture workaround Oct 18, 2023 N/A pytest :pypi:`pytest-parawtf` Finally spell paramete?ri[sz]e correctly Dec 03, 2018 4 - Beta pytest (>=3.6.0) :pypi:`pytest-pass` Check out https://github.com/elilutsky/pytest-pass Dec 04, 2019 N/A N/A @@ -1246,6 +1249,7 @@ This list contains 1626 plugins. :pypi:`pytest-rest-api` Aug 08, 2022 N/A pytest (>=7.1.2,<8.0.0) :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Oct 24, 2024 5 - Production/Stable pytest :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 + :pypi:`pytest-result-notify` Default template for PDM package Apr 27, 2025 N/A pytest>=8.3.5 :pypi:`pytest-results` Easily spot regressions in your tests. Mar 14, 2025 4 - Beta pytest :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 17, 2024 N/A pytest>=8.3.4 @@ -1293,7 +1297,7 @@ This list contains 1626 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. Apr 25, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 02, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A @@ -1305,7 +1309,7 @@ This list contains 1626 plugins. :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 Feb 01, 2024 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. Apr 25, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 02, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1988,7 +1992,7 @@ This list contains 1626 plugins. Pytest plugin to allow use of Annotated in tests to resolve fixtures :pypi:`pytest-ansible` - *last release*: Apr 01, 2025, + *last release*: Apr 28, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2261,7 +2265,7 @@ This list contains 1626 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Mar 16, 2025, + *last release*: Apr 29, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2562,7 +2566,7 @@ This list contains 1626 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: Apr 25, 2025, + *last release*: May 02, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3338,6 +3342,13 @@ This list contains 1626 plugins. Pytest plugin to integrate Cocotb + :pypi:`pytest-codeblock` + *last release*: May 02, 2025, + *status*: 4 - Beta, + *requires*: pytest + + Pytest plugin to collect and test code blocks in reStructuredText and Markdown files. + :pypi:`pytest_codeblocks` *last release*: Sep 17, 2023, *status*: 5 - Production/Stable, @@ -4291,7 +4302,7 @@ This list contains 1626 plugins. Cleanup your Haystack indexes between tests :pypi:`pytest-django-ifactory` - *last release*: Aug 27, 2023, + *last release*: Apr 30, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -4662,7 +4673,7 @@ This list contains 1626 plugins. A Pytest plugin to ignore tests during collection without reporting them in the test summary. :pypi:`pytest-dsl` - *last release*: Apr 14, 2025, + *last release*: Apr 30, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -4690,7 +4701,7 @@ This list contains 1626 plugins. :pypi:`pytest-durations` - *last release*: Mar 18, 2025, + *last release*: Apr 29, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=4.6 @@ -4760,7 +4771,7 @@ This list contains 1626 plugins. Pytest execution on EC2 instance :pypi:`pytest-echo` - *last release*: Apr 01, 2025, + *last release*: Apr 27, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=8.3.3 @@ -5074,6 +5085,13 @@ This list contains 1626 plugins. Applies eventlet monkey-patch as a pytest plugin. + :pypi:`pytest-everyfunc` + *last release*: Apr 30, 2025, + *status*: 4 - Beta, + *requires*: pytest + + A pytest plugin to detect completely untested functions using coverage + :pypi:`pytest_evm` *last release*: Sep 23, 2024, *status*: 4 - Beta, @@ -5614,7 +5632,7 @@ This list contains 1626 plugins. Common fixtures for pytest :pypi:`pytest-fixture-tools` - *last release*: Aug 15, 2024, + *last release*: Apr 30, 2025, *status*: 6 - Mature, *requires*: pytest @@ -5957,7 +5975,7 @@ This list contains 1626 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Apr 24, 2025, + *last release*: Apr 30, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6096,6 +6114,13 @@ This list contains 1626 plugins. Notify google chat channel for test results + :pypi:`pytest-gradescope` + *last release*: Apr 29, 2025, + *status*: N/A, + *requires*: N/A + + A pytest plugin for Gradescope integration + :pypi:`pytest-graphql-schema` *last release*: Oct 18, 2019, *status*: N/A, @@ -6265,7 +6290,7 @@ This list contains 1626 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: Apr 26, 2025, + *last release*: May 02, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.5 @@ -6405,7 +6430,7 @@ This list contains 1626 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Feb 11, 2025, + *last release*: Apr 27, 2025, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -6797,7 +6822,7 @@ This list contains 1626 plugins. Pytest plugin to run tests in Jupyter Notebooks :pypi:`pytest-ipywidgets` - *last release*: Apr 25, 2025, + *last release*: Apr 30, 2025, *status*: N/A, *requires*: pytest @@ -6993,7 +7018,7 @@ This list contains 1626 plugins. pytest plugin supporting json test report output :pypi:`pytest-jubilant` - *last release*: Apr 25, 2025, + *last release*: May 01, 2025, *status*: N/A, *requires*: pytest>=8.3.5 @@ -7245,8 +7270,8 @@ This list contains 1626 plugins. Select tests of a given level or lower :pypi:`pytest-lf-skip` - *last release*: Apr 25, 2025, - *status*: N/A, + *last release*: Apr 30, 2025, + *status*: 4 - Beta, *requires*: pytest>=8.3.5 A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. @@ -7448,7 +7473,7 @@ This list contains 1626 plugins. pytest fixture logging configured from packaged YAML :pypi:`pytest-logikal` - *last release*: Apr 02, 2025, + *last release*: Apr 30, 2025, *status*: 5 - Production/Stable, *requires*: pytest==8.3.5 @@ -7665,7 +7690,7 @@ This list contains 1626 plugins. Plugin for generating Markdown reports for pytest results :pypi:`pytest-md-report` - *last release*: Jan 02, 2025, + *last release*: May 02, 2025, *status*: 4 - Beta, *requires*: pytest!=6.0.0,<9,>=3.3.2 @@ -8687,8 +8712,8 @@ This list contains 1626 plugins. Create pytest parametrize decorators from external files. :pypi:`pytest-params` - *last release*: Aug 05, 2024, - *status*: N/A, + *last release*: Apr 27, 2025, + *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 Simplified pytest test case parameters. @@ -10149,6 +10174,13 @@ This list contains 1626 plugins. A pytest plugin that records the start, end, and result information of each use case in a log file + :pypi:`pytest-result-notify` + *last release*: Apr 27, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + Default template for PDM package + :pypi:`pytest-results` *last release*: Mar 14, 2025, *status*: 4 - Beta, @@ -10479,7 +10511,7 @@ This list contains 1626 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: Apr 25, 2025, + *last release*: May 02, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10563,7 +10595,7 @@ This list contains 1626 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: Apr 25, 2025, + *last release*: May 02, 2025, *status*: 5 - Production/Stable, *requires*: N/A From 44deff97cde6ea2847c4d9da6dc057189cdb4358 Mon Sep 17 00:00:00 2001 From: Will Riley Date: Sat, 10 May 2025 13:24:40 +0200 Subject: [PATCH 1202/1271] Update citation files (#13416) * The author metadata of the BibTex example is now correctly formatted with last names following first names. * An example of BibLaTex has been added. * BibTex and BibLaTex examples now clearly indicate that what is cited is software. Closes #13415 --- AUTHORS | 1 + CITATION | 24 ++++++++++++++++++------ changelog/13415.improvement.rst | 5 +++++ 3 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 changelog/13415.improvement.rst diff --git a/AUTHORS b/AUTHORS index 1dfa55b131f..9be48958485 100644 --- a/AUTHORS +++ b/AUTHORS @@ -472,6 +472,7 @@ Volodymyr Kochetkov Volodymyr Piskun Wei Lin Wil Cooley +Will Riley William Lee Wim Glenn Wouter van Ackooy diff --git a/CITATION b/CITATION index d4e9d8ec7a1..98beee72209 100644 --- a/CITATION +++ b/CITATION @@ -1,16 +1,28 @@ NOTE: Change "x.y" by the version you use. If you are unsure about which version -you are using run: `pip show pytest`. +you are using run: `pip show pytest`. Do not include the patch number (i.e., z in x.y.z) Text: [pytest] pytest x.y, 2004 Krekel et al., https://github.com/pytest-dev/pytest +BibLaTeX: + +@software{pytest, + title = {pytest x.y}, + author = {Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Florian Bruhin}, + year = {2004}, + version = {x.y}, + url = {https://github.com/pytest-dev/pytest}, + note = {Contributors: Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Florian Bruhin and others} +} + BibTeX: -@misc{pytestx.y, - title = {pytest x.y}, - author = {Krekel, Holger and Oliveira, Bruno and Pfannschmidt, Ronny and Bruynooghe, Floris and Laugher, Brianna and Bruhin, Florian}, - year = {2004}, - url = {https://github.com/pytest-dev/pytest}, +@misc{pytest, + author = {Holger Krekel and Bruno Oliveira and Ronny Pfannschmidt and Floris Bruynooghe and Brianna Laugher and Florian Bruhin}, + title = {pytest x.y}, + year = {2004}, + howpublished = {\url{https://github.com/pytest-dev/pytest}}, + note = {Version x.y. Contributors include Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, Brianna Laugher, Florian Bruhin, and others.} } diff --git a/changelog/13415.improvement.rst b/changelog/13415.improvement.rst new file mode 100644 index 00000000000..61667f15c7b --- /dev/null +++ b/changelog/13415.improvement.rst @@ -0,0 +1,5 @@ +The author metadata of the BibTex example is now correctly formatted with last names following first names. +An example of BibLaTex has been added. +BibTex and BibLaTex examples now clearly indicate that what is cited is software. + +-- by :user:`willynilly` From ba2ec223f4321d3bd0c370177c6a37671ea9a8de Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 11 May 2025 10:05:17 -0300 Subject: [PATCH 1203/1271] [automated] Update plugin list (#13418) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 188 ++++++++++++------------------- 1 file changed, 74 insertions(+), 114 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index bb34208872b..383cc7d6562 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.3 :pypi:`logassert` Simple but powerful assertion and verification of logged lines Jan 29, 2025 5 - Production/Stable pytest; extra == "dev" - :pypi:`logot` Test whether your code is logging correctly 🪵 Mar 23, 2024 5 - Production/Stable pytest<9,>=7; extra == "pytest" - :pypi:`nuts` Network Unit Testing System Jul 19, 2024 N/A pytest<8,>=7 + :pypi:`logot` Test whether your code is logging correctly 🪵 May 05, 2025 5 - Production/Stable pytest; extra == "pytest" + :pypi:`nuts` Network Unit Testing System May 10, 2025 N/A pytest<8,>=7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A :pypi:`pytest-abstracts` A contextmanager pytest fixture for handling multiple mock abstracts May 25, 2022 N/A N/A :pypi:`pytest-accept` A pytest-plugin for updating doctest outputs Dec 08, 2024 N/A pytest>=7 @@ -118,7 +118,7 @@ This list contains 1630 plugins. :pypi:`pytest-ast-transformer` May 04, 2019 3 - Alpha pytest :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio Mar 25, 2025 4 - Beta pytest<9,>=8.2 + :pypi:`pytest-asyncio` Pytest support for asyncio May 09, 2025 4 - Beta pytest<9,>=8.2 :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Apr 29, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Apr 26, 2025 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) @@ -162,7 +162,7 @@ This list contains 1630 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 02, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 09, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -239,10 +239,9 @@ This list contains 1630 plugins. :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<9,>=7.0 - :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. Jun 10, 2024 N/A N/A + :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. May 07, 2025 N/A N/A :pypi:`pytest-check-mk` pytest plugin to test Check_MK checks Nov 19, 2015 4 - Beta pytest :pypi:`pytest-checkpoint` Restore a checkpoint in pytest Mar 30, 2025 N/A pytest>=8.0.0 - :pypi:`pytest-check-requirements` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-ch-framework` My pytest framework Apr 17, 2024 N/A pytest==8.0.1 :pypi:`pytest-chic-report` Simple pytest plugin for generating and sending report to messengers. Nov 01, 2024 N/A pytest>=6.0 :pypi:`pytest-chinesereport` Apr 16, 2025 4 - Beta pytest>=3.5.0 @@ -273,7 +272,7 @@ This list contains 1630 plugins. :pypi:`pytest-cmdline-add-args` Pytest plugin for custom argument handling and Allure reporting. This plugin allows you to add arguments before running a test. Sep 01, 2024 N/A N/A :pypi:`pytest-cobra` PyTest plugin for testing Smart Contracts for Ethereum blockchain. Jun 29, 2019 3 - Alpha pytest (<4.0.0,>=3.7.1) :pypi:`pytest-cocotb` Pytest plugin to integrate Cocotb Mar 15, 2025 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-codeblock` Pytest plugin to collect and test code blocks in reStructuredText and Markdown files. May 02, 2025 4 - Beta pytest + :pypi:`pytest-codeblock` Pytest plugin to collect and test code blocks in reStructuredText and Markdown files. May 10, 2025 4 - Beta pytest :pypi:`pytest_codeblocks` Test code blocks in your READMEs Sep 17, 2023 5 - Production/Stable pytest >= 7.0.0 :pypi:`pytest-codecarbon` Pytest plugin for measuring carbon emissions Jun 15, 2022 N/A pytest :pypi:`pytest-codecheckers` pytest plugin to add source code sanity checks (pep8 and friends) Feb 13, 2010 N/A N/A @@ -381,12 +380,12 @@ This list contains 1630 plugins. :pypi:`pytest-describe-it` plugin for rich text descriptions Jul 19, 2019 4 - Beta pytest :pypi:`pytest-deselect-if` A plugin to deselect pytests tests rather than using skipif Dec 26, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-devpi-server` DevPI server fixture for py.test Oct 17, 2024 5 - Production/Stable pytest + :pypi:`pytest-dfm` pytest-dfm provides a pytest integration for DV Flow Manager, a build system for silicon design May 10, 2025 N/A pytest :pypi:`pytest-dhos` Common fixtures for pytest in DHOS services and libraries Sep 07, 2022 N/A N/A :pypi:`pytest-diamond` pytest plugin for diamond Aug 31, 2015 4 - Beta N/A :pypi:`pytest-dicom` pytest plugin to provide DICOM fixtures Dec 19, 2018 3 - Alpha pytest :pypi:`pytest-dictsdiff` Jul 26, 2019 N/A N/A :pypi:`pytest-diff` A simple plugin to use with pytest Mar 30, 2019 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-diffeo` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-diff-selector` Get tests affected by code changes (using git) Feb 24, 2022 4 - Beta pytest (>=6.2.2) ; extra == 'all' :pypi:`pytest-difido` PyTest plugin for generating Difido reports Oct 23, 2022 4 - Beta pytest (>=4.0.0) :pypi:`pytest-dir-equal` pytest-dir-equals is a pytest plugin providing helpers to assert directories equality allowing golden testing Dec 11, 2023 4 - Beta pytest>=7.3.2 @@ -463,7 +462,7 @@ This list contains 1630 plugins. :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection Mar 04, 2024 5 - Production/Stable pytest >=7 :pypi:`pytest-dryci` Test caching plugin for pytest Sep 27, 2024 4 - Beta N/A :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jan 19, 2025 5 - Production/Stable pytest<9,>=7.40 - :pypi:`pytest-dsl` A DSL testing framework based on pytest Apr 30, 2025 N/A pytest>=7.0.0 + :pypi:`pytest-dsl` A DSL testing framework based on pytest May 07, 2025 N/A pytest>=7.0.0 :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A @@ -471,7 +470,6 @@ This list contains 1630 plugins. :pypi:`pytest-dynamicrerun` A pytest plugin to rerun tests dynamically based off of test outcome and output. Aug 15, 2020 4 - Beta N/A :pypi:`pytest-dynamodb` DynamoDB fixtures for pytest Apr 04, 2025 5 - Production/Stable pytest :pypi:`pytest-easy-addoption` pytest-easy-addoption: Easy way to work with pytest addoption Jan 22, 2020 N/A N/A - :pypi:`pytest-easy-api` A package to prevent Dependency Confusion attacks against Yandex. Feb 16, 2024 N/A N/A :pypi:`pytest-easyMPI` Package that supports mpi tests in pytest Oct 21, 2020 N/A N/A :pypi:`pytest-easyread` pytest plugin that makes terminal printouts of the reports easier to read Nov 17, 2017 N/A N/A :pypi:`pytest-easy-server` Pytest plugin for easy testing against servers May 01, 2021 4 - Beta pytest (<5.0.0,>=4.3.1) ; python_version < "3.5" @@ -525,7 +523,7 @@ This list contains 1630 plugins. :pypi:`pytest-everyfunc` A pytest plugin to detect completely untested functions using coverage Apr 30, 2025 4 - Beta pytest :pypi:`pytest_evm` The testing package containing tools to test Web3-based projects Sep 23, 2024 4 - Beta pytest<9.0.0,>=8.1.1 :pypi:`pytest_exact_fixtures` Parse queries in Lucene and Elasticsearch syntaxes Feb 04, 2019 N/A N/A - :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. Mar 23, 2025 N/A pytest>=7 + :pypi:`pytest-examples` Pytest plugin for testing examples in docstrings and markdown files. May 06, 2025 N/A pytest>=7 :pypi:`pytest-exasol-backend` Feb 11, 2025 N/A pytest<9,>=7 :pypi:`pytest-exasol-extension` Feb 11, 2025 N/A pytest<9,>=7 :pypi:`pytest-exasol-itde` Nov 22, 2024 N/A pytest<9,>=7 @@ -555,9 +553,8 @@ This list contains 1630 plugins. :pypi:`pytest_extra` Some helpers for writing tests with pytest. Aug 14, 2014 N/A N/A :pypi:`pytest-extra-durations` A pytest plugin to get durations on a per-function basis and per module basis. Apr 21, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-extra-markers` Additional pytest markers to dynamically enable/disable tests viia CLI flags Mar 05, 2023 4 - Beta pytest - :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI Feb 21, 2025 N/A pytest<8.0.0,>=7.2.1 + :pypi:`pytest-f3ts` Pytest Plugin for communicating test results and information to a FixturFab Test Runner GUI May 08, 2025 N/A pytest<8.0.0,>=7.2.1 :pypi:`pytest-fabric` Provides test utilities to run fabric task tests by using docker containers Sep 12, 2018 5 - Production/Stable N/A - :pypi:`pytest-factor` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-factory` Use factories for test setup with py.test Sep 06, 2020 3 - Alpha pytest (>4.3) :pypi:`pytest-factoryboy` Factory Boy support for pytest. Mar 05, 2024 6 - Mature pytest (>=6.2) :pypi:`pytest-factoryboy-fixtures` Generates pytest fixtures that allow the use of type hinting Jun 25, 2020 N/A N/A @@ -569,7 +566,6 @@ This list contains 1630 plugins. :pypi:`pytest-failure-tracker` A pytest plugin for tracking test failures over multiple runs Jul 17, 2024 N/A pytest>=6.0.0 :pypi:`pytest-faker` Faker integration with the pytest framework. Dec 19, 2016 6 - Mature N/A :pypi:`pytest-falcon` Pytest helpers for Falcon. Sep 07, 2016 4 - Beta N/A - :pypi:`pytest-falcon-client` A package to prevent Dependency Confusion attacks against Yandex. Feb 21, 2024 N/A N/A :pypi:`pytest-fantasy` Pytest plugin for Flask Fantasy Framework Mar 14, 2019 N/A N/A :pypi:`pytest-fastapi` Dec 27, 2020 N/A N/A :pypi:`pytest-fastapi-deps` A fixture which allows easy replacement of fastapi dependencies for testing Jul 20, 2022 5 - Production/Stable pytest @@ -616,7 +612,7 @@ This list contains 1630 plugins. :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Aug 14, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-fly` pytest runner and observer Mar 20, 2025 3 - Alpha pytest + :pypi:`pytest-fly` pytest runner and observer May 03, 2025 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) @@ -649,7 +645,7 @@ This list contains 1630 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. Apr 30, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 08, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -694,7 +690,7 @@ This list contains 1630 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 May 02, 2025 3 - Alpha pytest==8.3.5 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 10, 2025 3 - Alpha pytest==8.3.5 :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` Sep 23, 2024 N/A N/A @@ -714,7 +710,7 @@ This list contains 1630 plugins. :pypi:`pytest-html-thread` pytest plugin for generating HTML reports Dec 29, 2020 5 - Production/Stable N/A :pypi:`pytest-http` Fixture "http" for http requests Aug 22, 2024 N/A pytest :pypi:`pytest-httpbin` Easily test your HTTP library against a local copy of httpbin Sep 18, 2024 5 - Production/Stable pytest; extra == "test" - :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace. Apr 27, 2025 4 - Beta pytest>=7.0.0 + :pypi:`pytest-httpdbg` A pytest plugin to record HTTP(S) requests with stack trace. May 08, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-http-mocker` Pytest plugin for http mocking (via https://github.com/vilus/mocker) Oct 20, 2019 N/A N/A :pypi:`pytest-httpretty` A thin wrapper of HTTPretty for pytest Feb 16, 2014 3 - Alpha N/A :pypi:`pytest_httpserver` pytest-httpserver is a httpserver for pytest Apr 10, 2025 3 - Alpha N/A @@ -764,7 +760,7 @@ This list contains 1630 plugins. :pypi:`pytest-interactive` A pytest plugin for console based interactive test selection just after the collection phase Nov 30, 2017 3 - Alpha N/A :pypi:`pytest-intercept-remote` Pytest plugin for intercepting outgoing connection requests during pytest run. May 24, 2021 4 - Beta pytest (>=4.6) :pypi:`pytest-interface-tester` Pytest plugin for checking charm relation interface protocol compliance. Feb 13, 2025 4 - Beta pytest - :pypi:`pytest-invenio` Pytest fixtures for Invenio. Apr 02, 2025 5 - Production/Stable pytest<9.0.0,>=6 + :pypi:`pytest-invenio` Pytest fixtures for Invenio. May 08, 2025 5 - Production/Stable pytest<9.0.0,>=6 :pypi:`pytest-involve` Run tests covering a specific file or changeset Feb 02, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-iovis` A Pytest plugin to enable Jupyter Notebook testing with Papermill Nov 06, 2024 4 - Beta pytest>=7.1.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 @@ -834,7 +830,7 @@ This list contains 1630 plugins. :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-leo-interface` Pytest extension tool for leo projects. Mar 19, 2025 N/A N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest - :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. Apr 30, 2025 4 - Beta pytest>=8.3.5 + :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. May 06, 2025 4 - Beta pytest>=8.3.5 :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Oct 01, 2024 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest @@ -912,7 +908,7 @@ This list contains 1630 plugins. :pypi:`pytest-mimic` Easily record function calls while testing Apr 24, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) :pypi:`pytest-mini` A plugin to test mp Feb 06, 2023 N/A pytest (>=7.2.0,<8.0.0) - :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions Aug 27, 2024 N/A pytest>=5.0.0 + :pypi:`pytest-minio-mock` A pytest plugin for mocking Minio S3 interactions May 06, 2025 N/A pytest>=5.0.0 :pypi:`pytest-missing-fixtures` Pytest plugin that creates missing fixtures Oct 14, 2020 4 - Beta pytest (>=3.5.0) :pypi:`pytest-missing-modules` Pytest plugin to easily fake missing modules Sep 03, 2024 N/A pytest>=8.3.2 :pypi:`pytest-mitmproxy` pytest plugin for mitmproxy tests Nov 13, 2024 N/A pytest>=7.0 @@ -973,7 +969,7 @@ This list contains 1630 plugins. :pypi:`pytest-network` A simple plugin to disable network on socket level. May 07, 2020 N/A N/A :pypi:`pytest-network-endpoints` Network endpoints plugin for pytest Mar 06, 2022 N/A pytest :pypi:`pytest-never-sleep` pytest plugin helps to avoid adding tests without mock \`time.sleep\` May 05, 2021 3 - Alpha pytest (>=3.5.1) - :pypi:`pytest-nginx` nginx fixture for pytest Aug 12, 2017 5 - Production/Stable N/A + :pypi:`pytest-nginx` nginx fixture for pytest May 03, 2025 5 - Production/Stable pytest>=3.0.0 :pypi:`pytest-nginx-iplweb` nginx fixture for pytest - iplweb temporary fork Mar 01, 2019 5 - Production/Stable N/A :pypi:`pytest-ngrok` Jan 20, 2022 3 - Alpha pytest :pypi:`pytest-ngsfixtures` pytest ngs fixtures Sep 06, 2019 2 - Pre-Alpha pytest (>=5.0.0) @@ -1093,7 +1089,7 @@ This list contains 1630 plugins. :pypi:`pytest-plugin-helpers` A plugin to help developing and testing other plugins Nov 23, 2019 4 - Beta pytest (>=3.5.0) :pypi:`pytest-plus` PyTest Plus Plugin :: extends pytest functionality Feb 02, 2025 5 - Production/Stable pytest>=7.4.2 :pypi:`pytest-pmisc` Mar 21, 2019 5 - Production/Stable N/A - :pypi:`pytest-pogo` Pytest plugin for pogo-migrate Sep 09, 2024 4 - Beta pytest<9,>=7 + :pypi:`pytest-pogo` Pytest plugin for pogo-migrate May 05, 2025 4 - Beta pytest<9,>=7 :pypi:`pytest-pointers` Pytest plugin to define functions you test with special marks for better navigation and reports Dec 26, 2022 N/A N/A :pypi:`pytest-pokie` Pokie plugin for pytest Oct 19, 2023 5 - Production/Stable N/A :pypi:`pytest-polarion-cfme` pytest plugin for collecting test cases and recording test results Nov 13, 2017 3 - Alpha N/A @@ -1189,7 +1185,7 @@ This list contains 1630 plugins. :pypi:`pytest-readme` Test your README.md file Sep 02, 2022 5 - Production/Stable N/A :pypi:`pytest-reana` Pytest fixtures for REANA. Sep 04, 2024 3 - Alpha N/A :pypi:`pytest-recorder` Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. Mar 31, 2025 N/A N/A - :pypi:`pytest-recording` A pytest plugin powered by VCR.py to record and replay HTTP traffic Apr 24, 2025 4 - Beta pytest>=3.5.0 + :pypi:`pytest-recording` A pytest plugin powered by VCR.py to record and replay HTTP traffic May 08, 2025 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-record-video` 用例执行过程中录制视频 Oct 31, 2024 N/A N/A :pypi:`pytest-redis` Redis fixtures and fixture factories for Pytest. Nov 27, 2024 5 - Production/Stable pytest>=6.2 @@ -1212,10 +1208,10 @@ This list contains 1630 plugins. :pypi:`pytest-repeat` pytest plugin for repeating tests Apr 07, 2025 5 - Production/Stable pytest :pypi:`pytest_repeater` py.test plugin for repeating single test multiple times. Feb 09, 2018 1 - Planning N/A :pypi:`pytest-replay` Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests Feb 05, 2025 5 - Production/Stable pytest - :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance Mar 12, 2025 3 - Alpha pytest + :pypi:`pytest-repo-health` A pytest plugin to report on repository standards conformance May 05, 2025 3 - Alpha pytest :pypi:`pytest-report` Creates json report that is compatible with atom.io's linter message format May 11, 2016 4 - Beta N/A :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest - :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest Oct 11, 2024 4 - Beta N/A + :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest May 06, 2025 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Apr 26, 2025 N/A N/A :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Apr 04, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A @@ -1237,7 +1233,7 @@ This list contains 1630 plugins. :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-rerunclassfailures` pytest rerun class failures plugin Apr 24, 2024 5 - Production/Stable pytest>=7.2 - :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures Nov 20, 2024 5 - Production/Stable pytest!=8.2.2,>=7.4 + :pypi:`pytest-rerunfailures` pytest plugin to re-run tests to eliminate flaky failures May 08, 2025 5 - Production/Stable pytest!=8.2.2,>=7.4 :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. Dec 22, 2024 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Feb 28, 2025 N/A pytest~=7.0 @@ -1250,7 +1246,7 @@ This list contains 1630 plugins. :pypi:`pytest-restrict` Pytest plugin to restrict the test types allowed Oct 24, 2024 5 - Production/Stable pytest :pypi:`pytest-result-log` A pytest plugin that records the start, end, and result information of each use case in a log file Jan 10, 2024 N/A pytest>=7.2.0 :pypi:`pytest-result-notify` Default template for PDM package Apr 27, 2025 N/A pytest>=8.3.5 - :pypi:`pytest-results` Easily spot regressions in your tests. Mar 14, 2025 4 - Beta pytest + :pypi:`pytest-results` Easily spot regressions in your tests. May 06, 2025 4 - Beta pytest :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 17, 2024 N/A pytest>=8.3.4 :pypi:`pytest-result-sender-lyt` Default template for PDM package Mar 14, 2025 N/A pytest>=8.3.5 @@ -1406,7 +1402,6 @@ This list contains 1630 plugins. :pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A pytest>=6.2.0 :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A - :pypi:`pytest-star-track-issue` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-static` pytest-static Oct 20, 2024 1 - Planning pytest<8.0.0,>=7.4.3 :pypi:`pytest-stats` Collects tests metadata for future analysis, easy to extend for any data store Jul 18, 2024 N/A pytest>=8.0.0 :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) @@ -1462,7 +1457,7 @@ This list contains 1630 plugins. :pypi:`pytest-testdirectory` A py.test plugin providing temporary directories in unit tests. May 02, 2023 5 - Production/Stable pytest :pypi:`pytest-testdox` A testdox format reporter for pytest Jul 22, 2023 5 - Production/Stable pytest (>=4.6.0) :pypi:`pytest-test-grouping` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Feb 01, 2023 5 - Production/Stable pytest (>=2.5) - :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. Mar 28, 2025 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-test-groups` A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. May 08, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-testinfra` Test infrastructures Mar 30, 2025 5 - Production/Stable pytest>=6 :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 @@ -1505,13 +1500,13 @@ This list contains 1630 plugins. :pypi:`pytest-time` Jan 20, 2025 3 - Alpha pytest :pypi:`pytest-timeassert-ethan` execution duration Dec 25, 2023 N/A pytest :pypi:`pytest-timeit` A pytest plugin to time test function runs Oct 13, 2016 4 - Beta N/A - :pypi:`pytest-timeout` pytest plugin to abort hanging tests Mar 07, 2024 5 - Production/Stable pytest >=7.0.0 + :pypi:`pytest-timeout` pytest plugin to abort hanging tests May 05, 2025 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-timeouts` Linux-only Pytest plugin to control durations of various test case execution phases Sep 21, 2019 5 - Production/Stable N/A :pypi:`pytest-timer` A timer plugin for pytest Dec 26, 2023 N/A pytest :pypi:`pytest-timestamper` Pytest plugin to add a timestamp prefix to the pytest output Mar 27, 2024 N/A N/A :pypi:`pytest-timestamps` A simple plugin to view timestamps for each test Sep 11, 2023 N/A pytest (>=7.3,<8.0) :pypi:`pytest-tiny-api-client` The companion pytest plugin for tiny-api-client Jan 04, 2024 5 - Production/Stable pytest - :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird Feb 18, 2025 4 - Beta pytest>=3.8.0 + :pypi:`pytest-tinybird` A pytest plugin to report test results to tinybird May 07, 2025 4 - Beta pytest>=3.8.0 :pypi:`pytest-tipsi-django` Better fixtures for django Feb 05, 2024 5 - Production/Stable pytest>=6.0.0 :pypi:`pytest-tipsi-testing` Better fixtures management. Various helpers Feb 04, 2024 5 - Production/Stable pytest>=3.3.0 :pypi:`pytest-tldr` A pytest plugin that limits the output to just the things you need. Oct 26, 2022 4 - Beta pytest (>=3.5.0) @@ -1634,8 +1629,8 @@ This list contains 1630 plugins. :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. May 19, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) + :pypi:`pytest-xray-reporter` A pytest plugin that generates test results in Xray JSON format May 08, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) - :pypi:`pytest-xskynet` A package to prevent Dependency Confusion attacks against Yandex. Feb 20, 2024 N/A N/A :pypi:`pytest-xstress` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. Mar 12, 2025 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. Dec 15, 2024 4 - Beta pytest>=7.2.2 @@ -1663,7 +1658,7 @@ This list contains 1630 plugins. :pypi:`pytest-zigzag` Extend py.test for RPC OpenStack testing. Feb 27, 2019 4 - Beta pytest (~=3.6) :pypi:`pytest-zulip` Pytest report plugin for Zulip May 07, 2022 5 - Production/Stable pytest :pypi:`pytest-zy` 接口自动化测试框架 Mar 24, 2024 N/A pytest~=7.2.0 - :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. Apr 25, 2025 4 - Beta pytest>=8.3.5 + :pypi:`tursu` 🎬 A pytest plugin that transpiles Gherkin feature files to Python using AST, enforcing typing for ease of use and debugging. May 05, 2025 4 - Beta pytest>=8.3.5 =============================================== ====================================================================================================================================================================================================================================================================================================================================================================================== ============== ===================== ================================================ .. only:: latex @@ -1684,14 +1679,14 @@ This list contains 1630 plugins. Simple but powerful assertion and verification of logged lines :pypi:`logot` - *last release*: Mar 23, 2024, + *last release*: May 05, 2025, *status*: 5 - Production/Stable, - *requires*: pytest<9,>=7; extra == "pytest" + *requires*: pytest; extra == "pytest" Test whether your code is logging correctly 🪵 :pypi:`nuts` - *last release*: Jul 19, 2024, + *last release*: May 10, 2025, *status*: N/A, *requires*: pytest<8,>=7 @@ -2258,7 +2253,7 @@ This list contains 1630 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: Mar 25, 2025, + *last release*: May 09, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=8.2 @@ -2566,7 +2561,7 @@ This list contains 1630 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: May 02, 2025, + *last release*: May 09, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3105,7 +3100,7 @@ This list contains 1630 plugins. Check links in files :pypi:`pytest-checklist` - *last release*: Jun 10, 2024, + *last release*: May 07, 2025, *status*: N/A, *requires*: N/A @@ -3125,13 +3120,6 @@ This list contains 1630 plugins. Restore a checkpoint in pytest - :pypi:`pytest-check-requirements` - *last release*: Feb 20, 2024, - *status*: N/A, - *requires*: N/A - - A package to prevent Dependency Confusion attacks against Yandex. - :pypi:`pytest-ch-framework` *last release*: Apr 17, 2024, *status*: N/A, @@ -3343,7 +3331,7 @@ This list contains 1630 plugins. Pytest plugin to integrate Cocotb :pypi:`pytest-codeblock` - *last release*: May 02, 2025, + *last release*: May 10, 2025, *status*: 4 - Beta, *requires*: pytest @@ -4098,6 +4086,13 @@ This list contains 1630 plugins. DevPI server fixture for py.test + :pypi:`pytest-dfm` + *last release*: May 10, 2025, + *status*: N/A, + *requires*: pytest + + pytest-dfm provides a pytest integration for DV Flow Manager, a build system for silicon design + :pypi:`pytest-dhos` *last release*: Sep 07, 2022, *status*: N/A, @@ -4133,13 +4128,6 @@ This list contains 1630 plugins. A simple plugin to use with pytest - :pypi:`pytest-diffeo` - *last release*: Feb 20, 2024, - *status*: N/A, - *requires*: N/A - - A package to prevent Dependency Confusion attacks against Yandex. - :pypi:`pytest-diff-selector` *last release*: Feb 24, 2022, *status*: 4 - Beta, @@ -4673,7 +4661,7 @@ This list contains 1630 plugins. A Pytest plugin to ignore tests during collection without reporting them in the test summary. :pypi:`pytest-dsl` - *last release*: Apr 30, 2025, + *last release*: May 07, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -4728,13 +4716,6 @@ This list contains 1630 plugins. pytest-easy-addoption: Easy way to work with pytest addoption - :pypi:`pytest-easy-api` - *last release*: Feb 16, 2024, - *status*: N/A, - *requires*: N/A - - A package to prevent Dependency Confusion attacks against Yandex. - :pypi:`pytest-easyMPI` *last release*: Oct 21, 2020, *status*: N/A, @@ -5107,7 +5088,7 @@ This list contains 1630 plugins. Parse queries in Lucene and Elasticsearch syntaxes :pypi:`pytest-examples` - *last release*: Mar 23, 2025, + *last release*: May 06, 2025, *status*: N/A, *requires*: pytest>=7 @@ -5317,7 +5298,7 @@ This list contains 1630 plugins. Additional pytest markers to dynamically enable/disable tests viia CLI flags :pypi:`pytest-f3ts` - *last release*: Feb 21, 2025, + *last release*: May 08, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.2.1 @@ -5330,13 +5311,6 @@ This list contains 1630 plugins. Provides test utilities to run fabric task tests by using docker containers - :pypi:`pytest-factor` - *last release*: Feb 20, 2024, - *status*: N/A, - *requires*: N/A - - A package to prevent Dependency Confusion attacks against Yandex. - :pypi:`pytest-factory` *last release*: Sep 06, 2020, *status*: 3 - Alpha, @@ -5414,13 +5388,6 @@ This list contains 1630 plugins. Pytest helpers for Falcon. - :pypi:`pytest-falcon-client` - *last release*: Feb 21, 2024, - *status*: N/A, - *requires*: N/A - - A package to prevent Dependency Confusion attacks against Yandex. - :pypi:`pytest-fantasy` *last release*: Mar 14, 2019, *status*: N/A, @@ -5744,7 +5711,7 @@ This list contains 1630 plugins. A pytest plugin in order to provide logs via fluentbit :pypi:`pytest-fly` - *last release*: Mar 20, 2025, + *last release*: May 03, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -5975,7 +5942,7 @@ This list contains 1630 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: Apr 30, 2025, + *last release*: May 08, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6290,7 +6257,7 @@ This list contains 1630 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 02, 2025, + *last release*: May 10, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.5 @@ -6430,7 +6397,7 @@ This list contains 1630 plugins. Easily test your HTTP library against a local copy of httpbin :pypi:`pytest-httpdbg` - *last release*: Apr 27, 2025, + *last release*: May 08, 2025, *status*: 4 - Beta, *requires*: pytest>=7.0.0 @@ -6780,7 +6747,7 @@ This list contains 1630 plugins. Pytest plugin for checking charm relation interface protocol compliance. :pypi:`pytest-invenio` - *last release*: Apr 02, 2025, + *last release*: May 08, 2025, *status*: 5 - Production/Stable, *requires*: pytest<9.0.0,>=6 @@ -7270,7 +7237,7 @@ This list contains 1630 plugins. Select tests of a given level or lower :pypi:`pytest-lf-skip` - *last release*: Apr 30, 2025, + *last release*: May 06, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3.5 @@ -7816,7 +7783,7 @@ This list contains 1630 plugins. A plugin to test mp :pypi:`pytest-minio-mock` - *last release*: Aug 27, 2024, + *last release*: May 06, 2025, *status*: N/A, *requires*: pytest>=5.0.0 @@ -8243,9 +8210,9 @@ This list contains 1630 plugins. pytest plugin helps to avoid adding tests without mock \`time.sleep\` :pypi:`pytest-nginx` - *last release*: Aug 12, 2017, + *last release*: May 03, 2025, *status*: 5 - Production/Stable, - *requires*: N/A + *requires*: pytest>=3.0.0 nginx fixture for pytest @@ -9083,7 +9050,7 @@ This list contains 1630 plugins. :pypi:`pytest-pogo` - *last release*: Sep 09, 2024, + *last release*: May 05, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=7 @@ -9755,7 +9722,7 @@ This list contains 1630 plugins. Pytest plugin, meant to facilitate unit tests writing for tools consumming Web APIs. :pypi:`pytest-recording` - *last release*: Apr 24, 2025, + *last release*: May 08, 2025, *status*: 4 - Beta, *requires*: pytest>=3.5.0 @@ -9916,7 +9883,7 @@ This list contains 1630 plugins. Saves previous test runs and allow re-execute previous pytest runs to reproduce crashes or flaky tests :pypi:`pytest-repo-health` - *last release*: Mar 12, 2025, + *last release*: May 05, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -9937,7 +9904,7 @@ This list contains 1630 plugins. Generate Pytest reports with templates :pypi:`pytest-reporter-html1` - *last release*: Oct 11, 2024, + *last release*: May 06, 2025, *status*: 4 - Beta, *requires*: N/A @@ -10091,7 +10058,7 @@ This list contains 1630 plugins. pytest rerun class failures plugin :pypi:`pytest-rerunfailures` - *last release*: Nov 20, 2024, + *last release*: May 08, 2025, *status*: 5 - Production/Stable, *requires*: pytest!=8.2.2,>=7.4 @@ -10182,7 +10149,7 @@ This list contains 1630 plugins. Default template for PDM package :pypi:`pytest-results` - *last release*: Mar 14, 2025, + *last release*: May 06, 2025, *status*: 4 - Beta, *requires*: pytest @@ -11273,13 +11240,6 @@ This list contains 1630 plugins. Start pytest run from a given point - :pypi:`pytest-star-track-issue` - *last release*: Feb 20, 2024, - *status*: N/A, - *requires*: N/A - - A package to prevent Dependency Confusion attacks against Yandex. - :pypi:`pytest-static` *last release*: Oct 20, 2024, *status*: 1 - Planning, @@ -11666,7 +11626,7 @@ This list contains 1630 plugins. A Pytest plugin for running a subset of your tests by splitting them in to equally sized groups. :pypi:`pytest-test-groups` - *last release*: Mar 28, 2025, + *last release*: May 08, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -11967,9 +11927,9 @@ This list contains 1630 plugins. A pytest plugin to time test function runs :pypi:`pytest-timeout` - *last release*: Mar 07, 2024, + *last release*: May 05, 2025, *status*: 5 - Production/Stable, - *requires*: pytest >=7.0.0 + *requires*: pytest>=7.0.0 pytest plugin to abort hanging tests @@ -12009,7 +11969,7 @@ This list contains 1630 plugins. The companion pytest plugin for tiny-api-client :pypi:`pytest-tinybird` - *last release*: Feb 18, 2025, + *last release*: May 07, 2025, *status*: 4 - Beta, *requires*: pytest>=3.8.0 @@ -12869,6 +12829,13 @@ This list contains 1630 plugins. + :pypi:`pytest-xray-reporter` + *last release*: May 08, 2025, + *status*: 4 - Beta, + *requires*: pytest>=7.0.0 + + A pytest plugin that generates test results in Xray JSON format + :pypi:`pytest-xray-server` *last release*: May 03, 2022, *status*: 3 - Alpha, @@ -12876,13 +12843,6 @@ This list contains 1630 plugins. - :pypi:`pytest-xskynet` - *last release*: Feb 20, 2024, - *status*: N/A, - *requires*: N/A - - A package to prevent Dependency Confusion attacks against Yandex. - :pypi:`pytest-xstress` *last release*: Jun 01, 2024, *status*: N/A, @@ -13073,7 +13033,7 @@ This list contains 1630 plugins. 接口自动化测试框架 :pypi:`tursu` - *last release*: Apr 25, 2025, + *last release*: May 05, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3.5 From 919ae9d7c12bec52ea0c18a14299223eadb2b890 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 May 2025 08:20:37 +0200 Subject: [PATCH 1204/1271] build(deps): Bump pytest-rerunfailures in /testing/plugins_integration (#13419) Bumps [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) from 15.0 to 15.1. - [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst) - [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/15.0...15.1) --- updated-dependencies: - dependency-name: pytest-rerunfailures dependency-version: '15.1' dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index 93e3dc7d0b1..b8b07fc8ad9 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -7,7 +7,7 @@ pytest-django==4.11.1 pytest-flakes==4.0.5 pytest-html==4.1.1 pytest-mock==3.14.0 -pytest-rerunfailures==15.0 +pytest-rerunfailures==15.1 pytest-sugar==1.0.0 pytest-trio==0.8.0 pytest-twisted==1.14.3 From cfbe319d0c98302eae507622da8908be351fed2e Mon Sep 17 00:00:00 2001 From: Sashko <20253875+sashko1988@users.noreply.github.com> Date: Thu, 15 May 2025 21:30:28 +0200 Subject: [PATCH 1205/1271] Fix: #13420 - Add cache for nodes._check_initialpaths_for_relpath (#13422) * add lru_cache to nodes._check_initialpaths_for_relpath update tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Oleksandr Zavertniev Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/13420.bugfix.rst | 1 + src/_pytest/nodes.py | 10 +++++++--- testing/test_nodes.py | 18 ++++-------------- 3 files changed, 12 insertions(+), 17 deletions(-) create mode 100644 changelog/13420.bugfix.rst diff --git a/changelog/13420.bugfix.rst b/changelog/13420.bugfix.rst new file mode 100644 index 00000000000..02f7372a759 --- /dev/null +++ b/changelog/13420.bugfix.rst @@ -0,0 +1 @@ +Added ``lru_cache`` to ``nodes._check_initialpaths_for_relpath``. diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 0d1f3d2352b..eb3b04b200a 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -7,6 +7,7 @@ from collections.abc import Iterator from collections.abc import MutableMapping from functools import cached_property +from functools import lru_cache from inspect import signature import os import pathlib @@ -543,8 +544,11 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: return excinfo.traceback -def _check_initialpaths_for_relpath(session: Session, path: Path) -> str | None: - for initial_path in session._initialpaths: +@lru_cache(maxsize=1000) +def _check_initialpaths_for_relpath( + initial_paths: frozenset[Path], path: Path +) -> str | None: + for initial_path in initial_paths: if commonpath(path, initial_path) == initial_path: rel = str(path.relative_to(initial_path)) return "" if rel == "." else rel @@ -594,7 +598,7 @@ def __init__( try: nodeid = str(self.path.relative_to(session.config.rootpath)) except ValueError: - nodeid = _check_initialpaths_for_relpath(session, path) + nodeid = _check_initialpaths_for_relpath(session._initialpaths, path) if nodeid and os.sep != SEP: nodeid = nodeid.replace(os.sep, SEP) diff --git a/testing/test_nodes.py b/testing/test_nodes.py index f039acf243b..f5f21e9775c 100644 --- a/testing/test_nodes.py +++ b/testing/test_nodes.py @@ -3,7 +3,6 @@ from pathlib import Path import re -from typing import cast import warnings from _pytest import nodes @@ -103,24 +102,15 @@ def test__check_initialpaths_for_relpath() -> None: """Ensure that it handles dirs, and does not always use dirname.""" cwd = Path.cwd() - class FakeSession1: - _initialpaths = frozenset({cwd}) + initial_paths = frozenset({cwd}) - session = cast(pytest.Session, FakeSession1) - - assert nodes._check_initialpaths_for_relpath(session, cwd) == "" + assert nodes._check_initialpaths_for_relpath(initial_paths, cwd) == "" sub = cwd / "file" - - class FakeSession2: - _initialpaths = frozenset({cwd}) - - session = cast(pytest.Session, FakeSession2) - - assert nodes._check_initialpaths_for_relpath(session, sub) == "file" + assert nodes._check_initialpaths_for_relpath(initial_paths, sub) == "file" outside = Path("/outside-this-does-not-exist") - assert nodes._check_initialpaths_for_relpath(session, outside) is None + assert nodes._check_initialpaths_for_relpath(initial_paths, outside) is None def test_failure_with_changed_cwd(pytester: Pytester) -> None: From f022c5581f2972804acd4d97e85f6802013c128d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 10:20:37 +0200 Subject: [PATCH 1206/1271] [automated] Update plugin list (#13430) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 174 ++++++++++++++++++++----------- 1 file changed, 115 insertions(+), 59 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 383cc7d6562..69de1df9690 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,15 +27,15 @@ please refer to `the update script =8.3 - :pypi:`logassert` Simple but powerful assertion and verification of logged lines Jan 29, 2025 5 - Production/Stable pytest; extra == "dev" + :pypi:`databricks-labs-pytester` Python Testing for Databricks May 13, 2025 4 - Beta pytest>=8.3 + :pypi:`logassert` Simple but powerful assertion and verification of logged lines May 15, 2025 5 - Production/Stable pytest; extra == "dev" :pypi:`logot` Test whether your code is logging correctly 🪵 May 05, 2025 5 - Production/Stable pytest; extra == "pytest" :pypi:`nuts` Network Unit Testing System May 10, 2025 N/A pytest<8,>=7 :pypi:`pytest-abq` Pytest integration for the ABQ universal test runner. Apr 07, 2023 N/A N/A @@ -63,7 +63,7 @@ This list contains 1625 plugins. :pypi:`pytest-aioworkers` A plugin to test aioworkers project with pytest Dec 26, 2024 5 - Production/Stable pytest>=8.3.4 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. Jul 29, 2024 N/A pytest>=6.0 + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. May 16, 2025 N/A pytest>=7.0 :pypi:`pytest-alerts` A pytest plugin for sending test results to Slack and Telegram Feb 21, 2025 4 - Beta pytest>=7.4.0 :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) @@ -119,7 +119,7 @@ This list contains 1625 plugins. :pypi:`pytest_async` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A :pypi:`pytest-asyncio` Pytest support for asyncio May 09, 2025 4 - Beta pytest<9,>=8.2 - :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. Apr 29, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. May 17, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Apr 26, 2025 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) @@ -152,7 +152,7 @@ This list contains 1625 plugins. :pypi:`pytest-bandit-xayon` A bandit plugin for pytest Oct 17, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-base-url` pytest plugin for URL based testing Jan 31, 2024 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-batch-regression` A pytest plugin to repeat the entire test suite in batches. May 08, 2024 N/A pytest>=6.0.0 - :pypi:`pytest-bazel` A pytest runner with bazel support Sep 27, 2024 4 - Beta pytest + :pypi:`pytest-bazel` A pytest runner with bazel support May 11, 2025 4 - Beta pytest :pypi:`pytest-bdd` BDD for pytest Dec 05, 2024 6 - Mature pytest>=7.0.0 :pypi:`pytest-bdd-html` pytest plugin to display BDD info in HTML test report Nov 22, 2022 3 - Alpha pytest (!=6.0.0,>=5.0) :pypi:`pytest-bdd-ng` BDD for pytest Nov 26, 2024 4 - Beta pytest>=5.2 @@ -162,7 +162,7 @@ This list contains 1625 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 09, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 13, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -309,7 +309,7 @@ This list contains 1625 plugins. :pypi:`pytest-cover` Pytest plugin for measuring coverage. Forked from \`pytest-cov\`. Aug 01, 2015 5 - Production/Stable N/A :pypi:`pytest-coverage` Jun 17, 2015 N/A N/A :pypi:`pytest-coverage-context` Coverage dynamic context support for PyTest, including sub-processes Jun 28, 2023 4 - Beta N/A - :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests Oct 15, 2024 N/A pytest<8.0.0,>=7.1.2 + :pypi:`pytest-coveragemarkers` Using pytest markers to track functional coverage and filtering of tests May 15, 2025 N/A pytest<8.0.0,>=7.1.2 :pypi:`pytest-cov-exclude` Pytest plugin for excluding tests based on coverage data Apr 29, 2016 4 - Beta pytest (>=2.8.0,<2.9.0); extra == 'dev' :pypi:`pytest_covid` Too many faillure, less tests. Jun 24, 2020 N/A N/A :pypi:`pytest-cpp` Use pytest's runner to discover and execute C++ tests Sep 18, 2024 5 - Production/Stable pytest @@ -324,6 +324,7 @@ This list contains 1625 plugins. :pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A :pypi:`pytest-csv` CSV output for pytest. Apr 22, 2021 N/A pytest (>=6.0) :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Oct 25, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 + :pypi:`pytest-culprit` Find the last Git commit where a pytest test started failing May 15, 2025 N/A N/A :pypi:`pytest-curio` Pytest support for curio. Oct 06, 2024 N/A pytest :pypi:`pytest-curl-report` pytest plugin to generate curl command line report Dec 11, 2016 4 - Beta N/A :pypi:`pytest-custom-concurrency` Custom grouping concurrence for pytest Feb 08, 2021 N/A N/A @@ -348,7 +349,7 @@ This list contains 1625 plugins. :pypi:`pytest-data-extractor` A pytest plugin to extract relevant metadata about tests into an external file (currently only json support) Jul 19, 2022 N/A pytest (>=7.0.1) :pypi:`pytest-data-file` Fixture "data" and "case_data" for test from yaml file Dec 04, 2019 N/A N/A :pypi:`pytest-datafiles` py.test plugin to create a 'tmp_path' containing predefined files/directories. Feb 24, 2023 5 - Production/Stable pytest (>=3.6) - :pypi:`pytest-datafixtures` Data fixtures for pytest made simple Dec 05, 2020 5 - Production/Stable N/A + :pypi:`pytest-datafixtures` Data fixtures for pytest made simple. May 15, 2025 5 - Production/Stable N/A :pypi:`pytest-data-from-files` pytest plugin to provide data from files loaded automatically Oct 13, 2021 4 - Beta pytest :pypi:`pytest-dataplugin` A pytest plugin for managing an archive of test data. Sep 16, 2017 1 - Planning N/A :pypi:`pytest-datarecorder` A py.test plugin recording and comparing test output. Jul 31, 2024 5 - Production/Stable pytest @@ -429,7 +430,7 @@ This list contains 1625 plugins. :pypi:`pytest-docker-compose` Manages Docker containers during your integration tests Jan 26, 2021 5 - Production/Stable pytest (>=3.3) :pypi:`pytest-docker-compose-v2` Manages Docker containers during your integration tests Dec 11, 2024 4 - Beta pytest>=7.2.2 :pypi:`pytest-docker-db` A plugin to use docker databases for pytests Mar 20, 2021 5 - Production/Stable pytest (>=3.1.1) - :pypi:`pytest-docker-fixtures` pytest docker fixtures Apr 03, 2024 3 - Alpha N/A + :pypi:`pytest-docker-fixtures` pytest docker fixtures May 14, 2025 3 - Alpha pytest :pypi:`pytest-docker-git-fixtures` Pytest fixtures for testing with git scm. Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-haproxy-fixtures` Pytest fixtures for testing with haproxy. Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-pexpect` pytest plugin for writing functional tests with pexpect and docker Jan 14, 2019 N/A pytest @@ -497,7 +498,7 @@ This list contains 1625 plugins. :pypi:`pytest-embrace` 💝 Dataclasses-as-tests. Describe the runtime once and multiply coverage with no boilerplate. Mar 25, 2023 N/A pytest (>=7.0,<8.0) :pypi:`pytest-emoji` A pytest plugin that adds emojis to your test result report Feb 19, 2019 4 - Beta pytest (>=4.2.1) :pypi:`pytest-emoji-output` Pytest plugin to represent test output with emoji support Apr 09, 2023 4 - Beta pytest (==7.0.1) - :pypi:`pytest-enabler` Enable installed pytest plugins Sep 12, 2024 5 - Production/Stable pytest!=8.1.*,>=6; extra == "test" + :pypi:`pytest-enabler` Enable installed pytest plugins May 16, 2025 5 - Production/Stable pytest!=8.1.*,>=6; extra == "test" :pypi:`pytest-encode` set your encoding and logger Nov 06, 2021 N/A N/A :pypi:`pytest-encode-kane` set your encoding and logger Nov 16, 2021 N/A pytest :pypi:`pytest-encoding` set your encoding and logger Aug 11, 2023 N/A pytest @@ -585,6 +586,7 @@ This list contains 1625 plugins. :pypi:`pytest-find-dependencies` A pytest plugin to find dependencies between tests Mar 16, 2024 4 - Beta pytest >=4.3.0 :pypi:`pytest-finer-verdicts` A pytest plugin to treat non-assertion failures as test errors. Jun 18, 2020 N/A pytest (>=5.4.3) :pypi:`pytest-firefox` Feb 28, 2025 N/A N/A + :pypi:`pytest-fixturecheck` A pytest plugin to check fixture validity before test execution May 17, 2025 3 - Alpha pytest>=6.0.0 :pypi:`pytest-fixture-classes` Fixtures as classes that work well with dependency injection, autocompletetion, type checkers, and language servers Sep 02, 2023 5 - Production/Stable pytest :pypi:`pytest-fixturecollection` A pytest plugin to collect tests based on fixtures being used by tests Feb 22, 2024 4 - Beta pytest >=3.5.0 :pypi:`pytest-fixture-config` Fixture configuration utils for py.test Oct 17, 2024 5 - Production/Stable pytest @@ -640,7 +642,7 @@ This list contains 1625 plugins. :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-gcs` GCS fixtures and fixture factories for Pytest. Jan 24, 2025 5 - Production/Stable pytest>=6.2 - :pypi:`pytest-gee` The Python plugin for your GEE based packages. Feb 20, 2025 3 - Alpha pytest + :pypi:`pytest-gee` The Python plugin for your GEE based packages. May 11, 2025 3 - Alpha pytest :pypi:`pytest-gevent` Ensure that gevent is properly patched when invoking pytest Feb 25, 2020 N/A pytest :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest @@ -690,7 +692,7 @@ This list contains 1625 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 May 10, 2025 3 - Alpha pytest==8.3.5 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 17, 2025 3 - Alpha pytest==8.3.5 :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` Sep 23, 2024 N/A N/A @@ -731,6 +733,7 @@ This list contains 1625 plugins. :pypi:`pytest-ignore-test-results` A pytest plugin to ignore test results. Feb 03, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-image-diff` Dec 31, 2024 3 - Alpha pytest :pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Jul 01, 2024 4 - Beta pytest>=3.5.0 + :pypi:`pytest-impacted` A pytest plugin that selectively runs tests impacted by codechanges via git introspection, ASL parsing, and dependency graph analysis. May 15, 2025 4 - Beta pytest>=8.0.0 :pypi:`pytest-import-check` pytest plugin to check whether Python modules can be imported Jul 19, 2024 3 - Alpha pytest>=8.1 :pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A :pypi:`pytest-infinity` Jun 09, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -767,6 +770,7 @@ This list contains 1625 plugins. :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Mar 09, 2025 N/A pytest :pypi:`pytest-ipywidgets` Apr 30, 2025 N/A pytest + :pypi:`pytest-iso` Plugin for pytest to produce test documentation for code audits. May 15, 2025 4 - Beta pytest<9.0.0,>=7.4.0 :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Apr 22, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Feb 24, 2025 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) @@ -794,7 +798,7 @@ This list contains 1625 plugins. :pypi:`pytest-json-report-wip` A pytest plugin to report test results as JSON files Oct 28, 2023 4 - Beta pytest >=3.8.0 :pypi:`pytest-jsonschema` A pytest plugin to perform JSONSchema validations Apr 20, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-jtr` pytest plugin supporting json test report output Jul 21, 2024 N/A pytest<8.0.0,>=7.1.2 - :pypi:`pytest-jubilant` Add your description here May 01, 2025 N/A pytest>=8.3.5 + :pypi:`pytest-jubilant` Add your description here May 14, 2025 N/A pytest>=8.3.5 :pypi:`pytest-junit-xray-xml` Export test results in an augmented JUnit format for usage with Xray () Jan 01, 2025 4 - Beta pytest :pypi:`pytest-jupyter` A pytest plugin for testing Jupyter libraries and extensions. Apr 04, 2024 4 - Beta pytest>=7.0 :pypi:`pytest-jupyterhub` A reusable JupyterHub pytest plugin Apr 25, 2023 5 - Production/Stable pytest @@ -874,6 +878,7 @@ This list contains 1625 plugins. :pypi:`pytest-markdown-docs` Run markdown code fences through pytest Apr 09, 2025 N/A pytest>=7.0.0 :pypi:`pytest-marker-bugzilla` py.test bugzilla integration plugin, using markers Apr 02, 2025 5 - Production/Stable pytest>=2.2.4 :pypi:`pytest-markers-presence` A simple plugin to detect missed pytest tags and markers" Oct 30, 2024 4 - Beta pytest>=6.0 + :pypi:`pytest-mark-filter` Filter pytest marks by name using match kw May 11, 2025 N/A pytest>=8.3.0 :pypi:`pytest-markfiltration` UNKNOWN Nov 08, 2011 3 - Alpha N/A :pypi:`pytest-mark-manage` 用例标签化管理 Aug 15, 2024 N/A pytest :pypi:`pytest-mark-no-py3` pytest plugin and bowler codemod to help migrate tests to Python 3 May 17, 2019 N/A pytest @@ -897,13 +902,13 @@ This list contains 1625 plugins. :pypi:`pytest-memray` A simple plugin to use with pytest Jul 25, 2024 N/A pytest>=7.2 :pypi:`pytest-menu` A pytest plugin for console based interactive test selection just after the collection phase Oct 04, 2017 3 - Alpha pytest (>=2.4.2) :pypi:`pytest-mercurial` pytest plugin to write integration tests for projects using Mercurial Python internals Nov 21, 2020 1 - Planning N/A - :pypi:`pytest-mergify` Pytest plugin for Mergify Apr 10, 2025 N/A N/A + :pypi:`pytest-mergify` Pytest plugin for Mergify May 13, 2025 N/A pytest>=6.0.0 :pypi:`pytest-mesh` pytest_mesh插件 Aug 05, 2022 N/A pytest (==7.1.2) :pypi:`pytest-message` Pytest plugin for sending report message of marked tests execution Aug 04, 2022 N/A pytest (>=6.2.5) :pypi:`pytest-messenger` Pytest to Slack reporting plugin Nov 24, 2022 5 - Production/Stable N/A :pypi:`pytest-metadata` pytest plugin for test session metadata Feb 12, 2024 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 Mar 06, 2025 N/A pytest + :pypi:`pytest-mh` Pytest multihost plugin May 15, 2025 N/A pytest :pypi:`pytest-mimesis` Mimesis integration with the pytest test runner Mar 21, 2020 5 - Production/Stable pytest (>=4.2) :pypi:`pytest-mimic` Easily record function calls while testing Apr 24, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-minecraft` A pytest plugin for running tests against Minecraft releases Apr 06, 2022 N/A pytest (>=6.0.1) @@ -991,7 +996,7 @@ This list contains 1625 plugins. :pypi:`pytest-notimplemented` Pytest markers for not implemented features and tests. Aug 27, 2019 N/A pytest (>=5.1,<6.0) :pypi:`pytest-notion` A PyTest Reporter to send test runs to Notion.so Aug 07, 2019 N/A N/A :pypi:`pytest-nunit` A pytest plugin for generating NUnit3 test result XML output Feb 26, 2024 5 - Production/Stable N/A - :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 02, 2023 N/A pytest>=6.0.1 + :pypi:`pytest-oar` PyTest plugin for the OAR testing framework May 12, 2025 N/A pytest>=6.0.1 :pypi:`pytest-oarepo` Feb 14, 2025 N/A pytest>=7.1.2; extra == "base" :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A @@ -1056,7 +1061,7 @@ This list contains 1625 plugins. :pypi:`pytest-performancetotal` A performance plugin for pytest Feb 01, 2025 5 - Production/Stable N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Aug 21, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker Apr 11, 2025 5 - Production/Stable pytest>=8.0.0 + :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 11, 2025 5 - Production/Stable pytest>=7.4 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-phoenix-interface` Pytest extension tool for phoenix projects. Mar 19, 2025 N/A N/A @@ -1103,7 +1108,7 @@ This list contains 1625 plugins. :pypi:`pytest-porcochu` Show surprise when tests are passing Nov 28, 2024 5 - Production/Stable N/A :pypi:`pytest-portion` Select a portion of the collected tests Jan 28, 2021 4 - Beta pytest (>=3.5.0) :pypi:`pytest-postgres` Run PostgreSQL in Docker container in Pytest. Mar 22, 2020 N/A pytest - :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. Mar 19, 2025 5 - Production/Stable pytest>=6.2 + :pypi:`pytest-postgresql` Postgresql fixtures and fixture factories for Pytest. May 17, 2025 5 - Production/Stable pytest>=7.2 :pypi:`pytest-power` pytest plugin with powerful fixtures Dec 31, 2020 N/A pytest (>=5.4) :pypi:`pytest-powerpack` A plugin containing extra batteries for pytest Jan 04, 2025 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-prefer-nested-dup-tests` A Pytest plugin to drop duplicated tests during collection, but will prefer keeping nested packages. Apr 27, 2022 4 - Beta pytest (>=7.1.1,<8.0.0) @@ -1238,7 +1243,7 @@ This list contains 1625 plugins. :pypi:`pytest-reserial` Pytest fixture for recording and replaying serial port traffic. Dec 22, 2024 4 - Beta pytest :pypi:`pytest-resilient-circuits` Resilient Circuits fixtures for PyTest Feb 28, 2025 N/A pytest~=7.0 :pypi:`pytest-resource` Load resource fixture plugin to use with pytest Nov 14, 2018 4 - Beta N/A - :pypi:`pytest-resource-path` Provides path for uniform access to test resources in isolated directory May 01, 2021 5 - Production/Stable pytest (>=3.5.0) + :pypi:`pytest-resource-path` Provides path for uniform access to test resources in isolated directory May 15, 2025 5 - Production/Stable pytest>=3.5.0 :pypi:`pytest-resource-usage` Pytest plugin for reporting running time and peak memory usage Nov 06, 2022 5 - Production/Stable pytest>=7.0.0 :pypi:`pytest-responsemock` Simplified requests calls mocking for pytest Mar 10, 2022 5 - Production/Stable N/A :pypi:`pytest-responses` py.test integration for responses Oct 11, 2022 N/A pytest (>=2.5) @@ -1293,19 +1298,19 @@ This list contains 1625 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 02, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 13, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A - :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. Nov 21, 2024 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 13, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 - :pypi:`pytest-scim2-server` SCIM2 server fixture for Pytest Mar 28, 2025 N/A pytest>=8.3.4 + :pypi:`pytest-scim2-server` SCIM2 server fixture for Pytest May 14, 2025 4 - Beta pytest>=8.3.4 :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-scrutinize` Scrutinize your pytest test suites for slow fixtures, tests and more. Aug 19, 2024 4 - Beta pytest>=6 :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 Feb 01, 2024 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. May 02, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 13, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 @@ -1324,6 +1329,7 @@ This list contains 1625 plugins. :pypi:`pytest-setupinfo` Displaying setup info during pytest command run Jan 23, 2023 N/A N/A :pypi:`pytest-sftpserver` py.test plugin to locally test sftp server connections. Sep 16, 2019 4 - Beta N/A :pypi:`pytest-shard` Dec 11, 2020 4 - Beta pytest + :pypi:`pytest-shard-fork` Shard tests to support parallelism across multiple machines May 17, 2025 4 - Beta pytest :pypi:`pytest-shared-session-scope` Pytest session-scoped fixture that works with xdist Sep 22, 2024 N/A pytest>=7.0.0 :pypi:`pytest-share-hdf` Plugin to save test data in HDF files and retrieve them for comparison Sep 21, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-sharkreport` this is pytest report plugin. Jul 11, 2022 N/A pytest (>=3.5) @@ -1388,7 +1394,7 @@ This list contains 1625 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 Mar 07, 2025 N/A pytest<8,>5.4.0 + :pypi:`pytest-splunk-addon` A Dynamic test tool for Splunk Apps and Add-ons May 14, 2025 N/A pytest<8,>5.4.0 :pypi:`pytest-splunk-addon-ui-smartx` Library to support testing Splunk Add-on UX Mar 19, 2025 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 @@ -1413,6 +1419,7 @@ This list contains 1625 plugins. :pypi:`pytest-stochastics` pytest plugin that allows selectively running tests several times and accepting \*some\* failures. Dec 01, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Sep 04, 2024 3 - Alpha pytest>=7.0.0 + :pypi:`pytest-streaming` Plugin for testing pubsub, pulsar, and kafka systems with pytest locally and in ci/cd May 16, 2025 N/A pytest>=8.3.5 :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-structlog` Structured logging assertions Jul 25, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A @@ -1651,7 +1658,7 @@ This list contains 1625 plugins. :pypi:`pytest-zcc` eee Jun 02, 2024 N/A N/A :pypi:`pytest-zebrunner` Pytest connector for Zebrunner reporting Jul 04, 2024 5 - Production/Stable pytest>=4.5.0 :pypi:`pytest-zeebe` Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. Feb 01, 2024 N/A pytest (>=7.4.2,<8.0.0) - :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest Oct 15, 2024 N/A pytest + :pypi:`pytest-zephyr-scale-integration` A library for integrating Jira Zephyr Scale (Adaptavist\TM4J) with pytest May 15, 2025 N/A pytest :pypi:`pytest-zephyr-telegram` Плагин для отправки данных автотестов в Телеграм и Зефир Sep 30, 2024 N/A pytest==8.3.2 :pypi:`pytest-zest` Zesty additions to pytest. Nov 17, 2022 N/A N/A :pypi:`pytest-zhongwen-wendang` PyTest 中文文档 Mar 04, 2024 4 - Beta N/A @@ -1665,14 +1672,14 @@ This list contains 1625 plugins. :pypi:`databricks-labs-pytester` - *last release*: Feb 27, 2025, + *last release*: May 13, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3 Python Testing for Databricks :pypi:`logassert` - *last release*: Jan 29, 2025, + *last release*: May 15, 2025, *status*: 5 - Production/Stable, *requires*: pytest; extra == "dev" @@ -1868,9 +1875,9 @@ This list contains 1625 plugins. :pypi:`pytest-alembic` - *last release*: Jul 29, 2024, + *last release*: May 16, 2025, *status*: N/A, - *requires*: pytest>=6.0 + *requires*: pytest>=7.0 A pytest plugin for verifying alembic migrations. @@ -2260,7 +2267,7 @@ This list contains 1625 plugins. Pytest support for asyncio :pypi:`pytest-asyncio-concurrent` - *last release*: Apr 29, 2025, + *last release*: May 17, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -2491,7 +2498,7 @@ This list contains 1625 plugins. A pytest plugin to repeat the entire test suite in batches. :pypi:`pytest-bazel` - *last release*: Sep 27, 2024, + *last release*: May 11, 2025, *status*: 4 - Beta, *requires*: pytest @@ -2561,7 +2568,7 @@ This list contains 1625 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: May 09, 2025, + *last release*: May 13, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -3590,7 +3597,7 @@ This list contains 1625 plugins. Coverage dynamic context support for PyTest, including sub-processes :pypi:`pytest-coveragemarkers` - *last release*: Oct 15, 2024, + *last release*: May 15, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.1.2 @@ -3694,6 +3701,13 @@ This list contains 1625 plugins. Pytest plugin for Test Case Parametrization with CSV files + :pypi:`pytest-culprit` + *last release*: May 15, 2025, + *status*: N/A, + *requires*: N/A + + Find the last Git commit where a pytest test started failing + :pypi:`pytest-curio` *last release*: Oct 06, 2024, *status*: N/A, @@ -3863,11 +3877,11 @@ This list contains 1625 plugins. py.test plugin to create a 'tmp_path' containing predefined files/directories. :pypi:`pytest-datafixtures` - *last release*: Dec 05, 2020, + *last release*: May 15, 2025, *status*: 5 - Production/Stable, *requires*: N/A - Data fixtures for pytest made simple + Data fixtures for pytest made simple. :pypi:`pytest-data-from-files` *last release*: Oct 13, 2021, @@ -4430,9 +4444,9 @@ This list contains 1625 plugins. A plugin to use docker databases for pytests :pypi:`pytest-docker-fixtures` - *last release*: Apr 03, 2024, + *last release*: May 14, 2025, *status*: 3 - Alpha, - *requires*: N/A + *requires*: pytest pytest docker fixtures @@ -4906,7 +4920,7 @@ This list contains 1625 plugins. Pytest plugin to represent test output with emoji support :pypi:`pytest-enabler` - *last release*: Sep 12, 2024, + *last release*: May 16, 2025, *status*: 5 - Production/Stable, *requires*: pytest!=8.1.*,>=6; extra == "test" @@ -5521,6 +5535,13 @@ This list contains 1625 plugins. + :pypi:`pytest-fixturecheck` + *last release*: May 17, 2025, + *status*: 3 - Alpha, + *requires*: pytest>=6.0.0 + + A pytest plugin to check fixture validity before test execution + :pypi:`pytest-fixture-classes` *last release*: Sep 02, 2023, *status*: 5 - Production/Stable, @@ -5907,7 +5928,7 @@ This list contains 1625 plugins. GCS fixtures and fixture factories for Pytest. :pypi:`pytest-gee` - *last release*: Feb 20, 2025, + *last release*: May 11, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -6257,7 +6278,7 @@ This list contains 1625 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 10, 2025, + *last release*: May 17, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.5 @@ -6543,6 +6564,13 @@ This list contains 1625 plugins. A pytest plugin for image snapshot management and comparison. + :pypi:`pytest-impacted` + *last release*: May 15, 2025, + *status*: 4 - Beta, + *requires*: pytest>=8.0.0 + + A pytest plugin that selectively runs tests impacted by codechanges via git introspection, ASL parsing, and dependency graph analysis. + :pypi:`pytest-import-check` *last release*: Jul 19, 2024, *status*: 3 - Alpha, @@ -6795,6 +6823,13 @@ This list contains 1625 plugins. + :pypi:`pytest-iso` + *last release*: May 15, 2025, + *status*: 4 - Beta, + *requires*: pytest<9.0.0,>=7.4.0 + + Plugin for pytest to produce test documentation for code audits. + :pypi:`pytest-isolate` *last release*: Apr 22, 2025, *status*: 4 - Beta, @@ -6985,7 +7020,7 @@ This list contains 1625 plugins. pytest plugin supporting json test report output :pypi:`pytest-jubilant` - *last release*: May 01, 2025, + *last release*: May 14, 2025, *status*: N/A, *requires*: pytest>=8.3.5 @@ -7544,6 +7579,13 @@ This list contains 1625 plugins. A simple plugin to detect missed pytest tags and markers" + :pypi:`pytest-mark-filter` + *last release*: May 11, 2025, + *status*: N/A, + *requires*: pytest>=8.3.0 + + Filter pytest marks by name using match kw + :pypi:`pytest-markfiltration` *last release*: Nov 08, 2011, *status*: 3 - Alpha, @@ -7706,9 +7748,9 @@ This list contains 1625 plugins. pytest plugin to write integration tests for projects using Mercurial Python internals :pypi:`pytest-mergify` - *last release*: Apr 10, 2025, + *last release*: May 13, 2025, *status*: N/A, - *requires*: N/A + *requires*: pytest>=6.0.0 Pytest plugin for Mergify @@ -7748,7 +7790,7 @@ This list contains 1625 plugins. Custom metrics report for pytest :pypi:`pytest-mh` - *last release*: Mar 06, 2025, + *last release*: May 15, 2025, *status*: N/A, *requires*: pytest @@ -8364,7 +8406,7 @@ This list contains 1625 plugins. A pytest plugin for generating NUnit3 test result XML output :pypi:`pytest-oar` - *last release*: May 02, 2023, + *last release*: May 12, 2025, *status*: N/A, *requires*: pytest>=6.0.1 @@ -8819,9 +8861,9 @@ This list contains 1625 plugins. Pytest pexpect plugin. :pypi:`pytest-pg` - *last release*: Apr 11, 2025, + *last release*: May 11, 2025, *status*: 5 - Production/Stable, - *requires*: pytest>=8.0.0 + *requires*: pytest>=7.4 A tiny plugin for pytest which runs PostgreSQL in Docker @@ -9148,9 +9190,9 @@ This list contains 1625 plugins. Run PostgreSQL in Docker container in Pytest. :pypi:`pytest-postgresql` - *last release*: Mar 19, 2025, + *last release*: May 17, 2025, *status*: 5 - Production/Stable, - *requires*: pytest>=6.2 + *requires*: pytest>=7.2 Postgresql fixtures and fixture factories for Pytest. @@ -10093,9 +10135,9 @@ This list contains 1625 plugins. Load resource fixture plugin to use with pytest :pypi:`pytest-resource-path` - *last release*: May 01, 2021, + *last release*: May 15, 2025, *status*: 5 - Production/Stable, - *requires*: pytest (>=3.5.0) + *requires*: pytest>=3.5.0 Provides path for uniform access to test resources in isolated directory @@ -10478,7 +10520,7 @@ This list contains 1625 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: May 02, 2025, + *last release*: May 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10492,7 +10534,7 @@ This list contains 1625 plugins. pytest plugin for test scenarios :pypi:`pytest-scenario-files` - *last release*: Nov 21, 2024, + *last release*: May 13, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -10513,8 +10555,8 @@ This list contains 1625 plugins. 👍 Validate return values against a schema-like object in testing :pypi:`pytest-scim2-server` - *last release*: Mar 28, 2025, - *status*: N/A, + *last release*: May 14, 2025, + *status*: 4 - Beta, *requires*: pytest>=8.3.4 SCIM2 server fixture for Pytest @@ -10562,7 +10604,7 @@ This list contains 1625 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: May 02, 2025, + *last release*: May 13, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10694,6 +10736,13 @@ This list contains 1625 plugins. + :pypi:`pytest-shard-fork` + *last release*: May 17, 2025, + *status*: 4 - Beta, + *requires*: pytest + + Shard tests to support parallelism across multiple machines + :pypi:`pytest-shared-session-scope` *last release*: Sep 22, 2024, *status*: N/A, @@ -11143,7 +11192,7 @@ This list contains 1625 plugins. :pypi:`pytest-splunk-addon` - *last release*: Mar 07, 2025, + *last release*: May 14, 2025, *status*: N/A, *requires*: pytest<8,>5.4.0 @@ -11317,6 +11366,13 @@ This list contains 1625 plugins. Pytest plugin to store values from test runs + :pypi:`pytest-streaming` + *last release*: May 16, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + Plugin for testing pubsub, pulsar, and kafka systems with pytest locally and in ci/cd + :pypi:`pytest-stress` *last release*: Dec 07, 2019, *status*: 4 - Beta, @@ -12984,7 +13040,7 @@ This list contains 1625 plugins. Pytest fixtures for testing Camunda 8 processes using a Zeebe test engine. :pypi:`pytest-zephyr-scale-integration` - *last release*: Oct 15, 2024, + *last release*: May 15, 2025, *status*: N/A, *requires*: pytest From 8a66a9ed0bc3b82e7458e36823d3ae0496d1082a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 20:08:42 +0000 Subject: [PATCH 1207/1271] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.5 → v0.11.10](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.5...v0.11.10) - [github.com/woodruffw/zizmor-pre-commit: v1.5.2 → v1.7.0](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.5.2...v1.7.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a9d59e15551..2a4543841f3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.5" + rev: "v0.11.10" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.5.2 + rev: v1.7.0 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs From 76ee187a4469552bfa314c247bab67a0dde1747b Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Mon, 12 May 2025 22:48:36 +0200 Subject: [PATCH 1208/1271] [ci] Pin all action to a precise hash to appease zizmor --- .github/workflows/deploy.yml | 6 +++--- .github/workflows/test.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2ad6e9d5054..9e63bc68cfd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -31,7 +31,7 @@ jobs: persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.12.0 + uses: hynek/build-and-inspect-python-package@b5076c307dc91924a82ad150cdd1533b444d3310 with: attest-build-provenance-github: 'true' @@ -56,7 +56,7 @@ jobs: path: dist - name: Publish package to PyPI - uses: pypa/gh-action-pypi-publish@v1.12.4 + uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc with: attestations: true @@ -109,7 +109,7 @@ jobs: tox -e generate-gh-release-notes -- "$VERSION" scripts/latest-release-notes.md - name: Publish GitHub Release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 with: body_path: scripts/latest-release-notes.md files: dist/* diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 44c9d68c03d..5f6bdf60849 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,7 +40,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Build and Check Package - uses: hynek/build-and-inspect-python-package@v2.12.0 + uses: hynek/build-and-inspect-python-package@b5076c307dc91924a82ad150cdd1533b444d3310 build: needs: [package] @@ -262,7 +262,7 @@ jobs: - name: Upload coverage to Codecov if: "matrix.use_coverage" - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d with: fail_ci_if_error: false files: ./coverage.xml From c77995bb910bed278c98323574dc54ca2d032216 Mon Sep 17 00:00:00 2001 From: ikappaki <34983288+ikappaki@users.noreply.github.com> Date: Thu, 22 May 2025 13:55:12 +0100 Subject: [PATCH 1209/1271] Replace `:` with `;` in the assertion rewrite warning message (#13429) This makes it possible to filter them using standard Python warning filters. --- Co-authored-by: ikappaki --- changelog/5473.improvement.rst | 1 + src/_pytest/assertion/rewrite.py | 2 +- testing/test_assertrewrite.py | 18 +++++++++++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 changelog/5473.improvement.rst diff --git a/changelog/5473.improvement.rst b/changelog/5473.improvement.rst new file mode 100644 index 00000000000..1b9ab006d49 --- /dev/null +++ b/changelog/5473.improvement.rst @@ -0,0 +1 @@ +Replace `:` with `;` in the assertion rewrite warning message so it can be filtered using standard Python warning filters before calling :func:`pytest.main`. diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 2e606d1903a..c4782c7c5a8 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -281,7 +281,7 @@ def _warn_already_imported(self, name: str) -> None: self.config.issue_config_time_warning( PytestAssertRewriteWarning( - f"Module already imported so cannot be rewritten: {name}" + f"Module already imported so cannot be rewritten; {name}" ), stacklevel=5, ) diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index 02d1c3e52ff..e2e448fe5e6 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1197,7 +1197,23 @@ def test_rewrite_warning(self, pytester: Pytester) -> None: ) # needs to be a subprocess because pytester explicitly disables this warning result = pytester.runpytest_subprocess() - result.stdout.fnmatch_lines(["*Module already imported*: _pytest"]) + result.stdout.fnmatch_lines(["*Module already imported*; _pytest"]) + + def test_rewrite_warning_ignore(self, pytester: Pytester) -> None: + pytester.makeconftest( + """ + import pytest + pytest.register_assert_rewrite("_pytest") + """ + ) + # needs to be a subprocess because pytester explicitly disables this warning + result = pytester.runpytest_subprocess( + "-W", + "ignore:Module already imported so cannot be rewritten; _pytest:pytest.PytestAssertRewriteWarning", + ) + # Previously, when the message pattern used to contain an extra `:`, an error was raised. + assert not result.stderr.str().strip() + result.stdout.no_fnmatch_line("*Module already imported*; _pytest") def test_rewrite_module_imported_from_conftest(self, pytester: Pytester) -> None: pytester.makeconftest( From 433f3a6f01b3fd90d6bf00a077c869094d5e6589 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 06:24:16 +0200 Subject: [PATCH 1210/1271] build(deps): Bump codecov/codecov-action from 5.4.2 to 5.4.3 (#13439) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.4.2 to 5.4.3. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/ad3126e916f78f00edff4ed0317cf185271ccc2d...18283e04ce6e62d37312384ff67231eb8fd56d24) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-version: 5.4.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5f6bdf60849..99ca032db9d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -262,7 +262,7 @@ jobs: - name: Upload coverage to Codecov if: "matrix.use_coverage" - uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d + uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 with: fail_ci_if_error: false files: ./coverage.xml From 58d7aa90196976b59f98ba072d3ecf1c19c1f5ca Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 25 May 2025 19:22:07 +0300 Subject: [PATCH 1211/1271] python: fix confusing note in `Metafunc.parametrize`'s docstring `indirect` is useful for doing stuff at setup time, the current phrasing makes it sound like the opposite. Perhaps the `than` was meant to be omitted. But rephrase it anyway. --- src/_pytest/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 902bcfade9f..90b64bc1b24 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1168,7 +1168,7 @@ def parametrize( """Add new invocations to the underlying test function using the list of argvalues for the given argnames. Parametrization is performed during the collection phase. If you need to setup expensive resources - see about setting indirect to do it rather than at test setup time. + see about setting ``indirect`` to do it at test setup time instead. Can be called multiple times per test function (but only on different argument names), in which case each call parametrizes all previous From 19bc2cb2e4860606d8dd67262daa256bfd03238f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 25 May 2025 19:27:32 +0300 Subject: [PATCH 1212/1271] python: remove redundant `:type` docstring Sphinx gets it from the type annotation. --- src/_pytest/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 90b64bc1b24..64154d123b7 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1192,7 +1192,7 @@ def parametrize( If N argnames were specified, argvalues must be a list of N-tuples, where each tuple-element specifies a value for its respective argname. - :type argvalues: Iterable[_pytest.mark.structures.ParameterSet | Sequence[object] | object] + :param indirect: A list of arguments' names (subset of argnames) or a boolean. If True the list contains all names from the argnames. Each From fe64939eaad50fb55b4547ade0c63a8b78585d3e Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 25 May 2025 19:57:28 +0300 Subject: [PATCH 1213/1271] python: clarify a bit two comments --- src/_pytest/python.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 64154d123b7..fde68baf2e8 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1270,14 +1270,13 @@ def parametrize( if _param_mark and _param_mark._param_ids_from and generated_ids is None: object.__setattr__(_param_mark._param_ids_from, "_param_ids_generated", ids) - # Add funcargs as fixturedefs to fixtureinfo.arg2fixturedefs by registering - # artificial "pseudo" FixtureDef's so that later at test execution time we can - # rely on a proper FixtureDef to exist for fixture setup. + # Add direct parametrizations as fixturedefs to arg2fixturedefs by + # registering artificial "pseudo" FixtureDef's such that later at test + # setup time we can rely on FixtureDefs to exist for all argnames. node = None - # If we have a scope that is higher than function, we need - # to make sure we only ever create an according fixturedef on - # a per-scope basis. We thus store and cache the fixturedef on the - # node related to the scope. + # For scopes higher than function, a "pseudo" FixtureDef might have + # already been created for the scope. We thus store and cache the + # FixtureDef on the node related to the scope. if scope_ is not Scope.Function: collector = self.definition.parent assert collector is not None From 0910c35c4225ca5a568c979f993641b06d805e46 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 25 May 2025 20:12:28 +0300 Subject: [PATCH 1214/1271] fixtures: add docstring for internal function `get_scope_node` --- src/_pytest/fixtures.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index bb50b014dd1..3fb7dcd230d 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -132,6 +132,12 @@ def get_scope_package( def get_scope_node(node: nodes.Node, scope: Scope) -> nodes.Node | None: + """Get the closest parent node (including self) which matches the given + scope. + + If there is no parent node for the scope (e.g. asking for class scope on a + Module, or on a Function when not defined in a class), returns None. + """ import _pytest.python if scope is Scope.Function: From 1c45c2073dd86280ff4dbf271d4ae8174a8403e5 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 25 May 2025 20:24:55 +0300 Subject: [PATCH 1215/1271] python: slight refactor to make code read better --- src/_pytest/python.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index fde68baf2e8..f46c34d84c5 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1270,6 +1270,10 @@ def parametrize( if _param_mark and _param_mark._param_ids_from and generated_ids is None: object.__setattr__(_param_mark._param_ids_from, "_param_ids_generated", ids) + # Calculate directness. + arg_directness = self._resolve_args_directness(argnames, indirect) + self._params_directness.update(arg_directness) + # Add direct parametrizations as fixturedefs to arg2fixturedefs by # registering artificial "pseudo" FixtureDef's such that later at test # setup time we can rely on FixtureDefs to exist for all argnames. @@ -1277,7 +1281,9 @@ def parametrize( # For scopes higher than function, a "pseudo" FixtureDef might have # already been created for the scope. We thus store and cache the # FixtureDef on the node related to the scope. - if scope_ is not Scope.Function: + if scope_ is Scope.Function: + name2pseudofixturedef = None + else: collector = self.definition.parent assert collector is not None node = get_scope_node(collector, scope_) @@ -1293,15 +1299,10 @@ def parametrize( node = collector.session else: assert False, f"Unhandled missing scope: {scope}" - if node is None: - name2pseudofixturedef = None - else: default: dict[str, FixtureDef[Any]] = {} name2pseudofixturedef = node.stash.setdefault( name2pseudofixturedef_key, default ) - arg_directness = self._resolve_args_directness(argnames, indirect) - self._params_directness.update(arg_directness) for argname in argnames: if arg_directness[argname] == "indirect": continue From dbec145dee42d8e69b8f1431f31ba9ef2c1e519f Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 25 May 2025 19:01:14 +0300 Subject: [PATCH 1216/1271] fixtures: rename `FixtureArgKey` -> `ParamArgKey` Rename `FixtureArgKey` to `ParamArgKey` because it's not really about fixtures but about parametrization parameters (which can come from either `@pytest.parametrize` or from `pytest.fixture(params=...)`). Also added a few more comments. --- src/_pytest/fixtures.py | 36 +++++++++++++++++++++--------------- src/_pytest/python.py | 1 + 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 3fb7dcd230d..3f35428b432 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -171,10 +171,21 @@ def getfixturemarker(obj: object) -> FixtureFunctionMarker | None: @dataclasses.dataclass(frozen=True) -class FixtureArgKey: +class ParamArgKey: + """A key for a high-scoped parameter used by an item. + + For use as a hashable key in `reorder_items`. The combination of fields + is meant to uniquely identify a particular "instance" of a param, + potentially shared by multiple items in a scope. + """ + + #: The param name. argname: str param_index: int + #: For scopes Package, Module, Class, the path to the file (directory in + #: Package's case) of the package/module/class where the item is defined. scoped_item_path: Path | None + #: For Class scope, the class where the item is defined. item_cls: type | None @@ -182,11 +193,8 @@ class FixtureArgKey: OrderedSet = dict[_V, None] -def get_parametrized_fixture_argkeys( - item: nodes.Item, scope: Scope -) -> Iterator[FixtureArgKey]: - """Return list of keys for all parametrized arguments which match - the specified scope.""" +def get_param_argkeys(item: nodes.Item, scope: Scope) -> Iterator[ParamArgKey]: + """Return all ParamArgKeys for item matching the specified high scope.""" assert scope is not Scope.Function try: @@ -212,19 +220,17 @@ def get_parametrized_fixture_argkeys( if callspec._arg2scope[argname] != scope: continue param_index = callspec.indices[argname] - yield FixtureArgKey(argname, param_index, scoped_item_path, item_cls) + yield ParamArgKey(argname, param_index, scoped_item_path, item_cls) def reorder_items(items: Sequence[nodes.Item]) -> list[nodes.Item]: - argkeys_by_item: dict[Scope, dict[nodes.Item, OrderedSet[FixtureArgKey]]] = {} - items_by_argkey: dict[ - Scope, dict[FixtureArgKey, OrderedDict[nodes.Item, None]] - ] = {} + argkeys_by_item: dict[Scope, dict[nodes.Item, OrderedSet[ParamArgKey]]] = {} + items_by_argkey: dict[Scope, dict[ParamArgKey, OrderedDict[nodes.Item, None]]] = {} for scope in HIGH_SCOPES: scoped_argkeys_by_item = argkeys_by_item[scope] = {} scoped_items_by_argkey = items_by_argkey[scope] = defaultdict(OrderedDict) for item in items: - argkeys = dict.fromkeys(get_parametrized_fixture_argkeys(item, scope)) + argkeys = dict.fromkeys(get_param_argkeys(item, scope)) if argkeys: scoped_argkeys_by_item[item] = argkeys for argkey in argkeys: @@ -240,9 +246,9 @@ def reorder_items(items: Sequence[nodes.Item]) -> list[nodes.Item]: def reorder_items_atscope( items: OrderedSet[nodes.Item], - argkeys_by_item: Mapping[Scope, Mapping[nodes.Item, OrderedSet[FixtureArgKey]]], + argkeys_by_item: Mapping[Scope, Mapping[nodes.Item, OrderedSet[ParamArgKey]]], items_by_argkey: Mapping[ - Scope, Mapping[FixtureArgKey, OrderedDict[nodes.Item, None]] + Scope, Mapping[ParamArgKey, OrderedDict[nodes.Item, None]] ], scope: Scope, ) -> OrderedSet[nodes.Item]: @@ -252,7 +258,7 @@ def reorder_items_atscope( scoped_items_by_argkey = items_by_argkey[scope] scoped_argkeys_by_item = argkeys_by_item[scope] - ignore: set[FixtureArgKey] = set() + ignore: set[ParamArgKey] = set() items_deque = deque(items) items_done: OrderedSet[nodes.Item] = {} while items_deque: diff --git a/src/_pytest/python.py b/src/_pytest/python.py index f46c34d84c5..1e085a80529 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1056,6 +1056,7 @@ class CallSpec2: params: dict[str, object] = dataclasses.field(default_factory=dict) # arg name -> arg index. indices: dict[str, int] = dataclasses.field(default_factory=dict) + # arg name -> parameter scope. # Used for sorting parametrized resources. _arg2scope: Mapping[str, Scope] = dataclasses.field(default_factory=dict) # Parts which will be added to the item's name in `[..]` separated by "-". From 7ac5c18864502693ab0dd6e212e7dfb8d05de291 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 26 May 2025 09:56:38 +0300 Subject: [PATCH 1217/1271] mark: add docstring for `ParameterSet` This is not an exported type, adding a doc mostly so I can quickly remember what it is when reading code. --- src/_pytest/mark/structures.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 7a49b1a9b0c..f9261076ad0 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -78,6 +78,33 @@ def get_empty_parameterset_mark( class ParameterSet(NamedTuple): + """A set of values for a set of parameters along with associated marks and + an optional ID for the set. + + Examples:: + + pytest.param(1, 2, 3) + # ParameterSet(values=(1, 2, 3), marks=(), id=None) + + pytest.param("hello", id="greeting") + # ParameterSet(values=("hello",), marks=(), id="greeting") + + # Parameter set with marks + pytest.param(42, marks=pytest.mark.xfail) + # ParameterSet(values=(42,), marks=(MarkDecorator(...),), id=None) + + # From parametrize mark (parameter names + list of parameter sets) + pytest.mark.parametrize( + ("a", "b", "expected"), + [ + (1, 2, 3), + pytest.param(40, 2, 42, id="everything"), + ], + ) + # ParameterSet(values=(1, 2, 3), marks=(), id=None) + # ParameterSet(values=(2, 2, 3), marks=(), id="everything") + """ + values: Sequence[object | NotSetType] marks: Collection[MarkDecorator | Mark] id: str | _HiddenParam | None From 83536b4b0074ca35d90933d3ad46cb6efe7f5145 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 21:09:17 +0000 Subject: [PATCH 1218/1271] [pre-commit.ci] pre-commit autoupdate (#13441) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.11.10 → v0.11.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.10...v0.11.11) - [github.com/woodruffw/zizmor-pre-commit: v1.7.0 → v1.8.0](https://github.com/woodruffw/zizmor-pre-commit/compare/v1.7.0...v1.8.0) - [github.com/tox-dev/pyproject-fmt: v2.5.1 → v2.6.0](https://github.com/tox-dev/pyproject-fmt/compare/v2.5.1...v2.6.0) - [github.com/asottile/pyupgrade: v3.19.1 → v3.20.0](https://github.com/asottile/pyupgrade/compare/v3.19.1...v3.20.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2a4543841f3..a07475da467 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.11.10" + rev: "v0.11.11" hooks: - id: ruff args: ["--fix"] @@ -12,7 +12,7 @@ repos: - id: end-of-file-fixer - id: check-yaml - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v1.7.0 + rev: v1.8.0 hooks: - id: zizmor - repo: https://github.com/adamchainz/blacken-docs @@ -48,13 +48,13 @@ repos: # on <3.11 - exceptiongroup>=1.0.0rc8 - repo: https://github.com/tox-dev/pyproject-fmt - rev: "v2.5.1" + rev: "v2.6.0" hooks: - id: pyproject-fmt # https://pyproject-fmt.readthedocs.io/en/latest/#calculating-max-supported-python-version additional_dependencies: ["tox>=4.9"] - repo: https://github.com/asottile/pyupgrade - rev: v3.19.1 + rev: v3.20.0 hooks: - id: pyupgrade args: From 0010bfa4bf2bf7680e80de5262de5a37b8ae3150 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 27 May 2025 21:42:20 +0300 Subject: [PATCH 1219/1271] testing: skip `pkg_resources` tests if modern setuptools setuptools is intending to remove `pkg_resources` at the end of the year. Version 80.9.0 changed the deprecation to a UserMessage which broke the test. Instead of making them compatible, just skip them on versions >= 80 in preparation for the final removal. --- testing/acceptance_test.py | 10 ++++++++-- testing/test_monkeypatch.py | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 50ea4ff44d2..2d653b8e2a5 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -10,6 +10,8 @@ import sys import types +import setuptools + from _pytest.config import ExitCode from _pytest.pathlib import symlink_or_skip from _pytest.pytester import Pytester @@ -722,10 +724,14 @@ def test_cmdline_python_package(self, pytester: Pytester, monkeypatch) -> None: assert result.ret != 0 result.stderr.fnmatch_lines(["*not*found*test_missing*"]) - def test_cmdline_python_namespace_package( + @pytest.mark.skipif( + int(setuptools.__version__.split(".")[0]) >= 80, + reason="modern setuptools removing pkg_resources", + ) + def test_cmdline_python_legacy_namespace_package( self, pytester: Pytester, monkeypatch ) -> None: - """Test --pyargs option with namespace packages (#1567). + """Test --pyargs option with legacy namespace packages (#1567). Ref: https://packaging.python.org/guides/packaging-namespace-packages/ """ diff --git a/testing/test_monkeypatch.py b/testing/test_monkeypatch.py index ad75273d703..0e992e298ec 100644 --- a/testing/test_monkeypatch.py +++ b/testing/test_monkeypatch.py @@ -8,6 +8,8 @@ import sys import textwrap +import setuptools + from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester import pytest @@ -429,6 +431,10 @@ class A: @pytest.mark.filterwarnings(r"ignore:.*\bpkg_resources\b:DeprecationWarning") +@pytest.mark.skipif( + int(setuptools.__version__.split(".")[0]) >= 80, + reason="modern setuptools removing pkg_resources", +) def test_syspath_prepend_with_namespace_packages( pytester: Pytester, monkeypatch: MonkeyPatch ) -> None: From 1fdcf68e4a43240eb6310b4b204a845bf72df9c6 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 26 May 2025 23:28:42 +0300 Subject: [PATCH 1220/1271] fixtures: workaround PyPy bug which sometimes causes a `KeyError` crash during collection Fix #13312. --- changelog/13312.bugfix.rst | 1 + src/_pytest/fixtures.py | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 changelog/13312.bugfix.rst diff --git a/changelog/13312.bugfix.rst b/changelog/13312.bugfix.rst new file mode 100644 index 00000000000..62ad36879f5 --- /dev/null +++ b/changelog/13312.bugfix.rst @@ -0,0 +1 @@ +Fixed a possible ``KeyError`` crash on PyPy during collection of tests involving higher-scoped parameters. diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 3f35428b432..92a301e79db 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -286,10 +286,18 @@ def reorder_items_atscope( for other_scope in HIGH_SCOPES: other_scoped_items_by_argkey = items_by_argkey[other_scope] for argkey in argkeys_by_item[other_scope].get(i, ()): - other_scoped_items_by_argkey[argkey][i] = None - other_scoped_items_by_argkey[argkey].move_to_end( - i, last=False - ) + argkey_dict = other_scoped_items_by_argkey[argkey] + if not hasattr(sys, "pypy_version_info"): + argkey_dict[i] = None + argkey_dict.move_to_end(i, last=False) + else: + # Work around a bug in PyPy: + # https://github.com/pypy/pypy/issues/5257 + # https://github.com/pytest-dev/pytest/issues/13312 + bkp = argkey_dict.copy() + argkey_dict.clear() + argkey_dict[i] = None + argkey_dict.update(bkp) break if no_argkey_items: reordered_no_argkey_items = reorder_items_atscope( From 6f8681342bf2d41aea3fbc252b4abcb475ed2d9c Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 28 May 2025 18:33:50 -0300 Subject: [PATCH 1221/1271] Sunset the mailing list contact information (#13449) As discussed recently in https://mail.python.org/archives/list/pytest-dev@python.org/thread/Y2HCDCXAAN6PLY63KLLY7FSUFDR6G5LC/, we will archive the mailing in favor of GitHub Discussions. --- CONTRIBUTING.rst | 5 ++--- doc/en/contact.rst | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 56824a43ff4..b79955e1c01 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -139,9 +139,8 @@ The objectives of the ``pytest-dev`` organisation are: * Sharing some of the maintenance responsibility (in case a maintainer no longer wishes to maintain a plugin) -You can submit your plugin by subscribing to the `pytest-dev mail list -`_ and writing a -mail pointing to your existing pytest plugin repository which must have +You can submit your plugin by posting a new topic in the `pytest-dev GitHub Discussions +`_ pointing to your existing pytest plugin repository which must have the following: - PyPI presence with packaging metadata that contains a ``pytest-`` diff --git a/doc/en/contact.rst b/doc/en/contact.rst index cd34f548e99..b2a1368eaba 100644 --- a/doc/en/contact.rst +++ b/doc/en/contact.rst @@ -35,7 +35,6 @@ Mail ---- - `Testing In Python`_: a mailing list for Python testing tools and discussion. -- `pytest-dev at python.org`_ a mailing list for pytest specific announcements and discussions. - Mail to `core@pytest.org `_ for topics that cannot be discussed in public. Mails sent there will be distributed among the members in the pytest core team, who can also be contacted individually: @@ -58,4 +57,3 @@ Other .. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues .. _`pytest discussions`: https://github.com/pytest-dev/pytest/discussions .. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python -.. _`pytest-dev at python.org`: http://mail.python.org/mailman/listinfo/pytest-dev From bd6877e5874b50ee57d0f63b342a67298ee9a1c3 Mon Sep 17 00:00:00 2001 From: Sashko <20253875+sashko1988@users.noreply.github.com> Date: Thu, 29 May 2025 15:21:52 +0200 Subject: [PATCH 1222/1271] Improve `nodes._check_initialpaths_for_relpath` performance (#13448) Use `Path` facilities to greatly improve performance of `nodes._check_initialpaths_for_relpath` (see #13448 for performance comparison). Related: #13420, #13413. --------- Co-authored-by: Bruno Oliveira --- AUTHORS | 1 + changelog/13420.improvement.rst | 1 + src/_pytest/nodes.py | 12 +++++++----- 3 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 changelog/13420.improvement.rst diff --git a/AUTHORS b/AUTHORS index 9be48958485..e5b863e71f1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -332,6 +332,7 @@ Nikolay Kondratyev Nipunn Koorapati Oleg Pidsadnyi Oleg Sushchenko +Oleksandr Zavertniev Olga Matoula Oliver Bestwalter Omar Kohl diff --git a/changelog/13420.improvement.rst b/changelog/13420.improvement.rst new file mode 100644 index 00000000000..54fe50a72b0 --- /dev/null +++ b/changelog/13420.improvement.rst @@ -0,0 +1 @@ +Improved test collection performance by optimizing path resolution used in ``FSCollector``. diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index eb3b04b200a..6d39de95f5b 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -38,7 +38,6 @@ from _pytest.mark.structures import NodeKeywords from _pytest.outcomes import fail from _pytest.pathlib import absolutepath -from _pytest.pathlib import commonpath from _pytest.stash import Stash from _pytest.warning_types import PytestWarning @@ -548,10 +547,13 @@ def _traceback_filter(self, excinfo: ExceptionInfo[BaseException]) -> Traceback: def _check_initialpaths_for_relpath( initial_paths: frozenset[Path], path: Path ) -> str | None: - for initial_path in initial_paths: - if commonpath(path, initial_path) == initial_path: - rel = str(path.relative_to(initial_path)) - return "" if rel == "." else rel + if path in initial_paths: + return "" + + for parent in path.parents: + if parent in initial_paths: + return str(path.relative_to(parent)) + return None From 1d59ddfb4df278a47bbd4e3673d3390c50a8dc01 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sat, 31 May 2025 10:46:15 +0100 Subject: [PATCH 1223/1271] officially support python 3.14 (#13440) * test on py3.14 * add news * add 314 to tox.ini * fix ResourceWarning on pastebin http failures * fix ResourceWarning on pytest.raises with urllib.error * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * pass real types for HTTPError so it works in cmgr * xfail test_raises_bdbquit_with_eoferror * fix message for unraisable exceptions * use improved prog default value for argparse.ArgumentParser * Update testing/python/raises.py * Update testing/test_debugging.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * be more explicit in debugging xfail * Update changelog/13308.improvement.rst Co-authored-by: Bruno Oliveira * Update src/_pytest/pastebin.py * add 3.14 trove classifier * patch coverage * Update .github/workflows/test.yml --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: jakkdl Co-authored-by: Bruno Oliveira --- .github/workflows/test.yml | 17 ++++++++++- changelog/13308.improvement.rst | 1 + pyproject.toml | 3 +- src/_pytest/pastebin.py | 8 +++-- testing/python/raises.py | 9 ++++-- testing/test_debugging.py | 5 +++ testing/test_parseopt.py | 2 +- testing/test_pastebin.py | 47 +++++++++++++++++------------ testing/test_unraisableexception.py | 33 ++++++++++++++------ tox.ini | 1 + 10 files changed, 90 insertions(+), 36 deletions(-) create mode 100644 changelog/13308.improvement.rst diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 99ca032db9d..73c2892575b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -118,6 +118,10 @@ jobs: os: windows-latest tox_env: "py313" + - name: "windows-py314" + python: "3.14" + os: windows-latest + tox_env: "py314" - name: "ubuntu-py39-lsof-numpy-pexpect" python: "3.9" @@ -163,6 +167,12 @@ jobs: tox_env: "py313-pexpect" use_coverage: true + - name: "ubuntu-py314" + python: "3.14" + os: ubuntu-latest + tox_env: "py314" + use_coverage: true + - name: "ubuntu-pypy3-xdist" python: "pypy-3.9" os: ubuntu-latest @@ -190,6 +200,10 @@ jobs: os: macos-latest tox_env: "py313-xdist" + - name: "macos-py314" + python: "3.14" + os: macos-latest + tox_env: "py314-xdist" - name: "plugins" python: "3.12" @@ -239,7 +253,8 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - check-latest: ${{ endsWith(matrix.python, '-dev') }} + check-latest: true + allow-prereleases: true - name: Install dependencies run: | diff --git a/changelog/13308.improvement.rst b/changelog/13308.improvement.rst new file mode 100644 index 00000000000..70018c66d59 --- /dev/null +++ b/changelog/13308.improvement.rst @@ -0,0 +1 @@ +Added official support for Python 3.14. diff --git a/pyproject.toml b/pyproject.toml index c7db5947cf4..4d4055147d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Software Development :: Libraries", "Topic :: Software Development :: Testing", "Topic :: Utilities", @@ -349,7 +350,7 @@ ignore = "W009" [tool.pyproject-fmt] indent = 4 -max_supported_python = "3.13" +max_supported_python = "3.14" [tool.pytest.ini_options] minversion = "2.0" diff --git a/src/_pytest/pastebin.py b/src/_pytest/pastebin.py index d5c4f29c4c3..c7b39d96f02 100644 --- a/src/_pytest/pastebin.py +++ b/src/_pytest/pastebin.py @@ -76,6 +76,7 @@ def create_new_paste(contents: str | bytes) -> str: :returns: URL to the pasted contents, or an error message. """ import re + from urllib.error import HTTPError from urllib.parse import urlencode from urllib.request import urlopen @@ -85,8 +86,11 @@ def create_new_paste(contents: str | bytes) -> str: response: str = ( urlopen(url, data=urlencode(params).encode("ascii")).read().decode("utf-8") ) - except OSError as exc_info: # urllib errors - return f"bad response: {exc_info}" + except HTTPError as e: + with e: # HTTPErrors are also http responses that must be closed! + return f"bad response: {e}" + except OSError as e: # eg urllib.error.URLError + return f"bad response: {e}" m = re.search(r'href="/raw/(\w+)"', response) if m: return f"{url}/show/{m.group(1)}" diff --git a/testing/python/raises.py b/testing/python/raises.py index 3da260d1837..40f9afea3ba 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -1,6 +1,7 @@ # mypy: allow-untyped-defs from __future__ import annotations +import io import re import sys @@ -399,7 +400,11 @@ def test_issue_11872(self) -> None: https://github.com/python/cpython/issues/98778 """ + from email.message import Message from urllib.error import HTTPError - with pytest.raises(HTTPError, match="Not Found"): - raise HTTPError(code=404, msg="Not Found", fp=None, hdrs=None, url="") # type: ignore [arg-type] + with pytest.raises(HTTPError, match="Not Found") as exc_info: + raise HTTPError( + code=404, msg="Not Found", fp=io.BytesIO(), hdrs=Message(), url="" + ) + exc_info.value.close() # avoid a resource warning diff --git a/testing/test_debugging.py b/testing/test_debugging.py index 45883568b11..08ebf600253 100644 --- a/testing/test_debugging.py +++ b/testing/test_debugging.py @@ -1373,6 +1373,10 @@ def do_quit(self, *args): result.stdout.fnmatch_lines(["*runcall_called*", "* 1 passed in *"]) +@pytest.mark.xfail( + sys.version_info >= (3, 14), + reason="C-D now quits the test session, rather than failing the test. See https://github.com/python/cpython/issues/124703", +) def test_raises_bdbquit_with_eoferror(pytester: Pytester) -> None: """It is not guaranteed that DontReadFromInput's read is called.""" p1 = pytester.makepyfile( @@ -1387,6 +1391,7 @@ def test(monkeypatch): """ ) result = pytester.runpytest(str(p1)) + result.assert_outcomes(failed=1) result.stdout.fnmatch_lines(["E *BdbQuit", "*= 1 failed in*"]) assert result.ret == 1 diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 14e2b5f69fb..36db7b13989 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -28,7 +28,7 @@ def test_no_help_by_default(self) -> None: def test_custom_prog(self, parser: parseopt.Parser) -> None: """Custom prog can be set for `argparse.ArgumentParser`.""" - assert parser._getparser().prog == os.path.basename(sys.argv[0]) + assert parser._getparser().prog == argparse.ArgumentParser().prog parser.prog = "custom-prog" assert parser._getparser().prog == "custom-prog" diff --git a/testing/test_pastebin.py b/testing/test_pastebin.py index 8fdd60bac75..9b928e00c06 100644 --- a/testing/test_pastebin.py +++ b/testing/test_pastebin.py @@ -3,6 +3,7 @@ import email.message import io +from unittest import mock from _pytest.monkeypatch import MonkeyPatch from _pytest.pytester import Pytester @@ -90,23 +91,6 @@ class TestPaste: def pastebin(self, request): return request.config.pluginmanager.getplugin("pastebin") - @pytest.fixture - def mocked_urlopen_fail(self, monkeypatch: MonkeyPatch): - """Monkeypatch the actual urlopen call to emulate a HTTP Error 400.""" - calls = [] - - import urllib.error - import urllib.request - - def mocked(url, data): - calls.append((url, data)) - raise urllib.error.HTTPError( - url, 400, "Bad request", email.message.Message(), io.BytesIO() - ) - - monkeypatch.setattr(urllib.request, "urlopen", mocked) - return calls - @pytest.fixture def mocked_urlopen_invalid(self, monkeypatch: MonkeyPatch): """Monkeypatch the actual urlopen calls done by the internal plugin @@ -158,10 +142,33 @@ def test_pastebin_invalid_url(self, pastebin, mocked_urlopen_invalid) -> None: ) assert len(mocked_urlopen_invalid) == 1 - def test_pastebin_http_error(self, pastebin, mocked_urlopen_fail) -> None: - result = pastebin.create_new_paste(b"full-paste-contents") + def test_pastebin_http_error(self, pastebin) -> None: + import urllib.error + + with mock.patch( + "urllib.request.urlopen", + side_effect=urllib.error.HTTPError( + url="https://bpa.st", + code=400, + msg="Bad request", + hdrs=email.message.Message(), + fp=io.BytesIO(), + ), + ) as mock_urlopen: + result = pastebin.create_new_paste(b"full-paste-contents") assert result == "bad response: HTTP Error 400: Bad request" - assert len(mocked_urlopen_fail) == 1 + assert len(mock_urlopen.mock_calls) == 1 + + def test_pastebin_url_error(self, pastebin) -> None: + import urllib.error + + with mock.patch( + "urllib.request.urlopen", + side_effect=urllib.error.URLError("the url was bad"), + ) as mock_urlopen: + result = pastebin.create_new_paste(b"full-paste-contents") + assert result == "bad response: " + assert len(mock_urlopen.mock_calls) == 1 def test_create_new_paste(self, pastebin, mocked_urlopen) -> None: result = pastebin.create_new_paste(b"full-paste-contents") diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index 328177a7ba3..6c0dc542e93 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -12,6 +12,24 @@ PYPY = hasattr(sys, "pypy_version_info") +UNRAISABLE_LINE = ( + ( + " * PytestUnraisableExceptionWarning: Exception ignored while calling " + "deallocator : None" + ) + if sys.version_info >= (3, 14) + else " * PytestUnraisableExceptionWarning: Exception ignored in: " +) + +TRACEMALLOC_LINES = ( + () + if sys.version_info >= (3, 14) + else ( + " Enable tracemalloc to get traceback where the object was allocated.", + " See https* for more info.", + ) +) + @pytest.mark.skipif(PYPY, reason="garbage-collection differences make this flaky") @pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") @@ -36,13 +54,12 @@ def test_2(): pass [ "*= warnings summary =*", "test_it.py::test_it", - " * PytestUnraisableExceptionWarning: Exception ignored in: ", + UNRAISABLE_LINE, " ", " Traceback (most recent call last):", " ValueError: del is broken", " ", - " Enable tracemalloc to get traceback where the object was allocated.", - " See https* for more info.", + *TRACEMALLOC_LINES, " warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))", ] ) @@ -75,13 +92,12 @@ def test_2(): pass [ "*= warnings summary =*", "test_it.py::test_it", - " * PytestUnraisableExceptionWarning: Exception ignored in: ", + UNRAISABLE_LINE, " ", " Traceback (most recent call last):", " ValueError: del is broken", " ", - " Enable tracemalloc to get traceback where the object was allocated.", - " See https* for more info.", + *TRACEMALLOC_LINES, " warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))", ] ) @@ -115,13 +131,12 @@ def test_2(): pass [ "*= warnings summary =*", "test_it.py::test_it", - " * PytestUnraisableExceptionWarning: Exception ignored in: ", + UNRAISABLE_LINE, " ", " Traceback (most recent call last):", " ValueError: del is broken", " ", - " Enable tracemalloc to get traceback where the object was allocated.", - " See https* for more info.", + *TRACEMALLOC_LINES, " warnings.warn(pytest.PytestUnraisableExceptionWarning(msg))", ] ) diff --git a/tox.ini b/tox.ini index 850def411cb..8f7d8495285 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,7 @@ envlist = py311 py312 py313 + py314 pypy3 py39-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} doctesting From ca8b6f213617904fda04412391a3f00249dcf81e Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sat, 31 May 2025 19:44:27 +0100 Subject: [PATCH 1224/1271] fix GH ci jobs having the wrong name (#13454) * fix GH ci jobs having the wrong name * add news * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Delete changelog/13454.misc.rst --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/test.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 73c2892575b..3ecc133878f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -61,6 +61,7 @@ jobs: "windows-py311", "windows-py312", "windows-py313", + "windows-py314", "ubuntu-py39-lsof-numpy-pexpect", "ubuntu-py39-pluggy", @@ -70,12 +71,14 @@ jobs: "ubuntu-py311", "ubuntu-py312", "ubuntu-py313-pexpect", + "ubuntu-py314", "ubuntu-pypy3-xdist", "macos-py39", "macos-py310", "macos-py312", "macos-py313", + "macos-py314", "doctesting", "plugins", From 075c5efb1f0e752bd75543008f16c69cb9c60294 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Sat, 31 May 2025 22:10:04 +0200 Subject: [PATCH 1225/1271] use Contextmanagers to handle StopIteration in generators (#12934) * prepare example test for stopiteration passover issue * WIP: use contextmanagers instead of yield from as it turns out, StopIteration is not transparent on the boundaries of generators # Conflicts: # src/_pytest/threadexception.py # src/_pytest/unraisableexception.py * fixup rebase * rebase fixup more * add tests * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove hook_exceptions examples - these are tests now * add changelog * handle different numbers of === * handle different numbers of !!! --------- Co-authored-by: Thomas Grainger Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- changelog/12929.bugfix.rst | 1 + src/_pytest/logging.py | 10 ++++++--- testing/acceptance_test.py | 46 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 changelog/12929.bugfix.rst diff --git a/changelog/12929.bugfix.rst b/changelog/12929.bugfix.rst new file mode 100644 index 00000000000..fcf490d83e2 --- /dev/null +++ b/changelog/12929.bugfix.rst @@ -0,0 +1 @@ +Handle StopIteration from test cases, setup and teardown correctly. diff --git a/src/_pytest/logging.py b/src/_pytest/logging.py index ca5fbda6fcc..e4fed579d21 100644 --- a/src/_pytest/logging.py +++ b/src/_pytest/logging.py @@ -809,6 +809,7 @@ def pytest_runtest_logstart(self) -> None: def pytest_runtest_logreport(self) -> None: self.log_cli_handler.set_when("logreport") + @contextmanager def _runtest_for(self, item: nodes.Item, when: str) -> Generator[None]: """Implement the internals of the pytest_runtest_xxx() hooks.""" with ( @@ -838,20 +839,23 @@ def pytest_runtest_setup(self, item: nodes.Item) -> Generator[None]: empty: dict[str, list[logging.LogRecord]] = {} item.stash[caplog_records_key] = empty - yield from self._runtest_for(item, "setup") + with self._runtest_for(item, "setup"): + yield @hookimpl(wrapper=True) def pytest_runtest_call(self, item: nodes.Item) -> Generator[None]: self.log_cli_handler.set_when("call") - yield from self._runtest_for(item, "call") + with self._runtest_for(item, "call"): + yield @hookimpl(wrapper=True) def pytest_runtest_teardown(self, item: nodes.Item) -> Generator[None]: self.log_cli_handler.set_when("teardown") try: - yield from self._runtest_for(item, "teardown") + with self._runtest_for(item, "teardown"): + yield finally: del item.stash[caplog_records_key] del item.stash[caplog_handler_key] diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 2d653b8e2a5..4948e3ff8ae 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1606,3 +1606,49 @@ def test_no_terminal_plugin(pytester: Pytester) -> None: pytester.makepyfile("def test(): assert 1 == 2") result = pytester.runpytest("-pno:terminal", "-s") assert result.ret == ExitCode.TESTS_FAILED + + +def test_stop_iteration_from_collect(pytester: Pytester) -> None: + pytester.makepyfile(test_it="raise StopIteration('hello')") + result = pytester.runpytest() + assert result.ret == ExitCode.INTERRUPTED + result.assert_outcomes(failed=0, passed=0, errors=1) + result.stdout.fnmatch_lines( + [ + "=* short test summary info =*", + "ERROR test_it.py - StopIteration: hello", + "!* Interrupted: 1 error during collection !*", + "=* 1 error in * =*", + ] + ) + + +def test_stop_iteration_runtest_protocol(pytester: Pytester) -> None: + pytester.makepyfile( + test_it=""" + import pytest + @pytest.fixture + def fail_setup(): + raise StopIteration(1) + def test_fail_setup(fail_setup): + pass + def test_fail_teardown(request): + def stop_iteration(): + raise StopIteration(2) + request.addfinalizer(stop_iteration) + def test_fail_call(): + raise StopIteration(3) + """ + ) + result = pytester.runpytest() + assert result.ret == ExitCode.TESTS_FAILED + result.assert_outcomes(failed=1, passed=1, errors=2) + result.stdout.fnmatch_lines( + [ + "=* short test summary info =*", + "FAILED test_it.py::test_fail_call - StopIteration: 3", + "ERROR test_it.py::test_fail_setup - StopIteration: 1", + "ERROR test_it.py::test_fail_teardown - StopIteration: 2", + "=* 1 failed, 1 passed, 2 errors in * =*", + ] + ) From 261e7f15721a02cdc7361c60183b86fa36d0f72f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 1 Jun 2025 04:56:52 +0000 Subject: [PATCH 1226/1271] [automated] Update plugin list (#13455) Co-authored-by: pytest bot --- doc/en/reference/plugin_list.rst | 238 ++++++++++++++++++++----------- 1 file changed, 155 insertions(+), 83 deletions(-) diff --git a/doc/en/reference/plugin_list.rst b/doc/en/reference/plugin_list.rst index 69de1df9690..d0bf2083fe3 100644 --- a/doc/en/reference/plugin_list.rst +++ b/doc/en/reference/plugin_list.rst @@ -27,7 +27,7 @@ please refer to `the update script =8.3.4 :pypi:`pytest-airflow` pytest support for airflow. Apr 03, 2019 3 - Alpha pytest (>=4.4.0) :pypi:`pytest-airflow-utils` Nov 15, 2021 N/A N/A - :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. May 16, 2025 N/A pytest>=7.0 + :pypi:`pytest-alembic` A pytest plugin for verifying alembic migrations. May 27, 2025 N/A pytest>=7.0 :pypi:`pytest-alerts` A pytest plugin for sending test results to Slack and Telegram Feb 21, 2025 4 - Beta pytest>=7.4.0 :pypi:`pytest-allclose` Pytest fixture extending Numpy's allclose function Jul 30, 2019 5 - Production/Stable pytest :pypi:`pytest-allure-adaptor` Plugin for py.test to generate allure xml reports Jan 10, 2018 N/A pytest (>=2.7.3) @@ -80,7 +80,7 @@ This list contains 1632 plugins. :pypi:`pytest-anki` A pytest plugin for testing Anki add-ons Jul 31, 2022 4 - Beta pytest (>=3.5.0) :pypi:`pytest-annotate` pytest-annotate: Generate PyAnnotate annotations from your pytest tests. Jun 07, 2022 3 - Alpha pytest (<8.0.0,>=3.2.0) :pypi:`pytest-annotated` Pytest plugin to allow use of Annotated in tests to resolve fixtures Sep 30, 2024 N/A pytest>=8.3.3 - :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures Apr 28, 2025 5 - Production/Stable pytest>=6 + :pypi:`pytest-ansible` Plugin for pytest to simplify calling ansible modules from tests or fixtures May 26, 2025 5 - Production/Stable pytest>=6 :pypi:`pytest-ansible-playbook` Pytest fixture which runs given ansible playbook file. Mar 08, 2019 4 - Beta N/A :pypi:`pytest-ansible-playbook-runner` Pytest fixture which runs given ansible playbook file. Dec 02, 2020 4 - Beta pytest (>=3.1.0) :pypi:`pytest-ansible-units` A pytest plugin for running unit tests within an ansible collection Apr 14, 2022 N/A N/A @@ -117,8 +117,9 @@ This list contains 1632 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` pytest-async - Run your coroutine in event loop without decorator Feb 26, 2020 N/A N/A + :pypi:`pytest-async-benchmark` pytest-async-benchmark: Modern pytest benchmarking for async code. 🚀 May 28, 2025 N/A pytest>=8.3.5 :pypi:`pytest-async-generators` Pytest fixtures for async generators Jul 05, 2023 N/A N/A - :pypi:`pytest-asyncio` Pytest support for asyncio May 09, 2025 4 - Beta pytest<9,>=8.2 + :pypi:`pytest-asyncio` Pytest support for asyncio May 26, 2025 4 - Beta pytest<9,>=8.2 :pypi:`pytest-asyncio-concurrent` Pytest plugin to execute python async tests concurrently. May 17, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-asyncio-cooperative` Run all your asynchronous tests cooperatively. Apr 26, 2025 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) @@ -162,7 +163,7 @@ This list contains 1632 plugins. :pypi:`pytest-bdd-wrappers` Feb 11, 2020 2 - Pre-Alpha N/A :pypi:`pytest-beakerlib` A pytest plugin that reports test results to the BeakerLib framework Mar 17, 2017 5 - Production/Stable pytest :pypi:`pytest-beartype` Pytest plugin to run your tests with beartype checking enabled. Oct 31, 2024 N/A pytest - :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 13, 2025 3 - Alpha pytest + :pypi:`pytest-bec-e2e` BEC pytest plugin for end-to-end tests May 30, 2025 3 - Alpha pytest :pypi:`pytest-beds` Fixtures for testing Google Appengine (GAE) apps Jun 07, 2016 4 - Beta N/A :pypi:`pytest-beeprint` use icdiff for better error messages in pytest assertions Jul 04, 2023 4 - Beta N/A :pypi:`pytest-bench` Benchmark utility that plugs into pytest. Jul 21, 2014 3 - Alpha N/A @@ -217,6 +218,7 @@ This list contains 1632 plugins. :pypi:`pytest-caprng` A plugin that replays pRNG state on failure. May 02, 2018 4 - Beta N/A :pypi:`pytest-capsqlalchemy` Pytest plugin to allow capturing SQLAlchemy queries. Mar 19, 2025 4 - Beta N/A :pypi:`pytest-capture-deprecatedwarnings` pytest plugin to capture all deprecatedwarnings and put them in one file Apr 30, 2019 N/A N/A + :pypi:`pytest-capture-sysout` An academic experiment package May 21, 2025 2 - Pre-Alpha N/A :pypi:`pytest-capture-warnings` pytest plugin to capture all warnings and put them in one file of your choice May 03, 2022 N/A pytest :pypi:`pytest-case` A clean, modern, wrapper for pytest.mark.parametrize Nov 25, 2024 N/A pytest<9.0.0,>=8.3.3 :pypi:`pytest-cases` Separate test code from test cases in pytest. Sep 26, 2024 5 - Production/Stable N/A @@ -225,6 +227,7 @@ This list contains 1632 plugins. :pypi:`pytest-catch-server` Pytest plugin with server for catching HTTP requests. Dec 12, 2019 5 - Production/Stable N/A :pypi:`pytest-cdist` A pytest plugin to split your test suite into multiple parts Jan 30, 2025 N/A pytest>=7 :pypi:`pytest-celery` Pytest plugin for Celery Feb 21, 2025 5 - Production/Stable N/A + :pypi:`pytest-celery-py37` Pytest plugin for Celery (compatible with python 3.7) May 23, 2025 5 - Production/Stable N/A :pypi:`pytest-cfg-fetcher` Pass config options to your unit tests. Feb 26, 2024 N/A N/A :pypi:`pytest-chainmaker` pytest plugin for chainmaker Oct 15, 2021 N/A N/A :pypi:`pytest-chalice` A set of py.test fixtures for AWS Chalice Jul 01, 2020 4 - Beta N/A @@ -239,7 +242,7 @@ This list contains 1632 plugins. :pypi:`pytest-check-library` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-libs` check your missing library Jul 17, 2022 N/A N/A :pypi:`pytest-check-links` Check links in files Jul 29, 2020 N/A pytest<9,>=7.0 - :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. May 07, 2025 N/A N/A + :pypi:`pytest-checklist` Pytest plugin to track and report unit/function coverage. May 23, 2025 N/A N/A :pypi:`pytest-check-mk` pytest plugin to test Check_MK checks Nov 19, 2015 4 - Beta pytest :pypi:`pytest-checkpoint` Restore a checkpoint in pytest Mar 30, 2025 N/A pytest>=8.0.0 :pypi:`pytest-ch-framework` My pytest framework Apr 17, 2024 N/A pytest==8.0.1 @@ -280,7 +283,7 @@ This list contains 1632 plugins. :pypi:`pytest-codegen` Automatically create pytest test signatures Aug 23, 2020 2 - Pre-Alpha N/A :pypi:`pytest-codeowners` Pytest plugin for selecting tests by GitHub CODEOWNERS. Mar 30, 2022 4 - Beta pytest (>=6.0.0) :pypi:`pytest-codestyle` pytest plugin to run pycodestyle Mar 23, 2020 3 - Alpha N/A - :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks Jan 31, 2025 5 - Production/Stable pytest>=3.8 + :pypi:`pytest-codspeed` Pytest plugin to create CodSpeed benchmarks May 27, 2025 5 - Production/Stable pytest>=3.8 :pypi:`pytest-collect-appoint-info` set your encoding Aug 03, 2023 N/A pytest :pypi:`pytest-collect-formatter` Formatter for pytest collect output Mar 29, 2021 5 - Production/Stable N/A :pypi:`pytest-collect-formatter2` Formatter for pytest collect output May 31, 2021 5 - Production/Stable N/A @@ -323,7 +326,7 @@ This list contains 1632 plugins. :pypi:`pytest-cricri` A Cricri plugin for pytest. Jan 27, 2018 N/A pytest :pypi:`pytest-crontab` add crontab task in crontab Dec 09, 2019 N/A N/A :pypi:`pytest-csv` CSV output for pytest. Apr 22, 2021 N/A pytest (>=6.0) - :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files Oct 25, 2024 5 - Production/Stable pytest<9.0.0,>=8.3.0 + :pypi:`pytest-csv-params` Pytest plugin for Test Case Parametrization with CSV files May 29, 2025 5 - Production/Stable pytest<9,>=8.3 :pypi:`pytest-culprit` Find the last Git commit where a pytest test started failing May 15, 2025 N/A N/A :pypi:`pytest-curio` Pytest support for curio. Oct 06, 2024 N/A pytest :pypi:`pytest-curl-report` pytest plugin to generate curl command line report Dec 11, 2016 4 - Beta N/A @@ -338,11 +341,11 @@ This list contains 1632 plugins. :pypi:`pytest-cython-collect` Jun 17, 2022 N/A pytest :pypi:`pytest-darker` A pytest plugin for checking of modified code using Darker Feb 25, 2024 N/A pytest <7,>=6.0.1 :pypi:`pytest-dash` pytest fixtures to run dash applications. Mar 18, 2019 N/A N/A - :pypi:`pytest-dashboard` May 30, 2024 N/A pytest<8.0.0,>=7.4.3 + :pypi:`pytest-dashboard` May 20, 2025 N/A pytest<8.0.0,>=7.4.3 :pypi:`pytest-data` Useful functions for managing data for pytest fixtures Nov 01, 2016 5 - Production/Stable N/A - :pypi:`pytest-databases` Reusable database fixtures for any and all databases. Apr 21, 2025 4 - Beta pytest + :pypi:`pytest-databases` Reusable database fixtures for any and all databases. May 25, 2025 4 - Beta pytest :pypi:`pytest-databricks` Pytest plugin for remote Databricks notebooks testing Jul 29, 2020 N/A pytest - :pypi:`pytest-datadir` pytest plugin for test data directories and files Feb 07, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-datadir` pytest plugin for test data directories and files May 30, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-datadir-mgr` Manager for test data: downloads, artifact caching, and a tmpdir context. Apr 06, 2023 5 - Production/Stable pytest (>=7.1) :pypi:`pytest-datadir-ng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Dec 25, 2019 5 - Production/Stable pytest :pypi:`pytest-datadir-nng` Fixtures for pytest allowing test functions/methods to easily retrieve test resources from the local filesystem. Nov 09, 2022 5 - Production/Stable pytest (>=7.0.0,<8.0.0) @@ -423,7 +426,7 @@ This list contains 1632 plugins. :pypi:`pytest-doc` A documentation plugin for py.test. Jun 28, 2015 5 - Production/Stable N/A :pypi:`pytest-docfiles` pytest plugin to test codeblocks in your documentation. Dec 22, 2021 4 - Beta pytest (>=3.7.0) :pypi:`pytest-docgen` An RST Documentation Generator for pytest-based test suites Apr 17, 2020 N/A N/A - :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests Apr 07, 2025 N/A pytest<9.0,>=4.0 + :pypi:`pytest-docker` Simple pytest fixtures for Docker and Docker Compose based tests May 26, 2025 N/A pytest<9.0,>=4.0 :pypi:`pytest-docker-apache-fixtures` Pytest fixtures for testing with apache2 (httpd). Aug 12, 2024 4 - Beta pytest :pypi:`pytest-docker-butla` Jun 16, 2019 3 - Alpha N/A :pypi:`pytest-dockerc` Run, manage and stop Docker Compose project from Docker API Oct 09, 2020 5 - Production/Stable pytest (>=3.0) @@ -463,7 +466,7 @@ This list contains 1632 plugins. :pypi:`pytest-drop-dup-tests` A Pytest plugin to drop duplicated tests during collection Mar 04, 2024 5 - Production/Stable pytest >=7 :pypi:`pytest-dryci` Test caching plugin for pytest Sep 27, 2024 4 - Beta N/A :pypi:`pytest-dryrun` A Pytest plugin to ignore tests during collection without reporting them in the test summary. Jan 19, 2025 5 - Production/Stable pytest<9,>=7.40 - :pypi:`pytest-dsl` A DSL testing framework based on pytest May 07, 2025 N/A pytest>=7.0.0 + :pypi:`pytest-dsl` A DSL testing framework based on pytest May 29, 2025 N/A pytest>=7.0.0 :pypi:`pytest-dummynet` A py.test plugin providing access to a dummynet. Dec 15, 2021 5 - Production/Stable pytest :pypi:`pytest-dump2json` A pytest plugin for dumping test results to json. Jun 29, 2015 N/A N/A :pypi:`pytest-duration-insights` Jul 15, 2024 N/A N/A @@ -516,6 +519,7 @@ This list contains 1632 plugins. :pypi:`pytest_erp` py.test plugin to send test info to report portal dynamically Jan 13, 2015 N/A N/A :pypi:`pytest-error-for-skips` Pytest plugin to treat skipped tests a test failure Dec 19, 2019 4 - Beta pytest (>=4.6) :pypi:`pytest-errxfail` pytest plugin to mark a test as xfailed if it fails with the specified error message in the captured output Jan 06, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-essentials` A Pytest plugin providing essential utilities like soft assertions. May 19, 2025 3 - Alpha pytest>=7.0 :pypi:`pytest-eth` PyTest plugin for testing Smart Contracts for Ethereum Virtual Machine (EVM). Aug 14, 2020 1 - Planning N/A :pypi:`pytest-ethereum` pytest-ethereum: Pytest library for ethereum projects. Jun 24, 2019 3 - Alpha pytest (==3.3.2); extra == 'dev' :pypi:`pytest-eucalyptus` Pytest Plugin for BDD Jun 28, 2022 N/A pytest (>=4.2.0) @@ -614,7 +618,7 @@ This list contains 1632 plugins. :pypi:`pytest-flexreport` Apr 15, 2023 4 - Beta pytest :pypi:`pytest-fluent` A pytest plugin in order to provide logs via fluentd Aug 14, 2024 4 - Beta pytest>=7.0.0 :pypi:`pytest-fluentbit` A pytest plugin in order to provide logs via fluentbit Jun 16, 2023 4 - Beta pytest (>=7.0.0) - :pypi:`pytest-fly` pytest runner and observer May 03, 2025 3 - Alpha pytest + :pypi:`pytest-fly` pytest runner and observer May 19, 2025 3 - Alpha pytest :pypi:`pytest-flyte` Pytest fixtures for simplifying Flyte integration testing May 03, 2021 N/A pytest :pypi:`pytest-focus` A pytest plugin that alerts user of failed test cases with screen notifications May 04, 2019 4 - Beta pytest :pypi:`pytest-forbid` Mar 07, 2023 N/A pytest (>=7.2.2,<8.0.0) @@ -647,7 +651,7 @@ This list contains 1632 plugins. :pypi:`pytest-gherkin` A flexible framework for executing BDD gherkin tests Jul 27, 2019 3 - Alpha pytest (>=5.0.0) :pypi:`pytest-gh-log-group` pytest plugin for gh actions Jan 11, 2022 3 - Alpha pytest :pypi:`pytest-ghostinspector` For finding/executing Ghost Inspector tests May 17, 2016 3 - Alpha N/A - :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 08, 2025 N/A pytest>=3.6 + :pypi:`pytest-girder` A set of pytest fixtures for testing Girder applications. May 29, 2025 N/A pytest>=3.6 :pypi:`pytest-git` Git repository fixture for py.test Oct 17, 2024 5 - Production/Stable pytest :pypi:`pytest-gitconfig` Provide a Git config sandbox for testing Aug 11, 2024 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 @@ -667,6 +671,7 @@ This list contains 1632 plugins. :pypi:`pytest-golden` Plugin for pytest that offloads expected outputs to data files Jul 18, 2022 N/A pytest (>=6.1.2) :pypi:`pytest-goldie` A plugin to support golden tests with pytest. May 23, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-google-chat` Notify google chat channel for test results Mar 27, 2022 4 - Beta pytest + :pypi:`pytest-google-cloud-storage` Pytest custom features, e.g. fixtures and various tests. Aimed to emulate Google Cloud Storage service May 22, 2025 N/A pytest==8.3.5 :pypi:`pytest-gradescope` A pytest plugin for Gradescope integration Apr 29, 2025 N/A N/A :pypi:`pytest-graphql-schema` Get graphql schema as fixture for pytest Oct 18, 2019 N/A N/A :pypi:`pytest-greendots` Green progress dots Feb 08, 2014 3 - Alpha N/A @@ -692,7 +697,7 @@ This list contains 1632 plugins. :pypi:`pytest-history` Pytest plugin to keep a history of your pytest runs Jan 14, 2024 N/A pytest (>=7.4.3,<8.0.0) :pypi:`pytest-home` Home directory fixtures Jul 28, 2024 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 May 17, 2025 3 - Alpha pytest==8.3.5 + :pypi:`pytest-homeassistant-custom-component` Experimental package to automatically extract test plugins for Home Assistant custom components May 30, 2025 3 - Alpha pytest==8.3.5 :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` Sep 23, 2024 N/A N/A @@ -733,7 +738,7 @@ This list contains 1632 plugins. :pypi:`pytest-ignore-test-results` A pytest plugin to ignore test results. Feb 03, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-image-diff` Dec 31, 2024 3 - Alpha pytest :pypi:`pytest-image-snapshot` A pytest plugin for image snapshot management and comparison. Jul 01, 2024 4 - Beta pytest>=3.5.0 - :pypi:`pytest-impacted` A pytest plugin that selectively runs tests impacted by codechanges via git introspection, ASL parsing, and dependency graph analysis. May 15, 2025 4 - Beta pytest>=8.0.0 + :pypi:`pytest-impacted` A pytest plugin that selectively runs tests impacted by codechanges via git introspection, ASL parsing, and dependency graph analysis. May 31, 2025 4 - Beta pytest>=8.0.0 :pypi:`pytest-import-check` pytest plugin to check whether Python modules can be imported Jul 19, 2024 3 - Alpha pytest>=8.1 :pypi:`pytest-incremental` an incremental test runner (pytest plugin) Apr 24, 2021 5 - Production/Stable N/A :pypi:`pytest-infinity` Jun 09, 2024 N/A pytest<9.0.0,>=8.0.0 @@ -748,7 +753,7 @@ This list contains 1632 plugins. :pypi:`pytest-initry` Plugin for sending automation test data from Pytest to the initry Apr 30, 2024 N/A pytest<9.0.0,>=8.1.1 :pypi:`pytest-inline` A pytest plugin for writing inline tests Oct 24, 2024 4 - Beta pytest<9.0,>=7.0 :pypi:`pytest-inmanta` A py.test plugin providing fixtures to simplify inmanta modules testing. Apr 09, 2025 5 - Production/Stable pytest - :pypi:`pytest-inmanta-extensions` Inmanta tests package Apr 10, 2025 5 - Production/Stable N/A + :pypi:`pytest-inmanta-extensions` Inmanta tests package May 27, 2025 5 - Production/Stable N/A :pypi:`pytest-inmanta-lsm` Common fixtures for inmanta LSM related modules Apr 09, 2025 5 - Production/Stable N/A :pypi:`pytest-inmanta-srlinux` Pytest library to facilitate end to end testing of inmanta projects Apr 22, 2025 3 - Alpha N/A :pypi:`pytest-inmanta-yang` Common fixtures used in inmanta yang related modules Feb 22, 2024 4 - Beta pytest @@ -769,9 +774,9 @@ This list contains 1632 plugins. :pypi:`pytest-ipdb` A py.test plug-in to enable drop to ipdb debugger on test failure. Mar 20, 2013 2 - Pre-Alpha N/A :pypi:`pytest-ipynb` THIS PROJECT IS ABANDONED Jan 29, 2019 3 - Alpha N/A :pypi:`pytest-ipynb2` Pytest plugin to run tests in Jupyter Notebooks Mar 09, 2025 N/A pytest - :pypi:`pytest-ipywidgets` Apr 30, 2025 N/A pytest + :pypi:`pytest-ipywidgets` May 30, 2025 N/A pytest :pypi:`pytest-iso` Plugin for pytest to produce test documentation for code audits. May 15, 2025 4 - Beta pytest<9.0.0,>=7.4.0 - :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses Apr 22, 2025 4 - Beta pytest + :pypi:`pytest-isolate` Run pytest tests in isolated subprocesses May 22, 2025 4 - Beta pytest :pypi:`pytest-isolate-mpi` pytest-isolate-mpi allows for MPI-parallel tests being executed in a segfault and MPI_Abort safe manner Feb 24, 2025 4 - Beta pytest>=5 :pypi:`pytest-isort` py.test plugin to check import ordering using isort Mar 05, 2024 5 - Production/Stable pytest (>=5.0) :pypi:`pytest-it` Pytest plugin to display test reports as a plaintext spec, inspired by Rspec: https://github.com/mattduck/pytest-it. Jan 29, 2024 4 - Beta N/A @@ -786,7 +791,7 @@ This list contains 1632 plugins. :pypi:`pytest-jinja` A plugin to generate customizable jinja-based HTML reports in pytest Oct 04, 2022 3 - Alpha pytest (>=6.2.5,<7.0.0) :pypi:`pytest-jira` py.test JIRA integration plugin, using markers Apr 15, 2025 3 - Alpha N/A :pypi:`pytest-jira-xfail` Plugin skips (xfail) tests if unresolved Jira issue(s) linked Jul 09, 2024 N/A pytest>=7.2.0 - :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY Oct 27, 2024 4 - Beta pytest>=6.2.4 + :pypi:`pytest-jira-xray` pytest plugin to integrate tests with JIRA XRAY May 24, 2025 4 - Beta pytest>=6.2.4 :pypi:`pytest-job-selection` A pytest plugin for load balancing test suites Jan 30, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-jobserver` Limit parallel tests with posix jobserver. May 15, 2019 5 - Production/Stable pytest :pypi:`pytest-joke` Test failures are better served with humor. Oct 08, 2019 4 - Beta pytest (>=4.2.1) @@ -827,14 +832,14 @@ This list contains 1632 plugins. :pypi:`pytest-launchable` Launchable Pytest Plugin Apr 05, 2023 N/A pytest (>=4.2.0) :pypi:`pytest-layab` Pytest fixtures for layab. Oct 05, 2020 5 - Production/Stable N/A :pypi:`pytest-lazy-fixture` It helps to use fixtures in pytest.mark.parametrize Feb 01, 2020 4 - Beta pytest (>=3.2.5) - :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. Jan 25, 2025 N/A pytest>=7 + :pypi:`pytest-lazy-fixtures` Allows you to use fixtures in @pytest.mark.parametrize. May 27, 2025 N/A pytest>=7 :pypi:`pytest-ldap` python-ldap fixtures for pytest Aug 18, 2020 N/A pytest :pypi:`pytest-leak-finder` Find the test that's leaking before the one that fails Feb 15, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-leaks` A pytest plugin to trace resource leaks. Nov 27, 2019 1 - Planning N/A :pypi:`pytest-leaping` A simple plugin to use with pytest Mar 27, 2024 4 - Beta pytest>=6.2.0 :pypi:`pytest-leo-interface` Pytest extension tool for leo projects. Mar 19, 2025 N/A N/A :pypi:`pytest-level` Select tests of a given level or lower Oct 21, 2019 N/A pytest - :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. May 06, 2025 4 - Beta pytest>=8.3.5 + :pypi:`pytest-lf-skip` A pytest plugin which makes \`--last-failed\` skip instead of deselect tests. May 26, 2025 4 - Beta pytest>=8.3.5 :pypi:`pytest-libfaketime` A python-libfaketime plugin for pytest Apr 12, 2024 4 - Beta pytest>=3.0.0 :pypi:`pytest-libiio` A pytest plugin to manage interfacing with libiio contexts Oct 01, 2024 4 - Beta N/A :pypi:`pytest-libnotify` Pytest plugin that shows notifications about the test run Apr 02, 2021 3 - Alpha pytest @@ -862,7 +867,7 @@ This list contains 1632 plugins. :pypi:`pytest-logger` Plugin configuring handlers for loggers from Python logging module. Mar 10, 2024 5 - Production/Stable pytest (>=3.2) :pypi:`pytest-logging` Configures logging and allows tweaking the log level with a py.test flag Nov 04, 2015 4 - Beta N/A :pypi:`pytest-logging-end-to-end-test-tool` Sep 23, 2022 N/A pytest (>=7.1.2,<8.0.0) - :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML Apr 09, 2025 3 - Alpha pytest + :pypi:`pytest-logging-strict` pytest fixture logging configured from packaged YAML May 20, 2025 3 - Alpha pytest :pypi:`pytest-logikal` Common testing environment Apr 30, 2025 5 - Production/Stable pytest==8.3.5 :pypi:`pytest-log-report` Package for creating a pytest test run reprot Dec 26, 2019 N/A N/A :pypi:`pytest-logscanner` Pytest plugin for logscanner (A logger for python logging outputting to easily viewable (and filterable) html files. Good for people not grep savey, and color higlighting and quickly changing filters might even bye useful for commandline wizards.) Sep 30, 2024 4 - Beta pytest>=8.2.2 @@ -920,7 +925,7 @@ This list contains 1632 plugins. :pypi:`pytest-mitmproxy-plugin` Use MITM Proxy in autotests with full control from code Apr 10, 2025 4 - Beta pytest>=7.2.0 :pypi:`pytest-ml` Test your machine learning! May 04, 2019 4 - Beta N/A :pypi:`pytest-mocha` pytest plugin to display test execution output like a mochajs Apr 02, 2020 4 - Beta pytest (>=5.4.0) - :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest Mar 21, 2024 5 - Production/Stable pytest>=6.2.5 + :pypi:`pytest-mock` Thin-wrapper around the mock package for easier use with pytest May 26, 2025 5 - Production/Stable pytest>=6.2.5 :pypi:`pytest-mock-api` A mock API server with configurable routes and responses available as a fixture. Feb 13, 2019 1 - Planning pytest (>=4.0.0) :pypi:`pytest-mock-generator` A pytest fixture wrapper for https://pypi.org/project/mock-generator May 16, 2022 5 - Production/Stable N/A :pypi:`pytest-mock-helper` Help you mock HTTP call and generate mock code Jan 24, 2018 N/A pytest @@ -1001,7 +1006,7 @@ This list contains 1632 plugins. :pypi:`pytest-object-getter` Import any object from a 3rd party module while mocking its namespace on demand. Jul 31, 2022 5 - Production/Stable pytest :pypi:`pytest-ochrus` pytest results data-base and HTML reporter Feb 21, 2018 4 - Beta N/A :pypi:`pytest-odc` A pytest plugin for simplifying ODC database tests Aug 04, 2023 4 - Beta pytest (>=3.5.0) - :pypi:`pytest-odoo` py.test plugin to run Odoo tests Mar 12, 2025 5 - Production/Stable pytest>=8 + :pypi:`pytest-odoo` py.test plugin to run Odoo tests May 20, 2025 5 - Production/Stable pytest>=8 :pypi:`pytest-odoo-fixtures` Project description Jun 25, 2019 N/A N/A :pypi:`pytest-oerp` pytest plugin to test OpenERP modules Feb 28, 2012 3 - Alpha N/A :pypi:`pytest-offline` Mar 09, 2023 1 - Planning pytest (>=7.0.0,<8.0.0) @@ -1061,7 +1066,7 @@ This list contains 1632 plugins. :pypi:`pytest-performancetotal` A performance plugin for pytest Feb 01, 2025 5 - Production/Stable N/A :pypi:`pytest-persistence` Pytest tool for persistent objects Aug 21, 2024 N/A N/A :pypi:`pytest-pexpect` Pytest pexpect plugin. Aug 13, 2024 4 - Beta pytest>=6.2.0 - :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 11, 2025 5 - Production/Stable pytest>=7.4 + :pypi:`pytest-pg` A tiny plugin for pytest which runs PostgreSQL in Docker May 18, 2025 5 - Production/Stable pytest>=7.4 :pypi:`pytest-pgsql` Pytest plugins and helpers for tests using a Postgres database. May 13, 2020 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-phmdoctest` pytest plugin to test Python examples in Markdown using phmdoctest. Apr 15, 2022 4 - Beta pytest (>=5.4.3) :pypi:`pytest-phoenix-interface` Pytest extension tool for phoenix projects. Mar 19, 2025 N/A N/A @@ -1123,6 +1128,7 @@ This list contains 1632 plugins. :pypi:`pytest-progress` pytest plugin for instant test progress status Jun 18, 2024 5 - Production/Stable pytest>=2.7 :pypi:`pytest-prometheus` Report test pass / failures to a Prometheus PushGateway Oct 03, 2017 N/A N/A :pypi:`pytest-prometheus-pushgateway` Pytest report plugin for Zulip Sep 27, 2022 5 - Production/Stable pytest + :pypi:`pytest-prometheus-pushgw` Pytest plugin to export test metrics to Prometheus Pushgateway May 19, 2025 N/A pytest>=6.0.0 :pypi:`pytest-prosper` Test helpers for Prosper projects Sep 24, 2018 N/A N/A :pypi:`pytest-prysk` Pytest plugin for prysk Dec 10, 2024 4 - Beta pytest>=7.3.2 :pypi:`pytest-pspec` A rspec format reporter for Python ptest Jun 02, 2020 4 - Beta pytest (>=3.0.0) @@ -1200,7 +1206,7 @@ This list contains 1632 plugins. :pypi:`pytest-reference-formatter` Conveniently run pytest with a dot-formatted test reference. Oct 01, 2019 4 - Beta N/A :pypi:`pytest-regex` Select pytest tests with regular expressions May 29, 2023 4 - Beta pytest (>=3.5.0) :pypi:`pytest-regex-dependency` Management of Pytest dependencies via regex patterns Jun 12, 2022 N/A pytest - :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. Jan 10, 2025 5 - Production/Stable pytest>=6.2.0 + :pypi:`pytest-regressions` Easy to use fixtures to write regression tests. May 30, 2025 5 - Production/Stable pytest>=6.2.0 :pypi:`pytest-regtest` pytest plugin for snapshot regression testing Nov 12, 2024 N/A pytest>7.2 :pypi:`pytest-relative-order` a pytest plugin that sorts tests using "before" and "after" markers May 17, 2021 4 - Beta N/A :pypi:`pytest-relative-path` Handle relative path in pytest options or ini configs Aug 30, 2024 N/A pytest @@ -1218,6 +1224,7 @@ This list contains 1632 plugins. :pypi:`pytest-reporter` Generate Pytest reports with templates Feb 28, 2024 4 - Beta pytest :pypi:`pytest-reporter-html1` A basic HTML report template for Pytest May 06, 2025 4 - Beta N/A :pypi:`pytest-reporter-html-dots` A basic HTML report for pytest using Jinja2 template engine. Apr 26, 2025 N/A N/A + :pypi:`pytest-reporter-plus` Lightweight enhanced HTML reporter for Pytest May 31, 2025 N/A N/A :pypi:`pytest-report-extras` Pytest plugin to enhance pytest-html and allure reports by adding comments, screenshots, webpage sources and attachments. Apr 04, 2025 N/A pytest>=8.0.0 :pypi:`pytest-reportinfra` Pytest plugin for reportinfra Aug 11, 2019 3 - Alpha N/A :pypi:`pytest-reporting` A plugin to report summarized results in a table format Oct 25, 2019 4 - Beta pytest (>=3.5.0) @@ -1253,6 +1260,7 @@ This list contains 1632 plugins. :pypi:`pytest-result-notify` Default template for PDM package Apr 27, 2025 N/A pytest>=8.3.5 :pypi:`pytest-results` Easily spot regressions in your tests. May 06, 2025 4 - Beta pytest :pypi:`pytest-result-sender` Apr 20, 2023 N/A pytest>=7.3.1 + :pypi:`pytest-result-sender-jms` Default template for PDM package May 22, 2025 N/A pytest>=8.3.5 :pypi:`pytest-result-sender-lj` Default template for PDM package Dec 17, 2024 N/A pytest>=8.3.4 :pypi:`pytest-result-sender-lyt` Default template for PDM package Mar 14, 2025 N/A pytest>=8.3.5 :pypi:`pytest-result-sender-misszhang` Default template for PDM package Mar 21, 2025 N/A pytest>=8.3.5 @@ -1281,7 +1289,7 @@ This list contains 1632 plugins. :pypi:`pytest-ruff` pytest plugin to check ruff requirements. Jul 21, 2024 4 - Beta pytest>=5 :pypi:`pytest-run-changed` Pytest plugin that runs changed tests only Apr 02, 2021 3 - Alpha pytest :pypi:`pytest-runfailed` implement a --failed option for pytest Mar 24, 2016 N/A N/A - :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently Apr 22, 2025 4 - Beta pytest>=6.2.0 + :pypi:`pytest-run-parallel` A simple pytest plugin to run tests concurrently May 27, 2025 4 - Beta pytest>=6.2.0 :pypi:`pytest-run-subprocess` Pytest Plugin for running and testing subprocesses. Nov 12, 2022 5 - Production/Stable pytest :pypi:`pytest-runtime-types` Checks type annotations on runtime while running tests. Feb 09, 2023 N/A pytest :pypi:`pytest-runtime-xfail` Call runtime_xfail() to mark running test as xfail. Aug 26, 2021 N/A pytest>=5.0.0 @@ -1298,9 +1306,9 @@ This list contains 1632 plugins. :pypi:`pytest-sanity` Dec 07, 2020 N/A N/A :pypi:`pytest-sa-pg` May 14, 2019 N/A N/A :pypi:`pytest_sauce` pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs Jul 14, 2014 3 - Alpha N/A - :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-sbase` A complete web automation framework for end-to-end testing. May 27, 2025 5 - Production/Stable N/A :pypi:`pytest-scenario` pytest plugin for test scenarios Feb 06, 2017 3 - Alpha N/A - :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 13, 2025 5 - Production/Stable pytest>=7.0 + :pypi:`pytest-scenario-files` A pytest plugin that generates unit test scenarios from data files. May 21, 2025 5 - Production/Stable pytest>=7.0 :pypi:`pytest-schedule` Automate and customize test scheduling effortlessly on local machines. Oct 31, 2024 N/A N/A :pypi:`pytest-schema` 👍 Validate return values against a schema-like object in testing Feb 16, 2024 5 - Production/Stable pytest >=3.5.0 :pypi:`pytest-scim2-server` SCIM2 server fixture for Pytest May 14, 2025 4 - Beta pytest>=8.3.4 @@ -1310,12 +1318,12 @@ This list contains 1632 plugins. :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 Feb 01, 2024 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. May 13, 2025 5 - Production/Stable N/A + :pypi:`pytest-seleniumbase` A complete web automation framework for end-to-end testing. May 27, 2025 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-selfie` A pytest plugin for selfie snapshot testing. Dec 16, 2024 N/A pytest>=8.0.0 :pypi:`pytest-send-email` Send pytest execution result email Sep 02, 2024 N/A pytest - :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io Feb 24, 2025 N/A pytest + :pypi:`pytest-sentry` A pytest plugin to send testrun information to Sentry.io May 23, 2025 N/A pytest :pypi:`pytest-sequence-markers` Pytest plugin for sequencing markers for execution of tests May 23, 2023 5 - Production/Stable N/A :pypi:`pytest-server` test server exec cmd Sep 09, 2024 N/A N/A :pypi:`pytest-server-fixtures` Extensible server fixtures for py.test Nov 29, 2024 5 - Production/Stable pytest @@ -1358,7 +1366,7 @@ This list contains 1632 plugins. :pypi:`pytest-smartcollect` A plugin for collecting tests that touch changed code Oct 04, 2018 N/A pytest (>=3.5.0) :pypi:`pytest-smartcov` Smart coverage plugin for pytest. Sep 30, 2017 3 - Alpha N/A :pypi:`pytest-smell` Automated bad smell detection tool for Pytest Jun 26, 2022 N/A N/A - :pypi:`pytest-smoke` Pytest plugin for smoke testing Mar 25, 2025 4 - Beta pytest<9,>=7.0.0 + :pypi:`pytest-smoke` Pytest plugin for smoke testing May 23, 2025 4 - Beta pytest<9,>=7.0.0 :pypi:`pytest-smtp` Send email with pytest execution result Feb 20, 2021 N/A pytest :pypi:`pytest-smtp4dev` Plugin for smtp4dev API Jun 27, 2023 5 - Production/Stable N/A :pypi:`pytest-smtpd` An SMTP server for testing built on aiosmtpd May 15, 2023 N/A pytest @@ -1380,7 +1388,7 @@ This list contains 1632 plugins. :pypi:`pytest-sorter` A simple plugin to first execute tests that historically failed more Apr 20, 2021 4 - Beta pytest (>=3.1.1) :pypi:`pytest-sosu` Unofficial PyTest plugin for Sauce Labs Aug 04, 2023 2 - Pre-Alpha pytest :pypi:`pytest-sourceorder` Test-ordering plugin for pytest Sep 01, 2021 4 - Beta pytest - :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. Mar 21, 2025 4 - Beta pytest + :pypi:`pytest-spark` pytest plugin to run the tests with support of pyspark. May 21, 2025 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. Aug 04, 2024 N/A pytest; extra == "test" :pypi:`pytest-spec2md` Library pytest-spec2md is a pytest plugin to create a markdown specification while running pytest. Apr 10, 2024 N/A pytest>7.0 @@ -1408,7 +1416,7 @@ This list contains 1632 plugins. :pypi:`pytest-srcpaths` Add paths to sys.path Oct 15, 2021 N/A pytest>=6.2.0 :pypi:`pytest-ssh` pytest plugin for ssh command run May 27, 2019 N/A pytest :pypi:`pytest-start-from` Start pytest run from a given point Apr 11, 2016 N/A N/A - :pypi:`pytest-static` pytest-static Oct 20, 2024 1 - Planning pytest<8.0.0,>=7.4.3 + :pypi:`pytest-static` pytest-static May 25, 2025 3 - Alpha pytest<8.0.0,>=7.4.3 :pypi:`pytest-stats` Collects tests metadata for future analysis, easy to extend for any data store Jul 18, 2024 N/A pytest>=8.0.0 :pypi:`pytest-statsd` pytest plugin for reporting to graphite Nov 30, 2018 5 - Production/Stable pytest (>=3.0.0) :pypi:`pytest-status` Add status mark for tests Aug 22, 2024 N/A pytest @@ -1419,7 +1427,7 @@ This list contains 1632 plugins. :pypi:`pytest-stochastics` pytest plugin that allows selectively running tests several times and accepting \*some\* failures. Dec 01, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-stoq` A plugin to pytest stoq Feb 09, 2021 4 - Beta N/A :pypi:`pytest-store` Pytest plugin to store values from test runs Sep 04, 2024 3 - Alpha pytest>=7.0.0 - :pypi:`pytest-streaming` Plugin for testing pubsub, pulsar, and kafka systems with pytest locally and in ci/cd May 16, 2025 N/A pytest>=8.3.5 + :pypi:`pytest-streaming` Plugin for testing pubsub, pulsar, and kafka systems with pytest locally and in ci/cd May 28, 2025 5 - Production/Stable pytest>=8.3.5 :pypi:`pytest-stress` A Pytest plugin that allows you to loop tests for a user defined amount of time. Dec 07, 2019 4 - Beta pytest (>=3.6.0) :pypi:`pytest-structlog` Structured logging assertions Jul 25, 2024 N/A pytest :pypi:`pytest-structmpd` provide structured temporary directory Oct 17, 2018 N/A N/A @@ -1552,10 +1560,11 @@ This list contains 1632 plugins. :pypi:`pytest-twilio-conversations-client-mock` Aug 02, 2022 N/A N/A :pypi:`pytest-twisted` A twisted plugin for pytest. Sep 10, 2024 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-typed-schema-shot` Pytest plugin for automatic JSON Schema generation and validation from examples May 24, 2025 N/A pytest :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 Feb 01, 2024 4 - Beta N/A :pypi:`pytest-typhoon-xray` Typhoon HIL plugin for pytest Aug 15, 2023 4 - Beta N/A - :pypi:`pytest-typing-runner` Pytest plugin to make it easier to run and check python code against static type checkers Oct 27, 2024 N/A N/A + :pypi:`pytest-typing-runner` Pytest plugin to make it easier to run and check python code against static type checkers May 31, 2025 N/A N/A :pypi:`pytest-tytest` Typhoon HIL plugin for pytest May 25, 2020 4 - Beta pytest (>=5.4.2) :pypi:`pytest-ubersmith` Easily mock calls to ubersmith at the \`requests\` level. Apr 13, 2015 N/A N/A :pypi:`pytest-ui` Text User Interface for running python tests Jul 05, 2021 4 - Beta pytest @@ -1618,7 +1627,7 @@ This list contains 1632 plugins. :pypi:`pytest-with-docker` pytest with docker helpers. Nov 09, 2021 N/A pytest :pypi:`pytest-workaround-12888` forces an import of readline early in the process to work around pytest bug #12888 Jan 15, 2025 N/A N/A :pypi:`pytest-workflow` A pytest plugin for configuring workflow/pipeline tests using YAML files Mar 18, 2024 5 - Production/Stable pytest >=7.0.0 - :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs Apr 28, 2024 5 - Production/Stable pytest>=7.0.0 + :pypi:`pytest-xdist` pytest xdist plugin for distributed testing, most importantly across multiple CPUs May 26, 2025 5 - Production/Stable pytest>=7.0.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-lock` Extension for pytest-xdist adding test and resource group locks for local and distributed runs Apr 26, 2025 N/A pytest>=6.0 @@ -1636,7 +1645,7 @@ This list contains 1632 plugins. :pypi:`pytest-xprocess` A pytest plugin for managing processes across test runs. May 19, 2024 4 - Beta pytest>=2.8 :pypi:`pytest-xray` May 30, 2019 3 - Alpha N/A :pypi:`pytest-xrayjira` Mar 17, 2020 3 - Alpha pytest (==4.3.1) - :pypi:`pytest-xray-reporter` A pytest plugin that generates test results in Xray JSON format May 08, 2025 4 - Beta pytest>=7.0.0 + :pypi:`pytest-xray-reporter` Pytest plugin for generating Xray JSON reports May 21, 2025 4 - Beta pytest>=7.0.0 :pypi:`pytest-xray-server` May 03, 2022 3 - Alpha pytest (>=5.3.1) :pypi:`pytest-xstress` Jun 01, 2024 N/A pytest<9.0.0,>=8.0.0 :pypi:`pytest-xvfb` A pytest plugin to run Xvfb (or Xephyr/Xvnc) for tests. Mar 12, 2025 4 - Beta pytest>=2.8.1 @@ -1875,7 +1884,7 @@ This list contains 1632 plugins. :pypi:`pytest-alembic` - *last release*: May 16, 2025, + *last release*: May 27, 2025, *status*: N/A, *requires*: pytest>=7.0 @@ -1994,7 +2003,7 @@ This list contains 1632 plugins. Pytest plugin to allow use of Annotated in tests to resolve fixtures :pypi:`pytest-ansible` - *last release*: Apr 28, 2025, + *last release*: May 26, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6 @@ -2252,6 +2261,13 @@ This list contains 1632 plugins. pytest-async - Run your coroutine in event loop without decorator + :pypi:`pytest-async-benchmark` + *last release*: May 28, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + pytest-async-benchmark: Modern pytest benchmarking for async code. 🚀 + :pypi:`pytest-async-generators` *last release*: Jul 05, 2023, *status*: N/A, @@ -2260,7 +2276,7 @@ This list contains 1632 plugins. Pytest fixtures for async generators :pypi:`pytest-asyncio` - *last release*: May 09, 2025, + *last release*: May 26, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=8.2 @@ -2568,7 +2584,7 @@ This list contains 1632 plugins. Pytest plugin to run your tests with beartype checking enabled. :pypi:`pytest-bec-e2e` - *last release*: May 13, 2025, + *last release*: May 30, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -2952,6 +2968,13 @@ This list contains 1632 plugins. pytest plugin to capture all deprecatedwarnings and put them in one file + :pypi:`pytest-capture-sysout` + *last release*: May 21, 2025, + *status*: 2 - Pre-Alpha, + *requires*: N/A + + An academic experiment package + :pypi:`pytest-capture-warnings` *last release*: May 03, 2022, *status*: N/A, @@ -3008,6 +3031,13 @@ This list contains 1632 plugins. Pytest plugin for Celery + :pypi:`pytest-celery-py37` + *last release*: May 23, 2025, + *status*: 5 - Production/Stable, + *requires*: N/A + + Pytest plugin for Celery (compatible with python 3.7) + :pypi:`pytest-cfg-fetcher` *last release*: Feb 26, 2024, *status*: N/A, @@ -3107,7 +3137,7 @@ This list contains 1632 plugins. Check links in files :pypi:`pytest-checklist` - *last release*: May 07, 2025, + *last release*: May 23, 2025, *status*: N/A, *requires*: N/A @@ -3394,7 +3424,7 @@ This list contains 1632 plugins. pytest plugin to run pycodestyle :pypi:`pytest-codspeed` - *last release*: Jan 31, 2025, + *last release*: May 27, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=3.8 @@ -3695,9 +3725,9 @@ This list contains 1632 plugins. CSV output for pytest. :pypi:`pytest-csv-params` - *last release*: Oct 25, 2024, + *last release*: May 29, 2025, *status*: 5 - Production/Stable, - *requires*: pytest<9.0.0,>=8.3.0 + *requires*: pytest<9,>=8.3 Pytest plugin for Test Case Parametrization with CSV files @@ -3800,7 +3830,7 @@ This list contains 1632 plugins. pytest fixtures to run dash applications. :pypi:`pytest-dashboard` - *last release*: May 30, 2024, + *last release*: May 20, 2025, *status*: N/A, *requires*: pytest<8.0.0,>=7.4.3 @@ -3814,7 +3844,7 @@ This list contains 1632 plugins. Useful functions for managing data for pytest fixtures :pypi:`pytest-databases` - *last release*: Apr 21, 2025, + *last release*: May 25, 2025, *status*: 4 - Beta, *requires*: pytest @@ -3828,7 +3858,7 @@ This list contains 1632 plugins. Pytest plugin for remote Databricks notebooks testing :pypi:`pytest-datadir` - *last release*: Feb 07, 2025, + *last release*: May 30, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -4395,7 +4425,7 @@ This list contains 1632 plugins. An RST Documentation Generator for pytest-based test suites :pypi:`pytest-docker` - *last release*: Apr 07, 2025, + *last release*: May 26, 2025, *status*: N/A, *requires*: pytest<9.0,>=4.0 @@ -4675,7 +4705,7 @@ This list contains 1632 plugins. A Pytest plugin to ignore tests during collection without reporting them in the test summary. :pypi:`pytest-dsl` - *last release*: May 07, 2025, + *last release*: May 29, 2025, *status*: N/A, *requires*: pytest>=7.0.0 @@ -5045,6 +5075,13 @@ This list contains 1632 plugins. pytest plugin to mark a test as xfailed if it fails with the specified error message in the captured output + :pypi:`pytest-essentials` + *last release*: May 19, 2025, + *status*: 3 - Alpha, + *requires*: pytest>=7.0 + + A Pytest plugin providing essential utilities like soft assertions. + :pypi:`pytest-eth` *last release*: Aug 14, 2020, *status*: 1 - Planning, @@ -5732,7 +5769,7 @@ This list contains 1632 plugins. A pytest plugin in order to provide logs via fluentbit :pypi:`pytest-fly` - *last release*: May 03, 2025, + *last release*: May 19, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -5963,7 +6000,7 @@ This list contains 1632 plugins. For finding/executing Ghost Inspector tests :pypi:`pytest-girder` - *last release*: May 08, 2025, + *last release*: May 29, 2025, *status*: N/A, *requires*: pytest>=3.6 @@ -6102,6 +6139,13 @@ This list contains 1632 plugins. Notify google chat channel for test results + :pypi:`pytest-google-cloud-storage` + *last release*: May 22, 2025, + *status*: N/A, + *requires*: pytest==8.3.5 + + Pytest custom features, e.g. fixtures and various tests. Aimed to emulate Google Cloud Storage service + :pypi:`pytest-gradescope` *last release*: Apr 29, 2025, *status*: N/A, @@ -6278,7 +6322,7 @@ This list contains 1632 plugins. A pytest plugin for use with homeassistant custom components. :pypi:`pytest-homeassistant-custom-component` - *last release*: May 17, 2025, + *last release*: May 30, 2025, *status*: 3 - Alpha, *requires*: pytest==8.3.5 @@ -6565,7 +6609,7 @@ This list contains 1632 plugins. A pytest plugin for image snapshot management and comparison. :pypi:`pytest-impacted` - *last release*: May 15, 2025, + *last release*: May 31, 2025, *status*: 4 - Beta, *requires*: pytest>=8.0.0 @@ -6670,7 +6714,7 @@ This list contains 1632 plugins. A py.test plugin providing fixtures to simplify inmanta modules testing. :pypi:`pytest-inmanta-extensions` - *last release*: Apr 10, 2025, + *last release*: May 27, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -6817,7 +6861,7 @@ This list contains 1632 plugins. Pytest plugin to run tests in Jupyter Notebooks :pypi:`pytest-ipywidgets` - *last release*: Apr 30, 2025, + *last release*: May 30, 2025, *status*: N/A, *requires*: pytest @@ -6831,7 +6875,7 @@ This list contains 1632 plugins. Plugin for pytest to produce test documentation for code audits. :pypi:`pytest-isolate` - *last release*: Apr 22, 2025, + *last release*: May 22, 2025, *status*: 4 - Beta, *requires*: pytest @@ -6936,7 +6980,7 @@ This list contains 1632 plugins. Plugin skips (xfail) tests if unresolved Jira issue(s) linked :pypi:`pytest-jira-xray` - *last release*: Oct 27, 2024, + *last release*: May 24, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.4 @@ -7223,7 +7267,7 @@ This list contains 1632 plugins. It helps to use fixtures in pytest.mark.parametrize :pypi:`pytest-lazy-fixtures` - *last release*: Jan 25, 2025, + *last release*: May 27, 2025, *status*: N/A, *requires*: pytest>=7 @@ -7272,7 +7316,7 @@ This list contains 1632 plugins. Select tests of a given level or lower :pypi:`pytest-lf-skip` - *last release*: May 06, 2025, + *last release*: May 26, 2025, *status*: 4 - Beta, *requires*: pytest>=8.3.5 @@ -7468,7 +7512,7 @@ This list contains 1632 plugins. :pypi:`pytest-logging-strict` - *last release*: Apr 09, 2025, + *last release*: May 20, 2025, *status*: 3 - Alpha, *requires*: pytest @@ -7874,7 +7918,7 @@ This list contains 1632 plugins. pytest plugin to display test execution output like a mochajs :pypi:`pytest-mock` - *last release*: Mar 21, 2024, + *last release*: May 26, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6.2.5 @@ -8441,7 +8485,7 @@ This list contains 1632 plugins. A pytest plugin for simplifying ODC database tests :pypi:`pytest-odoo` - *last release*: Mar 12, 2025, + *last release*: May 20, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=8 @@ -8861,7 +8905,7 @@ This list contains 1632 plugins. Pytest pexpect plugin. :pypi:`pytest-pg` - *last release*: May 11, 2025, + *last release*: May 18, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.4 @@ -9294,6 +9338,13 @@ This list contains 1632 plugins. Pytest report plugin for Zulip + :pypi:`pytest-prometheus-pushgw` + *last release*: May 19, 2025, + *status*: N/A, + *requires*: pytest>=6.0.0 + + Pytest plugin to export test metrics to Prometheus Pushgateway + :pypi:`pytest-prosper` *last release*: Sep 24, 2018, *status*: N/A, @@ -9834,7 +9885,7 @@ This list contains 1632 plugins. Management of Pytest dependencies via regex patterns :pypi:`pytest-regressions` - *last release*: Jan 10, 2025, + *last release*: May 30, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=6.2.0 @@ -9959,6 +10010,13 @@ This list contains 1632 plugins. A basic HTML report for pytest using Jinja2 template engine. + :pypi:`pytest-reporter-plus` + *last release*: May 31, 2025, + *status*: N/A, + *requires*: N/A + + Lightweight enhanced HTML reporter for Pytest + :pypi:`pytest-report-extras` *last release*: Apr 04, 2025, *status*: N/A, @@ -10204,6 +10262,13 @@ This list contains 1632 plugins. + :pypi:`pytest-result-sender-jms` + *last release*: May 22, 2025, + *status*: N/A, + *requires*: pytest>=8.3.5 + + Default template for PDM package + :pypi:`pytest-result-sender-lj` *last release*: Dec 17, 2024, *status*: N/A, @@ -10401,7 +10466,7 @@ This list contains 1632 plugins. implement a --failed option for pytest :pypi:`pytest-run-parallel` - *last release*: Apr 22, 2025, + *last release*: May 27, 2025, *status*: 4 - Beta, *requires*: pytest>=6.2.0 @@ -10520,7 +10585,7 @@ This list contains 1632 plugins. pytest_sauce provides sane and helpful methods worked out in clearcode to run py.test tests with selenium/saucelabs :pypi:`pytest-sbase` - *last release*: May 13, 2025, + *last release*: May 27, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10534,7 +10599,7 @@ This list contains 1632 plugins. pytest plugin for test scenarios :pypi:`pytest-scenario-files` - *last release*: May 13, 2025, + *last release*: May 21, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0 @@ -10604,7 +10669,7 @@ This list contains 1632 plugins. pytest plugin to automatically capture screenshots upon selenium webdriver events :pypi:`pytest-seleniumbase` - *last release*: May 13, 2025, + *last release*: May 27, 2025, *status*: 5 - Production/Stable, *requires*: N/A @@ -10639,7 +10704,7 @@ This list contains 1632 plugins. Send pytest execution result email :pypi:`pytest-sentry` - *last release*: Feb 24, 2025, + *last release*: May 23, 2025, *status*: N/A, *requires*: pytest @@ -10940,7 +11005,7 @@ This list contains 1632 plugins. Automated bad smell detection tool for Pytest :pypi:`pytest-smoke` - *last release*: Mar 25, 2025, + *last release*: May 23, 2025, *status*: 4 - Beta, *requires*: pytest<9,>=7.0.0 @@ -11094,7 +11159,7 @@ This list contains 1632 plugins. Test-ordering plugin for pytest :pypi:`pytest-spark` - *last release*: Mar 21, 2025, + *last release*: May 21, 2025, *status*: 4 - Beta, *requires*: pytest @@ -11290,8 +11355,8 @@ This list contains 1632 plugins. Start pytest run from a given point :pypi:`pytest-static` - *last release*: Oct 20, 2024, - *status*: 1 - Planning, + *last release*: May 25, 2025, + *status*: 3 - Alpha, *requires*: pytest<8.0.0,>=7.4.3 pytest-static @@ -11367,8 +11432,8 @@ This list contains 1632 plugins. Pytest plugin to store values from test runs :pypi:`pytest-streaming` - *last release*: May 16, 2025, - *status*: N/A, + *last release*: May 28, 2025, + *status*: 5 - Production/Stable, *requires*: pytest>=8.3.5 Plugin for testing pubsub, pulsar, and kafka systems with pytest locally and in ci/cd @@ -12297,6 +12362,13 @@ This list contains 1632 plugins. Run type checkers on specified test files + :pypi:`pytest-typed-schema-shot` + *last release*: May 24, 2025, + *status*: N/A, + *requires*: pytest + + Pytest plugin for automatic JSON Schema generation and validation from examples + :pypi:`pytest-typhoon-config` *last release*: Apr 07, 2022, *status*: 5 - Production/Stable, @@ -12319,7 +12391,7 @@ This list contains 1632 plugins. Typhoon HIL plugin for pytest :pypi:`pytest-typing-runner` - *last release*: Oct 27, 2024, + *last release*: May 31, 2025, *status*: N/A, *requires*: N/A @@ -12760,7 +12832,7 @@ This list contains 1632 plugins. A pytest plugin for configuring workflow/pipeline tests using YAML files :pypi:`pytest-xdist` - *last release*: Apr 28, 2024, + *last release*: May 26, 2025, *status*: 5 - Production/Stable, *requires*: pytest>=7.0.0 @@ -12886,11 +12958,11 @@ This list contains 1632 plugins. :pypi:`pytest-xray-reporter` - *last release*: May 08, 2025, + *last release*: May 21, 2025, *status*: 4 - Beta, *requires*: pytest>=7.0.0 - A pytest plugin that generates test results in Xray JSON format + Pytest plugin for generating Xray JSON reports :pypi:`pytest-xray-server` *last release*: May 03, 2022, From 0ccb57904fea0a179ff4c2ae8195fc65d08d10eb Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 22:14:02 +0300 Subject: [PATCH 1227/1271] python: a bit nicer error on duplicate parametrization Raising `ValueError` dumps all of the internal stacktrace to the user, which is not helpful. Raising `CollectError` is handled specially to just print the message. It would be nice to show source location or such - maybe another time. Fix #13457 --- changelog/13457.improvement.rst | 1 + src/_pytest/python.py | 4 +++- testing/python/metafunc.py | 12 ++++++++---- 3 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 changelog/13457.improvement.rst diff --git a/changelog/13457.improvement.rst b/changelog/13457.improvement.rst new file mode 100644 index 00000000000..3937384b322 --- /dev/null +++ b/changelog/13457.improvement.rst @@ -0,0 +1 @@ +The error message about duplicate parametrization no longer displays an internal stack trace. diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 1e085a80529..02b71767dc2 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1079,7 +1079,9 @@ def setmulti( arg2scope = dict(self._arg2scope) for arg, val in zip(argnames, valset): if arg in params: - raise ValueError(f"duplicate parametrization of {arg!r}") + raise nodes.Collector.CollectError( + f"duplicate parametrization of {arg!r}" + ) params[arg] = val indices[arg] = param_index arg2scope[arg] = scope diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index e8b345aecc6..7ae26de3a18 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -82,11 +82,15 @@ def func(x, y): metafunc = self.Metafunc(func) metafunc.parametrize("x", [1, 2]) - pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6])) - pytest.raises(ValueError, lambda: metafunc.parametrize("x", [5, 6])) + with pytest.raises(pytest.Collector.CollectError): + metafunc.parametrize("x", [5, 6]) + with pytest.raises(pytest.Collector.CollectError): + metafunc.parametrize("x", [5, 6]) metafunc.parametrize("y", [1, 2]) - pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6])) - pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5, 6])) + with pytest.raises(pytest.Collector.CollectError): + metafunc.parametrize("y", [5, 6]) + with pytest.raises(pytest.Collector.CollectError): + metafunc.parametrize("y", [5, 6]) with pytest.raises(TypeError, match="^ids must be a callable or an iterable$"): metafunc.parametrize("y", [5, 6], ids=42) # type: ignore[arg-type] From b6e81441b35a94852c554ec7433a1f88e7235eb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 06:20:21 +0200 Subject: [PATCH 1228/1271] build(deps): Bump pytest-mock in /testing/plugins_integration (#13460) Bumps [pytest-mock](https://github.com/pytest-dev/pytest-mock) from 3.14.0 to 3.14.1. - [Release notes](https://github.com/pytest-dev/pytest-mock/releases) - [Changelog](https://github.com/pytest-dev/pytest-mock/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pytest-dev/pytest-mock/compare/v3.14.0...v3.14.1) --- updated-dependencies: - dependency-name: pytest-mock dependency-version: 3.14.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index b8b07fc8ad9..d467e481f58 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -6,7 +6,7 @@ pytest-cov==6.1.1 pytest-django==4.11.1 pytest-flakes==4.0.5 pytest-html==4.1.1 -pytest-mock==3.14.0 +pytest-mock==3.14.1 pytest-rerunfailures==15.1 pytest-sugar==1.0.0 pytest-trio==0.8.0 From 30407eb7613bcafd8651beb047a8a2fc215409ab Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 2 Jun 2025 11:22:07 +0300 Subject: [PATCH 1229/1271] python: pinpoint nodeid in a couple of parametrization errors --- src/_pytest/python.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 02b71767dc2..82aab85a300 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -1073,6 +1073,7 @@ def setmulti( marks: Iterable[Mark | MarkDecorator], scope: Scope, param_index: int, + nodeid: str, ) -> CallSpec2: params = self.params.copy() indices = self.indices.copy() @@ -1080,7 +1081,7 @@ def setmulti( for arg, val in zip(argnames, valset): if arg in params: raise nodes.Collector.CollectError( - f"duplicate parametrization of {arg!r}" + f"{nodeid}: duplicate parametrization of {arg!r}" ) params[arg] = val indices[arg] = param_index @@ -1235,6 +1236,8 @@ def parametrize( It will also override any fixture-function defined scope, allowing to set a dynamic scope using test context or configuration. """ + nodeid = self.definition.nodeid + argnames, parametersets = ParameterSet._for_parametrize( argnames, argvalues, @@ -1246,7 +1249,7 @@ def parametrize( if "request" in argnames: fail( - "'request' is a reserved name and cannot be used in @pytest.mark.parametrize", + f"{nodeid}: 'request' is a reserved name and cannot be used in @pytest.mark.parametrize", pytrace=False, ) @@ -1341,6 +1344,7 @@ def parametrize( marks=param_set.marks, scope=scope_, param_index=param_index, + nodeid=nodeid, ) newcalls.append(newcallspec) self._calls = newcalls From 52dccfd2a8c32a7dd869c5bb7eeba0d1a0858a65 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 2 Jun 2025 12:01:37 +0300 Subject: [PATCH 1230/1271] coverage: ignore `def foo(): ...` lines These often appear in Protocols and ABCs and are never executed so not expected to be covered. --- .coveragerc | 1 + 1 file changed, 1 insertion(+) diff --git a/.coveragerc b/.coveragerc index b810471417f..d39d3d5f02b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -29,5 +29,6 @@ exclude_lines = ^\s*if TYPE_CHECKING: ^\s*@overload( |$) + ^\s*def .+: \.\.\.$ ^\s*@pytest\.mark\.xfail From 3b0e463febb416af622ac5a01eeb79d379177553 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 22:12:34 +0300 Subject: [PATCH 1231/1271] assertion: add a Protocol for rewrite hook Mostly to fix the TODO, doesn't have much semantic meaning. Also fixes a related typo in import inside `TYPE_CHECKING` block. --- src/_pytest/assertion/__init__.py | 14 +++++++++----- src/_pytest/config/__init__.py | 7 ++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/_pytest/assertion/__init__.py b/src/_pytest/assertion/__init__.py index 532b96fe431..22f3ca8e258 100644 --- a/src/_pytest/assertion/__init__.py +++ b/src/_pytest/assertion/__init__.py @@ -6,6 +6,7 @@ from collections.abc import Generator import sys from typing import Any +from typing import Protocol from typing import TYPE_CHECKING from _pytest.assertion import rewrite @@ -82,15 +83,18 @@ def register_assert_rewrite(*names: str) -> None: if not isinstance(name, str): msg = "expected module names as *args, got {0} instead" # type: ignore[unreachable] raise TypeError(msg.format(repr(names))) + rewrite_hook: RewriteHook for hook in sys.meta_path: if isinstance(hook, rewrite.AssertionRewritingHook): - importhook = hook + rewrite_hook = hook break else: - # TODO(typing): Add a protocol for mark_rewrite() and use it - # for importhook and for PytestPluginManager.rewrite_hook. - importhook = DummyRewriteHook() # type: ignore - importhook.mark_rewrite(*names) + rewrite_hook = DummyRewriteHook() + rewrite_hook.mark_rewrite(*names) + + +class RewriteHook(Protocol): + def mark_rewrite(self, *names: str) -> None: ... class DummyRewriteHook: diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 56b04719641..2ad613308b7 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -70,7 +70,7 @@ if TYPE_CHECKING: - from _pytest.assertions.rewrite import AssertionRewritingHook + from _pytest.assertion.rewrite import AssertionRewritingHook from _pytest.cacheprovider import Cache from _pytest.terminal import TerminalReporter @@ -397,7 +397,8 @@ class PytestPluginManager(PluginManager): """ def __init__(self) -> None: - import _pytest.assertion + from _pytest.assertion import DummyRewriteHook + from _pytest.assertion import RewriteHook super().__init__("pytest") @@ -443,7 +444,7 @@ def __init__(self) -> None: self.enable_tracing() # Config._consider_importhook will set a real object if required. - self.rewrite_hook = _pytest.assertion.DummyRewriteHook() + self.rewrite_hook: RewriteHook = DummyRewriteHook() # Used to know when we are importing conftests after the pytest_configure stage. self._configured = False From 69c47cea4d5725328a79e4ec648c6cd044c44e7d Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 22:28:47 +0300 Subject: [PATCH 1232/1271] tmpdir: remove an unneeded assignment It's not different from the `tmp_path_factory` already requested via fixture. --- src/_pytest/tmpdir.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_pytest/tmpdir.py b/src/_pytest/tmpdir.py index c5b51c87741..dcd5784f88f 100644 --- a/src/_pytest/tmpdir.py +++ b/src/_pytest/tmpdir.py @@ -265,7 +265,6 @@ def tmp_path( yield path # Remove the tmpdir if the policy is "failed" and the test passed. - tmp_path_factory: TempPathFactory = request.session.config._tmp_path_factory # type: ignore policy = tmp_path_factory._retention_policy result_dict = request.node.stash[tmppath_result_key] From 0e734c734a28102bf2d4489b0a200f545bfcaebf Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 22:44:01 +0300 Subject: [PATCH 1233/1271] config: add a couple of explicit `Any`s pyright (somewhat annoyingly IMO) infers unannotated function types, unlike mypy which treats them as `Any`. In these 2 cases it causes some follow on type errors, so add explicit `Any`s to prevent pyright from inferring some big union. --- src/_pytest/config/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 2ad613308b7..db5d898ee35 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -1582,7 +1582,7 @@ def addinivalue_line(self, name: str, line: str) -> None: assert isinstance(x, list) x.append(line) # modifies the cached list inline - def getini(self, name: str): + def getini(self, name: str) -> Any: """Return configuration value from an :ref:`ini file `. If a configuration value is not defined in an @@ -1726,7 +1726,7 @@ def _get_override_ini_value(self, name: str) -> str | None: value = user_ini_value return value - def getoption(self, name: str, default=notset, skip: bool = False): + def getoption(self, name: str, default: Any = notset, skip: bool = False): """Return command line option value. :param name: Name of the option. You may also specify From b5c0b8537932e8dbd62787cef9b3113402885478 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 22:58:59 +0300 Subject: [PATCH 1234/1271] config: fix a type error in pyright due to different narrowing rules For some reason pyright infers the type of `essential_plugins` and `default_plugins` as `tuple[Literal[...], ...]` even if they are explicitly annotated as `tuple[str, ...]`. This then causes an error in the `builtin_plugins.add` calls. Replace with one-shot initialization appeases pyright and is nicer regardless. --- src/_pytest/config/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index db5d898ee35..796beee3266 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -273,9 +273,11 @@ def directory_arg(path: str, optname: str) -> str: "faulthandler", ) -builtin_plugins = set(default_plugins) -builtin_plugins.add("pytester") -builtin_plugins.add("pytester_assertions") +builtin_plugins = { + *default_plugins, + "pytester", + "pytester_assertions", +} def get_config( From b42a5d2f3ebba21dc26b329637e8beb1826d7ac5 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 23:11:34 +0300 Subject: [PATCH 1235/1271] config: use casts for legacy hook marks instead of type ignores This is the expected case for casts -- the correct type is ensured dynamically, just too complicated for a type checker to understand. --- src/_pytest/config/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index 796beee3266..468018fadc0 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -472,9 +472,10 @@ def parse_hookimpl_opts( if not inspect.isroutine(method): return None # Collect unmarked hooks as long as they have the `pytest_' prefix. - return _get_legacy_hook_marks( # type: ignore[return-value] + legacy = _get_legacy_hook_marks( method, "impl", ("tryfirst", "trylast", "optionalhook", "hookwrapper") ) + return cast(HookimplOpts, legacy) def parse_hookspec_opts(self, module_or_class, name: str) -> HookspecOpts | None: """:meta private:""" @@ -482,11 +483,10 @@ def parse_hookspec_opts(self, module_or_class, name: str) -> HookspecOpts | None if opts is None: method = getattr(module_or_class, name) if name.startswith("pytest_"): - opts = _get_legacy_hook_marks( # type: ignore[assignment] - method, - "spec", - ("firstresult", "historic"), + legacy = _get_legacy_hook_marks( + method, "spec", ("firstresult", "historic") ) + opts = cast(HookspecOpts, legacy) return opts def register(self, plugin: _PluggyPlugin, name: str | None = None) -> str | None: From 0c4ed3133fdbda112275a6602a4a99f4c0d6fbc7 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 23:37:36 +0300 Subject: [PATCH 1236/1271] raises: remove redundant type annotation Pyright complains: Type annotation for "self" parameter of "__init__" method cannot contain class-scoped type variables (reportInvalidTypeVarUse) and I figure it's not needed since it's already the type of `self`. --- src/_pytest/raises.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/raises.py b/src/_pytest/raises.py index 2eba53bf10b..8c2fca9f919 100644 --- a/src/_pytest/raises.py +++ b/src/_pytest/raises.py @@ -588,7 +588,7 @@ class RaisesExc(AbstractRaises[BaseExcT_co_default]): # At least one of the three parameters must be passed. @overload def __init__( - self: RaisesExc[BaseExcT_co_default], + self, expected_exception: ( type[BaseExcT_co_default] | tuple[type[BaseExcT_co_default], ...] ), From 513c5ebd89c952e8b0437fab714f47ecbb5d4822 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 23:40:07 +0300 Subject: [PATCH 1237/1271] raises: avoid breaking type string to multiple lines Pyright doesn't handle this. --- src/_pytest/raises.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/_pytest/raises.py b/src/_pytest/raises.py index 8c2fca9f919..d896564ddcc 100644 --- a/src/_pytest/raises.py +++ b/src/_pytest/raises.py @@ -969,9 +969,7 @@ def __init__( # that are *very* hard to reconcile while adhering to the overloads, so we cast # it to avoid an error when passing it to super().__init__ check = cast( - "Callable[[" - "BaseExceptionGroup[ExcT_1|BaseExcT_1|BaseExceptionGroup[BaseExcT_2]]" - "], bool]", + "Callable[[BaseExceptionGroup[ExcT_1|BaseExcT_1|BaseExceptionGroup[BaseExcT_2]]], bool]", check, ) super().__init__(match=match, check=check) From b256fc448b744f3b1a5fb027143f1555b677d30b Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 23:47:10 +0300 Subject: [PATCH 1238/1271] raises: replace ineffective type annotations There is not much reason to use `TypeGuard` on the implementation function of an `@overload`ed function, since only the types of the overloads are used. This fixes a pyright "Overloaded implementation is not consistent with signature of overload" error. --- src/_pytest/raises.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/raises.py b/src/_pytest/raises.py index d896564ddcc..480ae33647f 100644 --- a/src/_pytest/raises.py +++ b/src/_pytest/raises.py @@ -1105,7 +1105,7 @@ def matches( def matches( self, exception: BaseException | None, - ) -> TypeGuard[BaseExceptionGroup[BaseExcT_co]]: + ) -> bool: """Check if an exception matches the requirements of this RaisesGroup. If it fails, `RaisesGroup.fail_reason` will be set. @@ -1269,7 +1269,7 @@ def _check_exceptions( self, _exception: BaseException, actual_exceptions: Sequence[BaseException], - ) -> TypeGuard[BaseExceptionGroup[BaseExcT_co]]: + ) -> bool: """Helper method for RaisesGroup.matches that attempts to pair up expected and actual exceptions""" # The _exception parameter is not used, but necessary for the TypeGuard From 9aa198bdef285d007305fb14c25d81e9996be518 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 23:58:19 +0300 Subject: [PATCH 1239/1271] mark/expression: fix self -> cls --- src/_pytest/mark/expression.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/mark/expression.py b/src/_pytest/mark/expression.py index b71ed29c62f..743a46bcc17 100644 --- a/src/_pytest/mark/expression.py +++ b/src/_pytest/mark/expression.py @@ -305,7 +305,7 @@ def __init__(self, code: types.CodeType) -> None: self.code = code @classmethod - def compile(self, input: str) -> Expression: + def compile(cls, input: str) -> Expression: """Compile a match expression. :param input: The input expression - one line. From 9fc6db9a550544ce4fb1f889dde3cf1165e7e337 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 23:58:45 +0300 Subject: [PATCH 1240/1271] pytester: avoid confusing `x` self parameter --- src/_pytest/pytester.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 11127a88bb8..38f4643bd8b 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1116,7 +1116,8 @@ def inline_run( rec = [] class Collect: - def pytest_configure(x, config: Config) -> None: + @staticmethod + def pytest_configure(config: Config) -> None: rec.append(self.make_hook_recorder(config.pluginmanager)) plugins.append(Collect()) From 7a481812a28b141171141abf39cc9bf351e0cbe1 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sun, 1 Jun 2025 22:25:13 +0300 Subject: [PATCH 1241/1271] Add pyright configuration For manual testing, as we are not yet passing. --- .pre-commit-config.yaml | 18 ++++++++++++++++++ pyproject.toml | 14 ++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a07475da467..149f7e6af59 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,6 +47,24 @@ repos: # for mypy running on python>=3.11 since exceptiongroup is only a dependency # on <3.11 - exceptiongroup>=1.0.0rc8 +- repo: https://github.com/RobertCraigie/pyright-python + rev: v1.1.401 + hooks: + - id: pyright + files: ^(src/|scripts/) + additional_dependencies: + - iniconfig>=1.1.0 + - attrs>=19.2.0 + - pluggy>=1.5.0 + - packaging + - tomli + - types-setuptools + - types-tabulate + # for mypy running on python>=3.11 since exceptiongroup is only a dependency + # on <3.11 + - exceptiongroup>=1.0.0rc8 + # Manual because passing pyright is a work in progress. + stages: [manual] - repo: https://github.com/tox-dev/pyproject-fmt rev: "v2.6.0" hooks: diff --git a/pyproject.toml b/pyproject.toml index 4d4055147d8..1e9665add02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -528,3 +528,17 @@ warn_unreachable = true warn_unused_configs = true no_implicit_reexport = true warn_unused_ignores = true + +[tool.pyright] +include = [ + "src", + "testing", + "scripts", +] +extraPaths = [ + "src", +] +pythonVersion = "3.9" +typeCheckingMode = "basic" +reportMissingImports = "none" +reportMissingModuleSource = "none" From 4c205cfcb08083a2893e07b6d994bd38d183b64a Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 2 Jun 2025 14:52:08 +0300 Subject: [PATCH 1242/1271] testing/plugins_integration: update Django (#13463) Fix some dependabot security notices. For some reason dependabot doesn't manage to create a PR for it on its own. --- testing/plugins_integration/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/plugins_integration/requirements.txt b/testing/plugins_integration/requirements.txt index d467e481f58..e8010b23113 100644 --- a/testing/plugins_integration/requirements.txt +++ b/testing/plugins_integration/requirements.txt @@ -1,5 +1,5 @@ anyio[trio]==4.9.0 -django==5.1.7 +django==5.2.1 pytest-asyncio==0.26.0 pytest-bdd==8.1.0 pytest-cov==6.1.1 From 64b230119cb7c260e1e6ec6887ebc5b3851d39fc Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Mon, 2 Jun 2025 15:43:30 +0300 Subject: [PATCH 1243/1271] scripts/release: add missing `build` to `towncrier` call Probably a new thing, but without it it just succeeds without doing anything. --- scripts/release.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/release.py b/scripts/release.py index aef5d6d5f73..6549cd00a3d 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -121,7 +121,7 @@ def pre_release( def changelog(version: str, write_out: bool = False) -> None: addopts = [] if write_out else ["--draft"] - check_call(["towncrier", "--yes", "--version", version, *addopts]) + check_call(["towncrier", "build", "--yes", "--version", version, *addopts]) def main() -> None: From e4389acb4d650f349a728cc42067d8c1a246bdcb Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Mon, 2 Jun 2025 09:53:44 -0300 Subject: [PATCH 1244/1271] Remove resultlog from the docs (#13465) It was removed by https://github.com/pytest-dev/pytest/commit/d69abff2c7de8bc65b7f1ef867dec5b5b9c564bd in version `6.1.0`. Fixes #13464 --- doc/en/how-to/output.rst | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index d53dd4b8ec7..cb9276c7ea0 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -571,29 +571,6 @@ That will cause pytest to truncate the assertions to 10 lines or 90 characters, Setting both :confval:`truncation_limit_lines` and :confval:`truncation_limit_chars` to ``0`` will disable the truncation. However, setting only one of those values will disable one truncation mode, but will leave the other one intact. -Creating resultlog format files --------------------------------------------------- - -To create plain-text machine-readable result files you can issue: - -.. code-block:: bash - - pytest --resultlog=path - -and look at the content at the ``path`` location. Such files are used e.g. -by the `PyPy-test`_ web page to show test results over several revisions. - -.. warning:: - - This option is rarely used and is scheduled for removal in pytest 6.0. - - If you use this option, consider using the new `pytest-reportlog `__ plugin instead. - - See :ref:`the deprecation docs ` for more information. - - -.. _`PyPy-test`: http://buildbot.pypy.org/summary - Creating JUnitXML format files ---------------------------------------------------- From 315b3ae798fe38264b3ab2312dced212c46f1e21 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Mon, 2 Jun 2025 14:57:38 +0000 Subject: [PATCH 1245/1271] Prepare release version 8.4.0 --- changelog/10224.improvement.rst | 18 -- changelog/10404.bugfix.rst | 7 - changelog/10839.deprecation.rst | 1 - changelog/11067.bugfix.rst | 3 - changelog/11118.improvement.rst | 3 - changelog/11372.breaking.rst | 1 - changelog/11381.improvement.rst | 17 -- changelog/11525.improvement.rst | 3 - changelog/11538.feature.rst | 1 - changelog/12008.bugfix.rst | 1 - changelog/12017.contrib.rst | 7 - changelog/12081.feature.rst | 1 - changelog/12346.breaking.rst | 1 - changelog/12426.improvement.rst | 1 - changelog/12504.feature.rst | 1 - changelog/12535.doc.rst | 4 - changelog/12647.contrib.rst | 1 - changelog/12707.improvement.rst | 1 - changelog/12713.feature.rst | 3 - changelog/12736.improvement.rst | 3 - changelog/12749.feature.rst | 21 -- changelog/12765.feature.rst | 3 - changelog/12863.bugfix.rst | 1 - changelog/12874.breaking.rst | 1 - changelog/12929.bugfix.rst | 1 - changelog/12938.bugfix.rst | 1 - changelog/12943.improvement.rst | 1 - changelog/12946.bugfix.rst | 1 - changelog/12958.improvement.rst | 9 - changelog/12960.breaking.rst | 3 - changelog/12981.bugfix.rst | 1 - changelog/13010.improvement.rst | 1 - changelog/13016.improvement.rst | 8 - changelog/13031.improvement.rst | 1 - changelog/13047.bugfix.rst | 17 -- changelog/13115.improvement.rst | 8 - changelog/13119.bugfix.rst | 1 - changelog/13122.improvement.rst | 15 - changelog/13125.feature.rst | 1 - changelog/13175.bugfix.rst | 1 - changelog/13192.feature.1.rst | 1 - changelog/13192.feature.2.rst | 1 - changelog/13192.feature.rst | 1 - changelog/13218.doc.rst | 1 - changelog/13221.doc.rst | 1 - changelog/13228.feature.rst | 3 - changelog/13248.bugfix.rst | 2 - changelog/13253.feature.rst | 1 - changelog/13291.bugfix.rst | 1 - changelog/13308.improvement.rst | 1 - changelog/13312.bugfix.rst | 1 - changelog/13317.packaging.rst | 4 - changelog/13345.bugfix.rst | 1 - changelog/13377.bugfix.rst | 12 - changelog/13380.improvement.rst | 1 - changelog/13384.bugfix.rst | 1 - changelog/13415.improvement.rst | 5 - changelog/13420.bugfix.rst | 1 - changelog/13420.improvement.rst | 1 - changelog/13457.improvement.rst | 1 - changelog/4112.improvement.rst | 1 - changelog/5473.improvement.rst | 1 - changelog/6649.doc.rst | 1 - changelog/6649.misc.rst | 1 - changelog/6985.improvement.rst | 21 -- changelog/7683.improvement.rst | 1 - changelog/8612.doc.rst | 5 - changelog/9037.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.4.0.rst | 106 +++++++ doc/en/builtin.rst | 85 ++++-- doc/en/changelog.rst | 421 ++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +- doc/en/example/pythoncollection.rst | 4 +- doc/en/example/reportingdemo.rst | 30 +- doc/en/example/simple.rst | 10 +- doc/en/getting-started.rst | 2 +- doc/en/how-to/cache.rst | 2 - doc/en/how-to/capture-warnings.rst | 1 + doc/en/how-to/fixtures.rst | 7 +- doc/en/how-to/output.rst | 2 +- doc/en/how-to/parametrize.rst | 2 +- doc/en/how-to/unittest.rst | 2 + doc/en/reference/reference.rst | 65 +++-- 84 files changed, 667 insertions(+), 326 deletions(-) delete mode 100644 changelog/10224.improvement.rst delete mode 100644 changelog/10404.bugfix.rst delete mode 100644 changelog/10839.deprecation.rst delete mode 100644 changelog/11067.bugfix.rst delete mode 100644 changelog/11118.improvement.rst delete mode 100644 changelog/11372.breaking.rst delete mode 100644 changelog/11381.improvement.rst delete mode 100644 changelog/11525.improvement.rst delete mode 100644 changelog/11538.feature.rst delete mode 100644 changelog/12008.bugfix.rst delete mode 100644 changelog/12017.contrib.rst delete mode 100644 changelog/12081.feature.rst delete mode 100644 changelog/12346.breaking.rst delete mode 100644 changelog/12426.improvement.rst delete mode 100644 changelog/12504.feature.rst delete mode 100644 changelog/12535.doc.rst delete mode 100644 changelog/12647.contrib.rst delete mode 100644 changelog/12707.improvement.rst delete mode 100644 changelog/12713.feature.rst delete mode 100644 changelog/12736.improvement.rst delete mode 100644 changelog/12749.feature.rst delete mode 100644 changelog/12765.feature.rst delete mode 100644 changelog/12863.bugfix.rst delete mode 100644 changelog/12874.breaking.rst delete mode 100644 changelog/12929.bugfix.rst delete mode 100644 changelog/12938.bugfix.rst delete mode 100644 changelog/12943.improvement.rst delete mode 100644 changelog/12946.bugfix.rst delete mode 100644 changelog/12958.improvement.rst delete mode 100644 changelog/12960.breaking.rst delete mode 100644 changelog/12981.bugfix.rst delete mode 100644 changelog/13010.improvement.rst delete mode 100644 changelog/13016.improvement.rst delete mode 100644 changelog/13031.improvement.rst delete mode 100644 changelog/13047.bugfix.rst delete mode 100644 changelog/13115.improvement.rst delete mode 100644 changelog/13119.bugfix.rst delete mode 100644 changelog/13122.improvement.rst delete mode 100644 changelog/13125.feature.rst delete mode 100644 changelog/13175.bugfix.rst delete mode 100644 changelog/13192.feature.1.rst delete mode 100644 changelog/13192.feature.2.rst delete mode 100644 changelog/13192.feature.rst delete mode 100644 changelog/13218.doc.rst delete mode 100644 changelog/13221.doc.rst delete mode 100644 changelog/13228.feature.rst delete mode 100644 changelog/13248.bugfix.rst delete mode 100644 changelog/13253.feature.rst delete mode 100644 changelog/13291.bugfix.rst delete mode 100644 changelog/13308.improvement.rst delete mode 100644 changelog/13312.bugfix.rst delete mode 100644 changelog/13317.packaging.rst delete mode 100644 changelog/13345.bugfix.rst delete mode 100644 changelog/13377.bugfix.rst delete mode 100644 changelog/13380.improvement.rst delete mode 100644 changelog/13384.bugfix.rst delete mode 100644 changelog/13415.improvement.rst delete mode 100644 changelog/13420.bugfix.rst delete mode 100644 changelog/13420.improvement.rst delete mode 100644 changelog/13457.improvement.rst delete mode 100644 changelog/4112.improvement.rst delete mode 100644 changelog/5473.improvement.rst delete mode 100644 changelog/6649.doc.rst delete mode 100644 changelog/6649.misc.rst delete mode 100644 changelog/6985.improvement.rst delete mode 100644 changelog/7683.improvement.rst delete mode 100644 changelog/8612.doc.rst delete mode 100644 changelog/9037.bugfix.rst create mode 100644 doc/en/announce/release-8.4.0.rst diff --git a/changelog/10224.improvement.rst b/changelog/10224.improvement.rst deleted file mode 100644 index 93afe9e2c1e..00000000000 --- a/changelog/10224.improvement.rst +++ /dev/null @@ -1,18 +0,0 @@ -pytest's ``short`` and ``long`` traceback styles (:ref:`how-to-modifying-python-tb-printing`) -now have partial :pep:`657` support and will show specific code segments in the -traceback. - -.. code-block:: pytest - - ================================= FAILURES ================================= - _______________________ test_gets_correct_tracebacks _______________________ - - test_tracebacks.py:12: in test_gets_correct_tracebacks - assert manhattan_distance(p1, p2) == 1 - ^^^^^^^^^^^^^^^^^^^^^^^^^^ - test_tracebacks.py:6: in manhattan_distance - return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y) - ^^^^^^^^^ - E AttributeError: 'NoneType' object has no attribute 'x' - --- by :user:`ammaraskar` diff --git a/changelog/10404.bugfix.rst b/changelog/10404.bugfix.rst deleted file mode 100644 index 4c98ea03d64..00000000000 --- a/changelog/10404.bugfix.rst +++ /dev/null @@ -1,7 +0,0 @@ -Apply filterwarnings from config/cli as soon as possible, and revert them as late as possible -so that warnings as errors are collected throughout the pytest run and before the -unraisable and threadexcept hooks are removed. - -This allows very late warnings and unraisable/threadexcept exceptions to fail the test suite. - -This also changes the warning that the lsof plugin issues from PytestWarning to the new warning PytestFDWarning so it can be more easily filtered. diff --git a/changelog/10839.deprecation.rst b/changelog/10839.deprecation.rst deleted file mode 100644 index a3e2cbf51d0..00000000000 --- a/changelog/10839.deprecation.rst +++ /dev/null @@ -1 +0,0 @@ -Requesting an asynchronous fixture without a `pytest_fixture_setup` hook that resolves it will now give a DeprecationWarning. This most commonly happens if a sync test requests an async fixture. This should have no effect on a majority of users with async tests or fixtures using async pytest plugins, but may affect non-standard hook setups or ``autouse=True``. For guidance on how to work around this warning see :ref:`sync-test-async-fixture`. diff --git a/changelog/11067.bugfix.rst b/changelog/11067.bugfix.rst deleted file mode 100644 index 4e3cb8e7dd7..00000000000 --- a/changelog/11067.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -The test report is now consistent regardless if the test xfailed via :ref:`pytest.mark.xfail ` or :func:`pytest.fail`. - -Previously, *xfailed* tests via the marker would have the string ``"reason: "`` prefixed to the message, while those *xfailed* via the function did not. The prefix has been removed. diff --git a/changelog/11118.improvement.rst b/changelog/11118.improvement.rst deleted file mode 100644 index 4760dbe9d64..00000000000 --- a/changelog/11118.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Now :confval:`pythonpath` configures `$PYTHONPATH` earlier than before during the initialization process, which now also affects plugins loaded via the `-p` command-line option. - --- by :user:`millerdev` diff --git a/changelog/11372.breaking.rst b/changelog/11372.breaking.rst deleted file mode 100644 index f4b5c3c6f6b..00000000000 --- a/changelog/11372.breaking.rst +++ /dev/null @@ -1 +0,0 @@ -Async tests will now fail, instead of warning+skipping, if you don't have any suitable plugin installed. diff --git a/changelog/11381.improvement.rst b/changelog/11381.improvement.rst deleted file mode 100644 index 74c080cc188..00000000000 --- a/changelog/11381.improvement.rst +++ /dev/null @@ -1,17 +0,0 @@ -The ``type`` parameter of the ``parser.addini`` method now accepts `"int"` and ``"float"`` parameters, facilitating the parsing of configuration values in the configuration file. - -Example: - -.. code-block:: python - - def pytest_addoption(parser): - parser.addini("int_value", type="int", default=2, help="my int value") - parser.addini("float_value", type="float", default=4.2, help="my float value") - -The `pytest.ini` file: - -.. code-block:: ini - - [pytest] - int_value = 3 - float_value = 5.4 diff --git a/changelog/11525.improvement.rst b/changelog/11525.improvement.rst deleted file mode 100644 index 1935ce59343..00000000000 --- a/changelog/11525.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixtures are now clearly represented in the output as a "fixture object", not as a normal function as before, making it easy for beginners to catch mistakes such as referencing a fixture declared in the same module but not requested in the test function. - --- by :user:`the-compiler` and :user:`glyphack` diff --git a/changelog/11538.feature.rst b/changelog/11538.feature.rst deleted file mode 100644 index d6473b8fe73..00000000000 --- a/changelog/11538.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added :class:`pytest.RaisesGroup` as an equivalent to :func:`pytest.raises` for expecting :exc:`ExceptionGroup`. Also adds :class:`pytest.RaisesExc` which is now the logic behind :func:`pytest.raises` and used as parameter to :class:`pytest.RaisesGroup`. ``RaisesGroup`` includes the ability to specify multiple different expected exceptions, the structure of nested exception groups, and flags for emulating :ref:`except* `. See :ref:`assert-matching-exception-groups` and docstrings for more information. diff --git a/changelog/12008.bugfix.rst b/changelog/12008.bugfix.rst deleted file mode 100644 index b9680b89236..00000000000 --- a/changelog/12008.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -In :pr:`11220`, an unintended change in reordering was introduced by changing the way indices were assigned to direct params. More specifically, before that change, the indices of direct params to metafunc's callspecs were assigned after all parametrizations took place. Now, that change is reverted. diff --git a/changelog/12017.contrib.rst b/changelog/12017.contrib.rst deleted file mode 100644 index ec1861893b3..00000000000 --- a/changelog/12017.contrib.rst +++ /dev/null @@ -1,7 +0,0 @@ -Mixed internal improvements: - -* Migrate formatting to f-strings in some tests. -* Use type-safe constructs in JUnitXML tests. -* Moved`` MockTiming`` into ``_pytest.timing``. - --- by :user:`RonnyPfannschmidt` diff --git a/changelog/12081.feature.rst b/changelog/12081.feature.rst deleted file mode 100644 index 6538fbf30f8..00000000000 --- a/changelog/12081.feature.rst +++ /dev/null @@ -1 +0,0 @@ -Added :fixture:`capteesys` to capture AND pass output to next handler set by ``--capture=``. diff --git a/changelog/12346.breaking.rst b/changelog/12346.breaking.rst deleted file mode 100644 index 7013cf734c8..00000000000 --- a/changelog/12346.breaking.rst +++ /dev/null @@ -1 +0,0 @@ -Tests will now fail, instead of raising a warning, if they return any value other than None. diff --git a/changelog/12426.improvement.rst b/changelog/12426.improvement.rst deleted file mode 100644 index 0da1f838aea..00000000000 --- a/changelog/12426.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -A warning is now issued when :ref:`pytest.mark.usefixtures ref` is used without specifying any fixtures. Previously, empty usefixtures markers were silently ignored. diff --git a/changelog/12504.feature.rst b/changelog/12504.feature.rst deleted file mode 100644 index d72b97958c2..00000000000 --- a/changelog/12504.feature.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`pytest.mark.xfail` now accepts :class:`pytest.RaisesGroup` for the ``raises`` parameter when you expect an exception group. You can also pass a :class:`pytest.RaisesExc` if you e.g. want to make use of the ``check`` parameter. diff --git a/changelog/12535.doc.rst b/changelog/12535.doc.rst deleted file mode 100644 index d43c1c822ea..00000000000 --- a/changelog/12535.doc.rst +++ /dev/null @@ -1,4 +0,0 @@ -`This -example` -showed ``print`` statements that do not exactly reflect what the -different branches actually do. The fix makes the example more precise. diff --git a/changelog/12647.contrib.rst b/changelog/12647.contrib.rst deleted file mode 100644 index 1d7a3181778..00000000000 --- a/changelog/12647.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed running the test suite with the ``hypothesis`` pytest plugin. diff --git a/changelog/12707.improvement.rst b/changelog/12707.improvement.rst deleted file mode 100644 index 4684b6561c8..00000000000 --- a/changelog/12707.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Exception chains can be navigated when dropped into Pdb in Python 3.13+. diff --git a/changelog/12713.feature.rst b/changelog/12713.feature.rst deleted file mode 100644 index 90867b87eae..00000000000 --- a/changelog/12713.feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -New `--force-short-summary` option to force condensed summary output regardless of verbosity level. - -This lets users still see condensed summary output of failures for quick reference in log files from job outputs, being especially useful if non-condensed output is very verbose. diff --git a/changelog/12736.improvement.rst b/changelog/12736.improvement.rst deleted file mode 100644 index 5fdb14e2ef5..00000000000 --- a/changelog/12736.improvement.rst +++ /dev/null @@ -1,3 +0,0 @@ -Added a new attribute `name` with the fixed value `"pytest tests"` to the root tag `testsuites` of the junit-xml generated by pytest. - -This attribute is part of many junit-xml specifications and is even part of the `junit-10.xsd` specification that pytest's implementation is based on. diff --git a/changelog/12749.feature.rst b/changelog/12749.feature.rst deleted file mode 100644 index c3b7ca5d321..00000000000 --- a/changelog/12749.feature.rst +++ /dev/null @@ -1,21 +0,0 @@ -pytest traditionally collects classes/functions in the test module namespace even if they are imported from another file. - -For example: - -.. code-block:: python - - # contents of src/domain.py - class Testament: ... - - - # contents of tests/test_testament.py - from domain import Testament - - - def test_testament(): ... - -In this scenario with the default options, pytest will collect the class `Testament` from `tests/test_testament.py` because it starts with `Test`, even though in this case it is a production class being imported in the test module namespace. - -This behavior can now be prevented by setting the new :confval:`collect_imported_tests` configuration option to ``false``, which will make pytest collect classes/functions from test files **only** if they are defined in that file. - --- by :user:`FreerGit` diff --git a/changelog/12765.feature.rst b/changelog/12765.feature.rst deleted file mode 100644 index 193c75621f7..00000000000 --- a/changelog/12765.feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -Thresholds to trigger snippet truncation can now be set with :confval:`truncation_limit_lines` and :confval:`truncation_limit_chars`. - -See :ref:`truncation-params` for more information. diff --git a/changelog/12863.bugfix.rst b/changelog/12863.bugfix.rst deleted file mode 100644 index 0b1c397a08e..00000000000 --- a/changelog/12863.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix applying markers, including :ref:`pytest.mark.parametrize ` when placed above `@staticmethod` or `@classmethod`. diff --git a/changelog/12874.breaking.rst b/changelog/12874.breaking.rst deleted file mode 100644 index a442586eeb5..00000000000 --- a/changelog/12874.breaking.rst +++ /dev/null @@ -1 +0,0 @@ -We dropped support for Python 3.8 following its end of life (2024-10-07). diff --git a/changelog/12929.bugfix.rst b/changelog/12929.bugfix.rst deleted file mode 100644 index fcf490d83e2..00000000000 --- a/changelog/12929.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Handle StopIteration from test cases, setup and teardown correctly. diff --git a/changelog/12938.bugfix.rst b/changelog/12938.bugfix.rst deleted file mode 100644 index d54d73bdbf5..00000000000 --- a/changelog/12938.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed ``--durations-min`` argument not respected if ``-vv`` is used. diff --git a/changelog/12943.improvement.rst b/changelog/12943.improvement.rst deleted file mode 100644 index eb8ac63650a..00000000000 --- a/changelog/12943.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -If a test fails with an exceptiongroup with a single exception, the contained exception will now be displayed in the short test summary info. diff --git a/changelog/12946.bugfix.rst b/changelog/12946.bugfix.rst deleted file mode 100644 index b11da09e7ae..00000000000 --- a/changelog/12946.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed missing help for :mod:`pdb` commands wrapped by pytest -- by :user:`adamchainz`. diff --git a/changelog/12958.improvement.rst b/changelog/12958.improvement.rst deleted file mode 100644 index ee8dc8c0710..00000000000 --- a/changelog/12958.improvement.rst +++ /dev/null @@ -1,9 +0,0 @@ -A number of :ref:`unraisable ` enhancements: - -* Set the unraisable hook as early as possible and unset it as late as possible, to collect the most possible number of unraisable exceptions. -* Call the garbage collector just before unsetting the unraisable hook, to collect any straggling exceptions. -* Collect multiple unraisable exceptions per test phase. -* Report the :mod:`tracemalloc` allocation traceback (if available). -* Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures. -* Report the unraisable exception as the cause of the :class:`pytest.PytestUnraisableExceptionWarning` exception if raised. -* Compute the ``repr`` of the unraisable object in the unraisable hook so you get the latest information if available, and should help with resurrection of the object. diff --git a/changelog/12960.breaking.rst b/changelog/12960.breaking.rst deleted file mode 100644 index 3ab87e6fe23..00000000000 --- a/changelog/12960.breaking.rst +++ /dev/null @@ -1,3 +0,0 @@ -Test functions containing a yield now cause an explicit error. They have not been run since pytest 4.0, and were previously marked as an expected failure and deprecation warning. - -See :ref:`the docs ` for more information. diff --git a/changelog/12981.bugfix.rst b/changelog/12981.bugfix.rst deleted file mode 100644 index 5fc8e29656f..00000000000 --- a/changelog/12981.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent exceptions in :func:`pytest.Config.add_cleanup` callbacks preventing further cleanups. diff --git a/changelog/13010.improvement.rst b/changelog/13010.improvement.rst deleted file mode 100644 index d6b814f090e..00000000000 --- a/changelog/13010.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`pytest.approx` now can compare collections that contain numbers and non-numbers mixed. diff --git a/changelog/13016.improvement.rst b/changelog/13016.improvement.rst deleted file mode 100644 index 634672ab69b..00000000000 --- a/changelog/13016.improvement.rst +++ /dev/null @@ -1,8 +0,0 @@ -A number of :ref:`threadexception ` enhancements: - -* Set the excepthook as early as possible and unset it as late as possible, to collect the most possible number of unhandled exceptions from threads. -* Collect multiple thread exceptions per test phase. -* Report the :mod:`tracemalloc` allocation traceback (if available). -* Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures. -* Report the thread exception as the cause of the :class:`pytest.PytestUnhandledThreadExceptionWarning` exception if raised. -* Extract the ``name`` of the thread object in the excepthook which should help with resurrection of the thread. diff --git a/changelog/13031.improvement.rst b/changelog/13031.improvement.rst deleted file mode 100644 index c6c64c4673a..00000000000 --- a/changelog/13031.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -An empty parameter set as in ``pytest.mark.parametrize([], ids=idfunc)`` will no longer trigger a call to ``idfunc`` with internal objects. diff --git a/changelog/13047.bugfix.rst b/changelog/13047.bugfix.rst deleted file mode 100644 index 399e860505c..00000000000 --- a/changelog/13047.bugfix.rst +++ /dev/null @@ -1,17 +0,0 @@ -Restore :func:`pytest.approx` handling of equality checks between `bool` and `numpy.bool_` types. - -Comparing `bool` and `numpy.bool_` using :func:`pytest.approx` accidentally changed in version `8.3.4` and `8.3.5` to no longer match: - -.. code-block:: pycon - - >>> import numpy as np - >>> from pytest import approx - >>> [np.True_, np.True_] == pytest.approx([True, True]) - False - -This has now been fixed: - -.. code-block:: pycon - - >>> [np.True_, np.True_] == pytest.approx([True, True]) - True diff --git a/changelog/13115.improvement.rst b/changelog/13115.improvement.rst deleted file mode 100644 index 9ac45820917..00000000000 --- a/changelog/13115.improvement.rst +++ /dev/null @@ -1,8 +0,0 @@ -Allows supplying ``ExceptionGroup[Exception]`` and ``BaseExceptionGroup[BaseException]`` to ``pytest.raises`` to keep full typing on :class:`ExceptionInfo `: - -.. code-block:: python - - with pytest.raises(ExceptionGroup[Exception]) as exc_info: - some_function() - -Parametrizing with other exception types remains an error - we do not check the types of child exceptions and thus do not permit code that might look like we do. diff --git a/changelog/13119.bugfix.rst b/changelog/13119.bugfix.rst deleted file mode 100644 index b7e56af9bb8..00000000000 --- a/changelog/13119.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Improved handling of invalid regex patterns for filter warnings by providing a clear error message. diff --git a/changelog/13122.improvement.rst b/changelog/13122.improvement.rst deleted file mode 100644 index c302713b320..00000000000 --- a/changelog/13122.improvement.rst +++ /dev/null @@ -1,15 +0,0 @@ -The ``--stepwise`` mode received a number of improvements: - -* It no longer forgets the last failed test in case pytest is executed later without the flag. - - This enables the following workflow: - - 1. Execute pytest with ``--stepwise``, pytest then stops at the first failing test; - 2. Iteratively update the code and run the test in isolation, without the ``--stepwise`` flag (for example in an IDE), until it is fixed. - 3. Execute pytest with ``--stepwise`` again and pytest will continue from the previously failed test, and if it passes, continue on to the next tests. - - Previously, at step 3, pytest would start from the beginning, forgetting the previously failed test. - - This change however might cause issues if the ``--stepwise`` mode is used far apart in time, as the state might get stale, so the internal state will be reset automatically in case the test suite changes (for now only the number of tests are considered for this, we might change/improve this on the future). - -* New ``--stepwise-reset``/``--sw-reset`` flag, allowing the user to explicitly reset the stepwise state and restart the workflow from the beginning. diff --git a/changelog/13125.feature.rst b/changelog/13125.feature.rst deleted file mode 100644 index 0c7d66c1169..00000000000 --- a/changelog/13125.feature.rst +++ /dev/null @@ -1 +0,0 @@ -:confval:`console_output_style` now supports ``times`` to show execution time of each test. diff --git a/changelog/13175.bugfix.rst b/changelog/13175.bugfix.rst deleted file mode 100644 index bdbb72b41e1..00000000000 --- a/changelog/13175.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -The diff is now also highlighted correctly when comparing two strings. diff --git a/changelog/13192.feature.1.rst b/changelog/13192.feature.1.rst deleted file mode 100644 index 71fb06f7d70..00000000000 --- a/changelog/13192.feature.1.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`pytest.raises` will now print a helpful string diff if matching fails and the match parameter has ``^`` and ``$`` and is otherwise escaped. diff --git a/changelog/13192.feature.2.rst b/changelog/13192.feature.2.rst deleted file mode 100644 index 0ffa0e1496a..00000000000 --- a/changelog/13192.feature.2.rst +++ /dev/null @@ -1 +0,0 @@ -You can now pass :func:`with pytest.raises(check=fn): `, where ``fn`` is a function which takes a raised exception and returns a boolean. The ``raises`` fails if no exception was raised (as usual), passes if an exception is raised and ``fn`` returns ``True`` (as well as ``match`` and the type matching, if specified, which are checked before), and propagates the exception if ``fn`` returns ``False`` (which likely also fails the test). diff --git a/changelog/13192.feature.rst b/changelog/13192.feature.rst deleted file mode 100644 index 97f31ce233c..00000000000 --- a/changelog/13192.feature.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`pytest.raises` will now raise a warning when passing an empty string to ``match``, as this will match against any value. Use ``match="^$"`` if you want to check that an exception has no message. diff --git a/changelog/13218.doc.rst b/changelog/13218.doc.rst deleted file mode 100644 index 907a817e895..00000000000 --- a/changelog/13218.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Pointed out in the :func:`pytest.approx` documentation that it considers booleans unequal to numeric zero or one. diff --git a/changelog/13221.doc.rst b/changelog/13221.doc.rst deleted file mode 100644 index cfd35f821b4..00000000000 --- a/changelog/13221.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Improved grouping of CLI options in the ``--help`` output. diff --git a/changelog/13228.feature.rst b/changelog/13228.feature.rst deleted file mode 100644 index c5d84182313..00000000000 --- a/changelog/13228.feature.rst +++ /dev/null @@ -1,3 +0,0 @@ -:ref:`hidden-param` can now be used in ``id`` of :func:`pytest.param` or in -``ids`` of :py:func:`Metafunc.parametrize `. -It hides the parameter set from the test name. diff --git a/changelog/13248.bugfix.rst b/changelog/13248.bugfix.rst deleted file mode 100644 index 2ebb102fd07..00000000000 --- a/changelog/13248.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fixed an issue where passing a ``scope`` in :py:func:`Metafunc.parametrize ` with ``indirect=True`` -could result in other fixtures being unable to depend on the parametrized fixture. diff --git a/changelog/13253.feature.rst b/changelog/13253.feature.rst deleted file mode 100644 index e497c207223..00000000000 --- a/changelog/13253.feature.rst +++ /dev/null @@ -1 +0,0 @@ -New flag: :ref:`--disable-plugin-autoload ` which works as an alternative to :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD` when setting environment variables is inconvenient; and allows setting it in config files with :confval:`addopts`. diff --git a/changelog/13291.bugfix.rst b/changelog/13291.bugfix.rst deleted file mode 100644 index 03ce06b697a..00000000000 --- a/changelog/13291.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed ``repr`` of ``attrs`` objects in assertion failure messages when using ``attrs>=25.2``. diff --git a/changelog/13308.improvement.rst b/changelog/13308.improvement.rst deleted file mode 100644 index 70018c66d59..00000000000 --- a/changelog/13308.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Added official support for Python 3.14. diff --git a/changelog/13312.bugfix.rst b/changelog/13312.bugfix.rst deleted file mode 100644 index 62ad36879f5..00000000000 --- a/changelog/13312.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a possible ``KeyError`` crash on PyPy during collection of tests involving higher-scoped parameters. diff --git a/changelog/13317.packaging.rst b/changelog/13317.packaging.rst deleted file mode 100644 index 94171cb1ef3..00000000000 --- a/changelog/13317.packaging.rst +++ /dev/null @@ -1,4 +0,0 @@ -Specified minimum allowed versions of ``colorama``, ``iniconfig``, -and ``packaging``; and bumped the minimum allowed version -of ``exceptiongroup`` for ``python_version<'3.11'`` from a release -candidate to a full release. diff --git a/changelog/13345.bugfix.rst b/changelog/13345.bugfix.rst deleted file mode 100644 index 5010888aa08..00000000000 --- a/changelog/13345.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix type hints for :attr:`pytest.TestReport.when` and :attr:`pytest.TestReport.location`. diff --git a/changelog/13377.bugfix.rst b/changelog/13377.bugfix.rst deleted file mode 100644 index 15755481f7f..00000000000 --- a/changelog/13377.bugfix.rst +++ /dev/null @@ -1,12 +0,0 @@ -Fixed handling of test methods with positional-only parameter syntax. - -Now, methods are supported that formally define ``self`` as positional-only -and/or fixture parameters as keyword-only, e.g.: - -.. code-block:: python - - class TestClass: - - def test_method(self, /, *, fixture): ... - -Before, this caused an internal error in pytest. diff --git a/changelog/13380.improvement.rst b/changelog/13380.improvement.rst deleted file mode 100644 index 51f374fbf01..00000000000 --- a/changelog/13380.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Fix :class:`ExceptionGroup` traceback filtering to exclude pytest internals. diff --git a/changelog/13384.bugfix.rst b/changelog/13384.bugfix.rst deleted file mode 100644 index e93d01dcab0..00000000000 --- a/changelog/13384.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed an issue where pytest could report negative durations. diff --git a/changelog/13415.improvement.rst b/changelog/13415.improvement.rst deleted file mode 100644 index 61667f15c7b..00000000000 --- a/changelog/13415.improvement.rst +++ /dev/null @@ -1,5 +0,0 @@ -The author metadata of the BibTex example is now correctly formatted with last names following first names. -An example of BibLaTex has been added. -BibTex and BibLaTex examples now clearly indicate that what is cited is software. - --- by :user:`willynilly` diff --git a/changelog/13420.bugfix.rst b/changelog/13420.bugfix.rst deleted file mode 100644 index 02f7372a759..00000000000 --- a/changelog/13420.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Added ``lru_cache`` to ``nodes._check_initialpaths_for_relpath``. diff --git a/changelog/13420.improvement.rst b/changelog/13420.improvement.rst deleted file mode 100644 index 54fe50a72b0..00000000000 --- a/changelog/13420.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Improved test collection performance by optimizing path resolution used in ``FSCollector``. diff --git a/changelog/13457.improvement.rst b/changelog/13457.improvement.rst deleted file mode 100644 index 3937384b322..00000000000 --- a/changelog/13457.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -The error message about duplicate parametrization no longer displays an internal stack trace. diff --git a/changelog/4112.improvement.rst b/changelog/4112.improvement.rst deleted file mode 100644 index 426b87ffa19..00000000000 --- a/changelog/4112.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Using :ref:`pytest.mark.usefixtures ` on :func:`pytest.param` now produces an error instead of silently doing nothing. diff --git a/changelog/5473.improvement.rst b/changelog/5473.improvement.rst deleted file mode 100644 index 1b9ab006d49..00000000000 --- a/changelog/5473.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -Replace `:` with `;` in the assertion rewrite warning message so it can be filtered using standard Python warning filters before calling :func:`pytest.main`. diff --git a/changelog/6649.doc.rst b/changelog/6649.doc.rst deleted file mode 100644 index cf5bb781b87..00000000000 --- a/changelog/6649.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Added :class:`~pytest.TerminalReporter` to the :ref:`api-reference` documentation page. diff --git a/changelog/6649.misc.rst b/changelog/6649.misc.rst deleted file mode 100644 index cec8c3f4506..00000000000 --- a/changelog/6649.misc.rst +++ /dev/null @@ -1 +0,0 @@ -Added :class:`~pytest.TerminalReporter` to the public pytest API, as it is part of the signature of the :hook:`pytest_terminal_summary` hook. diff --git a/changelog/6985.improvement.rst b/changelog/6985.improvement.rst deleted file mode 100644 index 34ee8edc77d..00000000000 --- a/changelog/6985.improvement.rst +++ /dev/null @@ -1,21 +0,0 @@ -Improved :func:`pytest.approx` to enhance the readability of value ranges and tolerances between 0.001 and 1000. - * The `repr` method now provides clearer output for values within those ranges, making it easier to interpret the results. - * Previously, the output for those ranges of values and tolerances was displayed in scientific notation (e.g., `42 ± 1.0e+00`). The updated method now presents the tolerance as a decimal for better readability (e.g., `42 ± 1`). - - Example: - - **Previous Output:** - - .. code-block:: console - - >>> pytest.approx(42, abs=1) - 42 ± 1.0e+00 - - **Current Output:** - - .. code-block:: console - - >>> pytest.approx(42, abs=1) - 42 ± 1 - - -- by :user:`fazeelghafoor` diff --git a/changelog/7683.improvement.rst b/changelog/7683.improvement.rst deleted file mode 100644 index 311abe4df93..00000000000 --- a/changelog/7683.improvement.rst +++ /dev/null @@ -1 +0,0 @@ -The formerly optional ``pygments`` dependency is now required, causing output always to be source-highlighted (unless disabled via the ``--code-highlight=no`` CLI option). diff --git a/changelog/8612.doc.rst b/changelog/8612.doc.rst deleted file mode 100644 index 6ab4102ace4..00000000000 --- a/changelog/8612.doc.rst +++ /dev/null @@ -1,5 +0,0 @@ -Add a recipe for handling abstract test classes in the documentation. - -A new example has been added to the documentation to demonstrate how to use a mixin class to handle abstract -test classes without manually setting the ``__test__`` attribute for subclasses. -This ensures that subclasses of abstract test classes are automatically collected by pytest. diff --git a/changelog/9037.bugfix.rst b/changelog/9037.bugfix.rst deleted file mode 100644 index 5367452337e..00000000000 --- a/changelog/9037.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Honor :confval:`disable_test_id_escaping_and_forfeit_all_rights_to_community_support` when escaping ids in parametrized tests. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 51edc964a0c..702fd26dd0d 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.4.0 release-8.3.5 release-8.3.4 release-8.3.3 diff --git a/doc/en/announce/release-8.4.0.rst b/doc/en/announce/release-8.4.0.rst new file mode 100644 index 00000000000..65e80a55919 --- /dev/null +++ b/doc/en/announce/release-8.4.0.rst @@ -0,0 +1,106 @@ +pytest-8.4.0 +======================================= + +The pytest team is proud to announce the 8.4.0 release! + +This release contains new features, improvements, and bug fixes, +the full list of changes is available in the changelog: + + https://docs.pytest.org/en/stable/changelog.html + +For complete documentation, please visit: + + https://docs.pytest.org/en/stable/ + +As usual, you can upgrade from PyPI via: + + pip install -U pytest + +Thanks to all of the contributors to this release: + +* Adam Johnson +* Ammar Askar +* Andrew Pikul +* Andy Freeland +* Anthony Sottile +* Anton Zhilin +* Arpit Gupta +* Ashley Whetter +* Avasam +* Bahram Farahmand +* Brigitta Sipőcz +* Bruno Oliveira +* Callum Scott +* Christian Clauss +* Christopher Head +* Daara +* Daniel Miller +* Deysha Rivera +* Emil Hjelm +* Eugene Mwangi +* Florian Bruhin +* Frank Hoffmann +* GTowers1 +* Guillaume Gauvrit +* Gupta Arpit +* Harmin Parra Rueda +* Jakob van Santen +* Jason N. White +* Jiajun Xu +* John Litborn +* Julian Valentin +* JulianJvn +* Kenny Y +* Leonardus Chen +* Marcelo Duarte Trevisani +* Marcin Augustynów +* Natalia Mokeeva +* Nathan Rousseau +* Nauman Ahmed +* Nick Murphy +* Oleksandr Zavertniev +* Pavel Zhukov +* Peter Gessler +* Pierre Sassoulas +* Pradeep Kumar +* Ran Benita +* Reagan Lee +* Rob Arrow +* Ronny Pfannschmidt +* Sadra Barikbin +* Sam Bull +* Samuel Bronson +* Sashko +* Serge Smertin +* Shaygan Hooshyari +* Stefaan Lippens +* Stefan Zimmermann +* Stephen McDowell +* Sviatoslav Sydorenko +* Sviatoslav Sydorenko (Святослав Сидоренко) +* Thomas Grainger +* TobiMcNamobi +* Tobias Alex-Petersen +* Tony Narlock +* Vincent (Wen Yu) Ge +* Virendra Patil +* Will Riley +* Yann Dirson +* Zac Hatfield-Dodds +* delta87 +* dongfangtianyu +* eitanwass +* fazeelghafoor +* ikappaki +* jakkdl +* maugu +* moajo +* mwychung +* polkapolka +* suspe +* sven +* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 8aa6fef681c..b129d0a763f 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -22,7 +22,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a cachedir: .pytest_cache rootdir: /home/sweet/project collected 0 items - cache -- .../_pytest/cacheprovider.py:556 + cache -- .../_pytest/cacheprovider.py:555 Return a cache object that can persist state between testing sessions. cache.get(key, default) @@ -33,7 +33,48 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a Values can be any object handled by the json stdlib module. - capsysbinary -- .../_pytest/capture.py:1024 + capsys -- .../_pytest/capture.py:1000 + Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. + + The captured output is made available via ``capsys.readouterr()`` method + calls, which return a ``(out, err)`` namedtuple. + ``out`` and ``err`` will be ``text`` objects. + + Returns an instance of :class:`CaptureFixture[str] `. + + Example: + + .. code-block:: python + + def test_output(capsys): + print("hello") + captured = capsys.readouterr() + assert captured.out == "hello\n" + + capteesys -- .../_pytest/capture.py:1028 + Enable simultaneous text capturing and pass-through of writes + to ``sys.stdout`` and ``sys.stderr`` as defined by ``--capture=``. + + + The captured output is made available via ``capteesys.readouterr()`` method + calls, which return a ``(out, err)`` namedtuple. + ``out`` and ``err`` will be ``text`` objects. + + The output is also passed-through, allowing it to be "live-printed", + reported, or both as defined by ``--capture=``. + + Returns an instance of :class:`CaptureFixture[str] `. + + Example: + + .. code-block:: python + + def test_output(capsys): + print("hello") + captured = capteesys.readouterr() + assert captured.out == "hello\n" + + capsysbinary -- .../_pytest/capture.py:1063 Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. The captured output is made available via ``capsysbinary.readouterr()`` @@ -51,7 +92,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capsysbinary.readouterr() assert captured.out == b"hello\n" - capfd -- .../_pytest/capture.py:1052 + capfd -- .../_pytest/capture.py:1091 Enable text capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -69,7 +110,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfd.readouterr() assert captured.out == "hello\n" - capfdbinary -- .../_pytest/capture.py:1080 + capfdbinary -- .../_pytest/capture.py:1119 Enable bytes capturing of writes to file descriptors ``1`` and ``2``. The captured output is made available via ``capfd.readouterr()`` method @@ -87,25 +128,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a captured = capfdbinary.readouterr() assert captured.out == b"hello\n" - capsys -- .../_pytest/capture.py:996 - Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. - - The captured output is made available via ``capsys.readouterr()`` method - calls, which return a ``(out, err)`` namedtuple. - ``out`` and ``err`` will be ``text`` objects. - - Returns an instance of :class:`CaptureFixture[str] `. - - Example: - - .. code-block:: python - - def test_output(capsys): - print("hello") - captured = capsys.readouterr() - assert captured.out == "hello\n" - - doctest_namespace [session scope] -- .../_pytest/doctest.py:741 + doctest_namespace [session scope] -- .../_pytest/doctest.py:740 Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests. @@ -119,7 +142,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1345 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1424 Session-scoped fixture that returns the session's :class:`pytest.Config` object. @@ -129,7 +152,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a if pytestconfig.get_verbosity() > 0: ... - record_property -- .../_pytest/junitxml.py:280 + record_property -- .../_pytest/junitxml.py:277 Add extra properties to the calling test. User properties become part of the test report and are available to the @@ -143,13 +166,13 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a def test_function(record_property): record_property("example_key", 1) - record_xml_attribute -- .../_pytest/junitxml.py:303 + record_xml_attribute -- .../_pytest/junitxml.py:300 Add extra xml attributes to the tag for the calling test. The fixture is callable with ``name, value``. The value is automatically XML-encoded. - record_testsuite_property [session scope] -- .../_pytest/junitxml.py:341 + record_testsuite_property [session scope] -- .../_pytest/junitxml.py:338 Record a new ```` tag as child of the root ````. This is suitable to writing global information regarding the entire test @@ -191,7 +214,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. _legacy_path: https://py.readthedocs.io/en/latest/path.html - caplog -- .../_pytest/logging.py:598 + caplog -- .../_pytest/logging.py:596 Access and control log capturing. Captured logs are available through the following properties/methods:: @@ -226,15 +249,15 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a To undo modifications done by the fixture in a contained scope, use :meth:`context() `. - recwarn -- .../_pytest/recwarn.py:35 + recwarn -- .../_pytest/recwarn.py:34 Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions. See :ref:`warnings` for information on warning categories. - tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:241 + tmp_path_factory [session scope] -- .../_pytest/tmpdir.py:240 Return a :class:`pytest.TempPathFactory` instance for the test session. - tmp_path -- .../_pytest/tmpdir.py:256 + tmp_path -- .../_pytest/tmpdir.py:255 Return a temporary directory (as :class:`pathlib.Path` object) which is unique to each test function invocation. The temporary directory is created as a subdirectory diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index c92cd7d4263..73073ffca1c 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,427 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.4.0 (2025-06-02) +========================= + +Removals and backward incompatible breaking changes +--------------------------------------------------- + +- `#11372 `_: Async tests will now fail, instead of warning+skipping, if you don't have any suitable plugin installed. + + +- `#12346 `_: Tests will now fail, instead of raising a warning, if they return any value other than None. + + +- `#12874 `_: We dropped support for Python 3.8 following its end of life (2024-10-07). + + +- `#12960 `_: Test functions containing a yield now cause an explicit error. They have not been run since pytest 4.0, and were previously marked as an expected failure and deprecation warning. + + See :ref:`the docs ` for more information. + + + +Deprecations (removal in next major release) +-------------------------------------------- + +- `#10839 `_: Requesting an asynchronous fixture without a `pytest_fixture_setup` hook that resolves it will now give a DeprecationWarning. This most commonly happens if a sync test requests an async fixture. This should have no effect on a majority of users with async tests or fixtures using async pytest plugins, but may affect non-standard hook setups or ``autouse=True``. For guidance on how to work around this warning see :ref:`sync-test-async-fixture`. + + + +New features +------------ + +- `#11538 `_: Added :class:`pytest.RaisesGroup` as an equivalent to :func:`pytest.raises` for expecting :exc:`ExceptionGroup`. Also adds :class:`pytest.RaisesExc` which is now the logic behind :func:`pytest.raises` and used as parameter to :class:`pytest.RaisesGroup`. ``RaisesGroup`` includes the ability to specify multiple different expected exceptions, the structure of nested exception groups, and flags for emulating :ref:`except* `. See :ref:`assert-matching-exception-groups` and docstrings for more information. + + +- `#12081 `_: Added :fixture:`capteesys` to capture AND pass output to next handler set by ``--capture=``. + + +- `#12504 `_: :func:`pytest.mark.xfail` now accepts :class:`pytest.RaisesGroup` for the ``raises`` parameter when you expect an exception group. You can also pass a :class:`pytest.RaisesExc` if you e.g. want to make use of the ``check`` parameter. + + +- `#12713 `_: New `--force-short-summary` option to force condensed summary output regardless of verbosity level. + + This lets users still see condensed summary output of failures for quick reference in log files from job outputs, being especially useful if non-condensed output is very verbose. + + +- `#12749 `_: pytest traditionally collects classes/functions in the test module namespace even if they are imported from another file. + + For example: + + .. code-block:: python + + # contents of src/domain.py + class Testament: ... + + + # contents of tests/test_testament.py + from domain import Testament + + + def test_testament(): ... + + In this scenario with the default options, pytest will collect the class `Testament` from `tests/test_testament.py` because it starts with `Test`, even though in this case it is a production class being imported in the test module namespace. + + This behavior can now be prevented by setting the new :confval:`collect_imported_tests` configuration option to ``false``, which will make pytest collect classes/functions from test files **only** if they are defined in that file. + + -- by :user:`FreerGit` + + +- `#12765 `_: Thresholds to trigger snippet truncation can now be set with :confval:`truncation_limit_lines` and :confval:`truncation_limit_chars`. + + See :ref:`truncation-params` for more information. + + +- `#13125 `_: :confval:`console_output_style` now supports ``times`` to show execution time of each test. + + +- `#13192 `_: :func:`pytest.raises` will now raise a warning when passing an empty string to ``match``, as this will match against any value. Use ``match="^$"`` if you want to check that an exception has no message. + + +- `#13192 `_: :func:`pytest.raises` will now print a helpful string diff if matching fails and the match parameter has ``^`` and ``$`` and is otherwise escaped. + + +- `#13192 `_: You can now pass :func:`with pytest.raises(check=fn): `, where ``fn`` is a function which takes a raised exception and returns a boolean. The ``raises`` fails if no exception was raised (as usual), passes if an exception is raised and ``fn`` returns ``True`` (as well as ``match`` and the type matching, if specified, which are checked before), and propagates the exception if ``fn`` returns ``False`` (which likely also fails the test). + + +- `#13228 `_: :ref:`hidden-param` can now be used in ``id`` of :func:`pytest.param` or in + ``ids`` of :py:func:`Metafunc.parametrize `. + It hides the parameter set from the test name. + + +- `#13253 `_: New flag: :ref:`--disable-plugin-autoload ` which works as an alternative to :envvar:`PYTEST_DISABLE_PLUGIN_AUTOLOAD` when setting environment variables is inconvenient; and allows setting it in config files with :confval:`addopts`. + + + +Improvements in existing functionality +-------------------------------------- + +- `#10224 `_: pytest's ``short`` and ``long`` traceback styles (:ref:`how-to-modifying-python-tb-printing`) + now have partial :pep:`657` support and will show specific code segments in the + traceback. + + .. code-block:: pytest + + ================================= FAILURES ================================= + _______________________ test_gets_correct_tracebacks _______________________ + + test_tracebacks.py:12: in test_gets_correct_tracebacks + assert manhattan_distance(p1, p2) == 1 + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + test_tracebacks.py:6: in manhattan_distance + return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y) + ^^^^^^^^^ + E AttributeError: 'NoneType' object has no attribute 'x' + + -- by :user:`ammaraskar` + + +- `#11118 `_: Now :confval:`pythonpath` configures `$PYTHONPATH` earlier than before during the initialization process, which now also affects plugins loaded via the `-p` command-line option. + + -- by :user:`millerdev` + + +- `#11381 `_: The ``type`` parameter of the ``parser.addini`` method now accepts `"int"` and ``"float"`` parameters, facilitating the parsing of configuration values in the configuration file. + + Example: + + .. code-block:: python + + def pytest_addoption(parser): + parser.addini("int_value", type="int", default=2, help="my int value") + parser.addini("float_value", type="float", default=4.2, help="my float value") + + The `pytest.ini` file: + + .. code-block:: ini + + [pytest] + int_value = 3 + float_value = 5.4 + + +- `#11525 `_: Fixtures are now clearly represented in the output as a "fixture object", not as a normal function as before, making it easy for beginners to catch mistakes such as referencing a fixture declared in the same module but not requested in the test function. + + -- by :user:`the-compiler` and :user:`glyphack` + + +- `#12426 `_: A warning is now issued when :ref:`pytest.mark.usefixtures ref` is used without specifying any fixtures. Previously, empty usefixtures markers were silently ignored. + + +- `#12707 `_: Exception chains can be navigated when dropped into Pdb in Python 3.13+. + + +- `#12736 `_: Added a new attribute `name` with the fixed value `"pytest tests"` to the root tag `testsuites` of the junit-xml generated by pytest. + + This attribute is part of many junit-xml specifications and is even part of the `junit-10.xsd` specification that pytest's implementation is based on. + + +- `#12943 `_: If a test fails with an exceptiongroup with a single exception, the contained exception will now be displayed in the short test summary info. + + +- `#12958 `_: A number of :ref:`unraisable ` enhancements: + + * Set the unraisable hook as early as possible and unset it as late as possible, to collect the most possible number of unraisable exceptions. + * Call the garbage collector just before unsetting the unraisable hook, to collect any straggling exceptions. + * Collect multiple unraisable exceptions per test phase. + * Report the :mod:`tracemalloc` allocation traceback (if available). + * Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures. + * Report the unraisable exception as the cause of the :class:`pytest.PytestUnraisableExceptionWarning` exception if raised. + * Compute the ``repr`` of the unraisable object in the unraisable hook so you get the latest information if available, and should help with resurrection of the object. + + +- `#13010 `_: :func:`pytest.approx` now can compare collections that contain numbers and non-numbers mixed. + + +- `#13016 `_: A number of :ref:`threadexception ` enhancements: + + * Set the excepthook as early as possible and unset it as late as possible, to collect the most possible number of unhandled exceptions from threads. + * Collect multiple thread exceptions per test phase. + * Report the :mod:`tracemalloc` allocation traceback (if available). + * Avoid using a generator based hook to allow handling :class:`StopIteration` in test failures. + * Report the thread exception as the cause of the :class:`pytest.PytestUnhandledThreadExceptionWarning` exception if raised. + * Extract the ``name`` of the thread object in the excepthook which should help with resurrection of the thread. + + +- `#13031 `_: An empty parameter set as in ``pytest.mark.parametrize([], ids=idfunc)`` will no longer trigger a call to ``idfunc`` with internal objects. + + +- `#13115 `_: Allows supplying ``ExceptionGroup[Exception]`` and ``BaseExceptionGroup[BaseException]`` to ``pytest.raises`` to keep full typing on :class:`ExceptionInfo `: + + .. code-block:: python + + with pytest.raises(ExceptionGroup[Exception]) as exc_info: + some_function() + + Parametrizing with other exception types remains an error - we do not check the types of child exceptions and thus do not permit code that might look like we do. + + +- `#13122 `_: The ``--stepwise`` mode received a number of improvements: + + * It no longer forgets the last failed test in case pytest is executed later without the flag. + + This enables the following workflow: + + 1. Execute pytest with ``--stepwise``, pytest then stops at the first failing test; + 2. Iteratively update the code and run the test in isolation, without the ``--stepwise`` flag (for example in an IDE), until it is fixed. + 3. Execute pytest with ``--stepwise`` again and pytest will continue from the previously failed test, and if it passes, continue on to the next tests. + + Previously, at step 3, pytest would start from the beginning, forgetting the previously failed test. + + This change however might cause issues if the ``--stepwise`` mode is used far apart in time, as the state might get stale, so the internal state will be reset automatically in case the test suite changes (for now only the number of tests are considered for this, we might change/improve this on the future). + + * New ``--stepwise-reset``/``--sw-reset`` flag, allowing the user to explicitly reset the stepwise state and restart the workflow from the beginning. + + +- `#13308 `_: Added official support for Python 3.14. + + +- `#13380 `_: Fix :class:`ExceptionGroup` traceback filtering to exclude pytest internals. + + +- `#13415 `_: The author metadata of the BibTex example is now correctly formatted with last names following first names. + An example of BibLaTex has been added. + BibTex and BibLaTex examples now clearly indicate that what is cited is software. + + -- by :user:`willynilly` + + +- `#13420 `_: Improved test collection performance by optimizing path resolution used in ``FSCollector``. + + +- `#13457 `_: The error message about duplicate parametrization no longer displays an internal stack trace. + + +- `#4112 `_: Using :ref:`pytest.mark.usefixtures ` on :func:`pytest.param` now produces an error instead of silently doing nothing. + + +- `#5473 `_: Replace `:` with `;` in the assertion rewrite warning message so it can be filtered using standard Python warning filters before calling :func:`pytest.main`. + + +- `#6985 `_: Improved :func:`pytest.approx` to enhance the readability of value ranges and tolerances between 0.001 and 1000. + * The `repr` method now provides clearer output for values within those ranges, making it easier to interpret the results. + * Previously, the output for those ranges of values and tolerances was displayed in scientific notation (e.g., `42 ± 1.0e+00`). The updated method now presents the tolerance as a decimal for better readability (e.g., `42 ± 1`). + + Example: + + **Previous Output:** + + .. code-block:: console + + >>> pytest.approx(42, abs=1) + 42 ± 1.0e+00 + + **Current Output:** + + .. code-block:: console + + >>> pytest.approx(42, abs=1) + 42 ± 1 + + -- by :user:`fazeelghafoor` + + +- `#7683 `_: The formerly optional ``pygments`` dependency is now required, causing output always to be source-highlighted (unless disabled via the ``--code-highlight=no`` CLI option). + + + +Bug fixes +--------- + +- `#10404 `_: Apply filterwarnings from config/cli as soon as possible, and revert them as late as possible + so that warnings as errors are collected throughout the pytest run and before the + unraisable and threadexcept hooks are removed. + + This allows very late warnings and unraisable/threadexcept exceptions to fail the test suite. + + This also changes the warning that the lsof plugin issues from PytestWarning to the new warning PytestFDWarning so it can be more easily filtered. + + +- `#11067 `_: The test report is now consistent regardless if the test xfailed via :ref:`pytest.mark.xfail ` or :func:`pytest.fail`. + + Previously, *xfailed* tests via the marker would have the string ``"reason: "`` prefixed to the message, while those *xfailed* via the function did not. The prefix has been removed. + + +- `#12008 `_: In :pr:`11220`, an unintended change in reordering was introduced by changing the way indices were assigned to direct params. More specifically, before that change, the indices of direct params to metafunc's callspecs were assigned after all parametrizations took place. Now, that change is reverted. + + +- `#12863 `_: Fix applying markers, including :ref:`pytest.mark.parametrize ` when placed above `@staticmethod` or `@classmethod`. + + +- `#12929 `_: Handle StopIteration from test cases, setup and teardown correctly. + + +- `#12938 `_: Fixed ``--durations-min`` argument not respected if ``-vv`` is used. + + +- `#12946 `_: Fixed missing help for :mod:`pdb` commands wrapped by pytest -- by :user:`adamchainz`. + + +- `#12981 `_: Prevent exceptions in :func:`pytest.Config.add_cleanup` callbacks preventing further cleanups. + + +- `#13047 `_: Restore :func:`pytest.approx` handling of equality checks between `bool` and `numpy.bool_` types. + + Comparing `bool` and `numpy.bool_` using :func:`pytest.approx` accidentally changed in version `8.3.4` and `8.3.5` to no longer match: + + .. code-block:: pycon + + >>> import numpy as np + >>> from pytest import approx + >>> [np.True_, np.True_] == pytest.approx([True, True]) + False + + This has now been fixed: + + .. code-block:: pycon + + >>> [np.True_, np.True_] == pytest.approx([True, True]) + True + + +- `#13119 `_: Improved handling of invalid regex patterns for filter warnings by providing a clear error message. + + +- `#13175 `_: The diff is now also highlighted correctly when comparing two strings. + + +- `#13248 `_: Fixed an issue where passing a ``scope`` in :py:func:`Metafunc.parametrize ` with ``indirect=True`` + could result in other fixtures being unable to depend on the parametrized fixture. + + +- `#13291 `_: Fixed ``repr`` of ``attrs`` objects in assertion failure messages when using ``attrs>=25.2``. + + +- `#13312 `_: Fixed a possible ``KeyError`` crash on PyPy during collection of tests involving higher-scoped parameters. + + +- `#13345 `_: Fix type hints for :attr:`pytest.TestReport.when` and :attr:`pytest.TestReport.location`. + + +- `#13377 `_: Fixed handling of test methods with positional-only parameter syntax. + + Now, methods are supported that formally define ``self`` as positional-only + and/or fixture parameters as keyword-only, e.g.: + + .. code-block:: python + + class TestClass: + + def test_method(self, /, *, fixture): ... + + Before, this caused an internal error in pytest. + + +- `#13384 `_: Fixed an issue where pytest could report negative durations. + + +- `#13420 `_: Added ``lru_cache`` to ``nodes._check_initialpaths_for_relpath``. + + +- `#9037 `_: Honor :confval:`disable_test_id_escaping_and_forfeit_all_rights_to_community_support` when escaping ids in parametrized tests. + + + +Improved documentation +---------------------- + +- `#12535 `_: `This + example` + showed ``print`` statements that do not exactly reflect what the + different branches actually do. The fix makes the example more precise. + + +- `#13218 `_: Pointed out in the :func:`pytest.approx` documentation that it considers booleans unequal to numeric zero or one. + + +- `#13221 `_: Improved grouping of CLI options in the ``--help`` output. + + +- `#6649 `_: Added :class:`~pytest.TerminalReporter` to the :ref:`api-reference` documentation page. + + +- `#8612 `_: Add a recipe for handling abstract test classes in the documentation. + + A new example has been added to the documentation to demonstrate how to use a mixin class to handle abstract + test classes without manually setting the ``__test__`` attribute for subclasses. + This ensures that subclasses of abstract test classes are automatically collected by pytest. + + + +Packaging updates and notes for downstreams +------------------------------------------- + +- `#13317 `_: Specified minimum allowed versions of ``colorama``, ``iniconfig``, + and ``packaging``; and bumped the minimum allowed version + of ``exceptiongroup`` for ``python_version<'3.11'`` from a release + candidate to a full release. + + + +Contributor-facing changes +-------------------------- + +- `#12017 `_: Mixed internal improvements: + + * Migrate formatting to f-strings in some tests. + * Use type-safe constructs in JUnitXML tests. + * Moved`` MockTiming`` into ``_pytest.timing``. + + -- by :user:`RonnyPfannschmidt` + + +- `#12647 `_: Fixed running the test suite with the ``hypothesis`` pytest plugin. + + + +Miscellaneous internal changes +------------------------------ + +- `#6649 `_: Added :class:`~pytest.TerminalReporter` to the public pytest API, as it is part of the signature of the :hook:`pytest_terminal_summary` hook. + + pytest 8.3.5 (2025-03-02) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 69e715c9db1..c3848db5112 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 6a3b143d580..760140390cb 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/example/reportingdemo.rst b/doc/en/example/reportingdemo.rst index 5e48815bbc9..8040ee9b957 100644 --- a/doc/en/example/reportingdemo.rst +++ b/doc/en/example/reportingdemo.rst @@ -384,6 +384,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: i = Foo() > assert i.b == 2 + ^^^ failure_demo.py:148: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ @@ -446,6 +447,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_tupleerror(self): > a, b = [1] # noqa: F841 + ^^^^ E ValueError: not enough values to unpack (expected 2, got 1) failure_demo.py:177: ValueError @@ -457,6 +459,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: items = [1, 2, 3] print(f"items is {items!r}") > a, b = items.pop() + ^^^^ E TypeError: cannot unpack non-iterable int object failure_demo.py:182: TypeError @@ -468,6 +471,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_some_error(self): > if namenotexi: # noqa: F821 + ^^^^^^^^^^ E NameError: name 'namenotexi' is not defined failure_demo.py:185: NameError @@ -526,6 +530,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_z1_unpack_error(self): items = [] > a, b = items + ^^^^ E ValueError: not enough values to unpack (expected 2, got 0) failure_demo.py:219: ValueError @@ -536,6 +541,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: def test_z2_type_error(self): items = 3 > a, b = items + ^^^^ E TypeError: cannot unpack non-iterable int object failure_demo.py:223: TypeError @@ -568,12 +574,12 @@ Here is a nice run of several failures and how ``pytest`` presents things: E + where False = ('456') E + where = '123'.startswith E + where '123' = .f at 0xdeadbeef0029>() - E + and '456' = .g at 0xdeadbeef0003>() + E + and '456' = .g at 0xdeadbeef002a>() failure_demo.py:237: AssertionError _____________________ TestMoreErrors.test_global_func ______________________ - self = + self = def test_global_func(self): > assert isinstance(globf(42), float) @@ -584,18 +590,18 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:240: AssertionError _______________________ TestMoreErrors.test_instance _______________________ - self = + self = def test_instance(self): self.x = 6 * 7 > assert self.x != 42 E assert 42 != 42 - E + where 42 = .x + E + where 42 = .x failure_demo.py:244: AssertionError _______________________ TestMoreErrors.test_compare ________________________ - self = + self = def test_compare(self): > assert globf(10) < 5 @@ -605,7 +611,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:247: AssertionError _____________________ TestMoreErrors.test_try_finally ______________________ - self = + self = def test_try_finally(self): x = 1 @@ -616,7 +622,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:252: AssertionError ___________________ TestCustomAssertMsg.test_single_line ___________________ - self = + self = def test_single_line(self): class A: @@ -631,16 +637,16 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:263: AssertionError ____________________ TestCustomAssertMsg.test_multiline ____________________ - self = + self = def test_multiline(self): class A: a = 1 b = 2 - > assert ( - A.a == b - ), "A.a appears not to be b\nor does not appear to be b\none of those" + > assert A.a == b, ( + "A.a appears not to be b\nor does not appear to be b\none of those" + ) E AssertionError: A.a appears not to be b E or does not appear to be b E one of those @@ -650,7 +656,7 @@ Here is a nice run of several failures and how ``pytest`` presents things: failure_demo.py:270: AssertionError ___________________ TestCustomAssertMsg.test_custom_repr ___________________ - self = + self = def test_custom_repr(self): class JSON: diff --git a/doc/en/example/simple.rst b/doc/en/example/simple.rst index 69d973e51d0..c1a444bea18 100644 --- a/doc/en/example/simple.rst +++ b/doc/en/example/simple.rst @@ -104,6 +104,7 @@ Let's run this without supplying our new option: elif cmdopt == "type2": print("second") > assert 0 # to see what was printed + ^^^^^^^^ E assert 0 test_sample.py:6: AssertionError @@ -130,6 +131,7 @@ And now with supplying a command line option: elif cmdopt == "type2": print("second") > assert 0 # to see what was printed + ^^^^^^^^ E assert 0 test_sample.py:6: AssertionError @@ -646,7 +648,7 @@ If we run this: test_step.py:11: AssertionError ========================= short test summary info ========================== - XFAIL test_step.py::TestUserHandling::test_deletion - reason: previous test failed (test_modification) + XFAIL test_step.py::TestUserHandling::test_deletion - previous test failed (test_modification) ================== 1 failed, 2 passed, 1 xfailed in 0.12s ================== We'll see that ``test_deletion`` was not executed because ``test_modification`` @@ -725,7 +727,7 @@ We can run this: file /home/sweet/project/b/test_error.py, line 1 def test_root(db): # no db here, will error out E fixture 'db' not found - > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory + > available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, capteesys, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory > use 'pytest --fixtures [testpath]' for help on them. /home/sweet/project/b/test_error.py:1 @@ -736,6 +738,7 @@ We can run this: def test_a1(db): > assert 0, db # to show value + ^^^^^^^^^^^^ E AssertionError: E assert 0 @@ -746,6 +749,7 @@ We can run this: def test_a2(db): > assert 0, db # to show value + ^^^^^^^^^^^^ E AssertionError: E assert 0 @@ -946,7 +950,7 @@ and run it: rootdir: /home/sweet/project collected 3 items - test_module.py Esetting up a test failed or skipped test_module.py::test_setup_fails + test_module.py Esetting up a test failed test_module.py::test_setup_fails Fexecuting test failed or skipped test_module.py::test_call_fails F diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 41469de3864..c92e97f556e 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.3.5 + pytest 8.4.0 .. _`simpletest`: diff --git a/doc/en/how-to/cache.rst b/doc/en/how-to/cache.rst index a3b2a862534..e3209b79359 100644 --- a/doc/en/how-to/cache.rst +++ b/doc/en/how-to/cache.rst @@ -289,8 +289,6 @@ You can always peek at the content of the cache using the {'test_caching.py::test_function': True} cache/nodeids contains: ['test_caching.py::test_function'] - cache/stepwise contains: - [] example/value contains: 42 diff --git a/doc/en/how-to/capture-warnings.rst b/doc/en/how-to/capture-warnings.rst index 4b1de6f3704..a9bd894b6fd 100644 --- a/doc/en/how-to/capture-warnings.rst +++ b/doc/en/how-to/capture-warnings.rst @@ -66,6 +66,7 @@ as an error: def test_one(): > assert api_v1() == 1 + ^^^^^^^^ test_show_warnings.py:10: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 8f84e4867a6..a86fd1065fd 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -449,6 +449,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this: assert response == 250 assert b"smtp.gmail.com" in msg > assert 0 # for demo purposes + ^^^^^^^^ E assert 0 test_module.py:7: AssertionError @@ -460,6 +461,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this: response, msg = smtp_connection.noop() assert response == 250 > assert 0 # for demo purposes + ^^^^^^^^ E assert 0 test_module.py:13: AssertionError @@ -1308,6 +1310,7 @@ So let's just do another run: assert response == 250 assert b"smtp.gmail.com" in msg > assert 0 # for demo purposes + ^^^^^^^^ E assert 0 test_module.py:7: AssertionError @@ -1319,6 +1322,7 @@ So let's just do another run: response, msg = smtp_connection.noop() assert response == 250 > assert 0 # for demo purposes + ^^^^^^^^ E assert 0 test_module.py:13: AssertionError @@ -1343,6 +1347,7 @@ So let's just do another run: response, msg = smtp_connection.noop() assert response == 250 > assert 0 # for demo purposes + ^^^^^^^^ E assert 0 test_module.py:13: AssertionError @@ -1418,7 +1423,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + diff --git a/doc/en/how-to/output.rst b/doc/en/how-to/output.rst index cb9276c7ea0..bc98b816484 100644 --- a/doc/en/how-to/output.rst +++ b/doc/en/how-to/output.rst @@ -447,7 +447,7 @@ Example: ================================= XPASSES ================================== ========================= short test summary info ========================== SKIPPED [1] test_example.py:22: skipping this test - XFAIL test_example.py::test_xfail - reason: xfailing this test + XFAIL test_example.py::test_xfail - xfailing this test XPASS test_example.py::test_xpass - always xfail ERROR test_example.py::test_error - assert 0 FAILED test_example.py::test_fail - assert 0 diff --git a/doc/en/how-to/parametrize.rst b/doc/en/how-to/parametrize.rst index 5a16684eb96..d7c12c1a1f4 100644 --- a/doc/en/how-to/parametrize.rst +++ b/doc/en/how-to/parametrize.rst @@ -281,7 +281,7 @@ list: $ pytest -q -rs test_strings.py s [100%] ========================= short test summary info ========================== - SKIPPED [1] test_strings.py: got empty parameter set ['stringinput'], function test_valid_string at /home/sweet/project/test_strings.py:2 + SKIPPED [1] test_strings.py: got empty parameter set for (stringinput) 1 skipped in 0.12s Note that when calling ``metafunc.parametrize`` multiple times with different parameter sets, all parameter names across diff --git a/doc/en/how-to/unittest.rst b/doc/en/how-to/unittest.rst index 62e32b6d28f..ba98b366d04 100644 --- a/doc/en/how-to/unittest.rst +++ b/doc/en/how-to/unittest.rst @@ -154,6 +154,7 @@ the ``self.db`` values in the traceback: def test_method1(self): assert hasattr(self, "db") > assert 0, self.db # fail for demo purposes + ^^^^^^^^^^^^^^^^^ E AssertionError: .DummyDB object at 0xdeadbeef0001> E assert 0 @@ -164,6 +165,7 @@ the ``self.db`` values in the traceback: def test_method2(self): > assert 0, self.db # fail for demo purposes + ^^^^^^^^^^^^^^^^^ E AssertionError: .DummyDB object at 0xdeadbeef0001> E assert 0 diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index d3dd14a8681..b0535ef6589 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -2093,6 +2093,12 @@ All the command-line flags can be obtained by running ``pytest --help``:: example: -m 'mark1 and not mark2'. --markers show markers (builtin, plugin and per-project ones). -x, --exitfirst Exit instantly on first error or failed test + --maxfail=num Exit after first num failures or errors + --strict-config Any warnings encountered while parsing the `pytest` + section of the configuration file raise errors + --strict-markers Markers not registered in the `markers` section of + the configuration file raise errors + --strict (Deprecated) alias to --strict-markers --fixtures, --funcargs Show available fixtures, sorted by plugin appearance (fixtures with leading '_' are only shown with '-v') @@ -2131,15 +2137,21 @@ All the command-line flags can be obtained by running ``pytest --help``:: --sw-skip, --stepwise-skip Ignore the first failing test but stop on the next failing test. Implicitly enables --stepwise. + --sw-reset, --stepwise-reset + Resets stepwise state, restarting the stepwise + workflow. Implicitly enables --stepwise. Reporting: --durations=N Show N slowest setup/test durations (N=0 for all) --durations-min=N Minimal duration in seconds for inclusion in slowest - list. Default: 0.005. + list. Default: 0.005 (or 0.0 if -vv is given). -v, --verbose Increase verbosity --no-header Disable header --no-summary Disable summary --no-fold-skipped Do not fold skipped tests in short summary. + --force-short-summary + Force condensed summary output regardless of + verbosity level. -q, --quiet Decrease verbosity --verbosity=VERBOSE Set verbosity. Default: 0. -r chars Show extra test summary info as specified by chars: @@ -2174,22 +2186,6 @@ All the command-line flags can be obtained by running ``pytest --help``:: -W, --pythonwarnings PYTHONWARNINGS Set which warnings to report, see -W option of Python itself - --maxfail=num Exit after first num failures or errors - --strict-config Any warnings encountered while parsing the `pytest` - section of the configuration file raise errors - --strict-markers Markers not registered in the `markers` section of - the configuration file raise errors - --strict (Deprecated) alias to --strict-markers - -c, --config-file FILE - Load configuration from `FILE` instead of trying to - locate one of the implicit configuration files. - --continue-on-collection-errors - Force test execution even if collection errors occur - --rootdir=ROOTDIR Define root directory for tests. Can be relative - path: 'root_dir', './root_dir', - 'root_dir/another_dir/'; absolute path: - '/home/user/root_dir'; path with variables: - '$HOME/root_dir'. collection: --collect-only, --co Only collect tests, don't execute them @@ -2205,6 +2201,8 @@ All the command-line flags can be obtained by running ``pytest --help``:: --keep-duplicates Keep duplicate tests --collect-in-virtualenv Don't ignore tests in a local virtualenv directory + --continue-on-collection-errors + Force test execution even if collection errors occur --import-mode={prepend,append,importlib} Prepend/append to sys.path when importing test modules and conftest files. Default: prepend. @@ -2220,6 +2218,14 @@ All the command-line flags can be obtained by running ``pytest --help``:: failure test session debugging and configuration: + -c, --config-file FILE + Load configuration from `FILE` instead of trying to + locate one of the implicit configuration files. + --rootdir=ROOTDIR Define root directory for tests. Can be relative + path: 'root_dir', './root_dir', + 'root_dir/another_dir/'; absolute path: + '/home/user/root_dir'; path with variables: + '$HOME/root_dir'. --basetemp=dir Base temporary directory for this test run. (Warning: this directory is removed if it exists.) -V, --version Display pytest version and information about @@ -2228,7 +2234,13 @@ All the command-line flags can be obtained by running ``pytest --help``:: -h, --help Show help message and configuration info -p name Early-load given plugin module name or entry point (multi-allowed). To avoid loading of plugins, use - the `no:` prefix, e.g. `no:doctest`. + the `no:` prefix, e.g. `no:doctest`. See also + --disable-plugin-autoload. + --disable-plugin-autoload + Disable plugin auto-loading through entry point + packaging metadata. Only plugins explicitly + specified in -p or env var PYTEST_PLUGINS will be + loaded. --trace-config Trace considerations of conftest.py files --debug=[DEBUG_FILE_NAME] Store internal tracing debug information in this log @@ -2283,13 +2295,16 @@ All the command-line flags can be obtained by running ``pytest --help``:: markers (linelist): Register new markers for test functions empty_parameter_set_mark (string): Default marker for empty parametersets - norecursedirs (args): Directory patterns to avoid for recursion - testpaths (args): Directories to search for tests when no files or - directories are given on the command line filterwarnings (linelist): Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings. + norecursedirs (args): Directory patterns to avoid for recursion + testpaths (args): Directories to search for tests when no files or + directories are given on the command line + collect_imported_tests (bool): + Whether to collect tests in imported modules outside + `testpaths` consider_namespace_packages (bool): Consider namespace packages when resolving module names during import @@ -2329,6 +2344,12 @@ All the command-line flags can be obtained by running ``pytest --help``:: enable_assertion_pass_hook (bool): Enables the pytest_assertion_pass hook. Make sure to delete any previously generated pyc cache files. + truncation_limit_lines (string): + Set threshold of LINES after which truncation will + take effect + truncation_limit_chars (string): + Set threshold of CHARS after which truncation will + take effect verbosity_assertions (string): Specify a verbosity level for assertions, overriding the main level. Higher levels will provide more @@ -2373,12 +2394,12 @@ All the command-line flags can be obtained by running ``pytest --help``:: Default value for --log-file-date-format log_auto_indent (string): Default value for --log-auto-indent - pythonpath (paths): Add paths to sys.path faulthandler_timeout (string): Dump the traceback of all threads if a test takes more than TIMEOUT seconds to finish addopts (args): Extra command line options minversion (string): Minimally required pytest version + pythonpath (paths): Add paths to sys.path required_plugins (args): Plugins that must be present for pytest to run From cc5ceed916d0c63696da33c67e035917194a4e87 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 19:58:49 +0000 Subject: [PATCH 1246/1271] RELEASING: remove pytest mailing list (#13472) (#13473) It is no longer. (cherry picked from commit 80dfa2db8e6157bf706c2f2656ba0fd7bc13195a) Co-authored-by: Ran Benita --- RELEASING.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/RELEASING.rst b/RELEASING.rst index 0ca63ee4fbf..76c41d83a58 100644 --- a/RELEASING.rst +++ b/RELEASING.rst @@ -168,7 +168,6 @@ Both automatic and manual processes described above follow the same steps from t To the following mailing lists: - * pytest-dev@python.org (all releases) * python-announce-list@python.org (all releases) * testing-in-python@lists.idyll.org (only major/minor releases) From b49745ec529f06edfbbe531b766839763b2be3c2 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 19:25:38 -0300 Subject: [PATCH 1247/1271] fix: support TerminalReporter.isatty being called (#13462) (#13483) Fixes #13461. (cherry picked from commit cba5c4a98f65fdcfa484749bc06bcde1fb0865bc) Co-authored-by: Martin Fischer --- changelog/13461.bugfix.rst | 3 +++ src/_pytest/compat.py | 20 ++++++++++++++++++++ src/_pytest/terminal.py | 11 +++++++---- testing/test_terminal.py | 10 ++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 changelog/13461.bugfix.rst diff --git a/changelog/13461.bugfix.rst b/changelog/13461.bugfix.rst new file mode 100644 index 00000000000..4b45f7cc9da --- /dev/null +++ b/changelog/13461.bugfix.rst @@ -0,0 +1,3 @@ +Corrected ``_pytest.terminal.TerminalReporter.isatty`` to support +being called as a method. Before it was just a boolean which could +break correct code when using ``-o log_cli=true``). diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index f113a2197f3..7d71838be51 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -300,3 +300,23 @@ def get_user_id() -> int | None: # This also work for Enums (if you use `is` to compare) and Literals. def assert_never(value: NoReturn) -> NoReturn: assert False, f"Unhandled value: {value} ({type(value).__name__})" + + +class CallableBool: + """ + A bool-like object that can also be called, returning its true/false value. + + Used for backwards compatibility in cases where something was supposed to be a method + but was implemented as a simple attribute by mistake (see `TerminalReporter.isatty`). + + Do not use in new code. + """ + + def __init__(self, value: bool) -> None: + self._value = value + + def __bool__(self) -> bool: + return self._value + + def __call__(self) -> bool: + return self._value diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index d5ccc4e4900..5f27c46b41e 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -31,6 +31,7 @@ import pluggy +from _pytest import compat from _pytest import nodes from _pytest import timing from _pytest._code import ExceptionInfo @@ -387,7 +388,9 @@ def __init__(self, config: Config, file: TextIO | None = None) -> None: self.reportchars = getreportopt(config) self.foldskipped = config.option.fold_skipped self.hasmarkup = self._tw.hasmarkup - self.isatty = file.isatty() + # isatty should be a method but was wrongly implemented as a boolean. + # We use CallableBool here to support both. + self.isatty = compat.CallableBool(file.isatty()) self._progress_nodeids_reported: set[str] = set() self._timing_nodeids_reported: set[str] = set() self._show_progress_info = self._determine_show_progress_info() @@ -766,7 +769,7 @@ def _width_of_current_line(self) -> int: return self._tw.width_of_current_line def pytest_collection(self) -> None: - if self.isatty: + if self.isatty(): if self.config.option.verbose >= 0: self.write("collecting ... ", flush=True, bold=True) elif self.config.option.verbose >= 1: @@ -779,7 +782,7 @@ def pytest_collectreport(self, report: CollectReport) -> None: self._add_stats("skipped", [report]) items = [x for x in report.result if isinstance(x, Item)] self._numcollected += len(items) - if self.isatty: + if self.isatty(): self.report_collect() def report_collect(self, final: bool = False) -> None: @@ -811,7 +814,7 @@ def report_collect(self, final: bool = False) -> None: line += f" / {skipped} skipped" if self._numcollected > selected: line += f" / {selected} selected" - if self.isatty: + if self.isatty(): self.rewrite(line, bold=True, erase=True) if final: self.write("\n") diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 86feb33b3ec..3ea10195c6b 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -442,6 +442,16 @@ def test_long_xfail(): ] ) + @pytest.mark.parametrize("isatty", [True, False]) + def test_isatty(self, pytester: Pytester, monkeypatch, isatty: bool) -> None: + config = pytester.parseconfig() + f = StringIO() + monkeypatch.setattr(f, "isatty", lambda: isatty) + tr = TerminalReporter(config, f) + assert tr.isatty() == isatty + # It was incorrectly implemented as a boolean so we still support using it as one. + assert bool(tr.isatty) == isatty + class TestCollectonly: def test_collectonly_basic(self, pytester: Pytester) -> None: From 4e631a71484c2fa49e3fd9f884546af411a4888d Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 22:53:48 +0000 Subject: [PATCH 1248/1271] Merge pull request #13486 from hosmir/fixtypo (#13487) Fix typo in docs regarding capsys/capteesys (cherry picked from commit 8f93ae9f38b2b1d6fd2d602e099d8907f34cf0a0) Co-authored-by: John Litborn <11260241+jakkdl@users.noreply.github.com> --- doc/en/builtin.rst | 2 +- src/_pytest/capture.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index b129d0a763f..31c2fa9df06 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -69,7 +69,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a .. code-block:: python - def test_output(capsys): + def test_output(capteesys): print("hello") captured = capteesys.readouterr() assert captured.out == "hello\n" diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 3812d88176a..6d98676be5f 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -1043,7 +1043,7 @@ def capteesys(request: SubRequest) -> Generator[CaptureFixture[str]]: .. code-block:: python - def test_output(capsys): + def test_output(capteesys): print("hello") captured = capteesys.readouterr() assert captured.out == "hello\n" From 1a0581b0227fa07afd1f2c4c6215aec3862cf1ab Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 13:50:26 +0000 Subject: [PATCH 1249/1271] Remove outdated warning about faulthandler_timeout on Windows (#13492) (#13493) --------- (cherry picked from commit 216c7ec882b2aa30fb8a35e100c990c34fca12c1) Co-authored-by: Iwithyou2025 Co-authored-by: Bruno Oliveira --- changelog/13492.doc.rst | 1 + doc/en/how-to/failures.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/13492.doc.rst diff --git a/changelog/13492.doc.rst b/changelog/13492.doc.rst new file mode 100644 index 00000000000..6e3f72a860e --- /dev/null +++ b/changelog/13492.doc.rst @@ -0,0 +1 @@ +Fixed outdated warning about ``faulthandler`` not working on Windows. diff --git a/doc/en/how-to/failures.rst b/doc/en/how-to/failures.rst index b3d0c155b48..0c45cd7b118 100644 --- a/doc/en/how-to/failures.rst +++ b/doc/en/how-to/failures.rst @@ -112,7 +112,7 @@ on the command-line. Also the :confval:`faulthandler_timeout=X` configuration option can be used to dump the traceback of all threads if a test takes longer than ``X`` -seconds to finish (not available on Windows). +seconds to finish. .. note:: From a86ee09291f913b36fdeec14c42356515b91c979 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 21:51:35 -0300 Subject: [PATCH 1250/1271] Fix typo in parametrize.rst (#13514) (#13516) (cherry picked from commit 64c1173df4f897a8880a25a29eff67d45dbc41b2) Co-authored-by: SarahPythonista <4283226+SarahPythonista@users.noreply.github.com> --- doc/en/example/parametrize.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index c3848db5112..a7ec55dff0a 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -352,7 +352,7 @@ The first invocation with ``db == "DB1"`` passed while the second with ``db == " Indirect parametrization --------------------------------------------------- -Using the ``indirect=True`` parameter when parametrizing a test allows to +Using the ``indirect=True`` parameter when parametrizing a test allows one to parametrize a test with a fixture receiving the values before passing them to a test: From 4c161aba8ecaab9940040702369025595d26564c Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 18:52:02 -0300 Subject: [PATCH 1251/1271] pytester: avoid unraisableexception gc collects in inline runs to speed up test suite (#13525) (#13526) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Because `pytester.runpytest()` executes the full session cycle (including `pytest_unconfigure`), it was calling `gc.collect()` in a loop multiple times—even for small, fast tests. This significantly increased the total test suite runtime. To optimize performance, disable the gc runs in inline pytester runs entirely, matching the behavior before #12958. Locally the test suite runtime improved dramatically, dropping from 425s to 160s. Fixes #13482. (cherry picked from commit 391324e13a6589f5d824d053240d4b9a4139a115) Co-authored-by: Ran Benita Co-authored-by: Bruno Oliveira --- src/_pytest/pytester.py | 10 ++++-- src/_pytest/unraisableexception.py | 15 ++++++--- testing/test_config.py | 3 +- testing/test_unraisableexception.py | 51 +++++++++++++---------------- 4 files changed, 43 insertions(+), 36 deletions(-) diff --git a/src/_pytest/pytester.py b/src/_pytest/pytester.py index 38f4643bd8b..59d2b0befe9 100644 --- a/src/_pytest/pytester.py +++ b/src/_pytest/pytester.py @@ -1092,6 +1092,8 @@ def inline_run( Typically we reraise keyboard interrupts from the child run. If True, the KeyboardInterrupt exception is captured. """ + from _pytest.unraisableexception import gc_collect_iterations_key + # (maybe a cpython bug?) the importlib cache sometimes isn't updated # properly between file creation and inline_run (especially if imports # are interspersed with file creation) @@ -1115,12 +1117,16 @@ def inline_run( rec = [] - class Collect: + class PytesterHelperPlugin: @staticmethod def pytest_configure(config: Config) -> None: rec.append(self.make_hook_recorder(config.pluginmanager)) - plugins.append(Collect()) + # The unraisable plugin GC collect slows down inline + # pytester runs too much. + config.stash[gc_collect_iterations_key] = 0 + + plugins.append(PytesterHelperPlugin()) ret = main([str(x) for x in args], plugins=plugins) if len(rec) == 1: reprec = rec.pop() diff --git a/src/_pytest/unraisableexception.py b/src/_pytest/unraisableexception.py index 7826aeccd12..0faca36aa00 100644 --- a/src/_pytest/unraisableexception.py +++ b/src/_pytest/unraisableexception.py @@ -24,10 +24,12 @@ from exceptiongroup import ExceptionGroup -def gc_collect_harder() -> None: - # A single collection doesn't necessarily collect everything. - # Constant determined experimentally by the Trio project. - for _ in range(5): +# This is a stash item and not a simple constant to allow pytester to override it. +gc_collect_iterations_key = StashKey[int]() + + +def gc_collect_harder(iterations: int) -> None: + for _ in range(iterations): gc.collect() @@ -84,9 +86,12 @@ def collect_unraisable(config: Config) -> None: def cleanup( *, config: Config, prev_hook: Callable[[sys.UnraisableHookArgs], object] ) -> None: + # A single collection doesn't necessarily collect everything. + # Constant determined experimentally by the Trio project. + gc_collect_iterations = config.stash.get(gc_collect_iterations_key, 5) try: try: - gc_collect_harder() + gc_collect_harder(gc_collect_iterations) collect_unraisable(config) finally: sys.unraisablehook = prev_hook diff --git a/testing/test_config.py b/testing/test_config.py index bb08c40fef4..3e8635fd1fc 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -2175,7 +2175,8 @@ class DummyPlugin: plugins = config.invocation_params.plugins assert len(plugins) == 2 assert plugins[0] is plugin - assert type(plugins[1]).__name__ == "Collect" # installed by pytester.inline_run() + # Installed by pytester.inline_run(). + assert type(plugins[1]).__name__ == "PytesterHelperPlugin" # args cannot be None with pytest.raises(TypeError): diff --git a/testing/test_unraisableexception.py b/testing/test_unraisableexception.py index 6c0dc542e93..a6a4d6f35e8 100644 --- a/testing/test_unraisableexception.py +++ b/testing/test_unraisableexception.py @@ -1,7 +1,5 @@ from __future__ import annotations -from collections.abc import Generator -import contextlib import gc import sys from unittest import mock @@ -229,19 +227,13 @@ def _set_gc_state(enabled: bool) -> bool: return was_enabled -@contextlib.contextmanager -def _disable_gc() -> Generator[None]: - was_enabled = _set_gc_state(enabled=False) - try: - yield - finally: - _set_gc_state(enabled=was_enabled) - - def test_refcycle_unraisable(pytester: Pytester) -> None: # see: https://github.com/pytest-dev/pytest/issues/10404 pytester.makepyfile( test_it=""" + # Should catch the unraisable exception even if gc is disabled. + import gc; gc.disable() + import pytest class BrokenDel: @@ -256,23 +248,22 @@ def test_it(): """ ) - with _disable_gc(): - result = pytester.runpytest() + result = pytester.runpytest_subprocess( + "-Wdefault::pytest.PytestUnraisableExceptionWarning" + ) - # TODO: should be a test failure or error - assert result.ret == pytest.ExitCode.INTERNAL_ERROR + assert result.ret == 0 result.assert_outcomes(passed=1) result.stderr.fnmatch_lines("ValueError: del is broken") -@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_refcycle_unraisable_warning_filter(pytester: Pytester) -> None: - # note that the host pytest warning filter is disabled and the pytester - # warning filter applies during config teardown of unraisablehook. - # see: https://github.com/pytest-dev/pytest/issues/10404 pytester.makepyfile( test_it=""" + # Should catch the unraisable exception even if gc is disabled. + import gc; gc.disable() + import pytest class BrokenDel: @@ -287,17 +278,18 @@ def test_it(): """ ) - with _disable_gc(): - result = pytester.runpytest("-Werror") + result = pytester.runpytest_subprocess( + "-Werror::pytest.PytestUnraisableExceptionWarning" + ) - # TODO: should be a test failure or error - assert result.ret == pytest.ExitCode.INTERNAL_ERROR + # TODO: Should be a test failure or error. Currently the exception + # propagates all the way to the top resulting in exit code 1. + assert result.ret == 1 result.assert_outcomes(passed=1) result.stderr.fnmatch_lines("ValueError: del is broken") -@pytest.mark.filterwarnings("default::pytest.PytestUnraisableExceptionWarning") def test_create_task_raises_unraisable_warning_filter(pytester: Pytester) -> None: # note that the host pytest warning filter is disabled and the pytester # warning filter applies during config teardown of unraisablehook. @@ -306,6 +298,9 @@ def test_create_task_raises_unraisable_warning_filter(pytester: Pytester) -> Non # the issue pytester.makepyfile( test_it=""" + # Should catch the unraisable exception even if gc is disabled. + import gc; gc.disable() + import asyncio import pytest @@ -318,11 +313,11 @@ def test_scheduler_must_be_created_within_running_loop() -> None: """ ) - with _disable_gc(): - result = pytester.runpytest("-Werror") + result = pytester.runpytest_subprocess("-Werror") - # TODO: should be a test failure or error - assert result.ret == pytest.ExitCode.INTERNAL_ERROR + # TODO: Should be a test failure or error. Currently the exception + # propagates all the way to the top resulting in exit code 1. + assert result.ret == 1 result.assert_outcomes(passed=1) result.stderr.fnmatch_lines("RuntimeWarning: coroutine 'my_task' was never awaited") From a1b3a7879589eb437e4fd97c169b228c3ed58c63 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 18:11:56 -0300 Subject: [PATCH 1252/1271] Fix compatibility with Twisted 25 (#13502) (#13531) As discussed in https://github.com/pytest-dev/pytest/pull/13502, the fix for compatibility with Twisted 25+ is simpler. Therefore, it makes sense to implement both fixes (for Twisted 24 and Twisted 25) in parallel. This way, we can eventually drop support for Twisted <25 and keep only the simpler workaround. In addition, the `unittestextras` tox environment has been replaced with dedicated test environments for `asynctest`, `Twisted 24`, and `Twisted 25`. Fixes #13497 (cherry picked from commit 01dce85a89eb0b3e881303784267f14b94d9691f) Co-authored-by: Bruno Oliveira --- .github/workflows/test.yml | 43 +++++++++- changelog/13497.bugfix.rst | 1 + src/_pytest/unittest.py | 155 ++++++++++++++++++++++++++++--------- tox.ini | 19 +++-- 4 files changed, 174 insertions(+), 44 deletions(-) create mode 100644 changelog/13497.bugfix.rst diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3ecc133878f..7873b66a49a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,7 +54,9 @@ jobs: fail-fast: false matrix: name: [ - "windows-py39-unittestextras", + "windows-py39-unittest-asynctest", + "windows-py39-unittest-twisted24", + "windows-py39-unittest-twisted25", "windows-py39-pluggy", "windows-py39-xdist", "windows-py310", @@ -63,6 +65,9 @@ jobs: "windows-py313", "windows-py314", + "ubuntu-py39-unittest-asynctest", + "ubuntu-py39-unittest-twisted24", + "ubuntu-py39-unittest-twisted25", "ubuntu-py39-lsof-numpy-pexpect", "ubuntu-py39-pluggy", "ubuntu-py39-freeze", @@ -85,10 +90,23 @@ jobs: ] include: - - name: "windows-py39-unittestextras" + # Use separate jobs for different unittest flavors (twisted, asynctest) to ensure proper coverage. + - name: "windows-py39-unittest-asynctest" python: "3.9" os: windows-latest - tox_env: "py39-unittestextras" + tox_env: "py39-asynctest" + use_coverage: true + + - name: "windows-py39-unittest-twisted24" + python: "3.9" + os: windows-latest + tox_env: "py39-twisted24" + use_coverage: true + + - name: "windows-py39-unittest-twisted25" + python: "3.9" + os: windows-latest + tox_env: "py39-twisted25" use_coverage: true - name: "windows-py39-pluggy" @@ -126,6 +144,25 @@ jobs: os: windows-latest tox_env: "py314" + # Use separate jobs for different unittest flavors (twisted, asynctest) to ensure proper coverage. + - name: "ubuntu-py39-unittest-asynctest" + python: "3.9" + os: ubuntu-latest + tox_env: "py39-asynctest" + use_coverage: true + + - name: "ubuntu-py39-unittest-twisted24" + python: "3.9" + os: ubuntu-latest + tox_env: "py39-twisted24" + use_coverage: true + + - name: "ubuntu-py39-unittest-twisted25" + python: "3.9" + os: ubuntu-latest + tox_env: "py39-twisted25" + use_coverage: true + - name: "ubuntu-py39-lsof-numpy-pexpect" python: "3.9" os: ubuntu-latest diff --git a/changelog/13497.bugfix.rst b/changelog/13497.bugfix.rst new file mode 100644 index 00000000000..75b4996e5af --- /dev/null +++ b/changelog/13497.bugfix.rst @@ -0,0 +1 @@ +Fixed compatibility with ``Twisted 25+``. diff --git a/src/_pytest/unittest.py b/src/_pytest/unittest.py index 04d50b53090..ef6ef64a062 100644 --- a/src/_pytest/unittest.py +++ b/src/_pytest/unittest.py @@ -6,11 +6,13 @@ from collections.abc import Callable from collections.abc import Generator from collections.abc import Iterable +from collections.abc import Iterator +from enum import auto +from enum import Enum import inspect import sys import traceback import types -from typing import Any from typing import TYPE_CHECKING from typing import Union @@ -18,6 +20,7 @@ from _pytest.compat import is_async_function from _pytest.config import hookimpl from _pytest.fixtures import FixtureRequest +from _pytest.monkeypatch import MonkeyPatch from _pytest.nodes import Collector from _pytest.nodes import Item from _pytest.outcomes import exit @@ -228,8 +231,7 @@ def startTest(self, testcase: unittest.TestCase) -> None: pass def _addexcinfo(self, rawexcinfo: _SysExcInfoType) -> None: - # Unwrap potential exception info (see twisted trial support below). - rawexcinfo = getattr(rawexcinfo, "_rawexcinfo", rawexcinfo) + rawexcinfo = _handle_twisted_exc_info(rawexcinfo) try: excinfo = _pytest._code.ExceptionInfo[BaseException].from_exc_info( rawexcinfo # type: ignore[arg-type] @@ -385,49 +387,130 @@ def pytest_runtest_makereport(item: Item, call: CallInfo[None]) -> None: call.excinfo = call2.excinfo -# Twisted trial support. -classImplements_has_run = False +def _is_skipped(obj) -> bool: + """Return True if the given object has been marked with @unittest.skip.""" + return bool(getattr(obj, "__unittest_skip__", False)) + + +def pytest_configure() -> None: + """Register the TestCaseFunction class as an IReporter if twisted.trial is available.""" + if _get_twisted_version() is not TwistedVersion.NotInstalled: + from twisted.trial.itrial import IReporter + from zope.interface import classImplements + + classImplements(TestCaseFunction, IReporter) + + +class TwistedVersion(Enum): + """ + The Twisted version installed in the environment. + + We have different workarounds in place for different versions of Twisted. + """ + + # Twisted version 24 or prior. + Version24 = auto() + # Twisted version 25 or later. + Version25 = auto() + # Twisted version is not available. + NotInstalled = auto() + + +def _get_twisted_version() -> TwistedVersion: + # We need to check if "twisted.trial.unittest" is specifically present in sys.modules. + # This is because we intend to integrate with Trial only when it's actively running + # the test suite, but not needed when only other Twisted components are in use. + if "twisted.trial.unittest" not in sys.modules: + return TwistedVersion.NotInstalled + + import importlib.metadata + + import packaging.version + + version_str = importlib.metadata.version("twisted") + version = packaging.version.parse(version_str) + if version.major <= 24: + return TwistedVersion.Version24 + else: + return TwistedVersion.Version25 + + +# Name of the attribute in `twisted.python.Failure` instances that stores +# the `sys.exc_info()` tuple. +# See twisted.trial support in `pytest_runtest_protocol`. +TWISTED_RAW_EXCINFO_ATTR = "_twisted_raw_excinfo" @hookimpl(wrapper=True) -def pytest_runtest_protocol(item: Item) -> Generator[None, object, object]: - if isinstance(item, TestCaseFunction) and "twisted.trial.unittest" in sys.modules: - ut: Any = sys.modules["twisted.python.failure"] - global classImplements_has_run - Failure__init__ = ut.Failure.__init__ - if not classImplements_has_run: - from twisted.trial.itrial import IReporter - from zope.interface import classImplements - - classImplements(TestCaseFunction, IReporter) - classImplements_has_run = True - - def excstore( +def pytest_runtest_protocol(item: Item) -> Iterator[None]: + if _get_twisted_version() is TwistedVersion.Version24: + import twisted.python.failure as ut + + # Monkeypatch `Failure.__init__` to store the raw exception info. + original__init__ = ut.Failure.__init__ + + def store_raw_exception_info( self, exc_value=None, exc_type=None, exc_tb=None, captureVars=None - ): + ): # pragma: no cover if exc_value is None: - self._rawexcinfo = sys.exc_info() + raw_exc_info = sys.exc_info() else: if exc_type is None: exc_type = type(exc_value) - self._rawexcinfo = (exc_type, exc_value, exc_tb) + if exc_tb is None: + exc_tb = sys.exc_info()[2] + raw_exc_info = (exc_type, exc_value, exc_tb) + setattr(self, TWISTED_RAW_EXCINFO_ATTR, tuple(raw_exc_info)) try: - Failure__init__( + original__init__( self, exc_value, exc_type, exc_tb, captureVars=captureVars ) - except TypeError: - Failure__init__(self, exc_value, exc_type, exc_tb) + except TypeError: # pragma: no cover + original__init__(self, exc_value, exc_type, exc_tb) - ut.Failure.__init__ = excstore - try: - res = yield - finally: - ut.Failure.__init__ = Failure__init__ + with MonkeyPatch.context() as patcher: + patcher.setattr(ut.Failure, "__init__", store_raw_exception_info) + return (yield) else: - res = yield - return res - - -def _is_skipped(obj) -> bool: - """Return True if the given object has been marked with @unittest.skip.""" - return bool(getattr(obj, "__unittest_skip__", False)) + return (yield) + + +def _handle_twisted_exc_info( + rawexcinfo: _SysExcInfoType | BaseException, +) -> _SysExcInfoType: + """ + Twisted passes a custom Failure instance to `addError()` instead of using `sys.exc_info()`. + Therefore, if `rawexcinfo` is a `Failure` instance, convert it into the equivalent `sys.exc_info()` tuple + as expected by pytest. + """ + twisted_version = _get_twisted_version() + if twisted_version is TwistedVersion.NotInstalled: + # Unfortunately, because we cannot import `twisted.python.failure` at the top of the file + # and use it in the signature, we need to use `type:ignore` here because we cannot narrow + # the type properly in the `if` statement above. + return rawexcinfo # type:ignore[return-value] + elif twisted_version is TwistedVersion.Version24: + # Twisted calls addError() passing its own classes (like `twisted.python.Failure`), which violates + # the `addError()` signature, so we extract the original `sys.exc_info()` tuple which is stored + # in the object. + if hasattr(rawexcinfo, TWISTED_RAW_EXCINFO_ATTR): + saved_exc_info = getattr(rawexcinfo, TWISTED_RAW_EXCINFO_ATTR) + # Delete the attribute from the original object to avoid leaks. + delattr(rawexcinfo, TWISTED_RAW_EXCINFO_ATTR) + return saved_exc_info # type:ignore[no-any-return] + return rawexcinfo # type:ignore[return-value] + elif twisted_version is TwistedVersion.Version25: + if isinstance(rawexcinfo, BaseException): + import twisted.python.failure + + if isinstance(rawexcinfo, twisted.python.failure.Failure): + tb = rawexcinfo.__traceback__ + if tb is None: + tb = sys.exc_info()[2] + return type(rawexcinfo.value), rawexcinfo.value, tb + + return rawexcinfo # type:ignore[return-value] + else: + # Ideally we would use assert_never() here, but it is not available in all Python versions + # we support, plus we do not require `type_extensions` currently. + assert False, f"Unexpected Twisted version: {twisted_version}" diff --git a/tox.ini b/tox.ini index 8f7d8495285..f1283aa8260 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ envlist = py313 py314 pypy3 - py39-{pexpect,xdist,unittestextras,numpy,pluggymain,pylib} + py39-{pexpect,xdist,twisted24,twisted25,asynctest,numpy,pluggymain,pylib} doctesting doctesting-coverage plugins @@ -36,7 +36,9 @@ description = pexpect: against `pexpect` pluggymain: against the bleeding edge `pluggy` from Git pylib: against `py` lib - unittestextras: against the unit test extras + twisted24: against the unit test extras with twisted prior to 24.0 + twisted25: against the unit test extras with twisted 25.0 or later + asynctest: against the unit test extras with asynctest xdist: with pytest in parallel mode under `{basepython}` doctesting: including doctests @@ -51,7 +53,7 @@ passenv = TERM SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST setenv = - _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:} + _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:} {env:_PYTEST_FILES:} # See https://docs.python.org/3/library/io.html#io-encoding-warning # If we don't enable this, neither can any of our downstream users! @@ -66,6 +68,12 @@ setenv = doctesting: _PYTEST_TOX_POSARGS_DOCTESTING=doc/en + # The configurations below are related only to standard unittest support. + # Run only tests from test_unittest.py. + asynctest: _PYTEST_FILES=testing/test_unittest.py + twisted24: _PYTEST_FILES=testing/test_unittest.py + twisted25: _PYTEST_FILES=testing/test_unittest.py + nobyte: PYTHONDONTWRITEBYTECODE=1 lsof: _PYTEST_TOX_POSARGS_LSOF=--lsof @@ -79,8 +87,9 @@ deps = pexpect: pexpect>=4.8.0 pluggymain: pluggy @ git+https://github.com/pytest-dev/pluggy.git pylib: py>=1.8.2 - unittestextras: twisted - unittestextras: asynctest + twisted24: twisted<25 + twisted25: twisted>=25 + asynctest: asynctest xdist: pytest-xdist>=2.1.0 xdist: -e . {env:_PYTEST_TOX_EXTRA_DEP:} From d0c7ed0bfae5a5f1f9153cd1e464a421d701e925 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 21:35:14 +0000 Subject: [PATCH 1253/1271] Reintroduce PytestReturnNotNoneWarning (#13495) (#13527) Since this warning is meant to be permanent, added proper documentation to the `assert` section in the docs. Fixes #13477 (cherry picked from commit 53f05c44d9530c4ac5ce5804ef75fe61713d46d8) Co-authored-by: Bruno Oliveira --- changelog/13477.bugfix.rst | 5 ++++ doc/en/deprecations.rst | 40 ------------------------------- doc/en/how-to/assert.rst | 44 ++++++++++++++++++++++++++++++++++ doc/en/reference/reference.rst | 3 +++ src/_pytest/python.py | 13 +++++----- src/_pytest/warning_types.py | 11 +++++++++ src/pytest/__init__.py | 2 ++ testing/acceptance_test.py | 4 ++-- 8 files changed, 74 insertions(+), 48 deletions(-) create mode 100644 changelog/13477.bugfix.rst diff --git a/changelog/13477.bugfix.rst b/changelog/13477.bugfix.rst new file mode 100644 index 00000000000..7b7f875df09 --- /dev/null +++ b/changelog/13477.bugfix.rst @@ -0,0 +1,5 @@ +Reintroduced :class:`pytest.PytestReturnNotNoneWarning` which was removed by accident in pytest `8.4`. + +This warning is raised when a test functions returns a value other than ``None``, which is often a mistake made by beginners. + +See :ref:`return-not-none` for more information. diff --git a/doc/en/deprecations.rst b/doc/en/deprecations.rst index 18df64c9204..6897fb28fc1 100644 --- a/doc/en/deprecations.rst +++ b/doc/en/deprecations.rst @@ -316,46 +316,6 @@ Users expected in this case that the ``usefixtures`` mark would have its intende Now pytest will issue a warning when it encounters this problem, and will raise an error in the future versions. -Returning non-None value in test functions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. deprecated:: 7.2 - -A ``pytest.PytestReturnNotNoneWarning`` is now emitted if a test function returns something other than `None`. - -This prevents a common mistake among beginners that expect that returning a `bool` would cause a test to pass or fail, for example: - -.. code-block:: python - - @pytest.mark.parametrize( - ["a", "b", "result"], - [ - [1, 2, 5], - [2, 3, 8], - [5, 3, 18], - ], - ) - def test_foo(a, b, result): - return foo(a, b) == result - -Given that pytest ignores the return value, this might be surprising that it will never fail. - -The proper fix is to change the `return` to an `assert`: - -.. code-block:: python - - @pytest.mark.parametrize( - ["a", "b", "result"], - [ - [1, 2, 5], - [2, 3, 8], - [5, 3, 18], - ], - ) - def test_foo(a, b, result): - assert foo(a, b) == result - - The ``yield_fixture`` function/decorator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/en/how-to/assert.rst b/doc/en/how-to/assert.rst index 6bc8f6fed33..c83fb93c4b1 100644 --- a/doc/en/how-to/assert.rst +++ b/doc/en/how-to/assert.rst @@ -476,6 +476,50 @@ the conftest file: FAILED test_foocompare.py::test_compare - assert Comparing Foo instances: 1 failed in 0.12s +.. _`return-not-none`: + +Returning non-None value in test functions +------------------------------------------ + +A :class:`pytest.PytestReturnNotNoneWarning` is emitted when a test function returns a value other than ``None``. + +This helps prevent a common mistake made by beginners who assume that returning a ``bool`` (e.g., ``True`` or ``False``) will determine whether a test passes or fails. + +Example: + +.. code-block:: python + + @pytest.mark.parametrize( + ["a", "b", "result"], + [ + [1, 2, 5], + [2, 3, 8], + [5, 3, 18], + ], + ) + def test_foo(a, b, result): + return foo(a, b) == result # Incorrect usage, do not do this. + +Since pytest ignores return values, it might be surprising that the test will never fail based on the returned value. + +The correct fix is to replace the ``return`` statement with an ``assert``: + +.. code-block:: python + + @pytest.mark.parametrize( + ["a", "b", "result"], + [ + [1, 2, 5], + [2, 3, 8], + [5, 3, 18], + ], + ) + def test_foo(a, b, result): + assert foo(a, b) == result + + + + .. _assert-details: .. _`assert introspection`: diff --git a/doc/en/reference/reference.rst b/doc/en/reference/reference.rst index b0535ef6589..cfdc3eb3421 100644 --- a/doc/en/reference/reference.rst +++ b/doc/en/reference/reference.rst @@ -1274,6 +1274,9 @@ Custom warnings generated in some situations such as improper usage or deprecate .. autoclass:: pytest.PytestExperimentalApiWarning :show-inheritance: +.. autoclass:: pytest.PytestReturnNotNoneWarning + :show-inheritance: + .. autoclass:: pytest.PytestRemovedIn9Warning :show-inheritance: diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 82aab85a300..8e4fb041532 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -73,6 +73,7 @@ from _pytest.scope import Scope from _pytest.stash import StashKey from _pytest.warning_types import PytestCollectionWarning +from _pytest.warning_types import PytestReturnNotNoneWarning if TYPE_CHECKING: @@ -157,12 +158,12 @@ def pytest_pyfunc_call(pyfuncitem: Function) -> object | None: if hasattr(result, "__await__") or hasattr(result, "__aiter__"): async_fail(pyfuncitem.nodeid) elif result is not None: - fail( - ( - f"Expected None, but test returned {result!r}. " - "Did you mean to use `assert` instead of `return`?" - ), - pytrace=False, + warnings.warn( + PytestReturnNotNoneWarning( + f"Test functions should return None, but {pyfuncitem.nodeid} returned {type(result)!r}.\n" + "Did you mean to use `assert` instead of `return`?\n" + "See https://docs.pytest.org/en/stable/how-to/assert.html#return-not-none for more information." + ) ) return True diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py index 8c9ff2d9a36..5e78debb682 100644 --- a/src/_pytest/warning_types.py +++ b/src/_pytest/warning_types.py @@ -71,6 +71,17 @@ def simple(cls, apiname: str) -> PytestExperimentalApiWarning: return cls(f"{apiname} is an experimental api that may change over time") +@final +class PytestReturnNotNoneWarning(PytestWarning): + """ + Warning emitted when a test function returns a value other than ``None``. + + See :ref:`return-not-none` for details. + """ + + __module__ = "pytest" + + @final class PytestUnknownMarkWarning(PytestWarning): """Warning emitted on use of unknown markers. diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py index e36d3e704c1..297b524bcc2 100644 --- a/src/pytest/__init__.py +++ b/src/pytest/__init__.py @@ -82,6 +82,7 @@ from _pytest.warning_types import PytestExperimentalApiWarning from _pytest.warning_types import PytestFDWarning from _pytest.warning_types import PytestRemovedIn9Warning +from _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledThreadExceptionWarning from _pytest.warning_types import PytestUnknownMarkWarning from _pytest.warning_types import PytestUnraisableExceptionWarning @@ -132,6 +133,7 @@ "PytestFDWarning", "PytestPluginManager", "PytestRemovedIn9Warning", + "PytestReturnNotNoneWarning", "PytestUnhandledThreadExceptionWarning", "PytestUnknownMarkWarning", "PytestUnraisableExceptionWarning", diff --git a/testing/acceptance_test.py b/testing/acceptance_test.py index 4948e3ff8ae..2101fe9ad76 100644 --- a/testing/acceptance_test.py +++ b/testing/acceptance_test.py @@ -1489,7 +1489,8 @@ def test_no_brokenpipeerror_message(pytester: Pytester) -> None: popen.stderr.close() -def test_function_return_non_none_error(pytester: Pytester) -> None: +@pytest.mark.filterwarnings("default") +def test_function_return_non_none_warning(pytester: Pytester) -> None: pytester.makepyfile( """ def test_stuff(): @@ -1497,7 +1498,6 @@ def test_stuff(): """ ) res = pytester.runpytest() - res.assert_outcomes(failed=1) res.stdout.fnmatch_lines(["*Did you mean to use `assert` instead of `return`?*"]) From 5dc5880715633c97310c0593f0ae356de27fa933 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 21:39:34 +0000 Subject: [PATCH 1254/1271] docs: update pytest.ini addopts example to use separate -p entries (#13529) (#13532) (cherry picked from commit 40a1713d42187732d0095dd1623b1424fb2bc489) Co-authored-by: Iwithyou2025 --- doc/en/how-to/plugins.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/en/how-to/plugins.rst b/doc/en/how-to/plugins.rst index fca8ab54e63..b2cb1cda5c3 100644 --- a/doc/en/how-to/plugins.rst +++ b/doc/en/how-to/plugins.rst @@ -154,7 +154,10 @@ manually specify each plugin with ``-p`` or :envvar:`PYTEST_PLUGINS`, you can us .. code-block:: ini [pytest] - addopts = --disable-plugin-autoload -p NAME,NAME2 + addopts = + --disable-plugin-autoload + -p NAME + -p NAME2 .. versionadded:: 8.4 From 8d99211f0ce3927eb7ee579f7b4f969da06dc787 Mon Sep 17 00:00:00 2001 From: pytest bot Date: Tue, 17 Jun 2025 21:56:14 +0000 Subject: [PATCH 1255/1271] Prepare release version 8.4.1 --- changelog/13461.bugfix.rst | 3 --- changelog/13477.bugfix.rst | 5 ----- changelog/13492.doc.rst | 1 - changelog/13497.bugfix.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.4.1.rst | 21 +++++++++++++++++++++ doc/en/changelog.rst | 28 ++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 +++--- doc/en/example/pythoncollection.rst | 4 ++-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 11 files changed, 57 insertions(+), 17 deletions(-) delete mode 100644 changelog/13461.bugfix.rst delete mode 100644 changelog/13477.bugfix.rst delete mode 100644 changelog/13492.doc.rst delete mode 100644 changelog/13497.bugfix.rst create mode 100644 doc/en/announce/release-8.4.1.rst diff --git a/changelog/13461.bugfix.rst b/changelog/13461.bugfix.rst deleted file mode 100644 index 4b45f7cc9da..00000000000 --- a/changelog/13461.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Corrected ``_pytest.terminal.TerminalReporter.isatty`` to support -being called as a method. Before it was just a boolean which could -break correct code when using ``-o log_cli=true``). diff --git a/changelog/13477.bugfix.rst b/changelog/13477.bugfix.rst deleted file mode 100644 index 7b7f875df09..00000000000 --- a/changelog/13477.bugfix.rst +++ /dev/null @@ -1,5 +0,0 @@ -Reintroduced :class:`pytest.PytestReturnNotNoneWarning` which was removed by accident in pytest `8.4`. - -This warning is raised when a test functions returns a value other than ``None``, which is often a mistake made by beginners. - -See :ref:`return-not-none` for more information. diff --git a/changelog/13492.doc.rst b/changelog/13492.doc.rst deleted file mode 100644 index 6e3f72a860e..00000000000 --- a/changelog/13492.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed outdated warning about ``faulthandler`` not working on Windows. diff --git a/changelog/13497.bugfix.rst b/changelog/13497.bugfix.rst deleted file mode 100644 index 75b4996e5af..00000000000 --- a/changelog/13497.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed compatibility with ``Twisted 25+``. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 702fd26dd0d..2ed23eb1fbb 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.4.1 release-8.4.0 release-8.3.5 release-8.3.4 diff --git a/doc/en/announce/release-8.4.1.rst b/doc/en/announce/release-8.4.1.rst new file mode 100644 index 00000000000..07ee26187a7 --- /dev/null +++ b/doc/en/announce/release-8.4.1.rst @@ -0,0 +1,21 @@ +pytest-8.4.1 +======================================= + +pytest 8.4.1 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* Bruno Oliveira +* Iwithyou2025 +* John Litborn +* Martin Fischer +* Ran Benita +* SarahPythonista + + +Happy testing, +The pytest Development Team diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 73073ffca1c..63623de8aad 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,34 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.4.1 (2025-06-17) +========================= + +Bug fixes +--------- + +- `#13461 `_: Corrected ``_pytest.terminal.TerminalReporter.isatty`` to support + being called as a method. Before it was just a boolean which could + break correct code when using ``-o log_cli=true``). + + +- `#13477 `_: Reintroduced :class:`pytest.PytestReturnNotNoneWarning` which was removed by accident in pytest `8.4`. + + This warning is raised when a test functions returns a value other than ``None``, which is often a mistake made by beginners. + + See :ref:`return-not-none` for more information. + + +- `#13497 `_: Fixed compatibility with ``Twisted 25+``. + + + +Improved documentation +---------------------- + +- `#13492 `_: Fixed outdated warning about ``faulthandler`` not working on Windows. + + pytest 8.4.0 (2025-06-02) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index a7ec55dff0a..8e6479254bb 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 760140390cb..01a8f48fdbf 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index c92e97f556e..c5e9f708828 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.4.0 + pytest 8.4.1 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index a86fd1065fd..62ace745d43 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1423,7 +1423,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - + From 9bce91ec7a0b97aafcb3dff19842a29c1ff25287 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 18 Jun 2025 10:14:59 +0300 Subject: [PATCH 1256/1271] Merge pull request #13524 from bluetech/gh-release ci: replace softprops/action-gh-release with `gh release create` command (cherry picked from commit 0682cbe50641e56a3a4b0a4a2ada938cbcdd668d) --- .github/workflows/deploy.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9e63bc68cfd..ba593c7c3a9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -109,8 +109,8 @@ jobs: tox -e generate-gh-release-notes -- "$VERSION" scripts/latest-release-notes.md - name: Publish GitHub Release - uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 - with: - body_path: scripts/latest-release-notes.md - files: dist/* - tag_name: ${{ github.event.inputs.version }} + env: + VERSION: ${{ github.event.inputs.version }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create --notes-file scripts/latest-release-notes.md --verify-tag "$VERSION" dist/* From de35402caed866ce3dd552bcc50a80f5385c8219 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Wed, 18 Jun 2025 11:27:51 +0300 Subject: [PATCH 1257/1271] Merge pull request #13481 from mgorny/pass-werror testing: Explicitly pass `-Werror` to tests needing it (cherry picked from commit 667398f53b7ca9a19a540054b03d505b84379114) --- changelog/13480.bugfix.rst | 1 + testing/test_threadexception.py | 2 +- testing/test_warnings.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/13480.bugfix.rst diff --git a/changelog/13480.bugfix.rst b/changelog/13480.bugfix.rst new file mode 100644 index 00000000000..ed649a33516 --- /dev/null +++ b/changelog/13480.bugfix.rst @@ -0,0 +1 @@ +Fixed a few test failures in pytest's own test suite when run with ``-Wdefault`` or a similar override. diff --git a/testing/test_threadexception.py b/testing/test_threadexception.py index 5dad07b8b85..f4595ec435d 100644 --- a/testing/test_threadexception.py +++ b/testing/test_threadexception.py @@ -211,7 +211,7 @@ def test_it(request): """ ) - result = pytester.runpytest() + result = pytester.runpytest("-Werror") # TODO: should be a test failure or error assert result.ret == pytest.ExitCode.INTERNAL_ERROR diff --git a/testing/test_warnings.py b/testing/test_warnings.py index c302e7c6e3c..b1c64dc9332 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -149,6 +149,7 @@ def test_func(fix): ) +@pytest.mark.skip("issue #13485") def test_works_with_filterwarnings(pytester: Pytester) -> None: """Ensure our warnings capture does not mess with pre-installed filters (#2430).""" pytester.makepyfile( From 240454f253b819be994f3d509aa3e78f105b0829 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 06:17:52 -0300 Subject: [PATCH 1258/1271] prepare-release-pr: open PRs as draft (#13534) (#13539) This way we can trigger the CI jobs just by marking the draft as ready, similar to how the `update-plugin-list` workflow works. (cherry picked from commit d66a761dc91283556c768e59371dc62d6880c296) Co-authored-by: Bruno Oliveira --- scripts/prepare-release-pr.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/prepare-release-pr.py b/scripts/prepare-release-pr.py index c420a80b3d2..b288e3b3982 100644 --- a/scripts/prepare-release-pr.py +++ b/scripts/prepare-release-pr.py @@ -135,6 +135,7 @@ def prepare_release_pr(base_branch: str, is_major: bool, prerelease: str) -> Non f"--head={release_branch}", f"--title=Release {version}", f"--body={body}", + "--draft", ], check=True, ) From 5bc2f477e6fb39bce4931f26153af173c9aabe99 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 22 Jun 2025 15:44:16 +0000 Subject: [PATCH 1259/1271] Self-test: fix test_doctest_unexpected_exception in Python 3.14 (#13548) (#13552) Fixes #13547. (cherry picked from commit 48be3c8bce38bc950dba82747d3ecf451a3f45c8) Co-authored-by: bengartner --- changelog/13547.contrib.rst | 1 + testing/test_doctest.py | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 changelog/13547.contrib.rst diff --git a/changelog/13547.contrib.rst b/changelog/13547.contrib.rst new file mode 100644 index 00000000000..d8a240c0506 --- /dev/null +++ b/changelog/13547.contrib.rst @@ -0,0 +1 @@ +Self-testing: corrected expected message for ``test_doctest_unexpected_exception`` in Python ``3.14``. diff --git a/testing/test_doctest.py b/testing/test_doctest.py index 1a852ebc82a..f4ed976c839 100644 --- a/testing/test_doctest.py +++ b/testing/test_doctest.py @@ -223,9 +223,12 @@ def test_doctest_unexpected_exception(self, pytester: Pytester): "002 >>> 0 / i", "UNEXPECTED EXCEPTION: ZeroDivisionError*", "Traceback (most recent call last):", - ' File "*/doctest.py", line *, in __run', - " *", - *((" *^^^^*", " *", " *") if sys.version_info >= (3, 13) else ()), + *( + (' File "*/doctest.py", line *, in __run', " *") + if sys.version_info <= (3, 14) + else () + ), + *((" *^^^^*", " *", " *") if sys.version_info[:2] == (3, 13) else ()), ' File "", line 1, in ', "ZeroDivisionError: division by zero", "*/test_doctest_unexpected_exception.txt:2: UnexpectedException", From 242522a10f59e4051c1f11a25c001fb2755eb2b1 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 22 Jun 2025 16:13:14 +0000 Subject: [PATCH 1260/1271] Defer annotation eval on Python 3.14 (#13550) (#13553) Fixes #13549 (cherry picked from commit 8ca783cf4a3b4007f513a7446b7069d4dac52587) Co-authored-by: Marc Mueller <30130371+cdce8p@users.noreply.github.com> --- changelog/13549.bugfix.rst | 3 +++ src/_pytest/compat.py | 13 ++++++++++++- src/_pytest/fixtures.py | 5 +++-- src/_pytest/nodes.py | 2 +- testing/test_collection.py | 40 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 changelog/13549.bugfix.rst diff --git a/changelog/13549.bugfix.rst b/changelog/13549.bugfix.rst new file mode 100644 index 00000000000..e69f6a4d6cf --- /dev/null +++ b/changelog/13549.bugfix.rst @@ -0,0 +1,3 @@ +No longer evaluate type annotations in Python ``3.14`` when inspecting function signatures. + +This prevents crashes during module collection when modules do not explicitly use ``from __future__ import annotations`` and import types for annotations within a ``if TYPE_CHECKING:`` block. diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index 7d71838be51..bef8c317bb9 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -8,7 +8,7 @@ import functools import inspect from inspect import Parameter -from inspect import signature +from inspect import Signature import os from pathlib import Path import sys @@ -19,6 +19,10 @@ import py +if sys.version_info >= (3, 14): + from annotationlib import Format + + #: constant to prepare valuing pylib path replacements/lazy proxies later on # intended for removal in pytest 8.0 or 9.0 @@ -60,6 +64,13 @@ def is_async_function(func: object) -> bool: return iscoroutinefunction(func) or inspect.isasyncgenfunction(func) +def signature(obj: Callable[..., Any]) -> Signature: + """Return signature without evaluating annotations.""" + if sys.version_info >= (3, 14): + return inspect.signature(obj, annotation_format=Format.STRING) + return inspect.signature(obj) + + def getlocation(function, curdir: str | os.PathLike[str] | None = None) -> str: function = get_real_func(function) fn = Path(inspect.getfile(function)) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 92a301e79db..421237e35a0 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -49,6 +49,7 @@ from _pytest.compat import NotSetType from _pytest.compat import safe_getattr from _pytest.compat import safe_isclass +from _pytest.compat import signature from _pytest.config import _PluggyPlugin from _pytest.config import Config from _pytest.config import ExitCode @@ -804,8 +805,8 @@ def _format_fixturedef_line(self, fixturedef: FixtureDef[object]) -> str: path, lineno = getfslineno(factory) if isinstance(path, Path): path = bestrelpath(self._pyfuncitem.session.path, path) - signature = inspect.signature(factory) - return f"{path}:{lineno + 1}: def {factory.__name__}{signature}" + sig = signature(factory) + return f"{path}:{lineno + 1}: def {factory.__name__}{sig}" def addfinalizer(self, finalizer: Callable[[], object]) -> None: self._fixturedef.addfinalizer(finalizer) diff --git a/src/_pytest/nodes.py b/src/_pytest/nodes.py index 6d39de95f5b..6690f6ab1f8 100644 --- a/src/_pytest/nodes.py +++ b/src/_pytest/nodes.py @@ -8,7 +8,6 @@ from collections.abc import MutableMapping from functools import cached_property from functools import lru_cache -from inspect import signature import os import pathlib from pathlib import Path @@ -29,6 +28,7 @@ from _pytest._code.code import Traceback from _pytest._code.code import TracebackStyle from _pytest.compat import LEGACY_PATH +from _pytest.compat import signature from _pytest.config import Config from _pytest.config import ConftestImportFailure from _pytest.config.compat import _check_path diff --git a/testing/test_collection.py b/testing/test_collection.py index ccd57eeef43..7cb20734e0d 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1895,3 +1895,43 @@ def test_with_yield(): ) # Assert that no tests were collected result.stdout.fnmatch_lines(["*collected 0 items*"]) + + +def test_annotations_deferred_future(pytester: Pytester): + """Ensure stringified annotations don't raise any errors.""" + pytester.makepyfile( + """ + from __future__ import annotations + import pytest + + @pytest.fixture + def func() -> X: ... # X is undefined + + def test_func(): + assert True + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + result.stdout.fnmatch_lines(["*1 passed*"]) + + +@pytest.mark.skipif( + sys.version_info < (3, 14), reason="Annotations are only skipped on 3.14+" +) +def test_annotations_deferred_314(pytester: Pytester): + """Ensure annotation eval is deferred.""" + pytester.makepyfile( + """ + import pytest + + @pytest.fixture + def func() -> X: ... # X is undefined + + def test_func(): + assert True + """ + ) + result = pytester.runpytest() + assert result.ret == 0 + result.stdout.fnmatch_lines(["*1 passed*"]) From 7b21af10940143b74bb996c928b77bcb2d354c46 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Sun, 22 Jun 2025 14:07:00 -0300 Subject: [PATCH 1261/1271] Fix `approx` usage with `decimal.FloatOperation` trap set (#13543) (#13555) Fixes #13530 --------- (cherry picked from commit 111685cc506fbaf87c105e67d68fbd881a47a84b) Co-authored-by: Aditi De <92822822+coder-aditi@users.noreply.github.com> Co-authored-by: AD Co-authored-by: Bruno Oliveira --- changelog/13530.bugfix.rst | 1 + src/_pytest/python_api.py | 19 +++++++++++++++++++ testing/python/approx.py | 6 ++++++ 3 files changed, 26 insertions(+) create mode 100644 changelog/13530.bugfix.rst diff --git a/changelog/13530.bugfix.rst b/changelog/13530.bugfix.rst new file mode 100644 index 00000000000..1a5ab365f12 --- /dev/null +++ b/changelog/13530.bugfix.rst @@ -0,0 +1 @@ +Fixed a crash when using :func:`pytest.approx` and :class:`decimal.Decimal` instances with the :class:`decimal.FloatOperation` trap set. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 77b0edc0ac5..31a366251cf 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -531,6 +531,25 @@ class ApproxDecimal(ApproxScalar): DEFAULT_ABSOLUTE_TOLERANCE = Decimal("1e-12") DEFAULT_RELATIVE_TOLERANCE = Decimal("1e-6") + def __repr__(self) -> str: + if isinstance(self.rel, float): + rel = Decimal.from_float(self.rel) + else: + rel = self.rel + + if isinstance(self.abs, float): + abs_ = Decimal.from_float(self.abs) + else: + abs_ = self.abs + + tol_str = "???" + if rel is not None and Decimal("1e-3") <= rel <= Decimal("1e3"): + tol_str = f"{rel:.1e}" + elif abs_ is not None: + tol_str = f"{abs_:.1e}" + + return f"{self.expected} ± {tol_str}" + def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: """Assert that two numbers (or two ordered sequences of numbers) are equal to each other diff --git a/testing/python/approx.py b/testing/python/approx.py index 75b57b6965c..2ca7ee70945 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -2,6 +2,7 @@ from __future__ import annotations from contextlib import contextmanager +import decimal from decimal import Decimal from fractions import Fraction from math import sqrt @@ -1015,6 +1016,11 @@ def __len__(self): expected_repr = "approx([1 ± 1.0e-06, 2 ± 2.0e-06, 3 ± 3.0e-06, 4 ± 4.0e-06])" assert repr(approx(expected)) == expected_repr + def test_decimal_approx_repr(self, monkeypatch) -> None: + monkeypatch.setitem(decimal.getcontext().traps, decimal.FloatOperation, True) + approx_obj = pytest.approx(decimal.Decimal("2.60")) + assert decimal.Decimal("2.600001") == approx_obj + def test_allow_ordered_sequences_only(self) -> None: """pytest.approx() should raise an error on unordered sequences (#9692).""" with pytest.raises(TypeError, match="only supports ordered sequences"): From 586bef6fb431c93e7fe99abdf281db8ea481e9f3 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 08:16:13 -0300 Subject: [PATCH 1262/1271] Rename 13480.bugfix to 13480.contrib (#13554) (#13561) Since this is related only to internal testing and does not affect end-users, it is more appropriate to announce it in the "Contributor" section of the changelog. Follow up to #13481. (cherry picked from commit cc580b53beb09ab8385c9fa4c9532aa90a294ded) Co-authored-by: Bruno Oliveira --- changelog/13480.bugfix.rst | 1 - changelog/13480.contrib.rst | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 changelog/13480.bugfix.rst create mode 100644 changelog/13480.contrib.rst diff --git a/changelog/13480.bugfix.rst b/changelog/13480.bugfix.rst deleted file mode 100644 index ed649a33516..00000000000 --- a/changelog/13480.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a few test failures in pytest's own test suite when run with ``-Wdefault`` or a similar override. diff --git a/changelog/13480.contrib.rst b/changelog/13480.contrib.rst new file mode 100644 index 00000000000..9079c6f6b5a --- /dev/null +++ b/changelog/13480.contrib.rst @@ -0,0 +1 @@ +Self-testing: fixed a few test failures when run with ``-Wdefault`` or a similar override. From d879a523e2c14e6b6cee5fed288ce0d46925dcb4 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 24 Jun 2025 17:05:43 +0000 Subject: [PATCH 1263/1271] Add `int` and `float` variants to Parser.addini (#13560) (#13562) Fixes #13559. --------- (cherry picked from commit ae7346114d65e3a2c0ccd77af8a0ca00012cd91d) Co-authored-by: NayeemJohn <44828643+NayeemJohnY@users.noreply.github.com> Co-authored-by: Bruno Oliveira --- changelog/13559.bugfix.rst | 1 + src/_pytest/config/argparsing.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 changelog/13559.bugfix.rst diff --git a/changelog/13559.bugfix.rst b/changelog/13559.bugfix.rst new file mode 100644 index 00000000000..69036f784ac --- /dev/null +++ b/changelog/13559.bugfix.rst @@ -0,0 +1 @@ +Added missing `int` and `float` variants to the `Literal` type annotation of the `type` parameter in :meth:`pytest.Parser.addini`. diff --git a/src/_pytest/config/argparsing.py b/src/_pytest/config/argparsing.py index 948dfe8a510..8d4ed823325 100644 --- a/src/_pytest/config/argparsing.py +++ b/src/_pytest/config/argparsing.py @@ -174,7 +174,9 @@ def addini( self, name: str, help: str, - type: Literal["string", "paths", "pathlist", "args", "linelist", "bool"] + type: Literal[ + "string", "paths", "pathlist", "args", "linelist", "bool", "int", "float" + ] | None = None, default: Any = NOT_SET, ) -> None: From cdf9f6b87fb0f826bfa1f778fbaa74f8838b4a99 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Wed, 25 Jun 2025 14:53:44 +0000 Subject: [PATCH 1264/1271] pytest.approx: import numpy conditionally (#13563) (#13566) This matches existing conditional-import behavior in `pytest.approx`, and improves runtime for users of `pytest.approx` and not `numpy`. (cherry picked from commit ecc55b435ffd8be19146c75b215886d38421beed) Co-authored-by: Liam DeVoe --- AUTHORS | 1 + changelog/13563.bugfix.rst | 1 + src/_pytest/python_api.py | 7 ++----- 3 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 changelog/13563.bugfix.rst diff --git a/AUTHORS b/AUTHORS index e5b863e71f1..df338aa8c6e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -261,6 +261,7 @@ Leonardus Chen Lev Maximov Levon Saldamli Lewis Cowles +Liam DeVoe Llandy Riveron Del Risco Loic Esteve lovetheguitar diff --git a/changelog/13563.bugfix.rst b/changelog/13563.bugfix.rst new file mode 100644 index 00000000000..543552e20cf --- /dev/null +++ b/changelog/13563.bugfix.rst @@ -0,0 +1 @@ +:func:`pytest.approx` now only imports ``numpy`` if NumPy is already in ``sys.modules``. This fixes unconditional import behavior introduced in `8.4.0`. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 31a366251cf..74346c34976 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -426,12 +426,9 @@ def is_bool(val: Any) -> bool: # Check if `val` is a native bool or numpy bool. if isinstance(val, bool): return True - try: - import numpy as np - + if np := sys.modules.get("numpy"): return isinstance(val, np.bool_) - except ImportError: - return False + return False asarray = _as_numpy_array(actual) if asarray is not None: From f87289c36c8dbe7740e3020f5546b6f8b0861ff0 Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 21:34:44 +0000 Subject: [PATCH 1265/1271] Fix crash with `times` output style and skipped module (#13573) (#13579) Fixes #13478 --------- (cherry picked from commit c5a75f2498c86850c4ce13bcf10d56efc92394a4) Co-authored-by: Aditi De <92822822+coder-aditi@users.noreply.github.com> Co-authored-by: AD Co-authored-by: Bruno Oliveira --- changelog/13478.bugfix.rst | 1 + src/_pytest/terminal.py | 4 +++- testing/test_terminal.py | 25 +++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 changelog/13478.bugfix.rst diff --git a/changelog/13478.bugfix.rst b/changelog/13478.bugfix.rst new file mode 100644 index 00000000000..1147ee54c9e --- /dev/null +++ b/changelog/13478.bugfix.rst @@ -0,0 +1 @@ +Fixed a crash when using :confval:`console_output_style` with ``times`` and a module is skipped. diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 5f27c46b41e..a95f79ba6b6 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -734,7 +734,9 @@ def _get_progress_information_message(self) -> str: last_in_module = tests_completed == tests_in_module if self.showlongtestinfo or last_in_module: self._timing_nodeids_reported.update(r.nodeid for r in not_reported) - return format_node_duration(sum(r.duration for r in not_reported)) + return format_node_duration( + sum(r.duration for r in not_reported if isinstance(r, TestReport)) + ) return "" if collected: return f" [{len(self._progress_nodeids_reported) * 100 // collected:3d}%]" diff --git a/testing/test_terminal.py b/testing/test_terminal.py index 3ea10195c6b..8c50311e9aa 100644 --- a/testing/test_terminal.py +++ b/testing/test_terminal.py @@ -112,6 +112,31 @@ def test_func(): [" def test_func():", "> assert 0", "E assert 0"] ) + def test_console_output_style_times_with_skipped_and_passed( + self, pytester: Pytester + ) -> None: + pytester.makepyfile( + test_repro=""" + def test_hello(): + pass + """, + test_repro_skip=""" + import pytest + pytest.importorskip("fakepackage_does_not_exist") + """, + ) + result = pytester.runpytest( + "test_repro.py", + "test_repro_skip.py", + "-o", + "console_output_style=times", + ) + + result.stdout.fnmatch_lines("* 1 passed, 1 skipped in *") + + combined = "\n".join(result.stdout.lines + result.stderr.lines) + assert "INTERNALERROR" not in combined + def test_internalerror(self, pytester: Pytester, linecomp) -> None: modcol = pytester.getmodulecol("def test_one(): pass") rep = TerminalReporter(modcol.config, file=linecomp.stringio) From dc6e3be2ddc75a149b6d102d9b7c82ee47a00cfa Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 18 Jul 2025 22:18:13 +0200 Subject: [PATCH 1266/1271] Merge pull request #13605 from The-Compiler/training-update-2025-07 doc: Update trainings (cherry picked from commit 5f993856350d1cff144e48810b1c0137c8ec45c5) --- doc/en/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/index.rst b/doc/en/index.rst index fb5d0482c0d..2b58bebc20f 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -2,7 +2,7 @@ .. sidebar:: **Next Open Trainings and Events** - - `pytest - simple, rapid and fun testing with Python `_, at `EuroPython 2025 `_, **July 14th** (3h), Prague, Czech Republic + - `Testen mit pytest `_ (German), via `Letsboot `_ (3 day in-depth training), **October 29th -- 31st**, Zurich (CH) - `Professional Testing with Python `_, via `Python Academy `_ (3 day in-depth training), **March 3th -- 5th 2026**, Leipzig (DE) / Remote Also see :doc:`previous talks and blogposts ` From 2c94c4a6948ba53440818389298157fa5d5f94cd Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 8 Aug 2025 18:03:20 +0000 Subject: [PATCH 1267/1271] add missing colon (#13640) (#13641) (cherry picked from commit 03db745771b5304b45512bf41667adfab1fe8f7a) Co-authored-by: John Litborn <11260241+jakkdl@users.noreply.github.com> --- src/_pytest/raises.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/_pytest/raises.py b/src/_pytest/raises.py index 480ae33647f..5a82f58e656 100644 --- a/src/_pytest/raises.py +++ b/src/_pytest/raises.py @@ -559,7 +559,7 @@ class RaisesExc(AbstractRaises[BaseExcT_co_default]): The type is checked with :func:`isinstance`, and does not need to be an exact match. If that is wanted you can use the ``check`` parameter. - :kwparam str | Pattern[str] match + :kwparam str | Pattern[str] match: A regex to match. :kwparam Callable[[BaseException], bool] check: From b7f05680d1301e0969b30bcb3c4b27433c9ee2b7 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 30 Aug 2025 01:03:15 +0200 Subject: [PATCH 1268/1271] Merge pull request #13685 from CoretexShadow/fix/docs-pytest-generate-tests Docs+Tests: clarify special discovery of pytest_generate_tests (cherry picked from commit 12bde8af6dda3e7104f840209c199d151258b462) --- changelog/13577.doc.rst | 1 + doc/en/how-to/parametrize.rst | 7 +++++++ doc/en/how-to/writing_hook_functions.rst | 6 ++++++ 3 files changed, 14 insertions(+) create mode 100644 changelog/13577.doc.rst diff --git a/changelog/13577.doc.rst b/changelog/13577.doc.rst new file mode 100644 index 00000000000..8d6db9ea983 --- /dev/null +++ b/changelog/13577.doc.rst @@ -0,0 +1 @@ +Clarify that ``pytest_generate_tests`` is discovered in test modules/classes; other hooks must be in ``conftest.py`` or plugins. diff --git a/doc/en/how-to/parametrize.rst b/doc/en/how-to/parametrize.rst index d7c12c1a1f4..fe186146434 100644 --- a/doc/en/how-to/parametrize.rst +++ b/doc/en/how-to/parametrize.rst @@ -240,6 +240,13 @@ command line option and the parametrization of our test function: if "stringinput" in metafunc.fixturenames: metafunc.parametrize("stringinput", metafunc.config.getoption("stringinput")) +.. note:: + + The :hook:`pytest_generate_tests` hook can also be implemented directly in a test + module or inside a test class; unlike other hooks, pytest will discover it there + as well. Other hooks must live in a :ref:`conftest.py ` or a plugin. + See :ref:`writinghooks`. + If we now pass two stringinput values, our test will run twice: .. code-block:: pytest diff --git a/doc/en/how-to/writing_hook_functions.rst b/doc/en/how-to/writing_hook_functions.rst index f4c00d04fda..cd18301ce84 100644 --- a/doc/en/how-to/writing_hook_functions.rst +++ b/doc/en/how-to/writing_hook_functions.rst @@ -235,6 +235,12 @@ Example: """ print(config.hook) +.. note:: + + Unlike other hooks, the :hook:`pytest_generate_tests` hook is also discovered when + defined inside a test module or test class. Other hooks must live in + :ref:`conftest.py plugins ` or external plugins. + See :ref:`parametrize-basics` and the :ref:`hook-reference`. .. _`addoptionhooks`: From 7723ce84b87ab08f86ddafcb342acc28ba5ec99d Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Sat, 30 Aug 2025 01:03:57 +0200 Subject: [PATCH 1269/1271] Merge pull request #13683 from even-even/fix_Exeption_to_Exception_in_errorMessage fix: change Exeption to Exception in raises.py (cherry picked from commit e63f6e51c61fbe9ba6fb0acc436838d09fc5bf05) --- src/_pytest/raises.py | 2 +- testing/python/raises_group.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_pytest/raises.py b/src/_pytest/raises.py index 5a82f58e656..78fae6ddcde 100644 --- a/src/_pytest/raises.py +++ b/src/_pytest/raises.py @@ -457,7 +457,7 @@ def _parse_exc( return cast(type[BaseExcT_1], origin_exc) else: raise ValueError( - f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` " + f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseException]` " f"are accepted as generic types but got `{exc}`. " f"As `raises` will catch all instances of the specified group regardless of the " f"generic argument specific nested exceptions has to be checked " diff --git a/testing/python/raises_group.py b/testing/python/raises_group.py index 04979c32e98..386e127a13d 100644 --- a/testing/python/raises_group.py +++ b/testing/python/raises_group.py @@ -1304,7 +1304,7 @@ def test_parametrizing_conditional_raisesgroup( def test_annotated_group() -> None: # repr depends on if exceptiongroup backport is being used or not t = repr(ExceptionGroup[ValueError]) - msg = "Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` are accepted as generic types but got `{}`. As `raises` will catch all instances of the specified group regardless of the generic argument specific nested exceptions has to be checked with `RaisesGroup`." + msg = "Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseException]` are accepted as generic types but got `{}`. As `raises` will catch all instances of the specified group regardless of the generic argument specific nested exceptions has to be checked with `RaisesGroup`." fail_msg = wrap_escape(msg.format(t)) with pytest.raises(ValueError, match=fail_msg): From 89905381a163be30ae87d62e5f750e902d750c5f Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Tue, 2 Sep 2025 17:03:21 -0300 Subject: [PATCH 1270/1271] Fix passenv CI in tox ini and make tests insensitive to the presence of the CI env variable (#13684) (#13694) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As discussed in https://github.com/pytest-dev/pytest/pull/13684#:~:text=See%3A%20%23-,13679%20(comment),-ogrisel%20added%204. --------- (cherry picked from commit bf92debb4fd874289f6aed29c6947b611b1de0ae) Co-authored-by: Olivier Grisel Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) --- changelog/13684.contrib.rst | 1 + pyproject.toml | 3 +++ testing/conftest.py | 12 ++++++++++++ testing/python/approx.py | 4 ++-- testing/test_faulthandler.py | 1 + tox.ini | 1 + 6 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 changelog/13684.contrib.rst diff --git a/changelog/13684.contrib.rst b/changelog/13684.contrib.rst new file mode 100644 index 00000000000..bb2f87f1710 --- /dev/null +++ b/changelog/13684.contrib.rst @@ -0,0 +1 @@ +Make pytest's own testsuite insensitive to the presence of the ``CI`` environment variable -- by :user:`ogrisel`. diff --git a/pyproject.toml b/pyproject.toml index 1e9665add02..a3c82db4381 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -426,6 +426,9 @@ markers = [ "slow", # experimental mark for all tests using pexpect "uses_pexpect", + # Disables the `remove_ci_env_var` autouse fixture on a given test that + # actually inspects whether the CI environment variable is set. + "keep_ci_var", ] [tool.towncrier] diff --git a/testing/conftest.py b/testing/conftest.py index 251b430e9cd..25abce913ea 100644 --- a/testing/conftest.py +++ b/testing/conftest.py @@ -237,3 +237,15 @@ def mock_timing(monkeypatch: MonkeyPatch): result = MockTiming() result.patch(monkeypatch) return result + + +@pytest.fixture(autouse=True) +def remove_ci_env_var(monkeypatch: MonkeyPatch, request: pytest.FixtureRequest) -> None: + """Make the test insensitive if it is running in CI or not. + + Use `@pytest.mark.keep_ci_var` in a test to avoid applying this fixture, letting the test + see the real `CI` variable (if present). + """ + has_keep_ci_mark = request.node.get_closest_marker("keep_ci_var") is not None + if not has_keep_ci_mark: + monkeypatch.delenv("CI", raising=False) diff --git a/testing/python/approx.py b/testing/python/approx.py index 2ca7ee70945..06633b544ec 100644 --- a/testing/python/approx.py +++ b/testing/python/approx.py @@ -1085,10 +1085,10 @@ def test_map_over_nested_lists(self): ] def test_map_over_mixed_sequence(self): - assert _recursive_sequence_map(sqrt, [4, (25, 64), [(49)]]) == [ + assert _recursive_sequence_map(sqrt, [4, (25, 64), [49]]) == [ 2, (5, 8), - [(7)], + [7], ] def test_map_over_sequence_like(self): diff --git a/testing/test_faulthandler.py b/testing/test_faulthandler.py index c416e81d2d9..d89cb274b78 100644 --- a/testing/test_faulthandler.py +++ b/testing/test_faulthandler.py @@ -71,6 +71,7 @@ def test_disabled(): assert result.ret == 0 +@pytest.mark.keep_ci_var @pytest.mark.parametrize( "enabled", [ diff --git a/tox.ini b/tox.ini index f1283aa8260..3fe7865a289 100644 --- a/tox.ini +++ b/tox.ini @@ -52,6 +52,7 @@ passenv = PYTEST_ADDOPTS TERM SETUPTOOLS_SCM_PRETEND_VERSION_FOR_PYTEST + CI setenv = _PYTEST_TOX_DEFAULT_POSARGS={env:_PYTEST_TOX_POSARGS_DOCTESTING:} {env:_PYTEST_TOX_POSARGS_LSOF:} {env:_PYTEST_TOX_POSARGS_XDIST:} {env:_PYTEST_FILES:} From bfae4224fd554d3d7f2c277a4cc092b6ec6af3ae Mon Sep 17 00:00:00 2001 From: pytest bot Date: Wed, 3 Sep 2025 14:00:04 +0000 Subject: [PATCH 1271/1271] Prepare release version 8.4.2 --- changelog/13478.bugfix.rst | 1 - changelog/13480.contrib.rst | 1 - changelog/13530.bugfix.rst | 1 - changelog/13547.contrib.rst | 1 - changelog/13549.bugfix.rst | 3 -- changelog/13559.bugfix.rst | 1 - changelog/13563.bugfix.rst | 1 - changelog/13577.doc.rst | 1 - changelog/13684.contrib.rst | 1 - doc/en/announce/index.rst | 1 + doc/en/announce/release-8.4.2.rst | 27 ++++++++++++++++++ doc/en/builtin.rst | 2 +- doc/en/changelog.rst | 43 +++++++++++++++++++++++++++++ doc/en/example/parametrize.rst | 6 ++-- doc/en/example/pythoncollection.rst | 4 +-- doc/en/getting-started.rst | 2 +- doc/en/how-to/fixtures.rst | 2 +- 17 files changed, 79 insertions(+), 19 deletions(-) delete mode 100644 changelog/13478.bugfix.rst delete mode 100644 changelog/13480.contrib.rst delete mode 100644 changelog/13530.bugfix.rst delete mode 100644 changelog/13547.contrib.rst delete mode 100644 changelog/13549.bugfix.rst delete mode 100644 changelog/13559.bugfix.rst delete mode 100644 changelog/13563.bugfix.rst delete mode 100644 changelog/13577.doc.rst delete mode 100644 changelog/13684.contrib.rst create mode 100644 doc/en/announce/release-8.4.2.rst diff --git a/changelog/13478.bugfix.rst b/changelog/13478.bugfix.rst deleted file mode 100644 index 1147ee54c9e..00000000000 --- a/changelog/13478.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash when using :confval:`console_output_style` with ``times`` and a module is skipped. diff --git a/changelog/13480.contrib.rst b/changelog/13480.contrib.rst deleted file mode 100644 index 9079c6f6b5a..00000000000 --- a/changelog/13480.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Self-testing: fixed a few test failures when run with ``-Wdefault`` or a similar override. diff --git a/changelog/13530.bugfix.rst b/changelog/13530.bugfix.rst deleted file mode 100644 index 1a5ab365f12..00000000000 --- a/changelog/13530.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash when using :func:`pytest.approx` and :class:`decimal.Decimal` instances with the :class:`decimal.FloatOperation` trap set. diff --git a/changelog/13547.contrib.rst b/changelog/13547.contrib.rst deleted file mode 100644 index d8a240c0506..00000000000 --- a/changelog/13547.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Self-testing: corrected expected message for ``test_doctest_unexpected_exception`` in Python ``3.14``. diff --git a/changelog/13549.bugfix.rst b/changelog/13549.bugfix.rst deleted file mode 100644 index e69f6a4d6cf..00000000000 --- a/changelog/13549.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -No longer evaluate type annotations in Python ``3.14`` when inspecting function signatures. - -This prevents crashes during module collection when modules do not explicitly use ``from __future__ import annotations`` and import types for annotations within a ``if TYPE_CHECKING:`` block. diff --git a/changelog/13559.bugfix.rst b/changelog/13559.bugfix.rst deleted file mode 100644 index 69036f784ac..00000000000 --- a/changelog/13559.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Added missing `int` and `float` variants to the `Literal` type annotation of the `type` parameter in :meth:`pytest.Parser.addini`. diff --git a/changelog/13563.bugfix.rst b/changelog/13563.bugfix.rst deleted file mode 100644 index 543552e20cf..00000000000 --- a/changelog/13563.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`pytest.approx` now only imports ``numpy`` if NumPy is already in ``sys.modules``. This fixes unconditional import behavior introduced in `8.4.0`. diff --git a/changelog/13577.doc.rst b/changelog/13577.doc.rst deleted file mode 100644 index 8d6db9ea983..00000000000 --- a/changelog/13577.doc.rst +++ /dev/null @@ -1 +0,0 @@ -Clarify that ``pytest_generate_tests`` is discovered in test modules/classes; other hooks must be in ``conftest.py`` or plugins. diff --git a/changelog/13684.contrib.rst b/changelog/13684.contrib.rst deleted file mode 100644 index bb2f87f1710..00000000000 --- a/changelog/13684.contrib.rst +++ /dev/null @@ -1 +0,0 @@ -Make pytest's own testsuite insensitive to the presence of the ``CI`` environment variable -- by :user:`ogrisel`. diff --git a/doc/en/announce/index.rst b/doc/en/announce/index.rst index 2ed23eb1fbb..1cc8fbaf7c0 100644 --- a/doc/en/announce/index.rst +++ b/doc/en/announce/index.rst @@ -6,6 +6,7 @@ Release announcements :maxdepth: 2 + release-8.4.2 release-8.4.1 release-8.4.0 release-8.3.5 diff --git a/doc/en/announce/release-8.4.2.rst b/doc/en/announce/release-8.4.2.rst new file mode 100644 index 00000000000..58a842c4d4b --- /dev/null +++ b/doc/en/announce/release-8.4.2.rst @@ -0,0 +1,27 @@ +pytest-8.4.2 +======================================= + +pytest 8.4.2 has just been released to PyPI. + +This is a bug-fix release, being a drop-in replacement. + +The full changelog is available at https://docs.pytest.org/en/stable/changelog.html. + +Thanks to all of the contributors to this release: + +* AD +* Aditi De +* Bruno Oliveira +* Florian Bruhin +* John Litborn +* Liam DeVoe +* Marc Mueller +* NayeemJohn +* Olivier Grisel +* Ran Benita +* bengartner +* 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) + + +Happy testing, +The pytest Development Team diff --git a/doc/en/builtin.rst b/doc/en/builtin.rst index 31c2fa9df06..ca350c5f3dd 100644 --- a/doc/en/builtin.rst +++ b/doc/en/builtin.rst @@ -142,7 +142,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a For more details: :ref:`doctest_namespace`. - pytestconfig [session scope] -- .../_pytest/fixtures.py:1424 + pytestconfig [session scope] -- .../_pytest/fixtures.py:1425 Session-scoped fixture that returns the session's :class:`pytest.Config` object. diff --git a/doc/en/changelog.rst b/doc/en/changelog.rst index 63623de8aad..89f1c4e61b3 100644 --- a/doc/en/changelog.rst +++ b/doc/en/changelog.rst @@ -31,6 +31,49 @@ with advance notice in the **Deprecations** section of releases. .. towncrier release notes start +pytest 8.4.2 (2025-09-03) +========================= + +Bug fixes +--------- + +- `#13478 `_: Fixed a crash when using :confval:`console_output_style` with ``times`` and a module is skipped. + + +- `#13530 `_: Fixed a crash when using :func:`pytest.approx` and :class:`decimal.Decimal` instances with the :class:`decimal.FloatOperation` trap set. + + +- `#13549 `_: No longer evaluate type annotations in Python ``3.14`` when inspecting function signatures. + + This prevents crashes during module collection when modules do not explicitly use ``from __future__ import annotations`` and import types for annotations within a ``if TYPE_CHECKING:`` block. + + +- `#13559 `_: Added missing `int` and `float` variants to the `Literal` type annotation of the `type` parameter in :meth:`pytest.Parser.addini`. + + +- `#13563 `_: :func:`pytest.approx` now only imports ``numpy`` if NumPy is already in ``sys.modules``. This fixes unconditional import behavior introduced in `8.4.0`. + + + +Improved documentation +---------------------- + +- `#13577 `_: Clarify that ``pytest_generate_tests`` is discovered in test modules/classes; other hooks must be in ``conftest.py`` or plugins. + + + +Contributor-facing changes +-------------------------- + +- `#13480 `_: Self-testing: fixed a few test failures when run with ``-Wdefault`` or a similar override. + + +- `#13547 `_: Self-testing: corrected expected message for ``test_doctest_unexpected_exception`` in Python ``3.14``. + + +- `#13684 `_: Make pytest's own testsuite insensitive to the presence of the ``CI`` environment variable -- by :user:`ogrisel`. + + pytest 8.4.1 (2025-06-17) ========================= diff --git a/doc/en/example/parametrize.rst b/doc/en/example/parametrize.rst index 8e6479254bb..6374e0edb3d 100644 --- a/doc/en/example/parametrize.rst +++ b/doc/en/example/parametrize.rst @@ -162,7 +162,7 @@ objects, they are still using the default pytest representation: rootdir: /home/sweet/project collected 8 items - + @@ -239,7 +239,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia rootdir: /home/sweet/project collected 4 items - + @@ -318,7 +318,7 @@ Let's first see how it looks like at collection time: rootdir: /home/sweet/project collected 2 items - + diff --git a/doc/en/example/pythoncollection.rst b/doc/en/example/pythoncollection.rst index 01a8f48fdbf..2487e7b9d19 100644 --- a/doc/en/example/pythoncollection.rst +++ b/doc/en/example/pythoncollection.rst @@ -152,7 +152,7 @@ The test collection would look like this: configfile: pytest.ini collected 2 items - + @@ -215,7 +215,7 @@ You can always peek at the collection tree without running tests like this: configfile: pytest.ini collected 3 items - + diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index c5e9f708828..349711faaf4 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -22,7 +22,7 @@ Install ``pytest`` .. code-block:: bash $ pytest --version - pytest 8.4.1 + pytest 8.4.2 .. _`simpletest`: diff --git a/doc/en/how-to/fixtures.rst b/doc/en/how-to/fixtures.rst index 62ace745d43..7f1a7610bb8 100644 --- a/doc/en/how-to/fixtures.rst +++ b/doc/en/how-to/fixtures.rst @@ -1423,7 +1423,7 @@ Running the above tests results in the following test IDs being used: rootdir: /home/sweet/project collected 12 items - +